]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/lockfile-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
15 #include "alloc-util.h"
18 #include "lockfile-util.h"
20 #include "path-util.h"
22 int make_lock_file(const char *p
, int operation
, LockFile
*ret
) {
23 _cleanup_close_
int fd
= -1;
24 _cleanup_free_
char *t
= NULL
;
28 * We use UNPOSIX locks if they are available. They have nice
29 * semantics, and are mostly compatible with NFS. However,
30 * they are only available on new kernels. When we detect we
31 * are running on an older kernel, then we fall back to good
32 * old BSD locks. They also have nice semantics, but are
33 * slightly problematic on NFS, where they are upgraded to
34 * POSIX locks, even though locally they are orthogonal to
44 .l_type
= (operation
& ~LOCK_NB
) == LOCK_EX
? F_WRLCK
: F_RDLCK
,
49 fd
= open(p
, O_CREAT
|O_RDWR
|O_NOFOLLOW
|O_CLOEXEC
|O_NOCTTY
, 0600);
53 r
= fcntl(fd
, (operation
& LOCK_NB
) ? F_OFD_SETLK
: F_OFD_SETLKW
, &fl
);
56 /* If the kernel is too old, use good old BSD locks */
58 r
= flock(fd
, operation
);
61 return errno
== EAGAIN
? -EBUSY
: -errno
;
64 /* If we acquired the lock, let's check if the file
65 * still exists in the file system. If not, then the
66 * previous exclusive owner removed it and then closed
67 * it. In such a case our acquired lock is worthless,
81 ret
->operation
= operation
;
89 int make_lock_file_for(const char *p
, int operation
, LockFile
*ret
) {
97 if (!filename_is_valid(fn
))
100 t
= newa(char, strlen(p
) + 2 + 4 + 1);
101 stpcpy(stpcpy(stpcpy(mempcpy(t
, p
, fn
- p
), ".#"), fn
), ".lck");
103 return make_lock_file(t
, operation
, ret
);
106 void release_lock_file(LockFile
*f
) {
114 /* If we are the exclusive owner we can safely delete
115 * the lock file itself. If we are not the exclusive
116 * owner, we can try becoming it. */
119 (f
->operation
& ~LOCK_NB
) == LOCK_SH
) {
120 static const struct flock fl
= {
122 .l_whence
= SEEK_SET
,
125 r
= fcntl(f
->fd
, F_OFD_SETLK
, &fl
);
126 if (r
< 0 && errno
== EINVAL
)
127 r
= flock(f
->fd
, LOCK_EX
|LOCK_NB
);
130 f
->operation
= LOCK_EX
|LOCK_NB
;
133 if ((f
->operation
& ~LOCK_NB
) == LOCK_EX
)
134 unlink_noerrno(f
->path
);
136 f
->path
= mfree(f
->path
);
139 f
->fd
= safe_close(f
->fd
);