[Fontconfig] fontconfig: Branch 'master'

Akira TAGOH tagoh at kemper.freedesktop.org
Tue Mar 5 02:24:41 PST 2013


 doc/fcconfig.fncs       |   21 ++++++++++
 fc-cache/fc-cache.c     |   38 +++++++++++++-----
 fontconfig/fontconfig.h |    7 +++
 src/fccache.c           |   99 ++++++++++++++++++++++++++++++++----------------
 src/fccfg.c             |   57 +++++++++++++++++++++++++++
 src/fcinit.c            |   30 ++++++++++----
 src/fcint.h             |   15 ++++++-
 src/fcstr.c             |   62 +++++++++++++++++++++++++++++-
 8 files changed, 275 insertions(+), 54 deletions(-)

New commits:
commit e96d7760886a3781a46b3271c76af99e15cb0146
Author: Akira TAGOH <akira at tagoh.org>
Date:   Wed Feb 6 19:35:30 2013 +0900

    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.

diff --git a/doc/fcconfig.fncs b/doc/fcconfig.fncs
index 10028b4..0491a56 100644
--- a/doc/fcconfig.fncs
+++ b/doc/fcconfig.fncs
@@ -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.
 @@
+
+ at RET@		const FcChar8 *
+ at FUNC@		FcConfigGetSysRoot
+ at TYPE1@		const FcConfig *		@ARG1@		config
+ at PURPOSE@	Obtain the system root directory
+ at DESC@
+Obtrains the system root directory in 'config' if available.
+@@
+
+ at RET@		void
+ at FUNC@		FcConfigSetSysRoot
+ at TYPE1@		FcConfig *			@ARG1@		config
+ at TYPE2@		const FcChar8 *			@ARG2@		sysroot
+ at PURPOSE@	Set the system root directory
+ at 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.
+@@
+
diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
index 2206096..aeb0af2 100644
--- a/fc-cache/fc-cache.c
+++ b/fc-cache/fc-cache.c
@@ -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]);
diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index ba4ee61..fc0ed1a 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -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);
diff --git a/src/fccache.c b/src/fccache.c
index 2c63125..9f1c298 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -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);
 }
 
diff --git a/src/fccfg.c b/src/fccfg.c
index db878d5..b762376 100644
--- a/src/fccfg.c
+++ b/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__
diff --git a/src/fcinit.c b/src/fcinit.c
index 2360764..b8d5d06 100644
--- a/src/fcinit.c
+++ b/src/fcinit.c
@@ -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
  */
diff --git a/src/fcint.h b/src/fcint.h
index 4eac610..d5a7217 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -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);
@@ -1073,6 +1082,10 @@ FcPrivate FcBool
 FcStrUsesHome (const FcChar8 *s);
 
 FcPrivate FcChar8 *
+FcStrBuildFilename (const FcChar8 *path,
+		    ...);
+
+FcPrivate FcChar8 *
 FcStrLastSlash (const FcChar8  *path);
 
 FcPrivate FcChar32
diff --git a/src/fcstr.c b/src/fcstr.c
index 414d6dd..4d11a4c 100644
--- a/src/fcstr.c
+++ b/src/fcstr.c
@@ -30,6 +30,7 @@
 #include <regex.h>
 #endif
 
+
 /* Objects MT-safe for readonly access. */
 
 FcChar8 *
@@ -864,6 +865,64 @@ FcStrUsesHome (const FcChar8 *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)
 {
     FcChar8 *new;
@@ -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;


More information about the Fontconfig mailing list