Blob Blame History Raw
diff -pruN fontconfig-2.13.0.orig/src/fccache.c fontconfig-2.13.0/src/fccache.c
--- fontconfig-2.13.0.orig/src/fccache.c	2017-12-18 21:45:13.000000000 +0900
+++ fontconfig-2.13.0/src/fccache.c	2018-06-08 18:39:33.079539192 +0900
@@ -51,13 +51,23 @@ FcDirCacheCreateUUID (FcChar8  *dir,
 		      FcBool    force,
 		      FcConfig *config)
 {
+    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+    FcChar8 *target;
     FcBool ret = FcTrue;
 #ifndef _WIN32
     FcChar8 *uuidname;
 
-    uuidname = FcStrBuildFilename (dir, ".uuid", NULL);
+    if (sysroot)
+	target = FcStrBuildFilename (sysroot, dir, NULL);
+    else
+	target = FcStrdup (dir);
+    uuidname = FcStrBuildFilename (target, ".uuid", NULL);
+
     if (!uuidname)
+    {
+	FcStrFree (target);
 	return FcFalse;
+    }
 
     if (force || access ((const char *) uuidname, F_OK) < 0)
     {
@@ -69,7 +79,7 @@ FcDirCacheCreateUUID (FcChar8  *dir,
 	struct stat statb;
 	struct timeval times[2];
 
-	if (FcStat (dir, &statb) != 0)
+	if (FcStat (target, &statb) != 0)
 	{
 	    ret = FcFalse;
 	    goto bail1;
@@ -96,7 +106,7 @@ FcDirCacheCreateUUID (FcChar8  *dir,
 	    hash_add = FcHashTableReplace;
 	else
 	    hash_add = FcHashTableAdd;
-	if (!hash_add (config->uuid_table, dir, uuid))
+	if (!hash_add (config->uuid_table, target, uuid))
 	{
 	    ret = FcFalse;
 	    goto bail3;
@@ -124,14 +134,15 @@ FcDirCacheCreateUUID (FcChar8  *dir,
 	    times[0].tv_usec = 0;
 	    times[1].tv_usec = 0;
 #endif
-	    if (utimes ((const  char *) dir, times) != 0)
+	    if (utimes ((const  char *) target, times) != 0)
 	    {
-		fprintf (stderr, "Unable to revert mtime: %s\n", dir);
+		fprintf (stderr, "Unable to revert mtime: %s\n", target);
 	    }
 	}
     }
-    bail1:
+bail1:
     FcStrFree (uuidname);
+    FcStrFree (target);
 #endif
 
     return ret;
@@ -144,10 +155,17 @@ FcDirCacheReadUUID (FcChar8  *dir,
 {
     void *u;
     uuid_t uuid;
+    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+    FcChar8 *target;
 
-    if (!FcHashTableFind (config->uuid_table, dir, &u))
+    if (sysroot)
+	target = FcStrBuildFilename (sysroot, dir, NULL);
+    else
+	target = FcStrdup (dir);
+
+    if (!FcHashTableFind (config->uuid_table, target, &u))
     {
-	FcChar8 *uuidname = FcStrBuildFilename (dir, ".uuid", NULL);
+	FcChar8 *uuidname = FcStrBuildFilename (target, ".uuid", NULL);
 	int fd;
 
 	if ((fd = FcOpen ((char *) uuidname, O_RDONLY)) >= 0)
@@ -162,7 +180,7 @@ FcDirCacheReadUUID (FcChar8  *dir,
 		{
 		    if (FcDebug () & FC_DBG_CACHE)
 			printf ("FcDirCacheReadUUID %s -> %s\n", uuidname, suuid);
-		    FcHashTableAdd (config->uuid_table, dir, uuid);
+		    FcHashTableAdd (config->uuid_table, target, uuid);
 		}
 	    }
 	    close (fd);
@@ -176,6 +194,7 @@ FcDirCacheReadUUID (FcChar8  *dir,
     }
     else
 	FcHashUuidFree (u);
+    FcStrFree (target);
 }
 #endif
 
@@ -259,19 +278,22 @@ static FcChar8 *
 FcDirCacheBasenameUUID (const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN], FcConfig *config)
 {
     void *u;
-    FcChar8 *alias;
+    FcChar8 *target;
+    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
 
-    if (!FcHashTableFind (config->alias_table, dir, (void **)&alias))
-	alias = FcStrdup (dir);
-    if (FcHashTableFind (config->uuid_table, alias, &u))
+    if (sysroot)
+	target = FcStrBuildFilename (sysroot, dir, NULL);
+    else
+	target = FcStrdup (dir);
+    if (FcHashTableFind (config->uuid_table, target, &u))
     {
 	uuid_unparse (u, (char *) cache_base);
 	strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
 	FcHashUuidFree (u);
-	FcStrFree (alias);
+	FcStrFree (target);
 	return cache_base;
     }
-    FcStrFree (alias);
+    FcStrFree (target);
     return NULL;
 }
 #endif
@@ -417,6 +439,7 @@ struct _FcCacheSkip {
     FcCache	    *cache;
     FcRef	    ref;
     intptr_t	    size;
+    void	   *allocated;
     dev_t	    cache_dev;
     ino_t	    cache_ino;
     time_t	    cache_mtime;
@@ -542,6 +565,7 @@ FcCacheInsert (FcCache *cache, struct st
 
     s->cache = cache;
     s->size = cache->size;
+    s->allocated = NULL;
     FcRefInit (&s->ref, 1);
     if (cache_stat)
     {
@@ -616,6 +640,7 @@ FcCacheRemoveUnlocked (FcCache *cache)
     FcCacheSkip	    **update[FC_CACHE_MAX_LEVEL];
     FcCacheSkip	    *s, **next;
     int		    i;
+    void            *allocated;
 
     /*
      * Find links along each chain
@@ -633,6 +658,15 @@ FcCacheRemoveUnlocked (FcCache *cache)
 	*update[i] = s->next[i];
     while (fcCacheMaxLevel > 0 && fcCacheChains[fcCacheMaxLevel - 1] == NULL)
 	fcCacheMaxLevel--;
+
+    allocated = s->allocated;
+    while (allocated)
+    {
+	/* First element in allocated chunk is the free list */
+	next = *(void **)allocated;
+	free (allocated);
+	allocated = next;
+    }
     free (s);
 }
 
@@ -702,6 +736,30 @@ FcCacheObjectDereference (void *object)
     unlock_cache ();
 }
 
+void *
+FcCacheAllocate (FcCache *cache, size_t len)
+{
+    FcCacheSkip	*skip;
+    void *allocated = NULL;
+
+    lock_cache ();
+    skip = FcCacheFindByAddrUnlocked (cache);
+    if (skip)
+    {
+      void *chunk = malloc (sizeof (void *) + len);
+      if (chunk)
+      {
+	  /* First element in allocated chunk is the free list */
+	  *(void **)chunk = skip->allocated;
+	  skip->allocated = chunk;
+	  /* Return the rest */
+	  allocated = ((FcChar8 *)chunk) + sizeof (void *);
+      }
+    }
+    unlock_cache ();
+    return allocated;
+}
+
 void
 FcCacheFini (void)
 {
@@ -955,7 +1013,6 @@ FcCache *
 FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
 {
     FcCache *cache = NULL;
-    const FcChar8 *d;
 
 #ifndef _WIN32
     FcDirCacheReadUUID ((FcChar8 *) dir, config);
@@ -965,10 +1022,6 @@ FcDirCacheLoad (const FcChar8 *dir, FcCo
 			    &cache, cache_file))
 	return NULL;
 
-    d = FcCacheDir (cache);
-    if (FcStrCmp (dir, d))
-	FcHashTableAdd (config->alias_table, (FcChar8 *) d, (FcChar8 *) dir);
-
     return cache;
 }
 
diff -pruN fontconfig-2.13.0.orig/src/fccfg.c fontconfig-2.13.0/src/fccfg.c
--- fontconfig-2.13.0.orig/src/fccfg.c	2018-06-08 18:34:36.546946321 +0900
+++ fontconfig-2.13.0/src/fccfg.c	2018-06-08 18:39:33.079539192 +0900
@@ -144,12 +144,6 @@ FcConfigCreate (void)
 					    FcHashUuidCopy,
 					    (FcDestroyFunc) FcStrFree,
 					    FcHashUuidFree);
-    config->alias_table = FcHashTableCreate ((FcHashFunc) FcStrHashIgnoreCase,
-					     (FcCompareFunc) FcStrCmp,
-					     FcHashStrCopy,
-					     FcHashStrCopy,
-					     (FcDestroyFunc) FcStrFree,
-					     (FcDestroyFunc) FcStrFree);
 
     FcRefInit (&config->ref, 1);
 
@@ -313,7 +307,6 @@ FcConfigDestroy (FcConfig *config)
 	FcStrFree (config->sysRoot);
 
     FcHashTableDestroy (config->uuid_table);
-    FcHashTableDestroy (config->alias_table);
 
     free (config);
 }
@@ -324,11 +317,15 @@ FcConfigDestroy (FcConfig *config)
 
 FcBool
 FcConfigAddCache (FcConfig *config, FcCache *cache,
-		  FcSetName set, FcStrSet *dirSet)
+		  FcSetName set, FcStrSet *dirSet, FcChar8 *forDir)
 {
     FcFontSet	*fs;
     intptr_t	*dirs;
     int		i;
+    FcBool      relocated = FcFalse;
+
+    if (strcmp ((char *)FcCacheDir(cache), (char *)forDir) != 0)
+      relocated = FcTrue;
 
     /*
      * Add fonts
@@ -342,23 +339,43 @@ FcConfigAddCache (FcConfig *config, FcCa
 	{
 	    FcPattern	*font = FcFontSetFont (fs, i);
 	    FcChar8	*font_file;
+	    FcChar8	*relocated_font_file = NULL;
 
-	    /*
-	     * Check to see if font is banned by filename
-	     */
 	    if (FcPatternObjectGetString (font, FC_FILE_OBJECT,
-					  0, &font_file) == FcResultMatch &&
-		!FcConfigAcceptFilename (config, font_file))
+					  0, &font_file) == FcResultMatch)
 	    {
-		continue;
+		if (relocated)
+		  {
+		    FcChar8 *slash = FcStrLastSlash (font_file);
+		    relocated_font_file = FcStrBuildFilename (forDir, slash + 1, NULL);
+		    font_file = relocated_font_file;
+		  }
+
+		/*
+		 * Check to see if font is banned by filename
+		 */
+		if (!FcConfigAcceptFilename (config, font_file))
+		{
+		    free (relocated_font_file);
+		    continue;
+		}
 	    }
-		
+
 	    /*
 	     * Check to see if font is banned by pattern
 	     */
 	    if (!FcConfigAcceptFont (config, font))
+	    {
+		free (relocated_font_file);
 		continue;
-		
+	    }
+
+	    if (relocated_font_file)
+	    {
+	      font = FcPatternCacheRewriteFile (font, cache, relocated_font_file);
+	      free (relocated_font_file);
+	    }
+
 	    if (FcFontSetAdd (config->fonts[set], font))
 		nref++;
 	}
@@ -374,18 +391,14 @@ FcConfigAddCache (FcConfig *config, FcCa
 	for (i = 0; i < cache->dirs_count; i++)
 	{
 	    const FcChar8 *dir = FcCacheSubdir (cache, i);
-	    FcChar8 *alias;
-	    FcChar8 *d = FcStrDirname (dir);
 	    FcChar8 *s = NULL;
 
-	    if (FcHashTableFind (config->alias_table, d, (void **)&alias))
+	    if (relocated)
 	    {
 		FcChar8 *base = FcStrBasename (dir);
-		dir = s = FcStrBuildFilename (alias, base, NULL);
-		FcStrFree (alias);
+		dir = s = FcStrBuildFilename (forDir, base, NULL);
 		FcStrFree (base);
 	    }
-	    FcStrFree (d);
 	    if (FcConfigAcceptFilename (config, dir))
 		FcStrSetAddFilename (dirSet, dir);
 	    if (s)
@@ -413,7 +426,7 @@ FcConfigAddDirList (FcConfig *config, Fc
 	cache = FcDirCacheRead (dir, FcFalse, config);
 	if (!cache)
 	    continue;
-	FcConfigAddCache (config, cache, set, dirSet);
+	FcConfigAddCache (config, cache, set, dirSet, dir);
 	FcDirCacheUnload (cache);
     }
     FcStrListDone (dirlist);
diff -pruN fontconfig-2.13.0.orig/src/fcint.h fontconfig-2.13.0/src/fcint.h
--- fontconfig-2.13.0.orig/src/fcint.h	2018-02-04 19:20:56.000000000 +0900
+++ fontconfig-2.13.0/src/fcint.h	2018-06-08 18:39:33.080539208 +0900
@@ -566,7 +566,6 @@ struct _FcConfig {
     FcStrSet	*availConfigFiles;  /* config files available */
     FcPtrList	*rulesetList;	    /* List of rulesets being installed */
     FcHashTable *uuid_table;	    /* UUID table for cachedirs */
-    FcHashTable *alias_table;	    /* alias table for cachedirs */
 };
 
 typedef struct _FcFileTime {
@@ -617,9 +616,13 @@ FcCacheObjectReference (void *object);
 FcPrivate void
 FcCacheObjectDereference (void *object);
 
+FcPrivate void *
+FcCacheAllocate (FcCache *cache, size_t len);
+
 FcPrivate void
 FcCacheFini (void);
 
+
 FcPrivate void
 FcDirCacheReference (FcCache *cache, int nref);
 
@@ -708,7 +711,7 @@ FcConfigModifiedTime (FcConfig *config);
 
 FcPrivate FcBool
 FcConfigAddCache (FcConfig *config, FcCache *cache,
-		  FcSetName set, FcStrSet *dirSet);
+		  FcSetName set, FcStrSet *dirSet, FcChar8 *forDir);
 
 FcPrivate FcRuleSet *
 FcRuleSetCreate (const FcChar8 *name);
@@ -1150,6 +1153,9 @@ FcPatternAppend (FcPattern *p, FcPattern
 FcPrivate int
 FcPatternPosition (const FcPattern *p, const char *object);
 
+FcPrivate FcPattern *
+FcPatternCacheRewriteFile (const FcPattern *pat, FcCache *cache, const FcChar8 *relocated_font_file);
+
 FcPrivate FcChar32
 FcStringHash (const FcChar8 *s);
 
diff -pruN fontconfig-2.13.0.orig/src/fclist.c fontconfig-2.13.0/src/fclist.c
--- fontconfig-2.13.0.orig/src/fclist.c	2017-12-05 21:44:22.000000000 +0900
+++ fontconfig-2.13.0/src/fclist.c	2018-06-08 18:39:33.049538728 +0900
@@ -448,41 +448,6 @@ FcListAppend (FcListHashTable	*table,
 	e = FcPatternObjectFindElt (font, FcObjectFromName (os->objects[o]));
 	if (e)
 	{
-	    if (FcRefIsConst (&font->ref) && !strcmp (os->objects[o], FC_FILE))
-	    {
-		FcChar8 *dir, *alias;
-		FcConfig *config = FcConfigGetCurrent (); /* FIXME: this may need to be exported as API? */
-
-		for (v = FcPatternEltValues (e); v->value.type != FcTypeString; v = FcValueListNext (v));
-		if (!v)
-		    goto bail2;
-		dir = FcStrDirname (FcValueString (&v->value));
-		if (FcHashTableFind (config->alias_table, dir, (void **) &alias))
-		{
-		    FcChar8 *base = FcStrBasename (FcValueString (&v->value));
-		    FcChar8 *s = FcStrBuildFilename (alias, base, NULL);
-		    FcValue vv;
-
-		    FcStrFree (alias);
-		    FcStrFree (base);
-		    vv.type = FcTypeString;
-		    vv.u.s = s;
-		    if (!FcPatternAdd (bucket->pattern,
-				       os->objects[o],
-				       FcValueCanonicalize (&vv),
-				       FcTrue))
-		    {
-			FcStrFree (s);
-			FcStrFree (dir);
-			goto bail2;
-		    }
-		    FcStrFree (s);
-		    FcStrFree (dir);
-		    goto bail3;
-		}
-		else
-		    FcStrFree (dir);
-	    }
 	    for (v = FcPatternEltValues(e), idx = 0; v;
 		 v = FcValueListNext(v), ++idx)
 	    {
@@ -491,7 +456,6 @@ FcListAppend (FcListHashTable	*table,
 				   FcValueCanonicalize(&v->value), defidx != idx))
 		    goto bail2;
 	    }
-	  bail3:;
 	}
     }
     *prev = bucket;
diff -pruN fontconfig-2.13.0.orig/src/fcmatch.c fontconfig-2.13.0/src/fcmatch.c
--- fontconfig-2.13.0.orig/src/fcmatch.c	2017-12-23 14:06:22.000000000 +0900
+++ fontconfig-2.13.0/src/fcmatch.c	2018-06-08 18:39:33.050538743 +0900
@@ -682,43 +682,9 @@ FcFontRenderPrepare (FcConfig	    *confi
 	}
 	else
 	{
-	    if (FcRefIsConst (&font->ref) && fe->object == FC_FILE_OBJECT)
-	    {
-		FcValueListPtr l = FcPatternEltValues (fe);
-		FcChar8 *dir, *alias;
-
-		while (l->value.type != FcTypeString)
-		    l = FcValueListNext (l);
-		if (!l)
-		    goto bail0;
-		dir = FcStrDirname (FcValueString (&l->value));
-		if (!config)
-		    config = FcConfigGetCurrent ();
-		if (config && FcHashTableFind (config->alias_table, dir, (void **) &alias))
-		{
-		    FcChar8 *base = FcStrBasename (FcValueString (&l->value));
-		    FcChar8 *s = FcStrBuildFilename (alias, base, NULL);
-		    FcValue v;
-
-		    FcStrFree (alias);
-		    FcStrFree (base);
-		    v.type = FcTypeString;
-		    v.u.s = s;
-		    FcPatternObjectAddWithBinding (new, fe->object,
-						   FcValueCanonicalize (&v),
-						   l->binding,
-						   FcTrue);
-		    FcStrFree (s);
-		    FcStrFree (dir);
-		    goto bail0;
-		}
-		else
-		    FcStrFree (dir);
-	    }
 	    FcPatternObjectListAdd (new, fe->object,
 				    FcValueListDuplicate (FcPatternEltValues (fe)),
 				    FcTrue);
-	  bail0:;
 	}
     }
     for (i = 0; i < pat->num; i++)
diff -pruN fontconfig-2.13.0.orig/src/fcpat.c fontconfig-2.13.0/src/fcpat.c
--- fontconfig-2.13.0.orig/src/fcpat.c	2017-12-20 19:20:15.000000000 +0900
+++ fontconfig-2.13.0/src/fcpat.c	2018-06-08 18:39:33.050538743 +0900
@@ -373,6 +373,71 @@ FcValueListHash (FcValueListPtr l)
     return hash;
 }
 
+static void *
+FcPatternGetCacheObject (FcPattern *p)
+{
+  /* We use a value to find the cache, instead of the FcPattern object
+   * because the pattern itself may be a cache allocation if we rewrote the path,
+   * so the p may not be in the cached region. */
+  return FcPatternEltValues(&FcPatternElts (p)[0]);
+}
+
+FcPattern *
+FcPatternCacheRewriteFile (const FcPattern *p,
+                           FcCache *cache,
+                           const FcChar8 *relocated_font_file)
+{
+    FcPatternElt *elts = FcPatternElts (p);
+    size_t i,j;
+    FcChar8 *data;
+    FcPattern *new_p;
+    FcPatternElt *new_elts;
+    FcValueList *new_value_list;
+    size_t new_path_len = strlen ((char *)relocated_font_file);
+    FcChar8 *new_path;
+
+    /* Allocate space for the patter, the PatternElt headers and
+     * the FC_FILE FcValueList and path that will be freed with the
+     * cache */
+    data = FcCacheAllocate (cache,
+			    sizeof (FcPattern) +
+			    p->num * sizeof (FcPatternElt) +
+			    sizeof (FcValueList) +
+			    new_path_len + 1);
+
+    new_p = (FcPattern *)data;
+    data += sizeof (FcPattern);
+    new_elts = (FcPatternElt *)(data);
+    data += p->num * sizeof (FcPatternElt);
+    new_value_list = (FcValueList *)data;
+    data += sizeof (FcValueList);
+    new_path = data;
+
+    *new_p = *p;
+    new_p->elts_offset = FcPtrToOffset (new_p, new_elts);
+
+    /* Copy all but the FILE values from the cache */
+    for (i = 0, j = 0; i < p->num; i++)
+    {
+	FcPatternElt *elt = &elts[i];
+	new_elts[j].object = elt->object;
+	if (elt->object != FC_FILE_OBJECT)
+	    new_elts[j++].values = FcPatternEltValues(elt);
+	else
+	    new_elts[j++].values = new_value_list;
+    }
+
+    new_value_list->next = NULL;
+    new_value_list->value.type = FcTypeString;
+    new_value_list->value.u.s = new_path;
+    new_value_list->binding = FcValueBindingWeak;
+
+    /* Add rewritten path at the end */
+    strcpy ((char *)new_path, (char *)relocated_font_file);
+
+    return new_p;
+}
+
 void
 FcPatternDestroy (FcPattern *p)
 {
@@ -384,10 +449,10 @@ FcPatternDestroy (FcPattern *p)
 
     if (FcRefIsConst (&p->ref))
     {
-	FcCacheObjectDereference (p);
+	FcCacheObjectDereference (FcPatternGetCacheObject(p));
 	return;
     }
-	
+
     if (FcRefDec (&p->ref) != 1)
 	return;
 
@@ -1155,7 +1220,7 @@ FcPatternReference (FcPattern *p)
     if (!FcRefIsConst (&p->ref))
 	FcRefInc (&p->ref);
     else
-	FcCacheObjectReference (p);
+	FcCacheObjectReference (FcPatternGetCacheObject(p));
 }
 
 FcPattern *
diff -pruN fontconfig-2.13.0.orig/test/run-test.sh fontconfig-2.13.0/test/run-test.sh
--- fontconfig-2.13.0.orig/test/run-test.sh	2017-12-18 21:25:18.000000000 +0900
+++ fontconfig-2.13.0/test/run-test.sh	2018-06-08 18:39:33.031538449 +0900
@@ -202,4 +202,29 @@ fi
 rm -rf $TESTTMPDIR out1 out2 xxx bind-fonts.conf
 fi
 
+dotest "sysroot option"
+prep
+mkdir -p $MyPWD/sysroot/$FONTDIR
+mkdir -p $MyPWD/sysroot/$CACHEDIR
+cp $FONT1 $MyPWD/sysroot/$FONTDIR
+cp $MyPWD/fonts.conf $MyPWD/sysroot/$MyPWD/fonts.conf
+$FCCACHE -y $MyPWD/sysroot
+stat $MyPWD/sysroot/$FONTDIR/.uuid
+if test $? != 0; then
+  echo "*** Test failed: $TEST"
+  exit 1
+fi
+
+dotest "creating uuid-based cache file on sysroot"
+uuid=`cat $MyPWD/sysroot/$FONTDIR/.uuid`
+ls $MyPWD/sysroot/$CACHEDIR/$uuid*
+if [ $? != 0 ]; then
+  echo "*** Test failed: $TEST"
+  echo "No cache for $uuid"
+  ls $MyPWD/sysroot/$CACHEDIR
+  exit 1
+fi
+
+rm -rf $MyPWD/sysroot
+
 rm -rf $FONTDIR $CACHEFILE $CACHEDIR $FONTCONFIG_FILE out