146 lines
3.4 KiB
Diff
146 lines
3.4 KiB
Diff
|
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
|