]> git.wh0rd.org Git - fontconfig.git/commitdiff
Add fcatomic.c
authorKeith Packard <keithp@keithp.com>
Sun, 3 Mar 2002 00:19:43 +0000 (00:19 +0000)
committerKeith Packard <keithp@keithp.com>
Sun, 3 Mar 2002 00:19:43 +0000 (00:19 +0000)
src/Imakefile
src/fcatomic.c [new file with mode: 0644]
src/fccache.c

index a5fc33af2cd5d27e7bead2c615a12efb792ef1d5..c86ae2b48a9301695b0a42686866c91cac9ce8d8 100644 (file)
@@ -28,11 +28,11 @@ DEFINES=-DFC_FALLBACK_FONTS='"$(FALLBACK_FONTS)"'
 EXPATLIB=-lexpat
 REQUIREDLIBS=$(LDPRELIBS) $(FREETYPE2LIB) $(EXPATLIB)
 
-SRCS=fcatomic.c fcblanks.c fccache.c fccfg.c fccharset.c fcdbg.c \
+SRCS=fcatomic.c fcavl.c fcblanks.c fccache.c fccfg.c fccharset.c fcdbg.c \
      fcdefault.c fcdir.c fcfreetype.c fcfs.c fcinit.c fclist.c fcmatch.c \
      fcmatrix.c fcname.c fcpat.c fcstr.c fcxml.c
 
-OBJS=fcatomic.o fcblanks.o fccache.o fccfg.o fccharset.o fcdbg.o \
+OBJS=fcatomic.o fcavl.o fcblanks.o fccache.o fccfg.o fccharset.o fcdbg.o \
      fcdefault.o fcdir.o fcfreetype.o fcfs.o fcinit.o fclist.o fcmatch.o \
      fcmatrix.o fcname.o fcpat.o fcstr.o fcxml.o
 
diff --git a/src/fcatomic.c b/src/fcatomic.c
new file mode 100644 (file)
index 0000000..bfae53c
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * fcatomic.c
+ *
+ * Lock cache and configuration files for atomic update
+ *
+ * Uses only regular filesystem calls so it should
+ * work even in the absense of functioning file locking
+ *
+ *  Four files:
+ *     file        - the data file accessed by other apps.
+ *     new         - a new version of the data file while it's being written
+ *     lck         - the lock file
+ *     tmp         - a temporary file made unique with mkstemp
+ *
+ *  Here's how it works:
+ *     Create 'tmp' and store our PID in it
+ *     Attempt to link it to 'lck'
+ *     Unlink 'tmp'
+ *     If the link succeeded, the lock is held
+ */
+
+#include "fcint.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <time.h>
+
+#define NEW_NAME       ".NEW"
+#define LCK_NAME       ".LCK"
+#define TMP_NAME       ".TMP-XXXXXX"
+
+FcAtomic *
+FcAtomicCreate (const FcChar8   *file)
+{
+    int            file_len = strlen ((char *) file);
+    int            new_len = file_len + sizeof (NEW_NAME);
+    int            lck_len = file_len + sizeof (LCK_NAME);
+    int            tmp_len = file_len + sizeof (TMP_NAME);
+    int            total_len = (sizeof (FcAtomic) +
+                        file_len + 1 +
+                        new_len + 1 +
+                        lck_len + 1 +
+                        tmp_len + 1);
+    FcAtomic   *atomic = malloc (total_len);
+    if (!atomic)
+       return 0;
+    
+    atomic->file = (FcChar8 *) (atomic + 1);
+    strcpy ((char *) atomic->file, (char *) file);
+
+    atomic->new = atomic->file + file_len + 1;
+    strcpy ((char *) atomic->new, (char *) file);
+    strcat ((char *) atomic->new, NEW_NAME);
+
+    atomic->lck = atomic->new + new_len + 1;
+    strcpy ((char *) atomic->lck, (char *) file);
+    strcat ((char *) atomic->lck, LCK_NAME);
+
+    atomic->tmp = atomic->lck + lck_len + 1;
+
+    return atomic;
+}
+
+FcBool
+FcAtomicLock (FcAtomic *atomic)
+{
+    int                fd = -1;
+    FILE       *f = 0;
+    int                ret;
+    struct stat        lck_stat;
+
+    strcpy ((char *) atomic->tmp, (char *) atomic->file);
+    strcat ((char *) atomic->tmp, TMP_NAME);
+    fd = mkstemp ((char *) atomic->tmp);
+    if (fd < 0)
+       return FcFalse;
+    f = fdopen (fd, "w");
+    if (!f)
+    {
+       close (fd);
+       unlink ((char *) atomic->tmp);
+       return FcFalse;
+    }
+    ret = fprintf (f, "%d\n", getpid());
+    if (ret <= 0)
+    {
+       fclose (f);
+       unlink ((char *) atomic->tmp);
+       return FcFalse;
+    }
+    if (fclose (f) == EOF)
+    {
+       unlink ((char *) atomic->tmp);
+       return FcFalse;
+    }
+    ret = link ((char *) atomic->tmp, (char *) atomic->lck);
+    (void) unlink ((char *) atomic->tmp);
+    if (ret < 0)
+    {
+       /*
+        * If the file is around and old (> 10 minutes),
+        * assume the lock is stale.  This assumes that any
+        * machines sharing the same filesystem will have clocks
+        * reasonably close to each other.
+        */
+       if (stat ((char *) atomic->lck, &lck_stat) >= 0)
+       {
+           time_t  now = time (0);
+           if ((long int) (now - lck_stat.st_mtime) > 10 * 60)
+           {
+               if (unlink ((char *) atomic->lck) == 0)
+                   return FcAtomicLock (atomic);
+           }
+       }
+       return FcFalse;
+    }
+    (void) unlink ((char *) atomic->new);
+    return FcTrue;
+}
+
+FcChar8 *
+FcAtomicNewFile (FcAtomic *atomic)
+{
+    return atomic->new;
+}
+
+FcChar8 *
+FcAtomicOrigFile (FcAtomic *atomic)
+{
+    return atomic->file;
+}
+
+FcBool
+FcAtomicReplaceOrig (FcAtomic *atomic)
+{
+    if (rename ((char *) atomic->new, (char *) atomic->file) < 0)
+       return FcFalse;
+    return FcTrue;
+}
+
+void
+FcAtomicDeleteNew (FcAtomic *atomic)
+{
+    unlink ((char *) atomic->new);
+}
+
+void
+FcAtomicUnlock (FcAtomic *atomic)
+{
+    unlink ((char *) atomic->lck);
+}
+
+void
+FcAtomicDestroy (FcAtomic *atomic)
+{
+    free (atomic);
+}
index 4b2fbd635375b686a9d19089f3d8567c3d65fa59..2ee4b1ae7bdc89f2504370e42476b72be9a287b9 100644 (file)
@@ -424,6 +424,10 @@ FcFileCacheSave (FcFileCache       *cache,
     if (!cache->updated && cache->referenced == cache->entries)
        return FcTrue;
     
+    /* Set-UID programs can't safely update the cache */
+    if (getuid () != geteuid ())
+       return FcFalse;
+    
     atomic = FcAtomicCreate (cache_file);
     if (!atomic)
        goto bail0;