mirror of
https://github.com/lunarmodules/luafilesystem.git
synced 2026-07-22 02:53:06 +00:00
overhaul of lock_dir to remove staleness checks (due to race condition) and simplify the function
This commit is contained in:
47
src/lfs.c
47
src/lfs.c
@@ -17,7 +17,7 @@
|
|||||||
** lfs.touch (filepath [, atime [, mtime]])
|
** lfs.touch (filepath [, atime [, mtime]])
|
||||||
** lfs.unlock (fh)
|
** lfs.unlock (fh)
|
||||||
**
|
**
|
||||||
** $Id: lfs.c,v 1.60 2009/06/03 20:49:18 mascarenhas Exp $
|
** $Id: lfs.c,v 1.61 2009/07/04 02:10:16 mascarenhas Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
@@ -247,55 +247,36 @@ static int lfs_unlock_dir(lua_State *L) {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
typedef struct lfs_Lock {
|
typedef struct lfs_Lock {
|
||||||
int fd;
|
|
||||||
char *ln;
|
char *ln;
|
||||||
} lfs_Lock;
|
} lfs_Lock;
|
||||||
static int lfs_lock_dir(lua_State *L) {
|
static int lfs_lock_dir(lua_State *L) {
|
||||||
struct stat statbuf;
|
|
||||||
lfs_Lock *lock;
|
lfs_Lock *lock;
|
||||||
size_t pathl; int fd;
|
size_t pathl;
|
||||||
char *tmpln, *ln;
|
char *ln;
|
||||||
const char *template = "/lockfile.XXXXXX";
|
|
||||||
const char *lockfile = "/lockfile.lfs";
|
const char *lockfile = "/lockfile.lfs";
|
||||||
const char *path = luaL_checklstring(L, 1, &pathl);
|
const char *path = luaL_checklstring(L, 1, &pathl);
|
||||||
time_t expires = (time_t)luaL_optint(L, 2, INT_MAX);
|
lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock));
|
||||||
tmpln = (char*)malloc(pathl + strlen(template) + 1);
|
|
||||||
if(!tmpln) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; }
|
|
||||||
strcpy(tmpln, path); strcat(tmpln, template);
|
|
||||||
fd = mkstemp(tmpln);
|
|
||||||
if(fd == -1) {
|
|
||||||
free(tmpln); lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
|
|
||||||
}
|
|
||||||
ln = (char*)malloc(pathl + strlen(lockfile) + 1);
|
ln = (char*)malloc(pathl + strlen(lockfile) + 1);
|
||||||
if(!ln) {
|
if(!ln) {
|
||||||
unlink(tmpln); free(tmpln); close(fd); lua_pushnil(L);
|
lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
|
||||||
lua_pushstring(L, strerror(errno)); return 2;
|
|
||||||
}
|
}
|
||||||
strcpy(ln, path); strcat(ln, lockfile);
|
strcpy(ln, path); strcat(ln, lockfile);
|
||||||
while(symlink(tmpln, ln) == -1) {
|
if(symlink("lock", ln) == -1) {
|
||||||
if(errno == EEXIST) {
|
free(ln); lua_pushnil(L);
|
||||||
if(lstat(ln, &statbuf) == -1) goto fail;
|
lua_pushstring(L, strerror(errno)); return 2;
|
||||||
if(time(NULL) - statbuf.st_mtimespec.tv_sec > expires) {
|
|
||||||
unlink(ln);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fail:
|
|
||||||
unlink(tmpln); free(tmpln); free(ln); close(fd);
|
|
||||||
lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
|
|
||||||
}
|
}
|
||||||
unlink(tmpln); free(tmpln);
|
lock->ln = ln;
|
||||||
lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock));
|
|
||||||
lock->fd = fd; lock->ln = ln;
|
|
||||||
luaL_getmetatable (L, LOCK_METATABLE);
|
luaL_getmetatable (L, LOCK_METATABLE);
|
||||||
lua_setmetatable (L, -2);
|
lua_setmetatable (L, -2);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
static int lfs_unlock_dir(lua_State *L) {
|
static int lfs_unlock_dir(lua_State *L) {
|
||||||
lfs_Lock *lock = luaL_checkudata(L, 1, LOCK_METATABLE);
|
lfs_Lock *lock = luaL_checkudata(L, 1, LOCK_METATABLE);
|
||||||
unlink(lock->ln);
|
if(lock->ln) {
|
||||||
close(lock->fd);
|
unlink(lock->ln);
|
||||||
free(lock->ln);
|
free(lock->ln);
|
||||||
|
lock->ln = NULL;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user