[Fontconfig] [PATCH 3/3] fc-cache: add a --root option

Mike Frysinger vapier at gentoo.org
Mon Nov 7 21:25:01 PST 2011


We have to add a few new helper options for setting/getting the config
root, and then hooking into the low level dir/file scanners to utilize
these new paths.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 fc-cache/fc-cache.c     |   43 +++++++++++++++++++++++++++++++++----------
 fc-cache/fc-cache.sgml  |   11 ++++++++++-
 fontconfig/fontconfig.h |    9 +++++++++
 src/fccache.c           |   40 ++++++++++++++++++++++++++++++++++++----
 src/fccfg.c             |   30 ++++++++++++++++++++++++++++--
 src/fcdir.c             |   13 +++++++++++--
 src/fcfreetype.c        |   10 +++++++++-
 src/fcxml.c             |   22 ++++++++++++++++++++--
 8 files changed, 156 insertions(+), 22 deletions(-)

diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
index 64eb22a..b57c731 100644
--- a/fc-cache/fc-cache.c
+++ b/fc-cache/fc-cache.c
@@ -69,6 +69,7 @@
 const struct option longopts[] = {
     {"force", 0, 0, 'f'},
     {"really-force", 0, 0, 'r'},
+    {"root", 1, 0, 'R'},
     {"system-only", 0, 0, 's'},
     {"version", 0, 0, 'V'},
     {"verbose", 0, 0, 'v'},
@@ -87,10 +88,10 @@ usage (char *program, int error)
 {
     FILE *file = error ? stderr : stdout;
 #if HAVE_GETOPT_LONG
-    fprintf (file, "usage: %s [-frsvVh] [--force|--really-force] [--system-only] [--verbose] [--version] [--help] [dirs]\n",
+    fprintf (file, "usage: %s [-frRsvVh] [--force|--really-force] [--root <root>] [--system-only] [--verbose] [--version] [--help] [dirs]\n",
 	     program);
 #else
-    fprintf (file, "usage: %s [-frsvVh] [dirs]\n",
+    fprintf (file, "usage: %s [-frRsvVh] [dirs]\n",
 	     program);
 #endif
     fprintf (file, "Build font information caches in [dirs]\n"
@@ -99,6 +100,7 @@ usage (char *program, int error)
 #if HAVE_GETOPT_LONG
     fprintf (file, "  -f, --force          scan directories with apparently valid caches\n");
     fprintf (file, "  -r, --really-force   erase all existing caches, then rescan\n");
+    fprintf (file, "  -R, --root <root>    change to <root> before loading files\n");
     fprintf (file, "  -s, --system-only    scan system-wide directories only\n");
     fprintf (file, "  -v, --verbose        display status information while busy\n");
     fprintf (file, "  -V, --version        display font config version and exit\n");
@@ -106,6 +108,7 @@ usage (char *program, int error)
 #else
     fprintf (file, "  -f         (force)   scan directories with apparently valid caches\n");
     fprintf (file, "  -r,   (really force) erase all existing caches, then rescan\n");
+    fprintf (file, "  -R <root>  (root)    change to <root> before loading files\n");
     fprintf (file, "  -s         (system)  scan system-wide directories only\n");
     fprintf (file, "  -v         (verbose) display status information while busy\n");
     fprintf (file, "  -V         (version) display font config version and exit\n");
@@ -253,25 +256,34 @@ cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
 {
     DIR		*d;
     struct dirent *ent;
+    FcChar8	*fullDir;
+    FcChar8	*checkDir;
     FcBool	ret = FcTrue;
     FcBool	remove;
     FcCache	*cache;
     struct stat	target_stat;
 
-    if (access ((char *) dir, W_OK) != 0)
+    fullDir = FcConfigGetRootPlus (dir);
+    if (fullDir)
+	checkDir = fullDir;
+    else
+	checkDir = dir;
+
+    if (access ((char *) checkDir, W_OK) != 0)
     {
 	if (verbose)
 	    printf ("%s: not cleaning %s cache directory\n", dir,
 		    access ((char *) dir, F_OK) == 0 ? "unwritable" : "non-existent");
-	return FcTrue;
+	goto done;
     }
     if (verbose)
 	printf ("%s: cleaning cache directory\n", dir);
-    d = opendir ((char *) dir);
+    d = opendir ((char *) checkDir);
     if (!d)
     {
 	perror ((char *) dir);
-	return FcFalse;
+	ret = FcFalse;
+	goto done;
     }
     while ((ent = readdir (d)))
     {
@@ -314,17 +326,25 @@ cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
 	}
 	if (remove)
 	{
-	    if (unlink ((char *) file_name) < 0)
+	    FcChar8 *unlink_file = FcConfigGetRootPlus (file_name);
+	    if (!unlink_file)
+		unlink_file = file_name;
+	    if (unlink ((char *) unlink_file) < 0)
 	    {
-		perror ((char *) file_name);
+		perror ((char *) unlink_file);
 		ret = FcFalse;
 	    }
+	    if (unlink_file != file_name)
+		FcStrFree (unlink_file);
 	}
 	FcDirCacheUnload (cache);
         FcStrFree (file_name);
     }
     
     closedir (d);
+ done:
+    if (fullDir)
+	FcStrFree (fullDir);
     return ret;
 }
 
@@ -366,9 +386,9 @@ main (int argc, char **argv)
     int		c;
 
 #if HAVE_GETOPT_LONG
-    while ((c = getopt_long (argc, argv, "frsVvh", longopts, NULL)) != -1)
+    while ((c = getopt_long (argc, argv, "frR:sVvh", longopts, NULL)) != -1)
 #else
-    while ((c = getopt (argc, argv, "frsVvh")) != -1)
+    while ((c = getopt (argc, argv, "frR:sVvh")) != -1)
 #endif
     {
 	switch (c) {
@@ -378,6 +398,9 @@ main (int argc, char **argv)
 	case 'f':
 	    force = FcTrue;
 	    break;
+	case 'R':
+	    FcConfigSetRoot (optarg);
+	    break;
 	case 's':
 	    systemOnly = FcTrue;
 	    break;
diff --git a/fc-cache/fc-cache.sgml b/fc-cache/fc-cache.sgml
index 3740be7..f5215df 100644
--- a/fc-cache/fc-cache.sgml
+++ b/fc-cache/fc-cache.sgml
@@ -63,9 +63,10 @@ manpage.1: manpage.sgml
     <cmdsynopsis>
       <command>&dhpackage;</command>
 
-      <arg><option>-frsvVh</option></arg>
+      <arg><option>-frRsvVh</option></arg>
       <arg><option>--force</option></arg>
       <arg><option>--really-force</option></arg>
+      <arg><option>--root</option></arg>
       <arg><option>--system-only</option></arg>
       <arg><option>--verbose</option></arg>
       <arg><option>--version</option></arg>
@@ -120,6 +121,14 @@ manpage.1: manpage.sgml
         </listitem>
       </varlistentry>
       <varlistentry>
+        <term><option>-R</option>
+          <option>--root</option>
+        </term>
+        <listitem>
+          <para>Change to root before loading files.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
         <term><option>-s</option>
           <option>--system-only</option>
         </term>
diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index cba961d..ae7403c 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -412,6 +412,15 @@ FcConfigSubstitute (FcConfig	*config,
 		    FcPattern	*p,
 		    FcMatchKind	kind);
 
+void
+FcConfigSetRoot (const char	*path);
+
+const FcChar8 *
+FcConfigGetRoot (void);
+
+FcChar8 *
+FcConfigGetRootPlus (const FcChar8	*path);
+
 /* fccharset.c */
 FcPublic FcCharSet*
 FcCharSetCreate (void);
diff --git a/src/fccache.c b/src/fccache.c
index c38a705..01ae89f 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -138,7 +138,16 @@ FcStat (const FcChar8 *file, struct stat *statb)
 int
 FcStat (const FcChar8 *file, struct stat *statb)
 {
-  return stat ((char *) file, statb);
+    int ret;
+    FcChar8 *fullFile = FcConfigGetRootPlus (file);
+
+    if (fullFile)
+	file = fullFile;
+    ret = stat ((char *) file, statb);
+    if (fullFile)
+	FcStrFree (fullFile);
+
+    return ret;
 }
 
 #endif
@@ -207,12 +216,18 @@ static int
 FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat)
 {
     int	fd;
+    FcChar8 *fullFile;
 
 #ifdef _WIN32
     if (FcStat (cache_file, file_stat) < 0)
         return -1;
 #endif
-    fd = open((char *) cache_file, O_RDONLY | O_BINARY);
+    fullFile = FcConfigGetRootPlus (cache_file);
+    if (fullFile)
+	cache_file = fullFile;
+    fd = open ((char *) cache_file, O_RDONLY | O_BINARY);
+    if (fullFile)
+	FcStrFree (fullFile);
     if (fd < 0)
 	return fd;
 #ifndef _WIN32
@@ -854,6 +869,8 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
     FcStrList	    *list;
     FcChar8	    *cache_dir = NULL;
     FcChar8	    *test_dir;
+    FcChar8	    *full_test_dir;
+    FcBool	    free_test_dir;
     FcCacheSkip     *skip;
     struct stat     cache_stat;
     int		    magic;
@@ -866,7 +883,19 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
     list = FcStrListCreate (config->cacheDirs);
     if (!list)
 	return FcFalse;
+    free_test_dir = FcFalse;
     while ((test_dir = FcStrListNext (list))) {
+	if (free_test_dir)
+	    FcStrFree (full_test_dir);
+	free_test_dir = FcFalse;
+
+	full_test_dir = FcConfigGetRootPlus (test_dir);
+	if (full_test_dir)
+	{
+	    free_test_dir = FcTrue;
+	    test_dir = full_test_dir;
+	}
+
 	if (access ((char *) test_dir, W_OK|X_OK) == 0)
 	{
 	    cache_dir = test_dir;
@@ -896,12 +925,12 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
     }
     FcStrListDone (list);
     if (!cache_dir)
-	return FcFalse;
+	goto bail0;
 
     FcDirCacheBasename (dir, cache_base);
     cache_hashed = FcStrPlus (cache_dir, cache_base);
     if (!cache_hashed)
-        return FcFalse;
+        goto bail0;
 
     if (FcDebug () & FC_DBG_CACHE)
         printf ("FcDirCacheWriteDir dir \"%s\" file \"%s\"\n",
@@ -968,6 +997,9 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
     FcAtomicDestroy (atomic);
  bail1:
     FcStrFree (cache_hashed);
+ bail0:
+    if (free_test_dir)
+	FcStrFree (full_test_dir);
     return FcFalse;
 }
 
diff --git a/src/fccfg.c b/src/fccfg.c
index 6d55f17..8274711 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -1693,9 +1693,12 @@ FcConfigFileExists (const FcChar8 *dir, const FcChar8 *file)
     if (!dir)
 	dir = (const FcChar8 *) "";
 
-    path = FcStrPathPlus (dir, file, NULL);
+    path = FcStrPathPlus (FcConfigGetRoot (), dir, file, NULL);
     if (access ((char *) path, R_OK) == 0)
-	return path;
+    {
+	FcStrFree (path);
+	return FcStrPathPlus (dir, file, NULL);
+    }
 
     FcStrFree (path);
     return 0;
@@ -2076,6 +2079,29 @@ FcConfigAcceptFont (FcConfig	    *config,
 	return FcFalse;
     return FcTrue;
 }
+
+static const FcChar8 *_fcRoot = (const FcChar8 *) "";
+
+void
+FcConfigSetRoot (const char *path)
+{
+    _fcRoot = (FcChar8 *) strdup (path);
+}
+
+const FcChar8 *
+FcConfigGetRoot (void)
+{
+    return _fcRoot;
+}
+
+FcChar8 *
+FcConfigGetRootPlus (const FcChar8 *path)
+{
+    if (!_fcRoot[0])
+	return NULL;
+    return FcStrPathPlus (_fcRoot, path, NULL);
+}
+
 #define __fccfg__
 #include "fcaliastail.h"
 #undef __fccfg__
diff --git a/src/fcdir.c b/src/fcdir.c
index d8b094f..0e885a2 100644
--- a/src/fcdir.c
+++ b/src/fcdir.c
@@ -142,6 +142,8 @@ FcDirScanConfig (FcFontSet	*set,
     FcStrSet		*files;
     FcChar8		*file;
     FcChar8		*base;
+    const FcChar8	*scanDir;
+    FcChar8		*fullDir;
     FcBool		ret = FcTrue;
     int			i;
 
@@ -167,8 +169,15 @@ FcDirScanConfig (FcFontSet	*set,
 
     if (FcDebug () & FC_DBG_SCAN)
 	printf ("\tScanning dir %s\n", dir);
-	
-    d = opendir ((char *) dir);
+
+    fullDir = FcConfigGetRootPlus (dir);
+    if (fullDir)
+	scanDir = fullDir;
+    else
+	scanDir = dir;
+    d = opendir ((char *) scanDir);
+    if (fullDir)
+	FcStrFree (fullDir);
     if (!d)
     {
 	/* Don't complain about missing directories */
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 56ee380..2fc4786 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1751,11 +1751,17 @@ FcFreeTypeQuery(const FcChar8	*file,
     FT_Face	    face;
     FT_Library	    ftLibrary;
     FcPattern	    *pat = NULL;
+    const FcChar8   *ftFile = file;
+    FcChar8	    *fullFile;
 
     if (FT_Init_FreeType (&ftLibrary))
 	return NULL;
 
-    if (FT_New_Face (ftLibrary, (char *) file, id, &face))
+    fullFile = FcConfigGetRootPlus (file);
+    if (fullFile)
+	ftFile = fullFile;
+
+    if (FT_New_Face (ftLibrary, (char *) ftFile, id, &face))
 	goto bail;
 
     *count = face->num_faces;
@@ -1764,6 +1770,8 @@ FcFreeTypeQuery(const FcChar8	*file,
 
     FT_Done_Face (face);
 bail:
+    if (fullFile)
+	FcStrFree (fullFile);
     FT_Done_FreeType (ftLibrary);
     return pat;
 }
diff --git a/src/fcxml.c b/src/fcxml.c
index ff30b7b..c49373d 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -2603,11 +2603,20 @@ FcConfigParseAndLoadDir (FcConfig	*config,
     DIR		    *d;
     struct dirent   *e;
     FcBool	    ret = FcTrue;
+    FcChar8	    *fullDir;
+    const FcChar8   *scanDir;
     FcChar8	    *file;
     FcChar8	    *base;
     FcStrSet	    *files;
 
-    d = opendir ((char *) dir);
+    fullDir = FcConfigGetRootPlus (dir);
+    if (fullDir)
+	scanDir = fullDir;
+    else
+	scanDir = dir;
+    d = opendir ((char *) scanDir);
+    if (fullDir)
+	FcStrFree (fullDir);
     if (!d)
     {
 	if (complain)
@@ -2685,6 +2694,8 @@ FcConfigParseAndLoad (FcConfig	    *config,
 
     XML_Parser	    p;
     FcChar8	    *filename;
+    const FcChar8   *readFile;
+    FcChar8	    *fullFile;
     int		    fd;
     int		    len;
     FcConfigParse   parse;
@@ -2723,7 +2734,14 @@ FcConfigParseAndLoad (FcConfig	    *config,
     if (FcDebug () & FC_DBG_CONFIG)
 	printf ("\tLoading config file %s\n", filename);
 
-    fd = open ((char *) filename, O_RDONLY);
+    fullFile = FcConfigGetRootPlus (filename);
+    if (fullFile)
+	readFile = fullFile;
+    else
+	readFile = filename;
+    fd = open ((char *) readFile, O_RDONLY);
+    if (fullFile)
+	FcStrFree (fullFile);
     if (fd == -1) {
 	FcStrFree (filename);
 	goto bail0;
-- 
1.7.6.1



More information about the Fontconfig mailing list