diff options
Diffstat (limited to 'fontconfig/src/fcstat.c')
-rw-r--r-- | fontconfig/src/fcstat.c | 56 |
1 files changed, 48 insertions, 8 deletions
diff --git a/fontconfig/src/fcstat.c b/fontconfig/src/fcstat.c index 0c15f8700..fd64d5cb3 100644 --- a/fontconfig/src/fcstat.c +++ b/fontconfig/src/fcstat.c @@ -26,6 +26,7 @@ #include "fcint.h" #include "fcarch.h" #include <dirent.h> +#include <limits.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -159,12 +160,14 @@ Adler32Finish (struct Adler32 *ctx) return ctx->a + (ctx->b << 16); } +#ifdef HAVE_STRUCT_DIRENT_D_TYPE /* dirent.d_type can be relied upon on FAT filesystem */ static FcBool FcDirChecksumScandirFilter(const struct dirent *entry) { return entry->d_type != DT_DIR; } +#endif static int FcDirChecksumScandirSorter(const struct dirent **lhs, const struct dirent **rhs) @@ -177,25 +180,62 @@ FcDirChecksum (const FcChar8 *dir, time_t *checksum) { struct Adler32 ctx; struct dirent **files; - int n; + int n, ret = 0; +#ifndef HAVE_STRUCT_DIRENT_D_TYPE + size_t len = strlen ((const char *)dir); +#endif Adler32Init (&ctx); n = scandir ((const char *)dir, &files, - &FcDirChecksumScandirFilter, - &FcDirChecksumScandirSorter); +#ifdef HAVE_STRUCT_DIRENT_D_TYPE + &FcDirChecksumScandirFilter, +#else + NULL, +#endif + &FcDirChecksumScandirSorter); if (n == -1) - return -1; + return -1; while (n--) { - Adler32Update (&ctx, files[n]->d_name, strlen(files[n]->d_name) + 1); - Adler32Update (&ctx, (char *)&files[n]->d_type, sizeof(files[n]->d_type)); - free(files[n]); + size_t dlen = strlen (files[n]->d_name); + int dtype; + +#ifdef HAVE_STRUCT_DIRENT_D_TYPE + dtype = files[n]->d_type; +#else + struct stat statb; + char f[PATH_MAX + 1]; + + memcpy (f, dir, len); + f[len] = FC_DIR_SEPARATOR; + memcpy (&f[len + 1], files[n]->d_name, dlen); + f[len + 1 + dlen] = 0; + if (lstat (f, &statb) < 0) + { + ret = -1; + goto bail; + } + if (S_ISDIR (statb.st_mode)) + goto bail; + + dtype = statb.st_mode; +#endif + Adler32Update (&ctx, files[n]->d_name, dlen + 1); + Adler32Update (&ctx, (char *)&dtype, sizeof (int)); + +#ifndef HAVE_STRUCT_DIRENT_D_TYPE + bail: +#endif + free (files[n]); } - free(files); + free (files); + if (ret == -1) + return -1; *checksum = Adler32Finish (&ctx); + return 0; } |