tor  0.4.2.1-alpha-dev
lockfile.c
Go to the documentation of this file.
1 /* Copyright (c) 2003-2004, Roger Dingledine
2  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3  * Copyright (c) 2007-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
13 #include "orconfig.h"
14 #include "lib/fs/files.h"
15 #include "lib/fs/lockfile.h"
16 #include "lib/log/log.h"
17 #include "lib/log/util_bug.h"
18 #include "lib/malloc/malloc.h"
19 
20 #ifdef HAVE_SYS_FILE_H
21 #include <sys/file.h>
22 #endif
23 #ifdef HAVE_FCNTL_H
24 #include <fcntl.h>
25 #endif
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #ifdef _WIN32
30 #include <windows.h>
31 #include <sys/locking.h>
32 #endif
33 
34 #include <errno.h>
35 #include <string.h>
36 
40  char *filename;
42  int fd;
43 };
44 
63 tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
64 {
65  tor_lockfile_t *result;
66  int fd;
67  *locked_out = 0;
68 
69  log_info(LD_FS, "Locking \"%s\"", filename);
70  fd = tor_open_cloexec(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
71  if (fd < 0) {
72  log_warn(LD_FS,"Couldn't open \"%s\" for locking: %s", filename,
73  strerror(errno));
74  return NULL;
75  }
76 
77 #ifdef _WIN32
78  _lseek(fd, 0, SEEK_SET);
79  if (_locking(fd, blocking ? _LK_LOCK : _LK_NBLCK, 1) < 0) {
80  if (errno != EACCES && errno != EDEADLOCK)
81  log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
82  else
83  *locked_out = 1;
84  close(fd);
85  return NULL;
86  }
87 #elif defined(HAVE_FLOCK)
88  if (flock(fd, LOCK_EX|(blocking ? 0 : LOCK_NB)) < 0) {
89  if (errno != EWOULDBLOCK)
90  log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
91  else
92  *locked_out = 1;
93  close(fd);
94  return NULL;
95  }
96 #else
97  {
98  struct flock lock;
99  memset(&lock, 0, sizeof(lock));
100  lock.l_type = F_WRLCK;
101  lock.l_whence = SEEK_SET;
102  if (fcntl(fd, blocking ? F_SETLKW : F_SETLK, &lock) < 0) {
103  if (errno != EACCES && errno != EAGAIN)
104  log_warn(LD_FS, "Couldn't lock \"%s\": %s", filename, strerror(errno));
105  else
106  *locked_out = 1;
107  close(fd);
108  return NULL;
109  }
110  }
111 #endif /* defined(_WIN32) || ... */
112 
113  result = tor_malloc(sizeof(tor_lockfile_t));
114  result->filename = tor_strdup(filename);
115  result->fd = fd;
116  return result;
117 }
118 
120 void
122 {
124 
125  log_info(LD_FS, "Unlocking \"%s\"", lockfile->filename);
126 #ifdef _WIN32
127  _lseek(lockfile->fd, 0, SEEK_SET);
128  if (_locking(lockfile->fd, _LK_UNLCK, 1) < 0) {
129  log_warn(LD_FS,"Error unlocking \"%s\": %s", lockfile->filename,
130  strerror(errno));
131  }
132 #elif defined(HAVE_FLOCK)
133  if (flock(lockfile->fd, LOCK_UN) < 0) {
134  log_warn(LD_FS, "Error unlocking \"%s\": %s", lockfile->filename,
135  strerror(errno));
136  }
137 #else
138  /* Closing the lockfile is sufficient. */
139 #endif /* defined(_WIN32) || ... */
140 
141  close(lockfile->fd);
142  lockfile->fd = -1;
145 }
#define SEEK_SET
Definition: fdio.c:35
tor_lockfile_t * tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
Definition: lockfile.c:63
int tor_open_cloexec(const char *path, int flags, unsigned mode)
Definition: files.c:54
char * filename
Definition: lockfile.c:40
#define tor_free(p)
Definition: malloc.h:52
Headers for util_malloc.c.
static tor_lockfile_t * lockfile
Definition: main.c:670
void tor_lockfile_unlock(tor_lockfile_t *lockfile)
Definition: lockfile.c:121
tor_assert(buffer)
#define LD_FS
Definition: log.h:68
Wrappers for reading and writing data to files on disk.
Headers for log.c.
Macros to manage assertions, fatal and non-fatal.
Header for lockfile.c.