summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
b7ec4e9)
Get the device/inode pair from the lockfile descriptor after we've
opened it (so this is the file we're actually going to lock). Once
we've acquired the lock, check that the file /name/ still has the same
device/inode pair. If nobody is allowed to move or unlink the lockfile
while we've got the lock, then we know (assuming this check passes) that
we've actually locked the right file and not some deleted thing.
become available, and then give up. This only makes sense with the
.B \-\-wait
option, so that is turned on automatically.
become available, and then give up. This only makes sense with the
.B \-\-wait
option, so that is turned on automatically.
+.PP
+It is safe to unlink or atomically replace the lockfile while holding
+the lock, though these actions will release the lock immediately. To
+safely delete the lockfile, for example, run
+.IP
+.B "locking lock rm lock"
+.PP
+Similarly, a file can be updated safely by
+.IP
+.nf
+.ft B
+locking file sh -c \e
+\h'8m'"update-file file >file.new && mv file.new file"
+.fi
+.ft R
.SH "BUGS"
The
.B locking
.SH "BUGS"
The
.B locking
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <mLib/mdwopt.h>
#include <mLib/quis.h>
#include <mLib/mdwopt.h>
#include <mLib/quis.h>
int t = -1;
int oflag;
unsigned int ot = 0;
int t = -1;
int oflag;
unsigned int ot = 0;
time_t nt;
pid_t kid;
int rc;
time_t nt;
pid_t kid;
int rc;
ot = alarm(0);
oalrm = signal(SIGALRM, alrm);
if (t >= 0) alarm(t);
ot = alarm(0);
oalrm = signal(SIGALRM, alrm);
if (t >= 0) alarm(t);
if ((fd = open(file, oflag, 0666)) < 0)
die(111, "error opening `%s': %s", file, strerror(errno));
if ((fd = open(file, oflag, 0666)) < 0)
die(111, "error opening `%s': %s", file, strerror(errno));
+ if (fstat(fd, &st))
+ die(111, "error from fstat on `%s': %s", file, strerror(errno));
err = fcntl(fd, f & f_wait ? F_SETLKW : F_SETLK, &l) >= 0 ? 0 : errno;
err = fcntl(fd, f & f_wait ? F_SETLKW : F_SETLK, &l) >= 0 ? 0 : errno;
+ if (stat(file, &nst)) {
+ if (errno == ENOENT) { close(fd); goto again; }
+ else die(111, "error from stat on `%s': %s", file, strerror(errno));
+ }
+ if (st.st_dev != nst.st_dev || st.st_ino != nst.st_ino)
+ { close(fd); goto again; }
done:
signal(SIGALRM, oalrm);
if (!ot)
done:
signal(SIGALRM, oalrm);
if (!ot)