Commit e96d7760 authored by Akira TAGOH's avatar Akira TAGOH

Bug 59456 - Adding a --sysroot like option to fc-cache

Add an ability to set the system root to generate the caches.
In order to do this, new APIs, FcConfigGetSysRoot() and
FcConfigSetSysRoot() is available.
parent 569657a2
......@@ -371,3 +371,24 @@ and parsed. If 'complain' is FcFalse, no warning will be displayed if
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.
@@
......@@ -67,6 +67,7 @@
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'},
......@@ -85,26 +86,28 @@ 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 [-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");
......@@ -270,6 +273,7 @@ main (int argc, char **argv)
FcBool really_force = FcFalse;
FcBool systemOnly = FcFalse;
FcConfig *config;
FcChar8 *sysroot = NULL;
int i;
int changed;
int ret;
......@@ -277,9 +281,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, "frsy:Vvh", longopts, NULL)) != -1)
#else
while ((c = getopt (argc, argv, "frsVvh")) != -1)
while ((c = getopt (argc, argv, "frsy:Vvh")) != -1)
#endif
{
switch (c) {
......@@ -292,6 +296,9 @@ main (int argc, char **argv)
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);
......@@ -312,7 +319,16 @@ main (int argc, char **argv)
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]);
......
......@@ -420,6 +420,13 @@ FcConfigSubstitute (FcConfig *config,
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);
......
......@@ -124,6 +124,7 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
FcChar8 cache_base[CACHEBASE_LEN];
FcStrList *list;
FcChar8 *cache_dir;
const FcChar8 *sysroot = FcConfigGetSysRoot (config);
FcDirCacheBasename (dir, cache_base);
......@@ -133,7 +134,10 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
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);
......@@ -197,7 +201,13 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
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);
......@@ -859,11 +869,12 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
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
......@@ -872,10 +883,18 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
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
......@@ -883,35 +902,38 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
/*
* 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",
......@@ -989,31 +1011,37 @@ FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose)
{
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;
}
......@@ -1030,10 +1058,10 @@ FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose)
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;
}
......@@ -1042,7 +1070,7 @@ FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose)
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
......@@ -1052,7 +1080,7 @@ FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose)
{
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);
......@@ -1070,7 +1098,7 @@ FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose)
closedir (d);
bail0:
FcStrFree (dir_base);
FcStrFree (dir);
return ret;
}
......@@ -1394,7 +1422,7 @@ FcDirCacheCreateTagFile (const FcChar8 *cache_dir)
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);
......@@ -1438,8 +1466,9 @@ FcDirCacheCreateTagFile (const FcChar8 *cache_dir)
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)
......@@ -1447,9 +1476,17 @@ FcCacheCreateTagFile (const FcConfig *config)
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);
}
......
......@@ -123,6 +123,8 @@ FcConfigCreate (void)
config->expr_pool = NULL;
config->sysRoot = NULL;
FcRefInit (&config->ref, 1);
return config;
......@@ -292,6 +294,8 @@ FcConfigDestroy (FcConfig *config)
free (page);
page = next;
}
if (config->sysRoot)
FcStrFree (config->sysRoot);
free (config);
}
......@@ -2309,6 +2313,59 @@ FcConfigAcceptFont (FcConfig *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__
......@@ -65,14 +65,16 @@ FcGetVersion (void)
* 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))
{
......@@ -120,15 +122,19 @@ FcInitLoadConfig (void)
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))
......@@ -139,6 +145,12 @@ FcInitLoadConfigAndFonts (void)
return config;
}
FcConfig *
FcInitLoadConfigAndFonts (void)
{
return FcInitLoadOwnConfigAndFonts (NULL);
}
/*
* Initialize the default library configuration
*/
......
......@@ -501,7 +501,9 @@ struct _FcConfig {
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 {
......@@ -819,6 +821,13 @@ FcHashGetSHA256Digest (const FcChar8 *input_strings,
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);
......@@ -1072,6 +1081,10 @@ FcStrContainsWord (const FcChar8 *s1, const FcChar8 *s2);
FcPrivate FcBool
FcStrUsesHome (const FcChar8 *s);
FcPrivate FcChar8 *
FcStrBuildFilename (const FcChar8 *path,
...);
FcPrivate FcChar8 *
FcStrLastSlash (const FcChar8 *path);
......
......@@ -30,6 +30,7 @@
#include <regex.h>
#endif
/* Objects MT-safe for readonly access. */
FcChar8 *
......@@ -863,6 +864,64 @@ FcStrUsesHome (const FcChar8 *s)
return *s == '~';
}
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)
{
......@@ -1052,8 +1111,7 @@ FcStrCanonFilename (const FcChar8 *s)
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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment