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