diff options
| author | mascarenhas <mascarenhas> | 2009-07-04 02:10:16 +0000 |
|---|---|---|
| committer | mascarenhas <mascarenhas> | 2009-07-04 02:10:16 +0000 |
| commit | c293392539848f91d99a7e7bab2203c852d924b9 (patch) | |
| tree | 5666cf19a8997b8423f4d78ff24bd4c2346457d7 /src | |
| parent | 327acf788fd2a28436bcc8f4848a3a2819fa1ca8 (diff) | |
| download | luafilesystem-c293392539848f91d99a7e7bab2203c852d924b9.tar.gz luafilesystem-c293392539848f91d99a7e7bab2203c852d924b9.tar.bz2 luafilesystem-c293392539848f91d99a7e7bab2203c852d924b9.zip | |
overhaul of lock_dir to remove staleness checks (due to race condition) and simplify the function
Diffstat (limited to 'src')
| -rw-r--r-- | src/lfs.c | 47 |
1 files changed, 14 insertions, 33 deletions
| @@ -17,7 +17,7 @@ | |||
| 17 | ** lfs.touch (filepath [, atime [, mtime]]) | 17 | ** lfs.touch (filepath [, atime [, mtime]]) |
| 18 | ** lfs.unlock (fh) | 18 | ** lfs.unlock (fh) |
| 19 | ** | 19 | ** |
| 20 | ** $Id: lfs.c,v 1.60 2009/06/03 20:49:18 mascarenhas Exp $ | 20 | ** $Id: lfs.c,v 1.61 2009/07/04 02:10:16 mascarenhas Exp $ |
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #ifndef _WIN32 | 23 | #ifndef _WIN32 |
| @@ -247,55 +247,36 @@ static int lfs_unlock_dir(lua_State *L) { | |||
| 247 | } | 247 | } |
| 248 | #else | 248 | #else |
| 249 | typedef struct lfs_Lock { | 249 | typedef struct lfs_Lock { |
| 250 | int fd; | ||
| 251 | char *ln; | 250 | char *ln; |
| 252 | } lfs_Lock; | 251 | } lfs_Lock; |
| 253 | static int lfs_lock_dir(lua_State *L) { | 252 | static int lfs_lock_dir(lua_State *L) { |
| 254 | struct stat statbuf; | ||
| 255 | lfs_Lock *lock; | 253 | lfs_Lock *lock; |
| 256 | size_t pathl; int fd; | 254 | size_t pathl; |
| 257 | char *tmpln, *ln; | 255 | char *ln; |
| 258 | const char *template = "/lockfile.XXXXXX"; | ||
| 259 | const char *lockfile = "/lockfile.lfs"; | 256 | const char *lockfile = "/lockfile.lfs"; |
| 260 | const char *path = luaL_checklstring(L, 1, &pathl); | 257 | const char *path = luaL_checklstring(L, 1, &pathl); |
| 261 | time_t expires = (time_t)luaL_optint(L, 2, INT_MAX); | 258 | lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock)); |
| 262 | tmpln = (char*)malloc(pathl + strlen(template) + 1); | ||
| 263 | if(!tmpln) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; } | ||
| 264 | strcpy(tmpln, path); strcat(tmpln, template); | ||
| 265 | fd = mkstemp(tmpln); | ||
| 266 | if(fd == -1) { | ||
| 267 | free(tmpln); lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; | ||
| 268 | } | ||
| 269 | ln = (char*)malloc(pathl + strlen(lockfile) + 1); | 259 | ln = (char*)malloc(pathl + strlen(lockfile) + 1); |
| 270 | if(!ln) { | 260 | if(!ln) { |
| 271 | unlink(tmpln); free(tmpln); close(fd); lua_pushnil(L); | 261 | lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; |
| 272 | lua_pushstring(L, strerror(errno)); return 2; | ||
| 273 | } | 262 | } |
| 274 | strcpy(ln, path); strcat(ln, lockfile); | 263 | strcpy(ln, path); strcat(ln, lockfile); |
| 275 | while(symlink(tmpln, ln) == -1) { | 264 | if(symlink("lock", ln) == -1) { |
| 276 | if(errno == EEXIST) { | 265 | free(ln); lua_pushnil(L); |
| 277 | if(lstat(ln, &statbuf) == -1) goto fail; | 266 | lua_pushstring(L, strerror(errno)); return 2; |
| 278 | if(time(NULL) - statbuf.st_mtimespec.tv_sec > expires) { | ||
| 279 | unlink(ln); | ||
| 280 | continue; | ||
| 281 | } | ||
| 282 | } | ||
| 283 | fail: | ||
| 284 | unlink(tmpln); free(tmpln); free(ln); close(fd); | ||
| 285 | lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; | ||
| 286 | } | 267 | } |
| 287 | unlink(tmpln); free(tmpln); | 268 | lock->ln = ln; |
| 288 | lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock)); | ||
| 289 | lock->fd = fd; lock->ln = ln; | ||
| 290 | luaL_getmetatable (L, LOCK_METATABLE); | 269 | luaL_getmetatable (L, LOCK_METATABLE); |
| 291 | lua_setmetatable (L, -2); | 270 | lua_setmetatable (L, -2); |
| 292 | return 1; | 271 | return 1; |
| 293 | } | 272 | } |
| 294 | static int lfs_unlock_dir(lua_State *L) { | 273 | static int lfs_unlock_dir(lua_State *L) { |
| 295 | lfs_Lock *lock = luaL_checkudata(L, 1, LOCK_METATABLE); | 274 | lfs_Lock *lock = luaL_checkudata(L, 1, LOCK_METATABLE); |
| 296 | unlink(lock->ln); | 275 | if(lock->ln) { |
| 297 | close(lock->fd); | 276 | unlink(lock->ln); |
| 298 | free(lock->ln); | 277 | free(lock->ln); |
| 278 | lock->ln = NULL; | ||
| 279 | } | ||
| 299 | return 0; | 280 | return 0; |
| 300 | } | 281 | } |
| 301 | #endif | 282 | #endif |
