2013-02-20 [colin] 3.9.0cvs95
[claws.git] / src / plugins / mailmbox / maillock.c
1 /*
2  * libEtPan! -- a mail stuff library
3  *
4  * Copyright (C) 2001, 2002 - DINH Viet Hoa
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the libEtPan! project nor the names of its
16  *    contributors may be used to endorse or promote products derived
17  *    from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31
32 /*
33  * $Id $
34  */
35
36 #include "maillock.h"
37
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <limits.h>
42 #include <unistd.h>
43 #include <stdio.h>
44 #include <time.h>
45 #include <string.h>
46
47 /* ********************************************************************** */
48
49 /* lock primitives */
50
51 /* the lock code is modified from the dot lock file code from mail.local.c */
52
53 /*
54                              SENDMAIL LICENSE
55
56 The following license terms and conditions apply, unless a different
57 license is obtained from Sendmail, Inc., 6425 Christie Ave, Fourth Floor,
58 Emeryville, CA 94608, or by electronic mail at license@sendmail.com.
59
60 License Terms:
61
62 Use, Modification and Redistribution (including distribution of any
63 modified or derived work) in source and binary forms is permitted only if
64 each of the following conditions is met:
65
66 1. Redistributions qualify as "freeware" or "Open Source Software" under
67    one of the following terms:
68
69    (a) Redistributions are made at no charge beyond the reasonable cost of
70        materials and delivery.
71
72    (b) Redistributions are accompanied by a copy of the Source Code or by an
73        irrevocable offer to provide a copy of the Source Code for up to three
74        years at the cost of materials and delivery.  Such redistributions
75        must allow further use, modification, and redistribution of the Source
76        Code under substantially the same terms as this license.  For the
77        purposes of redistribution "Source Code" means the complete compilable
78        and linkable source code of sendmail including all modifications.
79
80 2. Redistributions of source code must retain the copyright notices as they
81    appear in each source code file, these license terms, and the
82    disclaimer/limitation of liability set forth as paragraph 6 below.
83
84 3. Redistributions in binary form must reproduce the Copyright Notice,
85    these license terms, and the disclaimer/limitation of liability set
86    forth as paragraph 6 below, in the documentation and/or other materials
87    provided with the distribution.  For the purposes of binary distribution
88    the "Copyright Notice" refers to the following language:
89    "Copyright (c) 1998-2002 Sendmail, Inc.  All rights reserved."
90
91 4. Neither the name of Sendmail, Inc. nor the University of California nor
92    the names of their contributors may be used to endorse or promote
93    products derived from this software without specific prior written
94    permission.  The name "sendmail" is a trademark of Sendmail, Inc.
95
96 5. All redistributions must comply with the conditions imposed by the
97    University of California on certain embedded code, whose copyright
98    notice and conditions for redistribution are as follows:
99
100    (a) Copyright (c) 1988, 1993 The Regents of the University of
101        California.  All rights reserved.
102
103    (b) Redistribution and use in source and binary forms, with or without
104        modification, are permitted provided that the following conditions
105        are met:
106
107       (i)   Redistributions of source code must retain the above copyright
108             notice, this list of conditions and the following disclaimer.
109
110       (ii)  Redistributions in binary form must reproduce the above
111             copyright notice, this list of conditions and the following
112             disclaimer in the documentation and/or other materials provided
113             with the distribution.
114
115       (iii) Neither the name of the University nor the names of its
116             contributors may be used to endorse or promote products derived
117             from this software without specific prior written permission.
118
119 6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY
120    SENDMAIL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
121    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
122    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
123    NO EVENT SHALL SENDMAIL, INC., THE REGENTS OF THE UNIVERSITY OF
124    CALIFORNIA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
125    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
126    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
127    USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
128    ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
129    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
130    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
131 */
132
133 /*
134   TODO : lock, prefer fcntl() over flock()
135          AND use dotlock code above
136 */
137
138 #define LOCKTO_RM       300     /* timeout for stale lockfile removal */
139 #define LOCKTO_GLOB     400     /* global timeout for lockfile creation */
140
141 static int lock_common(const char * filename, int fd, short locktype)
142 {
143   char lockfilename[PATH_MAX];
144   struct flock lock;
145   /* dot lock file */
146   int statfailed = 0;
147   time_t start;
148   int r;
149   int res;
150
151   lock.l_start = 0;
152   lock.l_len = 0;
153   lock.l_pid = getpid();
154   lock.l_type = locktype;
155   lock.l_whence = SEEK_SET;
156
157   r = fcntl(fd, F_SETLKW, &lock);
158   if (r < 0) {
159     /* WARNING POSIX lock could not be applied */
160   }
161
162   /* dot lock file */
163
164   if (strlen(filename) + 6 > PATH_MAX) {
165     res = -1;
166     goto unlock;
167   }
168
169   snprintf(lockfilename, PATH_MAX, "%s.lock", filename);
170
171   time(&start);
172   while (1) {
173     int fd;
174     struct stat st;
175     time_t now;
176     
177     /* global timeout */
178     time(&now);
179     if (now > start + LOCKTO_GLOB) {
180       res = -1;
181       goto unlock;
182     }
183
184     fd = open(lockfilename, O_WRONLY|O_EXCL|O_CREAT, 0);
185     if (fd >= 0) {
186       /* defeat lock checking programs which test pid */
187       write(fd, "0", 2);
188       close(fd);
189       break;
190     }
191     
192     /* libEtPan! - adds a delay of 5 seconds between each tries */
193     sleep(5);
194     
195     if (stat(lockfilename, &st) < 0) {
196       if (statfailed++ > 5) {
197         res = -1;
198         goto unlock;
199       }
200       continue;
201     }
202     statfailed = 0;
203     time(&now);
204
205     if (now < st.st_ctime + LOCKTO_RM)
206       continue;
207     
208     /* try to remove stale lockfile */
209     if (unlink(lockfilename) < 0) {
210       res = -1;
211       goto unlock;
212     }
213
214     /*
215       libEtPan! - removes this delay of 5 seconds,
216        maybe it was misplaced ?
217     */
218 #if 0
219     sleep(5);
220 #endif
221   }
222
223   return 0;
224
225  unlock:
226   lock.l_start = 0;
227   lock.l_len = 0;
228   lock.l_pid = getpid();
229   lock.l_type = F_UNLCK;
230   lock.l_whence = SEEK_SET;
231
232   r = fcntl(fd, F_SETLK, &lock);
233   if (r < 0) {
234     /* WARNING POSIX lock could not be applied */
235   }
236   return res;
237 }
238
239 static int unlock_common(const char * filename, int fd)
240 {
241   char lockfilename[PATH_MAX];
242   struct flock lock;
243   int r;
244
245   if (strlen(filename) + 6 > PATH_MAX)
246     return -1;
247
248   snprintf(lockfilename, PATH_MAX, "%s.lock", filename);
249
250   unlink(lockfilename);
251
252   lock.l_start = 0;
253   lock.l_len = 0;
254   lock.l_pid = getpid();
255   lock.l_type = F_UNLCK;
256   lock.l_whence = SEEK_SET;
257
258   r = fcntl(fd, F_SETLK, &lock);
259   if (r < 0) {
260     /* WARNING POSIX lock could not be applied */
261   }
262
263   return 0;
264 }
265
266 int maillock_read_lock(const char * filename, int fd)
267 {
268   return lock_common(filename, fd, F_RDLCK);
269 }
270
271 int maillock_read_unlock(const char * filename, int fd)
272 {
273   return unlock_common(filename, fd);
274 }
275
276 int maillock_write_lock(const char * filename, int fd)
277 {
278   return lock_common(filename, fd, F_WRLCK);
279 }
280
281 int maillock_write_unlock(const char * filename, int fd)
282 {
283   return unlock_common(filename, fd);
284 }