summaryrefslogtreecommitdiff
path: root/src/common/compat.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2008-09-01 20:06:26 +0000
committerNick Mathewson <nickm@torproject.org>2008-09-01 20:06:26 +0000
commitf80ac31d742c2d86f1812b895ef61a5885e2447e (patch)
tree9b223723aced9e7a8acc55044120cc406c77bd9b /src/common/compat.c
parent6a29ad853b630a1970fd95e17ecd79306e7c39e6 (diff)
downloadtor-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.c75
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