diff options
author | Carsten Haitzler (Rasterman) <raster@rasterman.com> | 2020-06-18 11:03:02 +0100 |
---|---|---|
committer | Carsten Haitzler (Rasterman) <raster@rasterman.com> | 2020-06-18 11:13:52 +0100 |
commit | a5b84c6c6e7fb6b98d561335c1d72926db1f0e40 (patch) | |
tree | 7e3460457dd1368a984dcdadee133a11c717667a /src/bin/efreet | |
parent | cd9059d13ef6ec378f6e7b57b700be6b73850dac (diff) | |
download | efl-a5b84c6c6e7fb6b98d561335c1d72926db1f0e40.tar.gz |
efreetd - cache - add more statinfo work around 0 mtime distros
some distros 9notably in this case nixos) want to do reproducible
builds. to them this means going around setting mtime for all files to
0. this means efreetd not only thinks mtime is invalid/stupid (0 is
generally just that as midnight on jan 1 1970 is not exactly a
sensible dare for a modified timestamp of a file as no filesystem with
any sanity will have not been modified since that time), but it keeps
mtime at 0 even when things update. this totally breaks efreetd that
expects to find mtime increases over time as things change. it's
necessary because it has to perform a "are mu caches up to date" scan
of all file data it caches and it needs to know if it should rebuild
something based on this.
so this does a few things:
1. it makes mtime have to be an exact match to the cache, not cache
mtime >= file mtime. so any change forward or back is an inavlidation.
2. it now also uses ctime, mode, size, uid, gid, block count and if a
symlink, the sha1 of the symlink path in addition and any change to
these == invalid.
this adds a lot of code and changes how dirs get scanned a bit but it
means it can pick up changes on these 0 mtime distros.
interestingly the policy of mtime being 0 is to have a reprodcible fs
... but ctime still changes and is > 0, as does inode info, so it's
not actually possible to have it totally work... but they try still,
so this is a fix for that problem.
whilst i was doing thisi also noticed efreetd re-red dirs many times
due to icon theme inhritance. i also fixed that to do a LOT less
syscalls by only scanning a dir once as i was rejigging the scanning
code at the time anyway. this should optimize thr scan costs at
efreetd startup too.
@fix
@opt
Diffstat (limited to 'src/bin/efreet')
-rw-r--r-- | src/bin/efreet/efreet_icon_cache_create.c | 204 |
1 files changed, 140 insertions, 64 deletions
diff --git a/src/bin/efreet/efreet_icon_cache_create.c b/src/bin/efreet/efreet_icon_cache_create.c index 6810ca684e..6478df4dbd 100644 --- a/src/bin/efreet/efreet_icon_cache_create.c +++ b/src/bin/efreet/efreet_icon_cache_create.c @@ -38,38 +38,36 @@ static Eina_Hash *icon_themes = NULL; static Eina_Bool cache_directory_modified(Eina_Hash *dirs, const char *dir) { - Efreet_Cache_Directory *dcache; - long long time; - - if (!dirs) return EINA_TRUE; - - time = ecore_file_mod_time(dir); - if (!time) - return EINA_FALSE; - dcache = eina_hash_find(dirs, dir); - if (!dcache) - { + Efreet_Cache_Directory *dcache; + Efreet_Cache_Check check; + + if (!dirs) return EINA_TRUE; + if (!efreet_file_cache_fill(dir, &check)) return EINA_FALSE; + dcache = eina_hash_find(dirs, dir); + if (!dcache) + { dcache = malloc(sizeof (Efreet_Cache_Directory)); if (!dcache) return EINA_TRUE; - - dcache->modified_time = time; + dcache->check = check; eina_hash_add(dirs, dir, dcache); - } - else if (dcache->modified_time == time) return EINA_FALSE; - dcache->modified_time = time; - - return EINA_TRUE; + } + else if (efreet_file_cache_check(&check, &dcache->check)) + return EINA_FALSE; + else + dcache->check = check; + return EINA_TRUE; } static Eina_Bool cache_extension_lookup(const char *ext) { - unsigned int i; + unsigned int i; - for (i = 0; i < exts->count; ++i) - if (!strcmp(exts->data[i], ext)) - return EINA_TRUE; - return EINA_FALSE; + for (i = 0; i < exts->count; ++i) + { + if (!strcmp(exts->data[i], ext)) return EINA_TRUE; + } + return EINA_FALSE; } static Eina_Bool @@ -223,6 +221,37 @@ check_fallback_changed(Efreet_Cache_Icon_Theme *theme) return EINA_FALSE; } +typedef struct +{ + char *path; + int name_start; +} Scanned_Entry; + +static Eina_Hash *already_scanned_path = NULL; + +static void +cache_theme_change_verify(Efreet_Cache_Icon_Theme *theme) +{ + Eina_Bool changed = EINA_FALSE; + Eina_List *l; + Efreet_Icon_Theme_Directory *d; + char buf[PATH_MAX], *tdir, *sep; + + tdir = strdup(theme->path); + sep = strrchr(tdir, '/'); + if (sep) *sep = 0; + EINA_LIST_FOREACH(theme->theme.directories, l, d) + { + snprintf(buf, sizeof(buf), "%s/%s", tdir, d->name); + if (cache_directory_modified(theme->dirs, buf)) + { + changed = EINA_TRUE; + } + } + free(tdir); + if (changed) theme->changed = changed; +} + static Eina_Bool cache_scan_path_dir(Efreet_Icon_Theme *theme, const char *path, @@ -232,29 +261,63 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme, Eina_Iterator *it; char buf[PATH_MAX]; Eina_File_Direct_Info *entry; + Eina_List *dirs = NULL; + Eina_List *l; + char *ext; + Scanned_Entry *scentry; snprintf(buf, sizeof(buf), "%s/%s", path, dir->name); + // we wont ever free this - no point + if (!already_scanned_path) + already_scanned_path = eina_hash_string_superfast_new(NULL); + dirs = eina_hash_find(already_scanned_path, buf); + if ((intptr_t)dirs == (intptr_t)(-1L)) return EINA_TRUE; + else if (!dirs) + { + it = eina_file_stat_ls(buf); + if (!it) + { + eina_hash_add(already_scanned_path, buf, (void *)(intptr_t)(-1L)); + return EINA_TRUE; + } + + EINA_ITERATOR_FOREACH(it, entry) + { + if (entry->type == EINA_FILE_DIR) continue; + ext = strrchr(entry->path + entry->name_start, '.'); + if (!ext || !cache_extension_lookup(ext)) continue; + scentry = malloc(sizeof(Scanned_Entry)); + if (!scentry) + { + ERR("Out of memory"); + exit(1); + } + scentry->name_start = entry->name_start; + scentry->path = strdup(entry->path); + if (!scentry->path) + { + ERR("Out of memory"); + exit(1); + } + dirs = eina_list_append(dirs, scentry); + } + eina_iterator_free(it); + if (dirs) + eina_hash_add(already_scanned_path, buf, dirs); + else + eina_hash_add(already_scanned_path, buf, (void *)(intptr_t)(-1L)); + } - it = eina_file_stat_ls(buf); - if (!it) return EINA_TRUE; - - EINA_ITERATOR_FOREACH(it, entry) + EINA_LIST_FOREACH(dirs, l, scentry) { Efreet_Cache_Icon *icon; char *name; - char *ext; const char **tmp; unsigned int i; - if (entry->type == EINA_FILE_DIR) - continue; - - ext = strrchr(entry->path + entry->name_start, '.'); - if (!ext || !cache_extension_lookup(ext)) - continue; - + ext = strrchr(scentry->path + scentry->name_start, '.'); /* icon with known extension */ - name = entry->path + entry->name_start; + name = scentry->path + scentry->name_start; *ext = '\0'; icon = eina_hash_find(icons, name); @@ -284,7 +347,7 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme, /* check if the path already exist */ for (j = 0; j < icon->icons[i]->paths_count; ++j) - if (!strcmp(icon->icons[i]->paths[j], entry->path)) + if (!strcmp(icon->icons[i]->paths[j], scentry->path)) break; if (j != icon->icons[i]->paths_count) @@ -348,12 +411,9 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme, exit(1); } icon->icons[i]->paths = tmp; - icon->icons[i]->paths[icon->icons[i]->paths_count] = eina_stringshare_add(entry->path); + icon->icons[i]->paths[icon->icons[i]->paths_count] = eina_stringshare_add(scentry->path); eina_array_push(strs, icon->icons[i]->paths[icon->icons[i]->paths_count++]); } - - eina_iterator_free(it); - return EINA_TRUE; } @@ -364,7 +424,9 @@ cache_scan_path(Efreet_Icon_Theme *theme, Eina_Hash *icons, const char *path) Efreet_Icon_Theme_Directory *dir; EINA_LIST_FOREACH(theme->directories, l, dir) + { if (!cache_scan_path_dir(theme, path, dir, icons)) return EINA_FALSE; + } return EINA_TRUE; } @@ -511,13 +573,13 @@ icon_theme_index_read(Efreet_Cache_Icon_Theme *theme, const char *path) Efreet_Ini *ini; Efreet_Icon_Theme_Directory *dir; const char *tmp; - long long time; + Efreet_Cache_Check check; if (!theme || !path) return EINA_FALSE; - time = ecore_file_mod_time(path); - if (!time) return EINA_FALSE; - if (theme->path && !strcmp(theme->path, path) && theme->last_cache_check >= time) + if (!efreet_file_cache_fill(path, &check)) return EINA_FALSE; + if (theme->path && !strcmp(theme->path, path) && + efreet_file_cache_check(&check, &(theme->check))) { /* no change */ theme->valid = 1; @@ -528,8 +590,7 @@ icon_theme_index_read(Efreet_Cache_Icon_Theme *theme, const char *path) theme->path = eina_stringshare_add(path); eina_array_push(strs, theme->path); } - if (time > theme->last_cache_check) - theme->last_cache_check = time; + theme->check = check; theme->changed = 1; ini = efreet_ini_new(path); @@ -644,10 +705,10 @@ cache_theme_scan(const char *dir) Efreet_Cache_Icon_Theme *theme; const char *name; const char *path; - long long time; + Efreet_Cache_Check check; + Efreet_Cache_Directory *d; - time = ecore_file_mod_time(entry->path); - if (!time) continue; + if (!efreet_file_cache_fill(entry->path, &check)) continue; if ((entry->type != EINA_FILE_DIR) && (entry->type != EINA_FILE_LNK)) @@ -669,10 +730,26 @@ cache_theme_scan(const char *dir) (void *)theme->theme.name.internal, theme); theme->changed = 1; } - if (time > theme->last_cache_check) - { - theme->last_cache_check = time; + + d = NULL; + if (theme->dirs) + d = eina_hash_find(theme->dirs, entry->path); + if (!d) + { + if (!theme->dirs) + theme->dirs = eina_hash_string_superfast_new(NULL); theme->changed = 1; + d = NEW(Efreet_Cache_Directory, 1); + d->check = check; + eina_hash_add(theme->dirs, entry->path, d); + } + else + { + if (!efreet_file_cache_check(&check, &(d->check))) + { + d->check = check; + theme->changed = 1; + } } /* TODO: We need to handle change in order of included paths */ @@ -732,8 +809,7 @@ icon_theme_free(Efreet_Cache_Icon_Theme *theme) eina_list_free(theme->theme.paths); eina_list_free(theme->theme.inherits); - EINA_LIST_FREE(theme->theme.directories, data) - free(data); + EINA_LIST_FREE(theme->theme.directories, data) free(data); if (theme->dirs) efreet_hash_free(theme->dirs, free); free(theme); } @@ -926,7 +1002,7 @@ main(int argc, char **argv) if (!theme->theme.name.name) continue; #endif INF("scan theme %s", theme->theme.name.name); - + cache_theme_change_verify(theme); theme->changed = check_changed(theme); if (flush) theme->changed = EINA_TRUE; @@ -981,18 +1057,18 @@ main(int argc, char **argv) icons_it = eina_hash_iterator_tuple_new(icons); EINA_ITERATOR_FOREACH(icons_it, tuple) - eet_data_write(icon_ef, icon_edd, tuple->key, tuple->data, 1); + eet_data_write(icon_ef, icon_edd, tuple->key, tuple->data, EET_COMPRESSION_SUPERFAST); eina_iterator_free(icons_it); - INF("theme change: %s %lld", theme->theme.name.internal, theme->last_cache_check); - eet_data_write(theme_ef, theme_edd, theme->theme.name.internal, theme, 1); + INF("theme change: %s %lld", theme->theme.name.internal, theme->check.mtime); + eet_data_write(theme_ef, theme_edd, theme->theme.name.internal, theme, EET_COMPRESSION_SUPERFAST); } eina_hash_free(themes); eina_hash_free(icons); changed = EINA_TRUE; } - eet_data_write(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION, icon_version, 1); + eet_data_write(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION, icon_version, EET_COMPRESSION_SUPERFAST); eet_close(icon_ef); efreet_setowner(efreet_icon_cache_file(theme->theme.name.internal)); free(icon_version); @@ -1064,17 +1140,17 @@ main(int argc, char **argv) icons_it = eina_hash_iterator_tuple_new(icons); EINA_ITERATOR_FOREACH(icons_it, tuple) - eet_data_write(icon_ef, fallback_edd, tuple->key, tuple->data, 1); + eet_data_write(icon_ef, fallback_edd, tuple->key, tuple->data, EET_COMPRESSION_SUPERFAST); eina_iterator_free(icons_it); } eina_hash_free(icons); - eet_data_write(theme_ef, theme_edd, EFREET_CACHE_ICON_FALLBACK, theme, 1); + eet_data_write(theme_ef, theme_edd, EFREET_CACHE_ICON_FALLBACK, theme, EET_COMPRESSION_SUPERFAST); } icon_theme_free(theme); - eet_data_write(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION, icon_version, 1); + eet_data_write(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION, icon_version, EET_COMPRESSION_SUPERFAST); eet_close(icon_ef); efreet_setowner(efreet_icon_cache_file(EFREET_CACHE_ICON_FALLBACK)); free(icon_version); @@ -1082,7 +1158,7 @@ main(int argc, char **argv) eina_hash_free(icon_themes); /* save data */ - eet_data_write(theme_ef, efreet_version_edd(), EFREET_CACHE_VERSION, theme_version, 1); + eet_data_write(theme_ef, efreet_version_edd(), EFREET_CACHE_VERSION, theme_version, EET_COMPRESSION_SUPERFAST); eet_close(theme_ef); theme_ef = NULL; |