Move lockfile code into lib/fs

This commit is contained in:
Nick Mathewson 2018-06-28 11:33:50 -04:00
parent 84b8dfe635
commit aa3edfd205
6 changed files with 155 additions and 115 deletions

View File

@ -131,116 +131,6 @@ SecureZeroMemory(PVOID ptr, SIZE_T cnt)
#include "lib/net/address.h"
#include "lib/sandbox/sandbox.h"
/** Represents a lockfile on which we hold the lock. */
struct tor_lockfile_t {
/** Name of the file */
char *filename;
/** File descriptor used to hold the file open */
int fd;
};
/** Try to get a lock on the lockfile <b>filename</b>, creating it as
* necessary. If someone else has the lock and <b>blocking</b> is true,
* wait until the lock is available. Otherwise return immediately whether
* we succeeded or not.
*
* Set *<b>locked_out</b> to true if somebody else had the lock, and to false
* otherwise.
*
* Return a <b>tor_lockfile_t</b> on success, NULL on failure.
*
* (Implementation note: because we need to fall back to fcntl on some
* platforms, these locks are per-process, not per-thread. If you want
* to do in-process locking, use tor_mutex_t like a normal person.
* On Windows, when <b>blocking</b> is true, the maximum time that
* is actually waited is 10 seconds, after which NULL is returned
* and <b>locked_out</b> is set to 1.)
*/
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 = tor_open_cloexec(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_NBLCK, 1) < 0) {
if (errno != EACCES && errno != EDEADLOCK)
log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
else
*locked_out = 1;
close(fd);
return NULL;
}
#elif defined(HAVE_FLOCK)
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;
}
#else
{
struct flock lock;
memset(&lock, 0, sizeof(lock));
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
if (fcntl(fd, blocking ? F_SETLKW : F_SETLK, &lock) < 0) {
if (errno != EACCES && errno != EAGAIN)
log_warn(LD_FS, "Couldn't lock \"%s\": %s", filename, strerror(errno));
else
*locked_out = 1;
close(fd);
return NULL;
}
}
#endif /* defined(_WIN32) || ... */
result = tor_malloc(sizeof(tor_lockfile_t));
result->filename = tor_strdup(filename);
result->fd = fd;
return result;
}
/** Release the lock held as <b>lockfile</b>. */
void
tor_lockfile_unlock(tor_lockfile_t *lockfile)
{
tor_assert(lockfile);
log_info(LD_FS, "Unlocking \"%s\"", lockfile->filename);
#ifdef _WIN32
_lseek(lockfile->fd, 0, SEEK_SET);
if (_locking(lockfile->fd, _LK_UNLCK, 1) < 0) {
log_warn(LD_FS,"Error unlocking \"%s\": %s", lockfile->filename,
strerror(errno));
}
#elif defined(HAVE_FLOCK)
if (flock(lockfile->fd, LOCK_UN) < 0) {
log_warn(LD_FS, "Error unlocking \"%s\": %s", lockfile->filename,
strerror(errno));
}
#else
/* Closing the lockfile is sufficient. */
#endif /* defined(_WIN32) || ... */
close(lockfile->fd);
lockfile->fd = -1;
tor_free(lockfile->filename);
tor_free(lockfile);
}
/** Number of extra file descriptors to keep in reserve beyond those that we
* tell Tor it's allowed to use. */
#define ULIMIT_BUFFER 32 /* keep 32 extra fd's beyond ConnLimit_ */
@ -550,7 +440,6 @@ compute_num_cpus(void)
return num_cpus;
}
/** Called before we make any calls to network-related functions.
* (Some operating systems require their network libraries to be
* initialized.) */

View File

@ -108,10 +108,6 @@
#endif /* !defined(timercmp) */
/* ===== File compatibility */
typedef struct tor_lockfile_t tor_lockfile_t;
tor_lockfile_t *tor_lockfile_lock(const char *filename, int blocking,
int *locked_out);
void tor_lockfile_unlock(tor_lockfile_t *lockfile);
/* ===== Net compatibility */

View File

