]>
git.wh0rd.org - fontconfig.git/blob - src/fcatomic.c
2 * $RCSId: xc/lib/fontconfig/src/fcatomic.c,v 1.2 2002/03/04 21:15:28 tsi Exp $
4 * Copyright © 2002 Keith Packard
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.
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.
28 * Lock cache and configuration files for atomic update
30 * Uses only regular filesystem calls so it should
31 * work even in the absense of functioning file locking
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
37 * tmp - a temporary file made unique with mkstemp
39 * Here's how it works:
40 * Create 'tmp' and store our PID in it
41 * Attempt to link it to 'lck'
43 * If the link succeeded, the lock is held
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
51 #include <sys/types.h>
59 #define mkdir(path,mode) _mkdir(path)
62 #define NEW_NAME ".NEW"
63 #define LCK_NAME ".LCK"
64 #define TMP_NAME ".TMP-XXXXXX"
67 FcAtomicCreate (const FcChar8
*file
)
69 int file_len
= strlen ((char *) file
);
70 int new_len
= file_len
+ sizeof (NEW_NAME
);
71 int lck_len
= file_len
+ sizeof (LCK_NAME
);
72 int tmp_len
= file_len
+ sizeof (TMP_NAME
);
73 int total_len
= (sizeof (FcAtomic
) +
78 FcAtomic
*atomic
= malloc (total_len
);
81 FcMemAlloc (FC_MEM_ATOMIC
, total_len
);
83 atomic
->file
= (FcChar8
*) (atomic
+ 1);
84 strcpy ((char *) atomic
->file
, (char *) file
);
86 atomic
->new = atomic
->file
+ file_len
+ 1;
87 strcpy ((char *) atomic
->new, (char *) file
);
88 strcat ((char *) atomic
->new, NEW_NAME
);
90 atomic
->lck
= atomic
->new + new_len
+ 1;
91 strcpy ((char *) atomic
->lck
, (char *) file
);
92 strcat ((char *) atomic
->lck
, LCK_NAME
);
94 atomic
->tmp
= atomic
->lck
+ lck_len
+ 1;
100 FcAtomicLock (FcAtomic
*atomic
)
105 struct stat lck_stat
;
108 strcpy ((char *) atomic
->tmp
, (char *) atomic
->file
);
109 strcat ((char *) atomic
->tmp
, TMP_NAME
);
110 fd
= mkstemp ((char *) atomic
->tmp
);
113 f
= fdopen (fd
, "w");
117 unlink ((char *) atomic
->tmp
);
120 ret
= fprintf (f
, "%ld\n", (long)getpid());
124 unlink ((char *) atomic
->tmp
);
127 if (fclose (f
) == EOF
)
129 unlink ((char *) atomic
->tmp
);
132 ret
= link ((char *) atomic
->tmp
, (char *) atomic
->lck
);
133 (void) unlink ((char *) atomic
->tmp
);
135 ret
= mkdir ((char *) atomic
->lck
, 0600);
140 * If the file is around and old (> 10 minutes),
141 * assume the lock is stale. This assumes that any
142 * machines sharing the same filesystem will have clocks
143 * reasonably close to each other.
145 if (stat ((char *) atomic
->lck
, &lck_stat
) >= 0)
147 time_t now
= time (0);
148 if ((long int) (now
- lck_stat
.st_mtime
) > 10 * 60)
151 if (unlink ((char *) atomic
->lck
) == 0)
152 return FcAtomicLock (atomic
);
154 if (rmdir ((char *) atomic
->lck
) == 0)
155 return FcAtomicLock (atomic
);
161 (void) unlink ((char *) atomic
->new);
166 FcAtomicNewFile (FcAtomic
*atomic
)
172 FcAtomicOrigFile (FcAtomic
*atomic
)
178 FcAtomicReplaceOrig (FcAtomic
*atomic
)
180 if (rename ((char *) atomic
->new, (char *) atomic
->file
) < 0)
186 FcAtomicDeleteNew (FcAtomic
*atomic
)
188 unlink ((char *) atomic
->new);
192 FcAtomicUnlock (FcAtomic
*atomic
)
195 unlink ((char *) atomic
->lck
);
197 rmdir ((char *) atomic
->lck
);
202 FcAtomicDestroy (FcAtomic
*atomic
)
204 FcMemFree (FC_MEM_ATOMIC
, sizeof (FcAtomic
) +
205 strlen ((char *) atomic
->file
) * 4 + 1 +
206 sizeof (NEW_NAME
) + sizeof (LCK_NAME
) +