Add an ability to set the system root to generate the caches.
In order to do this, new APIs, FcConfigGetSysRoot() and
FcConfigSetSysRoot() is available.
Returns FcFalse if some error occurred while loading the file, either a
parse error, semantic error or allocation failure. Otherwise returns FcTrue.
@@
+
+@RET@ const FcChar8 *
+@FUNC@ FcConfigGetSysRoot
+@TYPE1@ const FcConfig * @ARG1@ config
+@PURPOSE@ Obtain the system root directory
+@DESC@
+Obtrains the system root directory in 'config' if available.
+@@
+
+@RET@ void
+@FUNC@ FcConfigSetSysRoot
+@TYPE1@ FcConfig * @ARG1@ config
+@TYPE2@ const FcChar8 * @ARG2@ sysroot
+@PURPOSE@ Set the system root directory
+@DESC@
+Set 'sysroot' as the system root directory. fontconfig prepend 'sysroot'
+to the cache directories in order to allow people to generate caches at
+the build time. Note that this causes changing current config. i.e.
+this function calls FcConfigSetCurrent() internally.
+@@
+
const struct option longopts[] = {
{"force", 0, 0, 'f'},
{"really-force", 0, 0, 'r'},
+ {"sysroot", 0, 0, 'y'},
{"system-only", 0, 0, 's'},
{"version", 0, 0, 'V'},
{"verbose", 0, 0, 'v'},
{
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 [-frsvVh] [-y SYSROOT] [--force|--really-force] [--sysroot=SYSROOT] [--system-only] [--verbose] [--version] [--help] [dirs]\n",
program);
#else
- fprintf (file, "usage: %s [-frsvVh] [dirs]\n",
+ fprintf (file, "usage: %s [-frsvVh] [-y SYSROOT] [dirs]\n",
program);
#endif
fprintf (file, "Build font information caches in [dirs]\n"
"(all directories in font configuration by default).\n");
fprintf (file, "\n");
#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, " -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");
- fprintf (file, " -h, --help display this help and exit\n");
+ 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, " -s, --system-only scan system-wide directories only\n");
+ fprintf (file, " -y, --sysroot=SYSROOT prepend SYSROOT to all paths for scanning\n");
+ fprintf (file, " -v, --verbose display status information while busy\n");
+ fprintf (file, " -V, --version display font config version and exit\n");
+ fprintf (file, " -h, --help display this help and exit\n");
#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, " -s (system) scan system-wide directories only\n");
+ fprintf (file, " -y SYSROOT (sysroot) prepend SYSROOT to all paths for scanning\n");
fprintf (file, " -v (verbose) display status information while busy\n");
fprintf (file, " -V (version) display font config version and exit\n");
fprintf (file, " -h (help) display this help and exit\n");
FcBool really_force = FcFalse;
FcBool systemOnly = FcFalse;
FcConfig *config;
+ FcChar8 *sysroot = NULL;
int i;
int changed;
int ret;
int c;
#if HAVE_GETOPT_LONG
- while ((c = getopt_long (argc, argv, "frsVvh", longopts, NULL)) != -1)
+ while ((c = getopt_long (argc, argv, "frsy:Vvh", longopts, NULL)) != -1)
#else
- while ((c = getopt (argc, argv, "frsVvh")) != -1)
+ while ((c = getopt (argc, argv, "frsy:Vvh")) != -1)
#endif
{
switch (c) {
case 's':
systemOnly = FcTrue;
break;
+ case 'y':
+ sysroot = FcStrCopy ((const FcChar8 *)optarg);
+ break;
case 'V':
fprintf (stderr, "fontconfig version %d.%d.%d\n",
FC_MAJOR, FC_MINOR, FC_REVISION);
if (systemOnly)
FcConfigEnableHome (FcFalse);
- config = FcInitLoadConfig ();
+ if (sysroot)
+ {
+ FcConfigSetSysRoot (NULL, sysroot);
+ FcStrFree (sysroot);
+ config = FcConfigGetCurrent();
+ }
+ else
+ {
+ config = FcInitLoadConfig ();
+ }
if (!config)
{
fprintf (stderr, "%s: Can't init font config library\n", argv[0]);
FcPattern *p,
FcMatchKind kind);
+FcPublic const FcChar8 *
+FcConfigGetSysRoot (const FcConfig *config);
+
+FcPublic void
+FcConfigSetSysRoot (FcConfig *config,
+ const FcChar8 *sysroot);
+
/* fccharset.c */
FcPublic FcCharSet*
FcCharSetCreate (void);
FcChar8 cache_base[CACHEBASE_LEN];
FcStrList *list;
FcChar8 *cache_dir;
+ const FcChar8 *sysroot = FcConfigGetSysRoot (config);
FcDirCacheBasename (dir, cache_base);
while ((cache_dir = FcStrListNext (list)))
{
- cache_hashed = FcStrPlus (cache_dir, cache_base);
+ if (sysroot)
+ cache_hashed = FcStrBuildFilename (sysroot, cache_dir, cache_base, NULL);
+ else
+ cache_hashed = FcStrBuildFilename (cache_dir, cache_base, NULL);
if (!cache_hashed)
break;
(void) unlink ((char *) cache_hashed);
while ((cache_dir = FcStrListNext (list)))
{
- FcChar8 *cache_hashed = FcStrPlus (cache_dir, cache_base);
+ const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+ FcChar8 *cache_hashed;
+
+ 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 = FcDirCacheOpenFile (cache_hashed, &file_stat);
FcAtomic *atomic;
FcStrList *list;
FcChar8 *cache_dir = NULL;
- FcChar8 *test_dir;
+ FcChar8 *test_dir, *d = NULL;
FcCacheSkip *skip;
struct stat cache_stat;
unsigned int magic;
int written;
+ const FcChar8 *sysroot = FcConfigGetSysRoot (config);
/*
* Write it to the first directory in the list which is writable
list = FcStrListCreate (config->cacheDirs);
if (!list)
return FcFalse;
- while ((test_dir = FcStrListNext (list))) {
- if (access ((char *) test_dir, W_OK) == 0)
+ while ((test_dir = FcStrListNext (list)))
+ {
+ if (d)
+ FcStrFree (d);
+ if (sysroot)
+ d = FcStrBuildFilename (sysroot, test_dir, NULL);
+ else
+ d = FcStrCopyFilename (test_dir);
+
+ if (access ((char *) d, W_OK) == 0)
{
- cache_dir = test_dir;
+ cache_dir = FcStrCopyFilename (d);
break;
}
else
/*
* If the directory doesn't exist, try to create it
*/
- if (access ((char *) test_dir, F_OK) == -1) {
- if (FcMakeDirectory (test_dir))
+ if (access ((char *) d, F_OK) == -1) {
+ if (FcMakeDirectory (d))
{
- cache_dir = test_dir;
+ cache_dir = FcStrCopyFilename (d);
/* Create CACHEDIR.TAG */
- FcDirCacheCreateTagFile (cache_dir);
+ FcDirCacheCreateTagFile (d);
break;
}
}
/*
* Otherwise, try making it writable
*/
- else if (chmod ((char *) test_dir, 0755) == 0)
+ else if (chmod ((char *) d, 0755) == 0)
{
- cache_dir = test_dir;
+ cache_dir = FcStrCopyFilename (d);
/* Try to create CACHEDIR.TAG too */
- FcDirCacheCreateTagFile (cache_dir);
+ FcDirCacheCreateTagFile (d);
break;
}
}
}
+ if (d)
+ FcStrFree (d);
FcStrListDone (list);
if (!cache_dir)
return FcFalse;
FcDirCacheBasename (dir, cache_base);
- cache_hashed = FcStrPlus (cache_dir, cache_base);
+ cache_hashed = FcStrBuildFilename (cache_dir, cache_base, NULL);
if (!cache_hashed)
return FcFalse;
+ FcStrFree (cache_dir);
if (FcDebug () & FC_DBG_CACHE)
printf ("FcDirCacheWriteDir dir \"%s\" file \"%s\"\n",
{
DIR *d;
struct dirent *ent;
- FcChar8 *dir_base;
+ FcChar8 *dir;
FcBool ret = FcTrue;
FcBool remove;
FcCache *cache;
struct stat target_stat;
+ const FcChar8 *sysroot;
- dir_base = FcStrPlus (cache_dir, (FcChar8 *) FC_DIR_SEPARATOR_S);
- if (!dir_base)
+ /* FIXME: this API needs to support non-current FcConfig */
+ sysroot = FcConfigGetSysRoot (NULL);
+ if (sysroot)
+ dir = FcStrBuildFilename (sysroot, cache_dir, NULL);
+ else
+ dir = FcStrCopyFilename (cache_dir);
+ if (!dir)
{
fprintf (stderr, "Fontconfig error: %s: out of memory\n", cache_dir);
return FcFalse;
}
- if (access ((char *) cache_dir, W_OK) != 0)
+ if (access ((char *) dir, W_OK) != 0)
{
if (verbose || FcDebug () & FC_DBG_CACHE)
- printf ("%s: not cleaning %s cache directory\n", cache_dir,
- access ((char *) cache_dir, F_OK) == 0 ? "unwritable" : "non-existent");
+ printf ("%s: not cleaning %s cache directory\n", dir,
+ access ((char *) dir, F_OK) == 0 ? "unwritable" : "non-existent");
goto bail0;
}
if (verbose || FcDebug () & FC_DBG_CACHE)
- printf ("%s: cleaning cache directory\n", cache_dir);
- d = opendir ((char *) cache_dir);
+ printf ("%s: cleaning cache directory\n", dir);
+ d = opendir ((char *) dir);
if (!d)
{
- perror ((char *) cache_dir);
+ perror ((char *) dir);
ret = FcFalse;
goto bail0;
}
strcmp(ent->d_name + 32, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX))
continue;
- file_name = FcStrPlus (dir_base, (FcChar8 *) ent->d_name);
+ file_name = FcStrBuildFilename (dir, (FcChar8 *)ent->d_name, NULL);
if (!file_name)
{
- fprintf (stderr, "Fontconfig error: %s: allocation failure\n", cache_dir);
+ fprintf (stderr, "Fontconfig error: %s: allocation failure\n", dir);
ret = FcFalse;
break;
}
if (!cache)
{
if (verbose || FcDebug () & FC_DBG_CACHE)
- printf ("%s: invalid cache file: %s\n", cache_dir, ent->d_name);
+ printf ("%s: invalid cache file: %s\n", dir, ent->d_name);
remove = FcTrue;
}
else
{
if (verbose || FcDebug () & FC_DBG_CACHE)
printf ("%s: %s: missing directory: %s \n",
- cache_dir, ent->d_name, target_dir);
+ dir, ent->d_name, target_dir);
remove = FcTrue;
}
FcDirCacheUnload (cache);
closedir (d);
bail0:
- FcStrFree (dir_base);
+ FcStrFree (dir);
return ret;
}
if (access ((char *) cache_dir, W_OK) == 0)
{
/* Create CACHEDIR.TAG */
- cache_tag = FcStrPlus (cache_dir, (const FcChar8 *) FC_DIR_SEPARATOR_S "CACHEDIR.TAG");
+ cache_tag = FcStrBuildFilename (cache_dir, "CACHEDIR.TAG", NULL);
if (!cache_tag)
return FcFalse;
atomic = FcAtomicCreate ((FcChar8 *)cache_tag);
void
FcCacheCreateTagFile (const FcConfig *config)
{
- FcChar8 *cache_dir = NULL;
+ FcChar8 *cache_dir = NULL, *d = NULL;
FcStrList *list;
+ const FcChar8 *sysroot = FcConfigGetSysRoot (config);
list = FcConfigGetCacheDirs (config);
if (!list)
while ((cache_dir = FcStrListNext (list)))
{
- if (FcDirCacheCreateTagFile (cache_dir))
+ if (d)
+ FcStrFree (d);
+ if (sysroot)
+ d = FcStrBuildFilename (sysroot, cache_dir, NULL);
+ else
+ d = FcStrCopyFilename (cache_dir);
+ if (FcDirCacheCreateTagFile (d))
break;
}
+ if (d)
+ FcStrFree (d);
FcStrListDone (list);
}
config->expr_pool = NULL;
+ config->sysRoot = NULL;
+
FcRefInit (&config->ref, 1);
return config;
free (page);
page = next;
}
+ if (config->sysRoot)
+ FcStrFree (config->sysRoot);
free (config);
}
return FcFalse;
return FcTrue;
}
+
+const FcChar8 *
+FcConfigGetSysRoot (const FcConfig *config)
+{
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return NULL;
+ }
+
+ return config->sysRoot;
+}
+
+void
+FcConfigSetSysRoot (FcConfig *config,
+ const FcChar8 *sysroot)
+{
+ FcChar8 *s;
+ FcBool init = FcFalse;
+
+ if (!config)
+ {
+ /* We can't use FcConfigGetCurrent() here to ensure
+ * the sysroot is set prior to initialize FcConfig,
+ * to avoid loading caches from non-sysroot dirs.
+ * So postpone the initialization later.
+ */
+ config = fc_atomic_ptr_get (&_fcConfig);
+ if (!config)
+ {
+ config = FcConfigCreate ();
+ if (!config)
+ return;
+ init = FcTrue;
+ }
+ }
+
+ s = FcStrCopyFilename (sysroot);
+ if (!s)
+ return;
+
+ if (config->sysRoot)
+ FcStrFree (config->sysRoot);
+
+ config->sysRoot = s;
+ if (init)
+ {
+ config = FcInitLoadOwnConfigAndFonts (config);
+ FcConfigSetCurrent (config);
+ }
+}
+
#define __fccfg__
#include "fcaliastail.h"
#undef __fccfg__
* Load the configuration files
*/
FcConfig *
-FcInitLoadConfig (void)
+FcInitLoadOwnConfig (FcConfig *config)
{
- FcConfig *config;
+ if (!config)
+ {
+ config = FcConfigCreate ();
+ if (!config)
+ return NULL;
+ }
FcInitDebug ();
- config = FcConfigCreate ();
- if (!config)
- return NULL;
if (!FcConfigParseAndLoad (config, 0, FcTrue))
{
return config;
}
+FcConfig *
+FcInitLoadConfig (void)
+{
+ return FcInitLoadOwnConfig (NULL);
+}
+
/*
* Load the configuration files and scan for available fonts
*/
FcConfig *
-FcInitLoadConfigAndFonts (void)
+FcInitLoadOwnConfigAndFonts (FcConfig *config)
{
- FcConfig *config = FcInitLoadConfig ();
-
- FcInitDebug ();
+ config = FcInitLoadOwnConfig (config);
if (!config)
return 0;
if (!FcConfigBuildFonts (config))
return config;
}
+FcConfig *
+FcInitLoadConfigAndFonts (void)
+{
+ return FcInitLoadOwnConfigAndFonts (NULL);
+}
+
/*
* Initialize the default library configuration
*/
FcRef ref; /* reference count */
- FcExprPage *expr_pool; /* pool of FcExpr's */
+ FcExprPage *expr_pool; /* pool of FcExpr's */
+
+ FcChar8 *sysRoot; /* override the system root directory */
};
typedef struct _FcFileTime {
FcPrivate FcChar8 *
FcHashGetSHA256DigestFromFile (const FcChar8 *filename);
+/* fcinit.c */
+FcPrivate FcConfig *
+FcInitLoadOwnConfig (FcConfig *config);
+
+FcPrivate FcConfig *
+FcInitLoadOwnConfigAndFonts (FcConfig *config);
+
/* fcxml.c */
FcPrivate void
FcTestDestroy (FcTest *test);
FcStrUsesHome (const FcChar8 *s);
FcPrivate FcChar8 *
+FcStrBuildFilename (const FcChar8 *path,
+ ...);
+
+FcPrivate FcChar8 *
FcStrLastSlash (const FcChar8 *path);
FcPrivate FcChar32
#include <regex.h>
#endif
+
/* Objects MT-safe for readonly access. */
FcChar8 *
}
FcChar8 *
+FcStrBuildFilename (const FcChar8 *path,
+ ...)
+{
+ va_list ap;
+ FcStrSet *sset = FcStrSetCreate ();
+ FcStrList *list;
+ FcChar8 *s, *ret = NULL, *p;
+ size_t len = 0;
+
+ if (!sset || !path)
+ return NULL;
+
+ if (!FcStrSetAdd (sset, path))
+ goto bail0;
+
+ va_start (ap, path);
+ while (1)
+ {
+ s = (FcChar8 *)va_arg (ap, FcChar8 *);
+ if (!s)
+ break;
+ if (!FcStrSetAdd (sset, s))
+ goto bail1;
+ }
+ list = FcStrListCreate (sset);
+ while ((s = FcStrListNext (list)))
+ {
+ len += strlen ((const char *)s) + 1;
+ }
+ list->n = 0;
+ ret = malloc (sizeof (FcChar8) * (len + 1));
+ if (!ret)
+ goto bail2;
+ p = ret;
+ while ((s = FcStrListNext (list)))
+ {
+ if (p != ret)
+ {
+ p[0] = FC_DIR_SEPARATOR;
+ p++;
+ }
+ len = strlen ((const char *)s);
+ memcpy (p, s, len);
+ p += len;
+ }
+ *p = 0;
+
+bail2:
+ FcStrListDone (list);
+bail1:
+ va_end (ap);
+bail0:
+ FcStrSetDestroy (sset);
+
+ return ret;
+}
+
+FcChar8 *
FcStrCopyFilename (const FcChar8 *s)
{
FcChar8 *new;
FcChar8 cwd[FC_MAX_FILE_LEN + 2];
if (getcwd ((char *) cwd, FC_MAX_FILE_LEN) == NULL)
return NULL;
- strcat ((char *) cwd, "/");
- full = FcStrPlus (cwd, s);
+ full = FcStrBuildFilename (cwd, s, NULL);
file = FcStrCanonAbsoluteFilename (full);
FcStrFree (full);
return file;