]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/lockfile-util.c
2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "alloc-util.h"
30 #include "lockfile-util.h"
32 #include "path-util.h"
34 int make_lock_file(const char *p
, int operation
, LockFile
*ret
) {
35 _cleanup_close_
int fd
= -1;
36 _cleanup_free_
char *t
= NULL
;
40 * We use UNPOSIX locks if they are available. They have nice
41 * semantics, and are mostly compatible with NFS. However,
42 * they are only available on new kernels. When we detect we
43 * are running on an older kernel, then we fall back to good
44 * old BSD locks. They also have nice semantics, but are
45 * slightly problematic on NFS, where they are upgraded to
46 * POSIX locks, even though locally they are orthogonal to
56 .l_type
= (operation
& ~LOCK_NB
) == LOCK_EX
? F_WRLCK
: F_RDLCK
,
61 fd
= open(p
, O_CREAT
|O_RDWR
|O_NOFOLLOW
|O_CLOEXEC
|O_NOCTTY
, 0600);
65 r
= fcntl(fd
, (operation
& LOCK_NB
) ? F_OFD_SETLK
: F_OFD_SETLKW
, &fl
);
68 /* If the kernel is too old, use good old BSD locks */
70 r
= flock(fd
, operation
);
73 return errno
== EAGAIN
? -EBUSY
: -errno
;
76 /* If we acquired the lock, let's check if the file
77 * still exists in the file system. If not, then the
78 * previous exclusive owner removed it and then closed
79 * it. In such a case our acquired lock is worthless,
93 ret
->operation
= operation
;
101 int make_lock_file_for(const char *p
, int operation
, LockFile
*ret
) {
109 if (!filename_is_valid(fn
))
112 t
= newa(char, strlen(p
) + 2 + 4 + 1);
113 stpcpy(stpcpy(stpcpy(mempcpy(t
, p
, fn
- p
), ".#"), fn
), ".lck");
115 return make_lock_file(t
, operation
, ret
);
118 void release_lock_file(LockFile
*f
) {
126 /* If we are the exclusive owner we can safely delete
127 * the lock file itself. If we are not the exclusive
128 * owner, we can try becoming it. */
131 (f
->operation
& ~LOCK_NB
) == LOCK_SH
) {
132 static const struct flock fl
= {
134 .l_whence
= SEEK_SET
,
137 r
= fcntl(f
->fd
, F_OFD_SETLK
, &fl
);
138 if (r
< 0 && errno
== EINVAL
)
139 r
= flock(f
->fd
, LOCK_EX
|LOCK_NB
);
142 f
->operation
= LOCK_EX
|LOCK_NB
;
145 if ((f
->operation
& ~LOCK_NB
) == LOCK_EX
)
146 unlink_noerrno(f
->path
);
148 f
->path
= mfree(f
->path
);
151 f
->fd
= safe_close(f
->fd
);