From db50cbdaf592349c204ab0af0e7061ea72237044 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Aug 2006 18:19:39 -0700 Subject: [PATCH] Eliminate NormalizeDir. Eliminate gratuitous stat/access calls per dir. Normalized directory names offer protection against looped directory trees but cost enormous numbers of system calls (stat per file in the hierarchy). Also, cache file directory name contents are validated each time the directory is modified, don't re-validate every time the cache file is loaded with an access and stat call. --- fc-cache/fc-cache.c | 7 +--- src/fccache.c | 55 +----------------------- src/fccfg.c | 100 -------------------------------------------- src/fcdir.c | 6 --- 4 files changed, 4 insertions(+), 164 deletions(-) diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c index 8519388..29974b2 100644 --- a/fc-cache/fc-cache.c +++ b/fc-cache/fc-cache.c @@ -126,7 +126,6 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool { int ret = 0; const FcChar8 *dir; - const FcChar8 *dir_orig; FcFontSet *set; FcStrSet *subdirs; FcStrList *sublist; @@ -136,13 +135,11 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool * Now scan all of the directories into separate databases * and write out the results */ - while ((dir_orig = FcStrListNext (list))) + while ((dir = FcStrListNext (list))) { - dir = FcConfigNormalizeFontDir (config, dir_orig); - if (verbose) { - printf ("%s: \"%s\": ", program, dir ? dir : dir_orig); + printf ("%s: \"%s\": ", program, dir); fflush (stdout); } diff --git a/src/fccache.c b/src/fccache.c index fd546bd..135cd29 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -319,10 +319,6 @@ FcGlobalCacheReadDir (FcFontSet *set, FcStrSet *dirs, FcGlobalCache * cache, con if (cache->fd == -1) return FcFalse; - if (config) - if (!(dir = (char *)FcConfigNormalizeFontDir (config, (FcChar8 *)dir))) - return FcFalse; /* non-existing directory */ - for (d = cache->dirs; d; d = d->next) { if (strcmp (d->name, dir) == 0) @@ -366,20 +362,12 @@ FcGlobalCacheDirFind (FcGlobalCache *cache, const char *name) FcBool FcGlobalCacheUpdate (FcGlobalCache *cache, FcStrSet *dirs, - const char *orig_name, + const char *name, FcFontSet *set, FcConfig *config) { FcGlobalCacheDir *d; int i; - const char *name; - - name = (char *)FcConfigNormalizeFontDir (config, (FcChar8 *)orig_name); - if (!name) - { - fprintf(stderr, "Invalid directory name %s\n", orig_name); - return FcFalse; - } d = FcGlobalCacheDirFind (cache, name); @@ -511,7 +499,7 @@ FcGlobalCacheSave (FcGlobalCache *cache, if (!dir->name || dir->state == FcGCDirDisabled) continue; - d = (const char *)FcConfigNormalizeFontDir (config, (const FcChar8 *)dir->name); + d = dir->name; if (!d) continue; @@ -846,8 +834,6 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config) FcChar8 *cache_dir; char dir_buf[FC_MAX_FILE_LEN]; - dir = FcConfigNormalizeFontDir (config, dir); - FcDirCacheBasename (dir, cache_base); list = FcStrListCreate (config->cacheDirs); @@ -888,7 +874,6 @@ FcCacheReadDirs (FcConfig * config, FcGlobalCache * cache, FcChar8 *dir; FcStrSet *subdirs; FcStrList *sublist; - struct stat statb; FcGlobalCacheDir *d; /* @@ -903,9 +888,6 @@ FcCacheReadDirs (FcConfig * config, FcGlobalCache * cache, * to avoid the looped directories via symlinks * Clearly a dir not in fonts.conf shouldn't be globally cached. */ - dir = (FcChar8 *)FcConfigNormalizeFontDir (config, dir); - if (!dir) - continue; if (FcStrSetMember (processed_dirs, dir)) continue; @@ -920,35 +902,6 @@ FcCacheReadDirs (FcConfig * config, FcGlobalCache * cache, continue; } - if (access ((char *) dir, X_OK) < 0) - { - switch (errno) { - case ENOENT: - case ENOTDIR: - case EACCES: - break; - default: - fprintf (stderr, "\"%s\": ", dir); - perror (""); - ret++; - } - FcStrSetDestroy (subdirs); - continue; - } - if (stat ((char *) dir, &statb) == -1) - { - fprintf (stderr, "\"%s\": ", dir); - perror (""); - FcStrSetDestroy (subdirs); - ret++; - continue; - } - if (!S_ISDIR (statb.st_mode)) - { - fprintf (stderr, "\"%s\": not a directory, skipping\n", dir); - FcStrSetDestroy (subdirs); - continue; - } if (FcDirCacheRead (set, subdirs, dir, config)) { /* if an old entry is found in the global cache, disable it */ @@ -1292,10 +1245,6 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *c FcChar8 *cache_dir = NULL; FcChar8 *test_dir; - dir = FcConfigNormalizeFontDir (FcConfigGetCurrent(), dir); - if (!dir) - return FcFalse; - /* * Write it to the first directory in the list which is writable */ diff --git a/src/fccfg.c b/src/fccfg.c index 8eb82e5..3c3681a 100644 --- a/src/fccfg.c +++ b/src/fccfg.c @@ -392,113 +392,13 @@ FcConfigGetConfigDirs (FcConfig *config) return FcStrListCreate (config->configDirs); } -static FcChar8 * -FcConfigInodeMatchFontDir (FcConfig *config, const FcChar8 *d) -{ - int n; - ino_t di; - dev_t dd; - struct stat s; - - /* first we do string matches rather than file accesses */ - /* FcStrSetMember doesn't tell us the index so that we can return - * the config-owned copy. */ - for (n = 0; n < config->fontDirs->num; n++) - { - if (!FcStrCmp (config->fontDirs->strs[n], d)) - return config->fontDirs->strs[n]; - } - - /* If this is a bottleneck, we can cache the fontDir inodes. */ - if (stat ((char *)d, &s) == -1) - return 0; - di = s.st_ino; dd = s.st_dev; - - for (n = 0; n < config->fontDirs->num; n++) - { - if (stat ((char *)config->fontDirs->strs[n], &s) == -1) - continue; - if (di == s.st_ino && dd == s.st_dev) - return config->fontDirs->strs[n]; - } - return 0; -} - FcBool FcConfigAddFontDir (FcConfig *config, const FcChar8 *d) { - /* Avoid adding d if it's an alias of something else, too. */ - if (FcConfigInodeMatchFontDir(config, d)) - return FcTrue; return FcStrSetAddFilename (config->fontDirs, d); } -static FcBool -FcConfigAddFontDirSubdirs (FcConfig *config, - const FcChar8 *d) -{ - DIR *dir; - struct dirent *e; - FcChar8 *subdir; - FcBool added = FcFalse; - - if (!(dir = opendir ((char *) d))) - return FcFalse; - if (!(subdir = (FcChar8 *) malloc (strlen ((char *) d) + FC_MAX_FILE_LEN + 2))) - { - fprintf (stderr, "out of memory"); - return FcFalse; - } - while ((e = readdir (dir))) - { - if (strcmp (e->d_name, ".") && strcmp (e->d_name, "..") && - strlen (e->d_name) < FC_MAX_FILE_LEN) - { - strcpy ((char *)subdir, (char *)d); - strcat ((char *)subdir, "/"); - strcat ((char *)subdir, e->d_name); - if (FcFileIsDir (subdir)) - { - if (FcConfigInodeMatchFontDir(config, subdir)) - continue; /* already added */ - FcStrSetAddFilename (config->fontDirs, subdir); - FcConfigAddFontDirSubdirs (config, subdir); - added = FcTrue; - } - } - } - free (subdir); - closedir (dir); - return added; -} - -const FcChar8 * -FcConfigNormalizeFontDir (FcConfig *config, - const FcChar8 *d) -{ - FcChar8 *d0; - int n, n0; - FcBool added = FcFalse; - - d0 = FcConfigInodeMatchFontDir(config, d); - if (d0) - return d0; - - /* Ok, we didn't find it in fontDirs; let's add subdirs.... */ - for (n = 0, n0 = config->fontDirs->num; n < n0; n++) - { - if (FcConfigAddFontDirSubdirs (config, config->fontDirs->strs[n])) - added = FcTrue; - } - - /* ... and try again. */ - if (added) - return FcConfigInodeMatchFontDir(config, d); - - return 0; -} - FcBool FcConfigAddDir (FcConfig *config, const FcChar8 *d) diff --git a/src/fcdir.c b/src/fcdir.c index 1545955..1452260 100644 --- a/src/fcdir.c +++ b/src/fcdir.c @@ -129,7 +129,6 @@ FcDirScanConfig (FcFontSet *set, FcChar8 **dirlist; int dirlistlen, dirlistalloc; FcChar8 *file; - const FcChar8 *d_can = 0; FcChar8 *base; FcBool ret = FcTrue; FcFontSet *tmpSet; @@ -138,11 +137,6 @@ FcDirScanConfig (FcFontSet *set, if (config && !FcConfigAcceptFilename (config, dir)) return FcTrue; - if (config) - d_can = FcConfigNormalizeFontDir (config, dir); - if (d_can) - dir = d_can; - if (!force) { /* -- 2.39.5