* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
#include "fcint.h"
#include "fcarch.h"
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/types.h>
-#include <time.h>
+#include <sys/stat.h>
#include <assert.h>
#if defined(HAVE_MMAP) || defined(__CYGWIN__)
# include <unistd.h>
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);
*/
static FcBool
FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
- FcBool (*callback) (int fd, struct stat *fd_stat,
+ FcBool (*callback) (FcConfig *config, int fd, struct stat *fd_stat,
struct stat *dir_stat, void *closure),
void *closure, FcChar8 **cache_file_ret)
{
int fd = -1;
FcChar8 cache_base[CACHEBASE_LEN];
FcStrList *list;
- FcChar8 *cache_dir;
+ FcChar8 *cache_dir, *d;
struct stat file_stat, dir_stat;
FcBool ret = FcFalse;
+ const FcChar8 *sysroot = FcConfigGetSysRoot (config);
- if (FcStatChecksum (dir, &dir_stat) < 0)
+ if (sysroot)
+ d = FcStrBuildFilename (sysroot, dir, NULL);
+ else
+ d = FcStrdup (dir);
+ if (FcStatChecksum (d, &dir_stat) < 0)
+ {
+ FcStrFree (d);
return FcFalse;
+ }
+ FcStrFree (d);
FcDirCacheBasename (dir, cache_base);
while ((cache_dir = FcStrListNext (list)))
{
- FcChar8 *cache_hashed = FcStrPlus (cache_dir, cache_base);
+ 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);
if (fd >= 0) {
- ret = (*callback) (fd, &file_stat, &dir_stat, closure);
+ ret = (*callback) (config, fd, &file_stat, &dir_stat, closure);
close (fd);
if (ret)
{
static int fcCacheMaxLevel;
-static int32_t
-FcRandom(void)
-{
- int32_t result;
-
-#if HAVE_RANDOM_R
- static struct random_data fcrandbuf;
- static char statebuf[256];
- static FcBool initialized = FcFalse;
-
- if (initialized != FcTrue)
- {
- initstate_r(time(NULL), statebuf, 256, &fcrandbuf);
- initialized = FcTrue;
- }
-
- random_r(&fcrandbuf, &result);
-#elif HAVE_RANDOM
- static char statebuf[256];
- char *state;
- static FcBool initialized = FcFalse;
-
- if (initialized != FcTrue)
- {
- state = initstate(time(NULL), statebuf, 256);
- initialized = FcTrue;
- }
- else
- state = setstate(statebuf);
-
- result = random();
-
- setstate(state);
-#elif HAVE_LRAND48
- result = lrand48();
-#elif HAVE_RAND_R
- static unsigned int seed = time(NULL);
-
- result = rand_r(&seed);
-#elif HAVE_RAND
- static FcBool initialized = FcFalse;
-
- if (initialized != FcTrue)
- {
- srand(time(NULL));
- initialized = FcTrue;
- }
- result = rand();
-#else
-# error no random number generator function available.
-#endif
-
- return result;
-}
-
-
static FcMutex *cache_lock;
static void
FcCacheSkip **next = fcCacheChains;
FcCacheSkip *s;
+ if (!object)
+ return NULL;
+
/*
* Walk chain pointers one level at a time
*/
skip = FcCacheFindByAddrUnlocked (object);
if (skip)
{
- if (FcRefDec (&skip->ref) <= 1)
+ if (FcRefDec (&skip->ref) == 1)
FcDirCacheDisposeUnlocked (skip->cache);
}
unlock_cache ();
}
static FcBool
-FcCacheTimeValid (FcCache *cache, struct stat *dir_stat)
+FcCacheTimeValid (FcConfig *config, FcCache *cache, struct stat *dir_stat)
{
struct stat dir_static;
if (!dir_stat)
{
- if (FcStatChecksum (FcCacheDir (cache), &dir_static) < 0)
+ const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+ FcChar8 *d;
+
+ if (sysroot)
+ d = FcStrBuildFilename (sysroot, FcCacheDir (cache), NULL);
+ else
+ d = FcStrdup (FcCacheDir (cache));
+ if (FcStatChecksum (d, &dir_static) < 0)
+ {
+ FcStrFree (d);
return FcFalse;
+ }
+ FcStrFree (d);
dir_stat = &dir_static;
}
if (FcDebug () & FC_DBG_CACHE)
return cache->checksum == (int) dir_stat->st_mtime;
}
+static FcBool
+FcCacheDirsValid (FcConfig *config, FcCache *cache)
+{
+ FcStrSet *dirs = FcStrSetCreate ();
+ FcBool ret = FcFalse;
+ const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+ FcChar8 *d;
+
+ if (!dirs)
+ goto bail;
+ if (sysroot)
+ d = FcStrBuildFilename (sysroot, FcCacheDir (cache), NULL);
+ else
+ d = FcStrdup (FcCacheDir (cache));
+ if (!FcDirScanOnly (dirs, d, config))
+ goto bail1;
+ ret = cache->dirs_count == dirs->num;
+ if (FcDebug () & FC_DBG_CACHE)
+ printf ("%s: cache: %d, fs: %d\n", d, cache->dirs_count, dirs->num);
+
+bail1:
+ FcStrSetDestroy (dirs);
+ FcStrFree (d);
+bail:
+ return ret;
+}
+
/*
* Map a cache file into memory
*/
static FcCache *
-FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat)
+FcDirCacheMapFd (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat)
{
FcCache *cache;
FcBool allocated = FcFalse;
cache = FcCacheFindByStat (fd_stat);
if (cache)
{
- if (FcCacheTimeValid (cache, dir_stat))
+ if (FcCacheTimeValid (config, cache, dir_stat) &&
+ FcCacheDirsValid (config, cache))
return cache;
FcDirCacheUnload (cache);
cache = NULL;
{
#if defined(HAVE_MMAP) || defined(__CYGWIN__)
cache = mmap (0, fd_stat->st_size, PROT_READ, MAP_SHARED, fd, 0);
-#ifdef HAVE_POSIX_FADVISE
+#if (HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
posix_fadvise (fd, 0, fd_stat->st_size, POSIX_FADV_WILLNEED);
#endif
if (cache == MAP_FAILED)
if (cache->magic != FC_CACHE_MAGIC_MMAP ||
cache->version < FC_CACHE_CONTENT_VERSION ||
cache->size != (intptr_t) fd_stat->st_size ||
- !FcCacheTimeValid (cache, dir_stat) ||
+ !FcCacheTimeValid (config, cache, dir_stat) ||
+ !FcCacheDirsValid (config, cache) ||
!FcCacheInsert (cache, fd_stat))
{
if (allocated)
}
static FcBool
-FcDirCacheMapHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
+FcDirCacheMapHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
{
- FcCache *cache = FcDirCacheMapFd (fd, fd_stat, dir_stat);
+ FcCache *cache = FcDirCacheMapFd (config, fd, fd_stat, dir_stat);
if (!cache)
return FcFalse;
FcDirCacheMapHelper,
&cache, cache_file))
return NULL;
+
return cache;
}
fd = FcDirCacheOpenFile (cache_file, file_stat);
if (fd < 0)
return NULL;
- cache = FcDirCacheMapFd (fd, file_stat, NULL);
+ cache = FcDirCacheMapFd (FcConfigGetCurrent (), fd, file_stat, NULL);
close (fd);
return cache;
}
* the magic number and the size field
*/
static FcBool
-FcDirCacheValidateHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure FC_UNUSED)
+FcDirCacheValidateHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure FC_UNUSED)
{
FcBool ret = FcTrue;
FcCache c;
return NULL;
}
-
-#ifdef _WIN32
-#include <direct.h>
-#define mkdir(path,mode) _mkdir(path)
-#endif
-
-static FcBool
-FcMakeDirectory (const FcChar8 *dir)
+FcCache *
+FcDirCacheRebuild (FcCache *cache, struct stat *dir_stat, FcStrSet *dirs)
{
- FcChar8 *parent;
- FcBool ret;
+ FcCache *new;
+ FcFontSet *set = FcFontSetDeserialize (FcCacheSet (cache));
+ const FcChar8 *dir = FcCacheDir (cache);
- if (strlen ((char *) dir) == 0)
- return FcFalse;
+ new = FcDirCacheBuild (set, dir, dir_stat, dirs);
+ FcFontSetDestroy (set);
- parent = FcStrDirname (dir);
- if (!parent)
- return FcFalse;
- if (access ((char *) parent, F_OK) == 0)
- ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0;
- else if (access ((char *) parent, F_OK) == -1)
- ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0;
- else
- ret = FcFalse;
- FcStrFree (parent);
- return ret;
+ return new;
}
/* write serialized state to the cache file */
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
{
+ FcChar8 *s;
+
target_dir = FcCacheDir (cache);
- if (stat ((char *) target_dir, &target_stat) < 0)
+ if (sysroot)
+ s = FcStrBuildFilename (sysroot, target_dir, NULL);
+ else
+ s = FcStrdup (target_dir);
+ if (stat ((char *) s, &target_stat) < 0)
{
if (verbose || FcDebug () & FC_DBG_CACHE)
printf ("%s: %s: missing directory: %s \n",
- cache_dir, ent->d_name, target_dir);
+ dir, ent->d_name, s);
remove = FcTrue;
}
+ FcDirCacheUnload (cache);
+ FcStrFree (s);
}
if (remove)
{
ret = FcFalse;
}
}
- FcDirCacheUnload (cache);
FcStrFree (file_name);
}
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);
}