nim / rpms / fontconfig

Forked from rpms/fontconfig 4 years ago
Clone
Blob Blame History Raw
diff --git a/src/fccache.c b/src/fccache.c
index fc3ed41..5a8720b 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -1142,6 +1142,70 @@ FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose)
     return ret;
 }
 
+int
+FcDirCacheLock (const FcChar8 *dir,
+		FcConfig      *config)
+{
+    FcChar8 *cache_hashed = NULL;
+    FcChar8 cache_base[CACHEBASE_LEN];
+    FcStrList *list;
+    FcChar8 *cache_dir;
+    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+    int fd = -1;
+
+    FcDirCacheBasename (dir, cache_base);
+    list = FcStrListCreate (config->cacheDirs);
+    if (!list)
+	return -1;
+
+    while ((cache_dir = FcStrListNext (list)))
+    {
+	if (sysroot)
+	    cache_hashed = FcStrBuildFilename (sysroot, cache_dir, cache_base, NULL);
+	else
+	    cache_hashed = FcStrBuildFilename (cache_dir, cache_base, NULL);
+	if (!cache_hashed)
+	    break;
+	fd = FcOpen ((const char *)cache_hashed, O_RDWR);
+	/* No caches in that directory. simply retry with another one */
+	if (fd != -1)
+	{
+	    struct flock fl;
+
+	    fl.l_type = F_WRLCK;
+	    fl.l_whence = SEEK_SET;
+	    fl.l_start = 0;
+	    fl.l_len = 0;
+	    fl.l_pid = getpid ();
+	    if (fcntl (fd, F_SETLKW, &fl) == -1)
+		goto bail;
+	    break;
+	}
+    }
+    return fd;
+bail:
+    if (fd != -1)
+	close (fd);
+    return -1;
+}
+
+void
+FcDirCacheUnlock (int fd)
+{
+    struct flock fl;
+
+    if (fd != -1)
+    {
+	fl.l_type = F_UNLCK;
+	fl.l_whence = SEEK_SET;
+	fl.l_start = 0;
+	fl.l_len = 0;
+	fl.l_pid = getpid ();
+	fcntl (fd, F_SETLK, &fl);
+	close (fd);
+    }
+}
+
 /*
  * Hokey little macro trick to permit the definitions of C functions
  * with the same name as CPP macros
diff --git a/src/fcdir.c b/src/fcdir.c
index 2e7f0dc..f4807dd 100644
--- a/src/fcdir.c
+++ b/src/fcdir.c
@@ -332,6 +332,7 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
     struct stat		dir_stat;
     const FcChar8	*sysroot = FcConfigGetSysRoot (config);
     FcChar8		*d;
+    int			fd = -1;
 
     if (sysroot)
 	d = FcStrBuildFilename (sysroot, dir, NULL);
@@ -352,6 +353,7 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
     if (!dirs)
 	goto bail1;
 
+    fd = FcDirCacheLock (dir, config);
     /*
      * Scan the dir
      */
@@ -371,6 +373,7 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
     FcDirCacheWrite (cache, config);
 
  bail2:
+    FcDirCacheUnlock (fd);
     FcStrSetDestroy (dirs);
  bail1:
     FcFontSetDestroy (set);
@@ -389,6 +392,7 @@ FcDirCacheRescan (const FcChar8 *dir, FcConfig *config)
     FcStrSet *dirs;
     const FcChar8 *sysroot = FcConfigGetSysRoot (config);
     FcChar8 *d = NULL;
+    int fd = -1;
 
     cache = FcDirCacheLoad (dir, config, NULL);
     if (!cache)
@@ -404,6 +408,7 @@ FcDirCacheRescan (const FcChar8 *dir, FcConfig *config)
     if (!dirs)
 	goto bail;
 
+    fd = FcDirCacheLock (dir, config);
     /*
      * Scan the dir
      */
@@ -422,6 +427,7 @@ FcDirCacheRescan (const FcChar8 *dir, FcConfig *config)
     FcDirCacheWrite (new, config);
 
 bail1:
+    FcDirCacheUnlock (fd);
     FcStrSetDestroy (dirs);
 bail:
     if (d)
diff --git a/src/fcint.h b/src/fcint.h
index 15e22fd..76becec 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -590,6 +590,13 @@ FcCacheFini (void);
 FcPrivate void
 FcDirCacheReference (FcCache *cache, int nref);
 
+FcPrivate int
+FcDirCacheLock (const FcChar8 *dir,
+		FcConfig      *config);
+
+FcPrivate void
+FcDirCacheUnlock (int fd);
+
 /* fccfg.c */
 
 FcPrivate FcBool