@ -9,6 +9,7 @@ src_lib_libtor_fs_a_SOURCES = \
src/lib/fs/conffile.c \
src/lib/fs/dir.c \
src/lib/fs/files.c \
src/lib/fs/lockfile.c \
src/lib/fs/mmap.c \
src/lib/fs/path.c \
src/lib/fs/storagedir.c \
@ -23,6 +24,7 @@ noinst_HEADERS += \
src/lib/fs/conffile.h \
src/lib/fs/dir.h \
src/lib/fs/files.h \
src/lib/fs/lockfile.h \
src/lib/fs/mmap.h \
src/lib/fs/path.h \
src/lib/fs/storagedir.h \

138
src/lib/fs/lockfile.c Normal file
View File

@ -0,0 +1,138 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#include "lib/fs/files.h"
#include "lib/fs/lockfile.h"
#include "lib/log/torlog.h"
#include "lib/log/util_bug.h"
#include "lib/malloc/util_malloc.h"
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef _WIN32
#include <windows.h>
#include <sys/locking.h>
#endif
#include <errno.h>
#include <string.h>
/** Represents a lockfile on which we hold the lock. */
struct tor_lockfile_t {
/** Name of the file */
char *filename;
/** File descriptor used to hold the file open */
int fd;
};
/** Try to get a lock on the lockfile <b>filename</b>, creating it as
* necessary. If someone else has the lock and <b>blocking</b> is true,
* wait until the lock is available. Otherwise return immediately whether
* we succeeded or not.
*
* Set *<b>locked_out</b> to true if somebody else had the lock, and to false
* otherwise.
*
* Return a <b>tor_lockfile_t</b> on success, NULL on failure.
*
* (Implementation note: because we need to fall back to fcntl on some
* platforms, these locks are per-process, not per-thread. If you want
* to do in-process locking, use tor_mutex_t like a normal person.
* On Windows, when <b>blocking</b> is true, the maximum time that
* is actually waited is 10 seconds, after which NULL is returned
* and <b>locked_out</b> is set to 1.)
*/
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 = tor_open_cloexec(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_NBLCK, 1) < 0) {
if (errno != EACCES && errno != EDEADLOCK)
log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
else
*locked_out = 1;
close(fd);
return NULL;
}
#elif defined(HAVE_FLOCK)
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;
}
#else
{
struct flock lock;
memset(&lock, 0, sizeof(lock));
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
if (fcntl(fd, blocking ? F_SETLKW : F_SETLK, &lock) < 0) {
if (errno != EACCES && errno != EAGAIN)
log_warn(LD_FS, "Couldn't lock \"%s\": %s", filename, strerror(errno));
else
*locked_out = 1;
close(fd);
return NULL;
}
}
#endif /* defined(_WIN32) || ... */
result = tor_malloc(sizeof(tor_lockfile_t));
result->filename = tor_strdup(filename);
result->fd = fd;
return result;
}
/** Release the lock held as <b>lockfile</b>. */
void
tor_lockfile_unlock(tor_lockfile_t *lockfile)
{
tor_assert(lockfile);
log_info(LD_FS, "Unlocking \"%s\"", lockfile->filename);
#ifdef _WIN32
_lseek(lockfile->fd, 0, SEEK_SET);
if (_locking(lockfile->fd, _LK_UNLCK, 1) < 0) {
log_warn(LD_FS,"Error unlocking \"%s\": %s", lockfile->filename,
strerror(errno));
}
#elif defined(HAVE_FLOCK)
if (flock(lockfile->fd, LOCK_UN) < 0) {
log_warn(LD_FS, "Error unlocking \"%s\": %s", lockfile->filename,
strerror(errno));
}
#else
/* Closing the lockfile is sufficient. */
#endif /* defined(_WIN32) || ... */
close(lockfile->fd);
lockfile->fd = -1;
tor_free(lockfile->filename);
tor_free(lockfile);
}

14
src/lib/fs/lockfile.h Normal file
View File

@ -0,0 +1,14 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_LOCKFILE_H
#define TOR_LOCKFILE_H
typedef struct tor_lockfile_t tor_lockfile_t;
tor_lockfile_t *tor_lockfile_lock(const char *filename, int blocking,
int *locked_out);
void tor_lockfile_unlock(tor_lockfile_t *lockfile);
#endif

View File

@ -112,6 +112,7 @@
#include "or/ext_orport.h"
#include "lib/memarea/memarea.h"
#include "lib/sandbox/sandbox.h"
#include "lib/fs/lockfile.h"
#include <event2/event.h>