]> git.wh0rd.org Git - fontconfig.git/commitdiff
fc-cache: add a --root option root
authorMike Frysinger <vapier@gentoo.org>
Tue, 8 Nov 2011 01:00:51 +0000 (20:00 -0500)
committerMike Frysinger <vapier@gentoo.org>
Tue, 8 Nov 2011 19:45:43 +0000 (14:45 -0500)
The point of the root support is to let fc-cache be usable on fs trees
other than just /.  This is useful to people cross-compiling, and for
non-root building (chroot won't work) for distro maintainers.  So now
we can tell fontconfig to search a specific root path to locate all of
its configs/fonts/caches/etc... without having to modify the configs.

We have to add a few new helper options for setting/getting the config
root, and then extend some of the existing API funcs to take a config
struct as an option.  This way the low level pieces know which paths
to actually search.

First we export the internal FcStat helper.  The fc-cache code uses
stat() directly, but we already have a FcStat helper to workaround
misc issues, so just use that one instead.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
fc-cache/fc-cache.c
fc-cache/fc-cache.sgml
fc-cat/fc-cat.c
fontconfig/fontconfig.h
src/fcatomic.c
src/fccache.c
src/fccfg.c
src/fcdir.c
src/fcfreetype.c
src/fcint.h
src/fcxml.c

index 98039f77ff778aaa1fd583bf5e066b42c195b0bf..59a24bbb324e5c98dfc1e1de3a686125395ff055 100644 (file)
@@ -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");
@@ -154,7 +157,7 @@ scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force,
            continue;
        }
 
-       if (stat ((char *) dir, &statb) == -1)
+       if (FcStat (config, dir, &statb) == -1)
        {
            switch (errno) {
            case ENOENT:
@@ -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 (config, 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)))
     {
@@ -294,7 +306,7 @@ cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
            break;
        }
        remove = FcFalse;
