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.
This commit is contained in:
parent
d2f786849c
commit
db50cbdaf5
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
100
src/fccfg.c
100
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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue