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:
Keith Packard 2006-08-27 18:19:39 -07:00
parent d2f786849c
commit db50cbdaf5
4 changed files with 4 additions and 164 deletions

View File

@ -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);
}

View File

@ -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
*/

View File

@ -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)

View File

@ -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)
{
/*