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.
This commit is contained in:
parent
569657a24c
commit
e96d776088
|
@ -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,10 +86,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 [-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"
|
||||
|
@ -98,6 +99,7 @@ usage (char *program, int error)
|
|||
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");
|
||||
|
@ -105,6 +107,7 @@ usage (char *program, int error)
|
|||
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);
|
||||
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)))
|
||||
{
|
||||
cache_dir = test_dir;
|
||||
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 = 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);
|
||||
}
|
||||
|
||||
|
|
57
src/fccfg.c
57
src/fccfg.c
|
@ -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__
|
||||
|
|
28
src/fcinit.c
28
src/fcinit.c
|
@ -65,14 +65,16 @@ FcGetVersion (void)
|
|||
* Load the configuration files
|
||||
*/
|
||||
FcConfig *
|
||||
FcInitLoadConfig (void)
|
||||
FcInitLoadOwnConfig (FcConfig *config)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
FcConfig *config;
|
||||
|
||||
FcInitDebug ();
|
||||
config = FcConfigCreate ();
|
||||
if (!config)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FcInitDebug ();
|
||||
|
||||
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
|
||||
*/
|
||||
|
|
13
src/fcint.h
13
src/fcint.h
|
@ -502,6 +502,8 @@ struct _FcConfig {
|
|||
FcRef ref; /* reference count */
|
||||
|
||||
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);
|
||||
|
||||
|
|
62
src/fcstr.c
62
src/fcstr.c
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue