tin  2.6.1
About: TIN is a threaded NNTP and spool based UseNet newsreader.
  Fossies Dox: tin-2.6.1.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

lock.c
Go to the documentation of this file.
1/*
2 * Project : tin - a Usenet reader
3 * Module : lock.c
4 * Author : Urs Janssen <urs@tin.org>
5 * Created : 1998-07-27
6 * Updated : 2013-11-17
7 * Notes :
8 *
9 * Copyright (c) 1998-2022 Urs Janssen <urs@tin.org>
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * 3. Neither the name of the copyright holder nor the names of its
24 * contributors may be used to endorse or promote products derived from
25 * this software without specific prior written permission.
26 *
27 * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40#ifndef TIN_H
41# include "tin.h"
42#endif /* !TIN_H */
43
44#if !defined(USE_FLOCK) && !defined(USE_LOCKF) && !defined(USE_FCNTL)
45# ifdef HAVE_FCNTL
46# define USE_FCNTL 1
47# else
48# ifdef HAVE_LOCKF
49# define USE_LOCKF 1
50# else
51# ifdef HAVE_FLOCK
52# define USE_FLOCK 1
53# endif /* HAVE_FLOCK */
54# endif /* HAVE_LOCKF */
55# endif /* HAVE_FCNTL */
56#endif /* !USE_FLOCK && !USE_LOCKF && !USE_FCNTL */
57
58/*
59 * TODO: add support for $LOCKEXT
60 */
61#define LOCK_SUFFIX ".lock"
62
63/*
64 * fd_lock(fd, block)
65 *
66 * try to lock a file descriptor with fcntl(), flock() or lockf()
67 *
68 * return codes:
69 * 0 = file locked successfully
70 * -1 = some error occurred
71 */
72int
74 int fd,
75 t_bool block)
76{
77 int rval = -1; /* assume an error */
78
79#ifdef USE_FCNTL
80 struct flock flk;
81
82 flk.l_type = F_WRLCK;
83 flk.l_whence = SEEK_SET;
84 flk.l_start = 0;
85 flk.l_len = 0;
86 if ((rval = fcntl(fd, block ? F_SETLKW : F_SETLK, &flk)))
87 return rval; /* fcntl locking failed */
88#else
89# ifdef USE_LOCKF
90 if ((rval = lockf(fd, block ? F_LOCK : F_TLOCK, 0L)))
91 return rval; /* lockf locking failed */
92# else
93# ifdef USE_FLOCK
94 if ((rval = flock(fd, block ? LOCK_EX : (LOCK_EX | LOCK_NB))))
95 return rval; /* flock locking failed */
96# endif /* USE_FLOCK */
97# endif /* USE_LOCKF */
98#endif /* USE_FCNTL */
99
100 return rval; /* available lock successfully applied or no locking available */
101}
102
103
104#if 0 /* unused */
105/*
106 * test_fd_lock(fd)
107 *
108 * check for an existing lock on file descriptor with fcntl(), lockf()
109 * or flock()
110 *
111 * return codes:
112 * 0 = file is not locked
113 * 1 = file is locked
114 * -1 = some error occurred
115 */
116int
117test_fd_lock(
118 int fd)
119{
120 int rval = -1; /* assume an error */
121
122 errno = 0;
123#ifdef USE_FCNTL
124 {
125 struct flock flk;
126
127 flk.l_type = F_WRLCK;
128 flk.l_whence = SEEK_SET;
129 flk.l_start = 0;
130 flk.l_len = 0;
131 if (fcntl(fd, F_GETLK, &flk) < 0)
132 return -1; /* some error occurred */
133 else {
134 if (flk.l_type != F_UNLCK)
135 return 1; /* file is locked */
136 else
137 rval = 0; /* file is not fcntl locked */
138 }
139 }
140#else
141# ifdef USE_LOCKF
142 if (lockf(fd, F_TEST, 0L)) {
143 if (errno == EACCES)
144 return 1; /* file is locked */
145 else
146 return -1; /* some error occurred */
147 } else
148 rval = 0; /* file is not lockf locked */
149# else
150# ifdef USE_FLOCK
151 if (flock(fd, (LOCK_EX|LOCK_NB))) {
152 if (errno == EWOULDBLOCK)
153 return 1; /* file is locked */
154 else
155 return -1; /* some error occurred */
156 } else
157 rval = 0; /* file is not flock locked */
158
159# endif /* USE_FLOCK */
160# endif /* USE_LOCKF */
161#endif /* USE_FCNTL */
162
163 return rval; /* file wasn't locked or no locking available */
164}
165#endif /* 0 */
166
167
168/*
169 * fd_unlock(fd)
170 *
171 * try to unlock a file descriptor with fcntl(), lockf() or flock()
172 *
173 * return codes:
174 * 0 = file unlocked successfully
175 * -1 = some error occurred
176 */
177int
179 int fd)
180{
181 int rval = -1; /* assume an error */
182
183#ifdef USE_FCNTL
184 {
185 struct flock flk;
186
187 flk.l_type = F_UNLCK;
188 flk.l_whence = SEEK_SET;
189 flk.l_start = 0;
190 flk.l_len = 0;
191 if ((rval = fcntl(fd, F_SETLK, &flk)))
192 return rval; /* couldn't release fcntl lock */
193 }
194#else
195# ifdef USE_LOCKF
196 if ((rval = lockf(fd, F_ULOCK, 0L)))
197 return rval; /* couldn't release lockf lock */
198# else
199# ifdef USE_FLOCK
200 if ((rval = flock(fd, LOCK_UN)))
201 return rval; /* couldn't release flock lock */
202# endif /* USE_FLOCK */
203# endif /* USE_LOCKF */
204#endif /* USE_FCNTL */
205
206 return rval; /* file successfully unlocked or no locking available */
207}
208
209
210/*
211 * dot_lock(filename)
212 *
213 * try to lock filename via dotfile locking
214 *
215 * return codes:
216 * TRUE = file locked successfully
217 * FALSE = some error occurred
218 */
219t_bool
221 const char *filename)
222{
223 char tempfile[PATH_LEN];
224 char lockfile[PATH_LEN];
225 char base_dir[PATH_LEN];
226 int dot_fd;
227 struct stat statbuf;
228 t_bool rval = FALSE;
229
230 dir_name(filename, base_dir);
231 if (!strcmp(filename, base_dir)) /* no filename portion */
232 return rval;
233 if ((dot_fd = my_tmpfile(tempfile, sizeof(tempfile) - 1, base_dir)) == -1)
234 return rval;
235 snprintf(lockfile, sizeof(lockfile), "%s%s", filename, LOCK_SUFFIX);
236
237#ifdef HAVE_LINK
238 if (stat(lockfile, &statbuf)) { /* lockfile doesn't exist */
239 if (!link(tempfile, lockfile)) { /* link successful */
240 if (!stat(tempfile, &statbuf)) { /* tempfile exist */
241 if (statbuf.st_nlink == 2) /* link count ok */
242 rval = TRUE;
243 }
244 }
245 }
246#endif /* HAVE_LINK */
247
248 close(dot_fd);
249 (void) unlink(tempfile);
250
251 if (!stat(lockfile, &statbuf)) { /* lockfile still here */
252 if (statbuf.st_nlink != 1) /* link count wrong? */
253 rval = FALSE; /* shouldn't happen */
254 }
255 return rval;
256}
257
258
259/*
260 * try to remove a dotlock for filename
261 *
262 * return codes:
263 * TRUE = file unlocked successfully
264 * FALSE = some error occurred
265 */
266t_bool
268 const char *filename)
269{
270 char *lockfile;
271 t_bool rval = FALSE;
272
273 lockfile = my_malloc(strlen(filename) + strlen(LOCK_SUFFIX) + 2);
274 strcpy(lockfile, filename);
275 strcat(lockfile, LOCK_SUFFIX);
276 if (!unlink(lockfile))
277 rval = TRUE;
278 free(lockfile);
279 return rval;
280}
unsigned t_bool
Definition: bool.h:77
#define TRUE
Definition: bool.h:74
#define FALSE
Definition: bool.h:70
#define LOCK_SUFFIX
Definition: lock.c:61
int fd_unlock(int fd)
Definition: lock.c:178
int fd_lock(int fd, t_bool block)
Definition: lock.c:73
t_bool dot_lock(const char *filename)
Definition: lock.c:220
t_bool dot_unlock(const char *filename)
Definition: lock.c:267
int errno
void dir_name(const char *fullpath, char *dir)
Definition: misc.c:881
int my_tmpfile(char *filename, size_t name_size, const char *base_dir)
Definition: my_tmpfile.c:57
#define SEEK_SET
Definition: tin.h:2512
#define my_malloc(size)
Definition: tin.h:2245
#define unlink(file)
Definition: tin.h:387
#define PATH_LEN
Definition: tin.h:843
#define snprintf
Definition: tin.h:2464