aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormascarenhas <mascarenhas>2009-03-25 19:14:17 +0000
committermascarenhas <mascarenhas>2009-03-25 19:14:17 +0000
commitd21c4ae194f84338cbcd85a878fdeefa46fff4f7 (patch)
tree4efaccb5521e3deb4cadb68b21cc56f254cde560 /src
parent342df4a5a3c67c4ff2567090d203280b6505f580 (diff)
downloadluafilesystem-d21c4ae194f84338cbcd85a878fdeefa46fff4f7.tar.gz
luafilesystem-d21c4ae194f84338cbcd85a878fdeefa46fff4f7.tar.bz2
luafilesystem-d21c4ae194f84338cbcd85a878fdeefa46fff4f7.zip
locking via lockfiles in posix systems. API:
lock, err = lfs.lock_dir(path, [seconds_stale]) Creates a lockfile (called lockfile.lfs) in <path> if it does not exist and returns the lock. If the lock already exists checks it it's stale, using the second parameter (default for the second parameter is INT_MAX, which in practice means the lock will never be stale. To free the the lock call lock:free(). In case of any errors it returns nil and the error message. In particular, if the lock exists and is not stale it returns the "File exists" message.
Diffstat (limited to 'src')
-rw-r--r--src/lfs.c82
1 files changed, 81 insertions, 1 deletions
diff --git a/src/lfs.c b/src/lfs.c
index a3bce1d..45adf4a 100644
--- a/src/lfs.c
+++ b/src/lfs.c
@@ -16,7 +16,7 @@
16** lfs.touch (filepath [, atime [, mtime]]) 16** lfs.touch (filepath [, atime [, mtime]])
17** lfs.unlock (fh) 17** lfs.unlock (fh)
18** 18**
19** $Id: lfs.c,v 1.56 2009/02/03 22:05:48 carregal Exp $ 19** $Id: lfs.c,v 1.57 2009/03/25 19:14:17 mascarenhas Exp $
20*/ 20*/
21 21
22#ifndef _WIN32 22#ifndef _WIN32
@@ -84,6 +84,11 @@ typedef struct dir_data {
84#endif 84#endif
85} dir_data; 85} dir_data;
86 86
87#define LOCK_METATABLE "lock metatable"
88typedef struct lfs_Lock {
89 int fd;
90 char *ln;
91} lfs_Lock;
87 92
88#ifdef _WIN32 93#ifdef _WIN32
89 #ifdef __BORLANDC__ 94 #ifdef __BORLANDC__
@@ -206,6 +211,64 @@ static int _file_lock (lua_State *L, FILE *fh, const char *mode, const long star
206} 211}
207 212
208#ifdef _WIN32 213#ifdef _WIN32
214static int lfs_lock_dir(lua_State *L) {
215 luaL_error(L, "not implemented for Windows");
216}
217static int lfs_unlock_dir(lua_State *L) {
218 luaL_error(L, "not implemented for Windows");
219}
220#else
221static int lfs_lock_dir(lua_State *L) {
222 struct stat statbuf;
223 lfs_Lock *lock;
224 size_t pathl; int fd;
225 char *tmpln, *ln;
226 const char *template = "/lockfile.XXXXXX";
227 const char *lockfile = "/lockfile.lfs";
228 const char *path = luaL_checklstring(L, 1, &pathl);
229 time_t expires = (time_t)luaL_optint(L, 2, INT_MAX);
230 tmpln = (char*)malloc(pathl + strlen(template) + 1);
231 if(!tmpln) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; }
232 strcpy(tmpln, path); strcat(tmpln, template);
233 fd = mkstemp(tmpln);
234 if(fd == -1) {
235 free(tmpln); lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
236 }
237 ln = (char*)malloc(pathl + strlen(lockfile) + 1);
238 if(!ln) {
239 unlink(tmpln); free(tmpln); close(fd); lua_pushnil(L);
240 lua_pushstring(L, strerror(errno)); return 2;
241 }
242 strcpy(ln, path); strcat(ln, lockfile);
243 while(symlink(tmpln, ln) == -1) {
244 if(errno == EEXIST) {
245 if(lstat(ln, &statbuf) == -1) goto fail;
246 if(time(NULL) - statbuf.st_mtimespec.tv_sec > expires) {
247 unlink(ln);
248 continue;
249 }
250 }
251 fail:
252 unlink(tmpln); free(tmpln); free(ln); close(fd);
253 lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
254 }
255 unlink(tmpln); free(tmpln);
256 lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock));
257 lock->fd = fd; lock->ln = ln;
258 luaL_getmetatable (L, LOCK_METATABLE);
259 lua_setmetatable (L, -2);
260 return 1;
261}
262static int lfs_unlock_dir(lua_State *L) {
263 lfs_Lock *lock = luaL_checkudata(L, 1, LOCK_METATABLE);
264 unlink(lock->ln);
265 close(lock->fd);
266 free(lock->ln);
267 return 0;
268}
269#endif
270
271#ifdef _WIN32
209static int lfs_g_setmode (lua_State *L, FILE *f, int arg) { 272static int lfs_g_setmode (lua_State *L, FILE *f, int arg) {
210 static const int mode[] = {_O_TEXT, _O_BINARY}; 273 static const int mode[] = {_O_TEXT, _O_BINARY};
211 static const char *const modenames[] = {"text", "binary", NULL}; 274 static const char *const modenames[] = {"text", "binary", NULL};
@@ -433,6 +496,21 @@ static int dir_create_meta (lua_State *L) {
433 return 1; 496 return 1;
434} 497}
435 498
499/*
500** Creates lock metatable.
501*/
502static int lock_create_meta (lua_State *L) {
503 luaL_newmetatable (L, LOCK_METATABLE);
504 /* set its __gc field */
505 lua_newtable(L);
506 lua_pushcfunction(L, lfs_unlock_dir);
507 lua_setfield(L, -2, "free");
508 lua_setfield(L, -2, "__index");
509 lua_pushcfunction(L, lfs_unlock_dir);
510 lua_setfield(L, -2, "__gc");
511 return 1;
512}
513
436 514
437#ifdef _WIN32 515#ifdef _WIN32
438 #ifndef S_ISDIR 516 #ifndef S_ISDIR
@@ -688,11 +766,13 @@ static const struct luaL_reg fslib[] = {
688 {"setmode", lfs_f_setmode}, 766 {"setmode", lfs_f_setmode},
689 {"touch", file_utime}, 767 {"touch", file_utime},
690 {"unlock", file_unlock}, 768 {"unlock", file_unlock},
769 {"lock_dir", lfs_lock_dir},
691 {NULL, NULL}, 770 {NULL, NULL},
692}; 771};
693 772
694int luaopen_lfs (lua_State *L) { 773int luaopen_lfs (lua_State *L) {
695 dir_create_meta (L); 774 dir_create_meta (L);
775 lock_create_meta (L);
696 luaL_register (L, "lfs", fslib); 776 luaL_register (L, "lfs", fslib);
697 set_info (L); 777 set_info (L);
698 return 1; 778 return 1;