]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/lockfile-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
10 #include "alloc-util.h"
13 #include "lockfile-util.h"
15 #include "path-util.h"
17 int make_lock_file(const char *p
, int operation
, LockFile
*ret
) {
18 _cleanup_close_
int fd
= -1;
19 _cleanup_free_
char *t
= NULL
;
23 * We use UNPOSIX locks if they are available. They have nice
24 * semantics, and are mostly compatible with NFS. However,
25 * they are only available on new kernels. When we detect we
26 * are running on an older kernel, then we fall back to good
27 * old BSD locks. They also have nice semantics, but are
28 * slightly problematic on NFS, where they are upgraded to
29 * POSIX locks, even though locally they are orthogonal to
39 .l_type
= (operation
& ~LOCK_NB
) == LOCK_EX
? F_WRLCK
: F_RDLCK
,
44 fd
= open(p
, O_CREAT
|O_RDWR
|O_NOFOLLOW
|O_CLOEXEC
|O_NOCTTY
, 0600);
48 r
= fcntl(fd
, (operation
& LOCK_NB
) ? F_OFD_SETLK
: F_OFD_SETLKW
, &fl
);
51 /* If the kernel is too old, use good old BSD locks */
53 r
= flock(fd
, operation
);
56 return errno
== EAGAIN
? -EBUSY
: -errno
;
59 /* If we acquired the lock, let's check if the file
60 * still exists in the file system. If not, then the
61 * previous exclusive owner removed it and then closed
62 * it. In such a case our acquired lock is worthless,
76 ret
->operation
= operation
;
84 int make_lock_file_for(const char *p
, int operation
, LockFile
*ret
) {
92 if (!filename_is_valid(fn
))
95 t
= newa(char, strlen(p
) + 2 + 4 + 1);
96 stpcpy(stpcpy(stpcpy(mempcpy(t
, p
, fn
- p
), ".#"), fn
), ".lck");
98 return make_lock_file(t
, operation
, ret
);
101 void release_lock_file(LockFile
*f
) {
109 /* If we are the exclusive owner we can safely delete
110 * the lock file itself. If we are not the exclusive
111 * owner, we can try becoming it. */
114 (f
->operation
& ~LOCK_NB
) == LOCK_SH
) {
115 static const struct flock fl
= {
117 .l_whence
= SEEK_SET
,
120 r
= fcntl(f
->fd
, F_OFD_SETLK
, &fl
);
121 if (r
< 0 && errno
== EINVAL
)
122 r
= flock(f
->fd
, LOCK_EX
|LOCK_NB
);
125 f
->operation
= LOCK_EX
|LOCK_NB
;
128 if ((f
->operation
& ~LOCK_NB
) == LOCK_EX
)
129 unlink_noerrno(f
->path
);
131 f
->path
= mfree(f
->path
);
134 f
->fd
= safe_close(f
->fd
);