-       cache = FcDirCacheLoadFile (file_name, NULL);
+       cache = FcDirCacheLoadFile2 (file_name, config, NULL);
        if (!cache)
        {
            if (verbose)
@@ -304,7 +316,7 @@ cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
        else
        {
            target_dir = FcCacheDir (cache);
-           if (stat ((char *) target_dir, &target_stat) < 0)
+           if (FcStat (config, target_dir, &target_stat) < 0)
            {
                if (verbose)
                    printf ("%s: %s: missing directory: %s \n",
@@ -314,17 +326,25 @@ cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
        }
        if (remove)
        {
-           if (unlink ((char *) file_name) < 0)
+           FcChar8 *unlink_file = FcConfigGetRootPlus (config, 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;
 }
 
@@ -359,6 +379,7 @@ main (int argc, char **argv)
     FcBool     really_force = FcFalse;
     FcBool     systemOnly = FcFalse;
     FcConfig   *config;
+    const char *rootDir;
     int                i;
     int                changed;
     int                ret;
@@ -366,9 +387,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 +399,9 @@ main (int argc, char **argv)
        case 'f':
            force = FcTrue;
            break;
+       case 'R':
+           rootDir = optarg;
+           break;
        case 's':
            systemOnly = FcTrue;
            break;
@@ -408,6 +432,7 @@ main (int argc, char **argv)
        return 1;
     }
     FcConfigSetCurrent (config);
+    FcConfigSetRoot (config, (const FcChar8 *) rootDir);
 
     if (argv[i])
     {
index 3740be77f66356c63106edd5e8fa56b29196c1f5..f5215df6288cf9f7894879bb4f5a3a49b59c6d28 100644 (file)
@@ -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>
@@ -119,6 +120,14 @@ manpage.1: manpage.sgml
           <para>Erase all existing cache files and rescan.</para>
         </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>
index c3d68296b97249403985431bd8f07576b518f8cc..8d19c615433737ac9808a2d190f0e795e5226334 100644 (file)
@@ -349,10 +349,10 @@ main (int argc, char **argv)
        FcChar8     *cache_file = NULL;
        struct stat file_stat;
        
-       if (FcFileIsDir (arg))
+       if (FcFileIsDir2 (config, arg))
            cache = FcDirCacheLoad (arg, config, &cache_file);
        else
-           cache = FcDirCacheLoadFile (arg, &file_stat);
+           cache = FcDirCacheLoadFile2 (arg, config, &file_stat);
        if (!cache)
        {
            perror ((char *) arg);
index 254acc31079cd709d1e1cb24a82b8f1ccdccea2a..f83cd3823979fed6f6df336e8174521de2749e78 100644 (file)
@@ -307,6 +307,9 @@ FcBlanksIsMember (FcBlanks *b, FcChar32 ucs4);
 
 /* fccache.c */
 
+FcPublic int
+FcStat (FcConfig *config, const FcChar8 *file, struct stat *statb);
+
 FcPublic const FcChar8 *
 FcCacheDir(const FcCache *c);
 
@@ -337,6 +340,9 @@ FcConfigEnableHome (FcBool enable);
 
 FcPublic FcChar8 *
 FcConfigFilename (const FcChar8 *url);
+
+FcPublic FcChar8 *
+FcConfigFilename2 (FcConfig *config, const FcChar8 *url);
     
 FcPublic FcConfig *
 FcConfigCreate (void);
@@ -409,6 +415,17 @@ FcConfigSubstitute (FcConfig       *config,
                    FcPattern   *p,
                    FcMatchKind kind);
 
+FcPublic void
+FcConfigSetRoot (FcConfig      *config,
+                const FcChar8  *path);
+
+FcPublic const FcChar8 *
+FcConfigGetRoot (FcConfig      *config);
+
+FcPublic FcChar8 *
+FcConfigGetRootPlus (FcConfig          *config,
+                    const FcChar8      *path);
+
 /* fccharset.c */
 FcPublic FcCharSet*
 FcCharSetCreate (void);
@@ -497,6 +514,9 @@ FcDefaultSubstitute (FcPattern *pattern);
 FcPublic FcBool
 FcFileIsDir (const FcChar8 *file);
 
+FcPublic FcBool
+FcFileIsDir2 (FcConfig *config, const FcChar8 *file);
+
 FcPublic FcBool
 FcFileScan (FcFontSet      *set,
            FcStrSet        *dirs,
@@ -525,6 +545,9 @@ FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config);
 FcPublic FcCache *
 FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat);
 
+FcPublic FcCache *
+FcDirCacheLoadFile2 (const FcChar8 *cache_file, FcConfig *config, struct stat *file_stat);
+
 FcPublic void
 FcDirCacheUnload (FcCache *cache);
 
@@ -532,6 +555,9 @@ FcDirCacheUnload (FcCache *cache);
 FcPublic FcPattern *
 FcFreeTypeQuery (const FcChar8 *file, int id, FcBlanks *blanks, int *count);
 
+FcPublic FcPattern *
+FcFreeTypeQuery2 (FcConfig *config, const FcChar8 *file, int id, FcBlanks *blanks, int *count);
+
 /* fcfs.c */
 
 FcPublic FcFontSet *
@@ -647,6 +673,9 @@ FcAtomicCreate (const FcChar8   *file);
 FcPublic FcBool
 FcAtomicLock (FcAtomic *atomic);
 
+FcPublic FcBool
+FcAtomicLock2 (FcConfig *config, FcAtomic *atomic);
+
 FcPublic FcChar8 *
 FcAtomicNewFile (FcAtomic *atomic);
 
index 33c1cc6287df4282feccde3f2a71dc6f9d9c1568..0dc29d59ae8c50bef0272b1e69ca4489368a5bbb 100644 (file)
@@ -98,6 +98,12 @@ FcAtomicCreate (const FcChar8   *file)
 
 FcBool
 FcAtomicLock (FcAtomic *atomic)
+{
+    return FcAtomicLock2 (FcConfigGetCurrent (), atomic);
+}
+
+FcBool
+FcAtomicLock2 (FcConfig *config, FcAtomic *atomic)
 {
     int                fd = -1;
     FILE       *f = 0;
@@ -142,17 +148,17 @@ FcAtomicLock (FcAtomic *atomic)
         * machines sharing the same filesystem will have clocks
         * reasonably close to each other.
         */
-       if (FcStat (atomic->lck, &lck_stat) >= 0)
+       if (FcStat (config, atomic->lck, &lck_stat) >= 0)
        {
            time_t  now = time (0);
            if ((long int) (now - lck_stat.st_mtime) > 10 * 60)
            {
 #ifdef HAVE_LINK
                if (unlink ((char *) atomic->lck) == 0)
-                   return FcAtomicLock (atomic);
+                   return FcAtomicLock2 (config, atomic);
 #else
                if (rmdir ((char *) atomic->lck) == 0)
-                   return FcAtomicLock (atomic);
+                   return FcAtomicLock2 (config, atomic);
 #endif
            }
        }
index c38a7050edd837cba58165ab42614ec7224d85df..e9f57f4ed736cf009dc2388b175457a1e73e4b49 100644 (file)
@@ -87,7 +87,7 @@ typedef __int64 INT64;
  */
 
 int
-FcStat (const FcChar8 *file, struct stat *statb)
+FcStat (FcConfig *config, const FcChar8 *file, struct stat *statb)
 {
     WIN32_FILE_ATTRIBUTE_DATA wfad;
     char full_path_name[MAX_PATH];
@@ -136,9 +136,18 @@ FcStat (const FcChar8 *file, struct stat *statb)
 #else
 
 int
-FcStat (const FcChar8 *file, struct stat *statb)
+FcStat (FcConfig *config, const FcChar8 *file, struct stat *statb)
 {
-  return stat ((char *) file, statb);
+    int ret;
+    FcChar8 *fullFile = FcConfigGetRootPlus (config, file);
+
+    if (fullFile)
+       file = fullFile;
+    ret = stat ((char *) file, statb);
+    if (fullFile)
+       FcStrFree (fullFile);
+
+    return ret;
 }
 
 #endif
@@ -204,15 +213,21 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
 }
 
 static int
-FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat)
+FcDirCacheOpenFile (FcConfig *config, const FcChar8 *cache_file, struct stat *file_stat)
 {
     int        fd;
+    FcChar8 *fullFile;
 
 #ifdef _WIN32
-    if (FcStat (cache_file, file_stat) < 0)
+    if (FcStat (config, cache_file, file_stat) < 0)
         return -1;
 #endif
-    fd = open((char *) cache_file, O_RDONLY | O_BINARY);
+    fullFile = FcConfigGetRootPlus (config, 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
@@ -232,7 +247,7 @@ FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat)
  */
 static FcBool
 FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
-                  FcBool (*callback) (int fd, struct stat *fd_stat,
+                  FcBool (*callback) (FcConfig *config, int fd, struct stat *fd_stat,
                                       struct stat *dir_stat, void *closure),
                   void *closure, FcChar8 **cache_file_ret)
 {
@@ -243,7 +258,7 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
     struct stat file_stat, dir_stat;
     FcBool     ret = FcFalse;
 
-    if (FcStat (dir, &dir_stat) < 0)
+    if (FcStat (config, dir, &dir_stat) < 0)
         return FcFalse;
 
     FcDirCacheBasename (dir, cache_base);
@@ -257,9 +272,9 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
         FcChar8        *cache_hashed = FcStrPlus (cache_dir, cache_base);
         if (!cache_hashed)
            break;
-        fd = FcDirCacheOpenFile (cache_hashed, &file_stat);
+        fd = FcDirCacheOpenFile (config, cache_hashed, &file_stat);
         if (fd >= 0) {
-           ret = (*callback) (fd, &file_stat, &dir_stat, closure);
+           ret = (*callback) (config, fd, &file_stat, &dir_stat, closure);
            close (fd);
            if (ret)
            {
@@ -519,13 +534,13 @@ FcCacheFini (void)
 }
 
 static FcBool
-FcCacheTimeValid (FcCache *cache, struct stat *dir_stat)
+FcCacheTimeValid (FcConfig *config, FcCache *cache, struct stat *dir_stat)
 {
     struct stat        dir_static;
 
     if (!dir_stat)
     {
-       if (FcStat (FcCacheDir (cache), &dir_static) < 0)
+       if (FcStat (config, FcCacheDir (cache), &dir_static) < 0)
            return FcFalse;
        dir_stat = &dir_static;
     }
@@ -539,7 +554,7 @@ FcCacheTimeValid (FcCache *cache, struct stat *dir_stat)
  * Map a cache file into memory
  */
 static FcCache *
-FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat)
+FcDirCacheMapFd (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat)
 {
     FcCache    *cache;
     FcBool     allocated = FcFalse;
@@ -549,7 +564,7 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat)
     cache = FcCacheFindByStat (fd_stat);
     if (cache)
     {
-       if (FcCacheTimeValid (cache, dir_stat))
+       if (FcCacheTimeValid (config, cache, dir_stat))
            return cache;
        FcDirCacheUnload (cache);
        cache = NULL;
@@ -597,7 +612,7 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat)
     if (cache->magic != FC_CACHE_MAGIC_MMAP ||
        cache->version < FC_CACHE_CONTENT_VERSION ||
        cache->size != fd_stat->st_size ||
-       !FcCacheTimeValid (cache, dir_stat) ||
+       !FcCacheTimeValid (config, cache, dir_stat) ||
        !FcCacheInsert (cache, fd_stat))
     {
        if (allocated)
@@ -636,9 +651,9 @@ FcDirCacheUnload (FcCache *cache)
 }
 
 static FcBool
-FcDirCacheMapHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
+FcDirCacheMapHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
 {
-    FcCache *cache = FcDirCacheMapFd (fd, fd_stat, dir_stat);
+    FcCache *cache = FcDirCacheMapFd (config, fd, fd_stat, dir_stat);
 
     if (!cache)
        return FcFalse;
@@ -660,6 +675,12 @@ FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
 
 FcCache *
 FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat)
+{
+    return FcDirCacheLoadFile2 (cache_file, FcConfigGetCurrent (), file_stat);
+}
+
+FcCache *
+FcDirCacheLoadFile2 (const FcChar8 *cache_file, FcConfig *config, struct stat *file_stat)
 {
     int        fd;
     FcCache *cache;
@@ -667,10 +688,10 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat)
 
     if (!file_stat)
        file_stat = &my_file_stat;
-    fd = FcDirCacheOpenFile (cache_file, file_stat);
+    fd = FcDirCacheOpenFile (config, cache_file, file_stat);
     if (fd < 0)
        return NULL;
-    cache = FcDirCacheMapFd (fd, file_stat, NULL);
+    cache = FcDirCacheMapFd (config, fd, file_stat, NULL);
     close (fd);
     return cache;
 }
@@ -680,7 +701,7 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat)
  * the magic number and the size field
  */
 static FcBool
-FcDirCacheValidateHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
+FcDirCacheValidateHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
 {
     FcBool  ret = FcTrue;
     FcCache    c;
@@ -854,6 +875,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 +889,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 (config, 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 +931,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",
@@ -911,7 +946,7 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
     if (!atomic)
        goto bail1;
 
-    if (!FcAtomicLock (atomic))
+    if (!FcAtomicLock2 (config, atomic))
        goto bail3;
 
     fd = open((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT | O_BINARY, 0666);
@@ -948,7 +983,7 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
      */
     if (cache->size < FC_CACHE_MIN_MMAP &&
        (skip = FcCacheFindByAddr (cache)) &&
-       FcStat (cache_hashed, &cache_stat))
+       FcStat (config, cache_hashed, &cache_stat))
     {
        skip->cache_dev = cache_stat.st_dev;
        skip->cache_ino = cache_stat.st_ino;
@@ -968,6 +1003,9 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
     FcAtomicDestroy (atomic);
  bail1:
     FcStrFree (cache_hashed);
+ bail0:
+    if (free_test_dir)
+       FcStrFree (full_test_dir);
     return FcFalse;
 }
 
index 6d55f171e216ca886ec6cbe4e78dc4137b4e2959..b0a0f84fb572c6a77fe76a936ec01c602c0388ed 100644 (file)
@@ -81,6 +81,8 @@ FcConfigCreate (void)
     if (!config->cacheDirs)
        goto bail8;
 
+    config->rootDir = FcStrCopy ((const FcChar8 *) "");
+
     config->blanks = 0;
 
     config->substPattern = 0;
@@ -121,7 +123,7 @@ bail0:
 }
 
 static FcFileTime
-FcConfigNewestFile (FcStrSet *files)
+FcConfigNewestFile (FcConfig *config, FcStrSet *files)
 {
     FcStrList      *list = FcStrListCreate (files);
     FcFileTime     newest = { 0, FcFalse };
@@ -131,7 +133,7 @@ FcConfigNewestFile (FcStrSet *files)
     if (list)
     {
        while ((file = FcStrListNext (list)))
-           if (FcStat (file, &statb) == 0)
+           if (FcStat (config, file, &statb) == 0)
                if (!newest.set || statb.st_mtime - newest.time > 0)
                {
                    newest.set = FcTrue;
@@ -153,9 +155,9 @@ FcConfigUptoDate (FcConfig *config)
        if (!config)
            return FcFalse;
     }
-    config_time = FcConfigNewestFile (config->configFiles);
-    config_dir_time = FcConfigNewestFile (config->configDirs);
-    font_time = FcConfigNewestFile (config->fontDirs);
+    config_time = FcConfigNewestFile (config, config->configFiles);
+    config_dir_time = FcConfigNewestFile (config, config->configDirs);
+    font_time = FcConfigNewestFile (config, config->fontDirs);
     if ((config_time.set && config_time.time - config->rescanTime > 0) ||
        (config_dir_time.set && (config_dir_time.time - config->rescanTime) > 0) ||
        (font_time.set && (font_time.time - config->rescanTime) > 0))
@@ -487,7 +489,7 @@ FcConfigAddConfigFile (FcConfig         *config,
                       const FcChar8   *f)
 {
     FcBool     ret;
-    FcChar8    *file = FcConfigFilename (f);
+    FcChar8    *file = FcConfigFilename2 (config, f);
 
     if (!file)
        return FcFalse;
@@ -1686,16 +1688,19 @@ DllMain (HINSTANCE hinstDLL,
 #endif
 
 static FcChar8 *
-FcConfigFileExists (const FcChar8 *dir, const FcChar8 *file)
+FcConfigFileExists (FcConfig *config, const FcChar8 *dir, const FcChar8 *file)
 {
     FcChar8    *path;
 
     if (!dir)
        dir = (const FcChar8 *) "";
 
-    path = FcStrPathPlus (dir, file, NULL);
+    path = FcStrPathPlus (FcConfigGetRoot (config), dir, file, NULL);
     if (access ((char *) path, R_OK) == 0)
-       return path;
+    {
+       FcStrFree (path);
+       return FcStrPathPlus (dir, file, NULL);
+    }
 
     FcStrFree (path);
     return 0;
@@ -1811,6 +1816,12 @@ FcConfigEnableHome (FcBool enable)
 
 FcChar8 *
 FcConfigFilename (const FcChar8 *url)
+{
+    return FcConfigFilename2 (FcConfigGetCurrent (), url);
+}
+
+FcChar8 *
+FcConfigFilename2 (FcConfig *config, const FcChar8 *url)
 {
     FcChar8    *file, *dir, **path, **p;
 
@@ -1833,7 +1844,7 @@ FcConfigFilename (const FcChar8 *url)
     case '~':
        dir = FcConfigHome ();
        if (dir)
-           file = FcConfigFileExists (dir, url + 1);
+           file = FcConfigFileExists (config, dir, url + 1);
        else
            file = 0;
        break;
@@ -1842,7 +1853,7 @@ FcConfigFilename (const FcChar8 *url)
     absolute_path:
 #endif
     case '/':
-       file = FcConfigFileExists (0, url);
+       file = FcConfigFileExists (config, 0, url);
        break;
     default:
        path = FcConfigGetPath ();
@@ -1850,7 +1861,7 @@ FcConfigFilename (const FcChar8 *url)
            return 0;
        for (p = path; *p; p++)
        {
-           file = FcConfigFileExists (*p, url);
+           file = FcConfigFileExists (config, *p, url);
            if (file)
                break;
        }
@@ -2076,6 +2087,34 @@ FcConfigAcceptFont (FcConfig         *config,
        return FcFalse;
     return FcTrue;
 }
+
+void
+FcConfigSetRoot (FcConfig      *config,
+                const FcChar8  *path)
+{
+    FcStrFree (config->rootDir);
+    config->rootDir = FcStrCopy (path);
+}
+
+const FcChar8 *
+FcConfigGetRoot (FcConfig      *config)
+{
+    return config->rootDir;
+}
+
+FcChar8 *
+FcConfigGetRootPlus (FcConfig          *config,
+                    const FcChar8      *path)
+{
+    /*
+     * Since we have older funcs which do not take a config, it
+     * might be NULL, so handle that as well rather than crash.
+     */
+    if (!config || !config->rootDir)
+       return NULL;
+    return FcStrPathPlus (config->rootDir, path, NULL);
+}
+
 #define __fccfg__
 #include "fcaliastail.h"
 #undef __fccfg__
index d8b094fbc7eec96a9705117993922002b20883c9..282dedd200b262b81b3c15e864fb1280b380fb4d 100644 (file)
 
 FcBool
 FcFileIsDir (const FcChar8 *file)
+{
+    return FcFileIsDir2 (FcConfigGetCurrent (), file);
+}
+
+FcBool
+FcFileIsDir2 (FcConfig *config, const FcChar8 *file)
 {
     struct stat            statb;
 
-    if (FcStat (file, &statb) != 0)
+    if (FcStat (config, file, &statb) != 0)
        return FcFalse;
     return S_ISDIR(statb.st_mode);
 }
@@ -58,7 +64,7 @@ FcFileScanFontConfig (FcFontSet               *set,
            printf ("\tScanning file %s...", file);
            fflush (stdout);
        }
-       font = FcFreeTypeQuery (file, id, blanks, &count);
+       font = FcFreeTypeQuery2 (config, file, id, blanks, &count);
        if (FcDebug () & FC_DBG_SCAN)
            printf ("done\n");
 
@@ -103,7 +109,7 @@ FcFileScanConfig (FcFontSet *set,
                  const FcChar8 *file,
                  FcConfig      *config)
 {
-    if (FcFileIsDir (file))
+    if (FcFileIsDir2 (config, file))
        return FcStrSetAdd (dirs, file);
     else
        return FcFileScanFontConfig (set, blanks, file, config);
@@ -142,6 +148,8 @@ FcDirScanConfig (FcFontSet  *set,
     FcStrSet           *files;
     FcChar8            *file;
     FcChar8            *base;
+    const FcChar8      *scanDir;
+    FcChar8            *fullDir;
     FcBool             ret = FcTrue;
     int                        i;
 
@@ -167,8 +175,15 @@ FcDirScanConfig (FcFontSet *set,
 
     if (FcDebug () & FC_DBG_SCAN)
        printf ("\tScanning dir %s\n", dir);
-       
-    d = opendir ((char *) dir);
+
+    fullDir = FcConfigGetRootPlus (config, dir);
+    if (fullDir)
+       scanDir = fullDir;
+    else
+       scanDir = dir;
+    d = opendir ((char *) scanDir);
+    if (fullDir)
+       FcStrFree (fullDir);
     if (!d)
     {
        /* Don't complain about missing directories */
@@ -242,7 +257,7 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
     if (FcDebug () & FC_DBG_FONTSET)
        printf ("cache scan dir %s\n", dir);
 
-    if (FcStat (dir, &dir_stat) < 0)
+    if (FcStat (config, dir, &dir_stat) < 0)
        goto bail;
 
     set = FcFontSetCreate();
index 56ee380cd649c7894c99a175803df6e2e2b59778..2eae80a1cb66f79d97ad1118869cb3f894850252 100644 (file)
@@ -1743,19 +1743,35 @@ bail0:
 }
 
 FcPattern *
-FcFreeTypeQuery(const FcChar8  *file,
-               int             id,
-               FcBlanks        *blanks,
-               int             *count)
+FcFreeTypeQuery (const FcChar8 *file,
+                int            id,
+                FcBlanks       *blanks,
+                int            *count)
+{
+    return FcFreeTypeQuery2 (FcConfigGetCurrent (), file, id, blanks, count);
+}
+
+FcPattern *
+FcFreeTypeQuery2 (FcConfig     *config,
+                 const FcChar8 *file,
+                 int           id,
+                 FcBlanks      *blanks,
+                 int           *count)
 {
     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 (config, file);
+    if (fullFile)
+       ftFile = fullFile;
+
+    if (FT_New_Face (ftLibrary, (char *) ftFile, id, &face))
        goto bail;
 
     *count = face->num_faces;
@@ -1764,6 +1780,8 @@ FcFreeTypeQuery(const FcChar8     *file,
 
     FT_Done_Face (face);
 bail:
+    if (fullFile)
+       FcStrFree (fullFile);
     FT_Done_FreeType (ftLibrary);
     return pat;
 }
index 0a1a90e264dd9ddfae4872bd45d0d644a1fd2849..0fcb7883daf3c4b5cc0650d43eff04f0a3c05934 100644 (file)
@@ -442,6 +442,10 @@ struct _FcBlanks {
 };
 
 struct _FcConfig {
+    /*
+     * The root directory to read config/font/cache/etc... files
+     */
+    FcChar8    *rootDir;
     /*
      * File names loaded from the configuration -- saved here as the
      * cache file must be consulted before the directories are scanned,
@@ -546,9 +550,6 @@ FcCacheFini (void);
 FcPrivate void
 FcDirCacheReference (FcCache *cache, int nref);
 
-FcPrivate int
-FcStat (const FcChar8 *file, struct stat *statb);
-
 /* fccfg.c */
 
 FcPrivate FcExpr *
index ff30b7bbdaff398971803913619b757ae24a83df..bf6dbfbd14d410eb037a69ef57b14a0c34307947 100644 (file)
@@ -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 (config, 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;
@@ -2697,7 +2708,7 @@ FcConfigParseAndLoad (FcConfig        *config,
     void           *buf;
 #endif
 
-    filename = FcConfigFilename (name);
+    filename = FcConfigFilename2 (config, name);
     if (!filename)
        goto bail0;
 
@@ -2713,7 +2724,7 @@ FcConfigParseAndLoad (FcConfig        *config,
        goto bail0;
     }
 
-    if (FcFileIsDir (filename))
+    if (FcFileIsDir2 (config, filename))
     {
        FcBool ret = FcConfigParseAndLoadDir (config, name, filename, complain);
        FcStrFree (filename);
@@ -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 (config, 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;