2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998 University of Maryland at College Park
4 * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of U.M. not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission. U.M. makes no representations about the
14 * suitability of this software for any purpose. It is provided "as is"
15 * without express or implied warranty.
17 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 * Authors: the Amanda Development Team. Its members are listed in a
25 * file named AUTHORS, in the root directory of this distribution.
28 /* moved from amflock.c by Dustin J. Mitchell <dustin@zmanda.com> */
32 static int ln_lock(char *res, int op);
33 char *_lnlock_dir = AMANDA_TMPDIR; /* amflock-test changes this; it's a constant otherwise */
35 /* XXX - error checking in this section needs to be tightened up */
37 /* Delete a lock file.
46 if (rc != 0 && errno == ENOENT) rc = 0;
51 /* Create a lock file.
62 (void)delete_lock(fn); /* that's MY file! */
65 fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0640);
67 if (fd == -1) return -1;
69 if((f = fdopen(fd, "w")) == NULL) {
73 g_fprintf(f, "%ld\n", pid);
79 /* Read the pid out of a lock file.
80 ** -1=error, otherwise pid.
84 char * fn) /* name of lock file */
90 if ((f = fopen(fn, "r")) == NULL) {
93 if (fscanf(f, "%ld", &pid) != 1) {
105 /* Link a lock if we can.
106 ** 0=done, 1=already locked, -1=error.
110 char * lk, /* real lock file */
111 char * tlk) /* temp lock file */
114 int serrno; /* saved errno */
115 struct stat lkstat, tlkstat;
117 /* an atomic check and set operation */
119 if (rc == 0) return 0; /* XXX do we trust it? */
121 /* link() says it failed - don't beleive it */
124 if (stat(lk, &lkstat) == 0 &&
125 stat(tlk, &tlkstat) == 0 &&
126 lkstat.st_ino == tlkstat.st_ino)
127 return 0; /* it did work! */
131 if (errno == EEXIST) rc = 1;
136 /* Steal a lock if we can.
137 ** 0=done; 1=still in use; -1 = error.
141 char * fn, /* name of lock file to steal */
142 long mypid, /* my process id */
143 char * sres) /* name of steal-resource to lock */
148 /* prevent a race with another stealer */
149 rc = ln_lock(sres, 1);
150 if (rc != 0) goto error;
154 if (errno == ENOENT) goto done;
158 if (pid == mypid) goto steal; /* i'm the locker! */
160 /* are they still there ? */
161 rc = kill((pid_t)pid, 0);
163 if (errno == ESRCH) goto steal; /* locker has gone */
167 rc = ln_lock(sres, 0);
168 if (rc != 0) goto error;
173 rc = delete_lock(fn);
174 if (rc != 0) goto error;
177 rc = ln_lock(sres, 0);
178 if (rc != 0) goto error;
183 rc = ln_lock(sres, 0);
190 char * res, /* name of resource to lock */
191 int op) /* true to lock; false to unlock */
194 char *lockfile = NULL;
195 char *tlockfile = NULL;
198 char pid_str[NUM_STR_SIZE];
200 mypid = (long)getpid();
202 lockfile = vstralloc(_lnlock_dir, "/am", res, ".lock", NULL);
205 /* unlock the resource */
206 assert(read_lock(lockfile) == mypid);
208 (void)delete_lock(lockfile);
213 /* lock the resource */
215 g_snprintf(pid_str, SIZEOF(pid_str), "%ld", mypid);
216 tlockfile = vstralloc(_lnlock_dir, "/am", res, ".", pid_str, NULL);
218 (void)create_lock(tlockfile, mypid);
220 mres = stralloc2(res, ".");
223 rc = link_lock(lockfile, tlockfile);
227 rc = steal_lock(lockfile, mypid, mres);
229 if (rc == 0) continue;
233 (void) delete_lock(tlockfile);
244 G_GNUC_UNUSED int fd,
247 return ln_lock(resource, 1);
252 G_GNUC_UNUSED int fd,
255 return ln_lock(resource, 0);
258 amflock_impl_t amflock_lnlock_impl = {
260 lnlock_lock, /* no read-only support */