diff options
author | Nick Mathewson <nickm@torproject.org> | 2008-09-01 20:06:26 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2008-09-01 20:06:26 +0000 |
commit | f80ac31d742c2d86f1812b895ef61a5885e2447e (patch) | |
tree | 9b223723aced9e7a8acc55044120cc406c77bd9b /src/common/compat.c | |
parent | 6a29ad853b630a1970fd95e17ecd79306e7c39e6 (diff) | |
download | tor-f80ac31d742c2d86f1812b895ef61a5885e2447e.tar.gz tor-f80ac31d742c2d86f1812b895ef61a5885e2447e.zip |
Add a lockfile to the Tor data directory to avoid situations where two Tors start with the same datadir, or where a --list-fingerprints races with a server to create keys, or such.
svn:r16722
Diffstat (limited to 'src/common/compat.c')
-rw-r--r-- | src/common/compat.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/src/common/compat.c b/src/common/compat.c index fcb6f9888d..59d85a41f8 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -26,6 +26,7 @@ const char compat_c_id[] = #ifdef MS_WINDOWS #include <process.h> #include <windows.h> +#include <sys/locking.h> #endif #ifdef HAVE_UNAME @@ -98,6 +99,9 @@ const char compat_c_id[] = #ifdef HAVE_SYS_SYSLIMITS_H #include <sys/syslimits.h> #endif +#ifdef HAVE_SYS_FILE_H +#include <sys/file.h> +#endif #ifdef USE_BSOCKETS #include <bsocket.h> @@ -488,6 +492,77 @@ touch_file(const char *fname) return 0; } +struct tor_lockfile_t { + char *filename; + int fd; +}; + +tor_lockfile_t * +tor_lockfile_lock(const char *filename, int blocking, int *locked_out) +{ + tor_lockfile_t *result; + int fd; + *locked_out = 0; + + log_info(LD_FS, "Locking \"%s\"", filename); + fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600); + if (fd < 0) { + log_warn(LD_FS,"Couldn't open \"%s\" for locking: %s", filename, + strerror(errno)); + return NULL; + } +#ifdef WIN32 + _lseek(fd, 0, SEEK_SET); + if (_locking(fd, blocking ? _LK_LOCK : _LK_NBLOCK, 0) < 0) { + if (errno != EDEADLOCK) + log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno)); + else + *locked_out = 1; + close(fd); + return NULL; + } +#else + if (flock(fd, LOCK_EX|(blocking ? 0 : LOCK_NB)) < 0) { + if (errno != EWOULDBLOCK) + log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno)); + else + *locked_out = 1; + close(fd); + return NULL; + } +#endif + + result = tor_malloc(sizeof(tor_lockfile_t)); + result->filename = tor_strdup(filename); + result->fd = fd; + return result; +} + +void +tor_lockfile_unlock(tor_lockfile_t *lockfile) +{ + tor_assert(lockfile); + + log_info(LD_FS, "Unlocking \"%s\"", lockfile->filename); +#ifdef WIN32 + _lseek(fd, 0, SEEK_SET); + if (_locking(fd, _LK_UNLCK, 0) < 0) { + log_warn(LD_FS,"Error unlocking \"%s\": %s", lockfile->filename, + strerror(errno)); + } +#else + if (flock(lockfile->fd, LOCK_UN) < 0) { + log_warn(LD_FS, "Error unlocking \"%s\": %s", lockfile->filename, + strerror(errno)); + } +#endif + + close(lockfile->fd); + lockfile->fd = -1; + tor_free(lockfile->filename); + tor_free(lockfile); +} + #undef DEBUG_SOCKET_COUNTING #ifdef DEBUG_SOCKET_COUNTING /** A bitarray of all fds that should be passed to tor_socket_close(). Only |