source: trunk/poppler/fontconfig-2.3.2-os2/src/fcatomic.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 16 years ago

First import

File size: 5.5 KB
Line 
1/*
2 * $RCSId: xc/lib/fontconfig/src/fcatomic.c,v 1.2 2002/03/04 21:15:28 tsi Exp $
3 *
4 * Copyright © 2002 Keith Packard
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission.  Keith Packard makes no
13 * representations about the suitability of this software for any purpose.  It
14 * is provided "as is" without express or implied warranty.
15 *
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25/*
26 * fcatomic.c
27 *
28 * Lock cache and configuration files for atomic update
29 *
30 * Uses only regular filesystem calls so it should
31 * work even in the absense of functioning file locking
32 *
33 * On Unix, four files are used:
34 *      file        - the data file accessed by other apps.
35 *      new         - a new version of the data file while it's being written
36 *      lck         - the lock file
37 *      tmp         - a temporary file made unique with mkstemp
38 *
39 *  Here's how it works:
40 *      Create 'tmp' and store our PID in it
41 *      Attempt to link it to 'lck'
42 *      Unlink 'tmp'
43 *      If the link succeeded, the lock is held
44 *
45 * On Windows, where there are no links, no tmp file is used, and lck
46 * is a directory that's mkdir'ed. If the mkdir succeeds, the lock is
47 * held.
48 */
49
50#include "fcint.h"
51#include <sys/types.h>
52#include <sys/stat.h>
53#include <fcntl.h>
54#include <unistd.h>
55#include <stdlib.h>
56#include <time.h>
57
58#if defined(__OS2__) && !defined(__INNOTEK_LIBC__)
59#include <direct.h>
60#define mkdir(path,mode) _mkdir(path)
61#endif
62
63#ifdef _WIN32
64#define mkdir(path,mode) _mkdir(path)
65#endif
66
67#define NEW_NAME        ".NEW"
68#define LCK_NAME        ".LCK"
69#define TMP_NAME        ".TMP-XXXXXX"
70
71FcAtomic *
72FcAtomicCreate (const FcChar8   *file)
73{
74    int     file_len = strlen ((char *) file);
75    int     new_len = file_len + sizeof (NEW_NAME);
76    int     lck_len = file_len + sizeof (LCK_NAME);
77    int     tmp_len = file_len + sizeof (TMP_NAME);
78    int     total_len = (sizeof (FcAtomic) +
79                         file_len + 1 +
80                         new_len + 1 +
81                         lck_len + 1 +
82                         tmp_len + 1);
83    FcAtomic    *atomic = malloc (total_len);
84    if (!atomic)
85        return 0;
86    FcMemAlloc (FC_MEM_ATOMIC, total_len);
87   
88    atomic->file = (FcChar8 *) (atomic + 1);
89    strcpy ((char *) atomic->file, (char *) file);
90
91    atomic->new = atomic->file + file_len + 1;
92    strcpy ((char *) atomic->new, (char *) file);
93    strcat ((char *) atomic->new, NEW_NAME);
94
95    atomic->lck = atomic->new + new_len + 1;
96    strcpy ((char *) atomic->lck, (char *) file);
97    strcat ((char *) atomic->lck, LCK_NAME);
98
99    atomic->tmp = atomic->lck + lck_len + 1;
100
101    return atomic;
102}
103
104FcBool
105FcAtomicLock (FcAtomic *atomic)
106{
107#ifdef HAVE_LINK
108    int         fd = -1;
109    FILE        *f = 0;
110#endif
111    int         ret;
112    struct stat lck_stat;
113
114#ifdef HAVE_LINK
115    strcpy ((char *) atomic->tmp, (char *) atomic->file);
116    strcat ((char *) atomic->tmp, TMP_NAME);
117    fd = mkstemp ((char *) atomic->tmp);
118    if (fd < 0)
119        return FcFalse;
120    f = fdopen (fd, "w");
121    if (!f)
122    {
123        close (fd);
124        unlink ((char *) atomic->tmp);
125        return FcFalse;
126    }
127    ret = fprintf (f, "%ld\n", (long)getpid());
128    if (ret <= 0)
129    {
130        fclose (f);
131        unlink ((char *) atomic->tmp);
132        return FcFalse;
133    }
134    if (fclose (f) == EOF)
135    {
136        unlink ((char *) atomic->tmp);
137        return FcFalse;
138    }
139    ret = link ((char *) atomic->tmp, (char *) atomic->lck);
140    (void) unlink ((char *) atomic->tmp);
141#else
142    ret = mkdir ((char *) atomic->lck, 0600);
143#endif
144    if (ret < 0)
145    {
146        /*
147         * If the file is around and old (> 10 minutes),
148         * assume the lock is stale.  This assumes that any
149         * machines sharing the same filesystem will have clocks
150         * reasonably close to each other.
151         */
152        if (stat ((char *) atomic->lck, &lck_stat) >= 0)
153        {
154            time_t  now = time (0);
155            if ((long int) (now - lck_stat.st_mtime) > 10 * 60)
156            {
157#ifdef HAVE_LINK
158                if (unlink ((char *) atomic->lck) == 0)
159                    return FcAtomicLock (atomic);
160#else
161                if (rmdir ((char *) atomic->lck) == 0)
162                    return FcAtomicLock (atomic);
163#endif
164            }
165        }
166        return FcFalse;
167    }
168    (void) unlink ((char *) atomic->new);
169    return FcTrue;
170}
171
172FcChar8 *
173FcAtomicNewFile (FcAtomic *atomic)
174{
175    return atomic->new;
176}
177
178FcChar8 *
179FcAtomicOrigFile (FcAtomic *atomic)
180{
181    return atomic->file;
182}
183
184FcBool
185FcAtomicReplaceOrig (FcAtomic *atomic)
186{
187    if (rename ((char *) atomic->new, (char *) atomic->file) < 0)
188        return FcFalse;
189    return FcTrue;
190}
191
192void
193FcAtomicDeleteNew (FcAtomic *atomic)
194{
195    unlink ((char *) atomic->new);
196}
197
198void
199FcAtomicUnlock (FcAtomic *atomic)
200{
201#ifdef HAVE_LINK
202    unlink ((char *) atomic->lck);
203#else
204    rmdir ((char *) atomic->lck);
205#endif
206}
207
208void
209FcAtomicDestroy (FcAtomic *atomic)
210{
211    FcMemFree (FC_MEM_ATOMIC, sizeof (FcAtomic) +
212               strlen ((char *) atomic->file) * 4 + 1 +
213               sizeof (NEW_NAME) + sizeof (LCK_NAME) + 
214               sizeof (TMP_NAME));
215
216    free (atomic);
217}
Note: See TracBrowser for help on using the repository browser.