Akira TAGOH wrote: > How about creating your tool with FcConfigGetFontDirs()? I don't get why > fc-cache needs to have such options. fc-cache isn't an interface to make > the config readable. Good point. Updated patch attached. :) Best wishes, -- ,''`. : :' : Chris Lamb `. `'` lamby@xxxxxxxxxx / chris-lamb.co.uk `-
From ccc5da9ed364df1334a3ff172d89f852d199955b Mon Sep 17 00:00:00 2001 From: Chris Lamb <chris@xxxxxxxxxxxxxxxx> Date: Sat, 28 Apr 2018 12:21:24 -0700 Subject: [PATCH] Ensure cache checksums are determinstic Whilst working on the Reproducible Builds[0] effort, we noticed that fontconfig generates unreproducible cache files. This is due to fc-cache uses the modification timestamps of each directory in the "checksum" and "checksum_nano" members of the _FcCache struct. This is so that it can identify which cache files are valid and/or require regeneration. This patch changes the behaviour of the checksum calculations to prefer the value of the SOURCE_DATE_EPOCH[1] environment variable over the directory's own mtime. This variable can then be exported by build systems to ensure reproducible output. If SOURCE_DATE_EPOCH is not set or is newer than the mtime of the directory, the existing behaviour is unchanged. This work was sponsored by Tails[2]. [0] https://reproducible-builds.org/ [1] https://reproducible-builds.org/specs/source-date-epoch/ [2] https://tails.boum.org/ --- src/fccache.c | 55 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/src/fccache.c b/src/fccache.c index 7abb750..e74d902 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -989,6 +989,51 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat) return cache; } +static int +FcDirChecksum (struct stat *statb) { + int ret = (int) statb->st_mtime; + char *endptr; + char *source_date_epoch; + unsigned long long epoch; + + source_date_epoch = getenv("SOURCE_DATE_EPOCH"); + if (source_date_epoch) { + epoch = strtoull(source_date_epoch, &endptr, 10); + + if (endptr == source_date_epoch) + fprintf (stderr, + "Fontconfig: SOURCE_DATE_EPOCH invalid\n"); + else if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0)) + || (errno != 0 && epoch == 0)) + fprintf (stderr, + "Fontconfig: SOURCE_DATE_EPOCH: strtoull: %s: %llu\n", + strerror(errno), epoch); + else if (*endptr != '\0') + fprintf (stderr, + "Fontconfig: SOURCE_DATE_EPOCHh has trailing garbage\n"); + else if (epoch > ULONG_MAX) + fprintf (stderr, + "Fontconfig: SOURCE_DATE_EPOCH must be <= %lu but saw: %llu\n", + ULONG_MAX, epoch); + else if (epoch < ret) + /* Only override if directory is newer */ + ret = (int) epoch; + } + + return ret; +} + +static int64_t +FcDirChecksumNano (struct stat *statb) { + /* No nanosecond component to parse */ + if (getenv("SOURCE_DATE_EPOCH")) + return 0; +#ifdef HAVE_STRUCT_STAT_ST_MTIM + return statb->st_mtim.tv_nsec; +#endif + return 0; +} + /* * Validate a cache file by reading the header and checking * the magic number and the size field @@ -1007,10 +1052,10 @@ FcDirCacheValidateHelper (FcConfig *config, int fd, struct stat *fd_stat, struct ret = FcFalse; else if (fd_stat->st_size != c.size) ret = FcFalse; - else if (c.checksum != (int) dir_stat->st_mtime) + else if (c.checksum != FcDirChecksum(dir_stat)) ret = FcFalse; #ifdef HAVE_STRUCT_STAT_ST_MTIM - else if (c.checksum_nano != dir_stat->st_mtim.tv_nsec) + else if (c.checksum_nano != FcDirChecksumNano(dir_stat)) ret = FcFalse; #endif return ret; @@ -1086,10 +1131,8 @@ FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, struct stat *dir_stat, FcSt cache->magic = FC_CACHE_MAGIC_ALLOC; cache->version = FC_CACHE_VERSION_NUMBER; cache->size = serialize->size; - cache->checksum = (int) dir_stat->st_mtime; -#ifdef HAVE_STRUCT_STAT_ST_MTIM - cache->checksum_nano = dir_stat->st_mtim.tv_nsec; -#endif + cache->checksum = FcDirChecksum(dir_stat); + cache->checksum_nano = FcDirChecksumNano(dir_stat); /* * Serialize directory name -- 2.17.0
_______________________________________________ Fontconfig mailing list Fontconfig@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/fontconfig