summaryrefslogtreecommitdiff
path: root/src/bin/efreet/efreet_icon_cache_create.c
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-06-18 11:03:02 +0100
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-06-18 11:13:52 +0100
commita5b84c6c6e7fb6b98d561335c1d72926db1f0e40 (patch)
tree7e3460457dd1368a984dcdadee133a11c717667a /src/bin/efreet/efreet_icon_cache_create.c
parentcd9059d13ef6ec378f6e7b57b700be6b73850dac (diff)
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 '')
-rw-r--r--src/bin/efreet/efreet_icon_cache_create.c204
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;
38static Eina_Bool 38static Eina_Bool
39cache_directory_modified(Eina_Hash *dirs, const char *dir) 39cache_directory_modified(Eina_Hash *dirs, const char *dir)
40{ 40{
41 Efreet_Cache_Directory *dcache; 41 Efreet_Cache_Directory *dcache;
42 long long time; 42 Efreet_Cache_Check check;
43 43
44 if (!dirs) return EINA_TRUE; 44 if (!dirs) return EINA_TRUE;
45 45 if (!efreet_file_cache_fill(dir, &check)) return EINA_FALSE;
46 time = ecore_file_mod_time(dir); 46 dcache = eina_hash_find(dirs, dir);
47 if (!time) 47 if (!dcache)
48 return EINA_FALSE; 48 {
49 dcache = eina_hash_find(dirs, dir);
50 if (!dcache)
51 {
52 dcache = malloc(sizeof (Efreet_Cache_Directory)); 49 dcache = malloc(sizeof (Efreet_Cache_Directory));
53 if (!dcache) return EINA_TRUE; 50 if (!dcache) return EINA_TRUE;
54 51 dcache->check = check;
55 dcache->modified_time = time;
56 eina_hash_add(dirs, dir, dcache); 52 eina_hash_add(dirs, dir, dcache);
57 } 53 }
58 else if (dcache->modified_time == time) return EINA_FALSE; 54 else if (efreet_file_cache_check(&check, &dcache->check))
59 dcache->modified_time = time; 55 return EINA_FALSE;
60 56 else
61 return EINA_TRUE; 57 dcache->check = check;
58 return EINA_TRUE;
62} 59}
63 60
64static Eina_Bool 61static Eina_Bool
65cache_extension_lookup(const char *ext) 62cache_extension_lookup(const char *ext)
66{ 63{
67 unsigned int i; 64 unsigned int i;
68 65
69 for (i = 0; i < exts->count; ++i) 66 for (i = 0; i < exts->count; ++i)
70 if (!strcmp(exts->data[i], ext)) 67 {
71 return EINA_TRUE; 68 if (!strcmp(exts->data[i], ext)) return EINA_TRUE;
72 return EINA_FALSE; 69 }
70 return EINA_FALSE;
73} 71}
74 72
75static Eina_Bool 73static Eina_Bool
@@ -223,6 +221,37 @@ check_fallback_changed(Efreet_Cache_Icon_Theme *theme)
223 return EINA_FALSE; 221 return EINA_FALSE;
224} 222}
225 223
224typedef struct
225{
226 char *path;
227 int name_start;
228} Scanned_Entry;
229
230static Eina_Hash *already_scanned_path = NULL;
231
232static void
233cache_theme_change_verify(Efreet_Cache_Icon_Theme *theme)
234{
235 Eina_Bool changed = EINA_FALSE;
236 Eina_List *l;
237 Efreet_Icon_Theme_Directory *d;
238 char buf[PATH_MAX], *tdir, *sep;
239
240 tdir = strdup(theme->path);
241 sep = strrchr(tdir, '/');
242 if (sep) *sep = 0;
243 EINA_LIST_FOREACH(theme->theme.directories, l, d)
244 {
245 snprintf(buf, sizeof(buf), "%s/%s", tdir, d->name);
246 if (cache_directory_modified(theme->dirs, buf))
247 {
248 changed = EINA_TRUE;
249 }
250 }
251 free(tdir);
252 if (changed) theme->changed = changed;
253}
254
226static Eina_Bool 255static Eina_Bool
227cache_scan_path_dir(Efreet_Icon_Theme *theme, 256cache_scan_path_dir(Efreet_Icon_Theme *theme,
228 const char *path, 257 const char *path,
@@ -232,29 +261,63 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme,
232 Eina_Iterator *it; 261 Eina_Iterator *it;
233 char buf[PATH_MAX]; 262 char buf[PATH_MAX];
234 Eina_File_Direct_Info *entry; 263 Eina_File_Direct_Info *entry;
264 Eina_List *dirs = NULL;
265 Eina_List *l;
266 char *ext;
267 Scanned_Entry *scentry;
235 268
236 snprintf(buf, sizeof(buf), "%s/%s", path, dir->name); 269 snprintf(buf, sizeof(buf), "%s/%s", path, dir->name);
270 // we wont ever free this - no point
271 if (!already_scanned_path)
272 already_scanned_path = eina_hash_string_superfast_new(NULL);
273 dirs = eina_hash_find(already_scanned_path, buf);
274 if ((intptr_t)dirs == (intptr_t)(-1L)) return EINA_TRUE;
275 else if (!dirs)
276 {
277 it = eina_file_stat_ls(buf);
278 if (!it)
279 {
280 eina_hash_add(already_scanned_path, buf, (void *)(intptr_t)(-1L));
281 return EINA_TRUE;
282 }
283
284 EINA_ITERATOR_FOREACH(it, entry)
285 {
286 if (entry->type == EINA_FILE_DIR) continue;
287 ext = strrchr(entry->path + entry->name_start, '.');
288 if (!ext || !cache_extension_lookup(ext)) continue;
289 scentry = malloc(sizeof(Scanned_Entry));
290 if (!scentry)
291 {
292 ERR("Out of memory");
293 exit(1);
294 }
295 scentry->name_start = entry->name_start;
296 scentry->path = strdup(entry->path);
297 if (!scentry->path)
298 {
299 ERR("Out of memory");
300 exit(1);
301 }
302 dirs = eina_list_append(dirs, scentry);
303 }
304 eina_iterator_free(it);
305 if (dirs)
306 eina_hash_add(already_scanned_path, buf, dirs);
307 else
308 eina_hash_add(already_scanned_path, buf, (void *)(intptr_t)(-1L));
309 }
237 310
238 it = eina_file_stat_ls(buf); 311 EINA_LIST_FOREACH(dirs, l, scentry)
239 if (!it) return EINA_TRUE;
240
241 EINA_ITERATOR_FOREACH(it, entry)
242 { 312 {
243 Efreet_Cache_Icon *icon; 313 Efreet_Cache_Icon *icon;
244 char *name; 314 char *name;
245 char *ext;
246 const char **tmp; 315 const char **tmp;
247 unsigned int i; 316 unsigned int i;
248 317
249 if (entry->type == EINA_FILE_DIR) 318 ext = strrchr(scentry->path + scentry->name_start, '.');
250 continue;
251
252 ext = strrchr(entry->path + entry->name_start, '.');
253 if (!ext || !cache_extension_lookup(ext))
254 continue;
255
256 /* icon with known extension */ 319 /* icon with known extension */
257 name = entry->path + entry->name_start; 320 name = scentry->path + scentry->name_start;
258 *ext = '\0'; 321 *ext = '\0';
259 322
260 icon = eina_hash_find(icons, name); 323 icon = eina_hash_find(icons, name);
@@ -284,7 +347,7 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme,
284 347
285 /* check if the path already exist */ 348 /* check if the path already exist */
286 for (j = 0; j < icon->icons[i]->paths_count; ++j) 349 for (j = 0; j < icon->icons[i]->paths_count; ++j)
287 if (!strcmp(icon->icons[i]->paths[j], entry->path)) 350 if (!strcmp(icon->icons[i]->paths[j], scentry->path))
288 break; 351 break;
289 352
290 if (j != icon->icons[i]->paths_count) 353 if (j != icon->icons[i]->paths_count)
@@ -348,12 +411,9 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme,
348 exit(1); 411 exit(1);
349 } 412 }
350 icon->icons[i]->paths = tmp; 413 icon->icons[i]->paths = tmp;
351 icon->icons[i]->paths[icon->icons[i]->paths_count] = eina_stringshare_add(entry->path); 414 icon->icons[i]->paths[icon->icons[i]->paths_count] = eina_stringshare_add(scentry->path);
352 eina_array_push(strs, icon->icons[i]->paths[icon->icons[i]->paths_count++]); 415 eina_array_push(strs, icon->icons[i]->paths[icon->icons[i]->paths_count++]);
353 } 416 }
354
355 eina_iterator_free(it);
356
357 return EINA_TRUE; 417 return EINA_TRUE;
358} 418}
359 419
@@ -364,7 +424,9 @@ cache_scan_path(Efreet_Icon_Theme *theme, Eina_Hash *icons, const char *path)
364 Efreet_Icon_Theme_Directory *dir; 424 Efreet_Icon_Theme_Directory *dir;
365 425
366 EINA_LIST_FOREACH(theme->directories, l, dir) 426 EINA_LIST_FOREACH(theme->directories, l, dir)
427 {
367 if (!cache_scan_path_dir(theme, path, dir, icons)) return EINA_FALSE; 428 if (!cache_scan_path_dir(theme, path, dir, icons)) return EINA_FALSE;
429 }
368 430
369 return EINA_TRUE; 431 return EINA_TRUE;
370} 432}
@@ -511,13 +573,13 @@ icon_theme_index_read(Efreet_Cache_Icon_Theme *theme, const char *path)
511 Efreet_Ini *ini; 573 Efreet_Ini *ini;
512 Efreet_Icon_Theme_Directory *dir; 574 Efreet_Icon_Theme_Directory *dir;
513 const char *tmp; 575 const char *tmp;
514 long long time; 576 Efreet_Cache_Check check;
515 577
516 if (!theme || !path) return EINA_FALSE; 578 if (!theme || !path) return EINA_FALSE;
517 579
518 time = ecore_file_mod_time(path); 580 if (!efreet_file_cache_fill(path, &check)) return EINA_FALSE;
519 if (!time) return EINA_FALSE; 581 if (theme->path && !strcmp(theme->path, path) &&
520 if (theme->path && !strcmp(theme->path, path) && theme->last_cache_check >= time) 582 efreet_file_cache_check(&check, &(theme->check)))
521 { 583 {
522 /* no change */ 584 /* no change */
523 theme->valid = 1; 585 theme->valid = 1;
@@ -528,8 +590,7 @@ icon_theme_index_read(Efreet_Cache_Icon_Theme *theme, const char *path)
528 theme->path = eina_stringshare_add(path); 590 theme->path = eina_stringshare_add(path);
529 eina_array_push(strs, theme->path); 591 eina_array_push(strs, theme->path);
530 } 592 }
531 if (time > theme->last_cache_check) 593 theme->check = check;
532 theme->last_cache_check = time;
533 theme->changed = 1; 594 theme->changed = 1;
534 595
535 ini = efreet_ini_new(path); 596 ini = efreet_ini_new(path);
@@ -644,10 +705,10 @@ cache_theme_scan(const char *dir)
644 Efreet_Cache_Icon_Theme *theme; 705 Efreet_Cache_Icon_Theme *theme;
645 const char *name; 706 const char *name;
646 const char *path; 707 const char *path;
647 long long time; 708 Efreet_Cache_Check check;
709 Efreet_Cache_Directory *d;
648 710
649 time = ecore_file_mod_time(entry->path); 711 if (!efreet_file_cache_fill(entry->path, &check)) continue;
650 if (!time) continue;
651 712
652 if ((entry->type != EINA_FILE_DIR) && 713 if ((entry->type != EINA_FILE_DIR) &&
653 (entry->type != EINA_FILE_LNK)) 714 (entry->type != EINA_FILE_LNK))
@@ -669,10 +730,26 @@ cache_theme_scan(const char *dir)
669 (void *)theme->theme.name.internal, theme); 730 (void *)theme->theme.name.internal, theme);
670 theme->changed = 1; 731 theme->changed = 1;
671 } 732 }
672 if (time > theme->last_cache_check) 733
673 { 734 d = NULL;
674 theme->last_cache_check = time; 735 if (theme->dirs)
736 d = eina_hash_find(theme->dirs, entry->path);
737 if (!d)
738 {
739 if (!theme->dirs)
740 theme->dirs = eina_hash_string_superfast_new(NULL);
675 theme->changed = 1; 741 theme->changed = 1;
742 d = NEW(Efreet_Cache_Directory, 1);
743 d->check = check;
744 eina_hash_add(theme->dirs, entry->path, d);
745 }
746 else
747 {
748 if (!efreet_file_cache_check(&check, &(d->check)))
749 {
750 d->check = check;
751 theme->changed = 1;
752 }
676 } 753 }
677 754
678 /* TODO: We need to handle change in order of included paths */ 755 /* TODO: We need to handle change in order of included paths */
@@ -732,8 +809,7 @@ icon_theme_free(Efreet_Cache_Icon_Theme *theme)
732 809
733 eina_list_free(theme->theme.paths); 810 eina_list_free(theme->theme.paths);
734 eina_list_free(theme->theme.inherits); 811 eina_list_free(theme->theme.inherits);
735 EINA_LIST_FREE(theme->theme.directories, data) 812 EINA_LIST_FREE(theme->theme.directories, data) free(data);
736 free(data);
737 if (theme->dirs) efreet_hash_free(theme->dirs, free); 813 if (theme->dirs) efreet_hash_free(theme->dirs, free);
738 free(theme); 814 free(theme);
739} 815}
@@ -926,7 +1002,7 @@ main(int argc, char **argv)
926 if (!theme->theme.name.name) continue; 1002 if (!theme->theme.name.name) continue;
927#endif 1003#endif
928 INF("scan theme %s", theme->theme.name.name); 1004 INF("scan theme %s", theme->theme.name.name);
929 1005 cache_theme_change_verify(theme);
930 theme->changed = check_changed(theme); 1006 theme->changed = check_changed(theme);
931 if (flush) 1007 if (flush)
932 theme->changed = EINA_TRUE; 1008 theme->changed = EINA_TRUE;
@@ -981,18 +1057,18 @@ main(int argc, char **argv)
981 1057
982 icons_it = eina_hash_iterator_tuple_new(icons); 1058 icons_it = eina_hash_iterator_tuple_new(icons);
983 EINA_ITERATOR_FOREACH(icons_it, tuple) 1059 EINA_ITERATOR_FOREACH(icons_it, tuple)
984 eet_data_write(icon_ef, icon_edd, tuple->key, tuple->data, 1); 1060 eet_data_write(icon_ef, icon_edd, tuple->key, tuple->data, EET_COMPRESSION_SUPERFAST);
985 eina_iterator_free(icons_it); 1061 eina_iterator_free(icons_it);
986 1062
987 INF("theme change: %s %lld", theme->theme.name.internal, theme->last_cache_check); 1063 INF("theme change: %s %lld", theme->theme.name.internal, theme->check.mtime);
988 eet_data_write(theme_ef, theme_edd, theme->theme.name.internal, theme, 1); 1064 eet_data_write(theme_ef, theme_edd, theme->theme.name.internal, theme, EET_COMPRESSION_SUPERFAST);
989 } 1065 }
990 eina_hash_free(themes); 1066 eina_hash_free(themes);
991 eina_hash_free(icons); 1067 eina_hash_free(icons);
992 changed = EINA_TRUE; 1068 changed = EINA_TRUE;
993 } 1069 }
994 1070
995 eet_data_write(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION, icon_version, 1); 1071 eet_data_write(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION, icon_version, EET_COMPRESSION_SUPERFAST);
996 eet_close(icon_ef); 1072 eet_close(icon_ef);
997 efreet_setowner(efreet_icon_cache_file(theme->theme.name.internal)); 1073 efreet_setowner(efreet_icon_cache_file(theme->theme.name.internal));
998 free(icon_version); 1074 free(icon_version);
@@ -1064,17 +1140,17 @@ main(int argc, char **argv)
1064 1140
1065 icons_it = eina_hash_iterator_tuple_new(icons); 1141 icons_it = eina_hash_iterator_tuple_new(icons);
1066 EINA_ITERATOR_FOREACH(icons_it, tuple) 1142 EINA_ITERATOR_FOREACH(icons_it, tuple)
1067 eet_data_write(icon_ef, fallback_edd, tuple->key, tuple->data, 1); 1143 eet_data_write(icon_ef, fallback_edd, tuple->key, tuple->data, EET_COMPRESSION_SUPERFAST);
1068 eina_iterator_free(icons_it); 1144 eina_iterator_free(icons_it);
1069 } 1145 }
1070 eina_hash_free(icons); 1146 eina_hash_free(icons);
1071 1147
1072 eet_data_write(theme_ef, theme_edd, EFREET_CACHE_ICON_FALLBACK, theme, 1); 1148 eet_data_write(theme_ef, theme_edd, EFREET_CACHE_ICON_FALLBACK, theme, EET_COMPRESSION_SUPERFAST);
1073 } 1149 }
1074 1150
1075 icon_theme_free(theme); 1151 icon_theme_free(theme);
1076 1152
1077 eet_data_write(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION, icon_version, 1); 1153 eet_data_write(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION, icon_version, EET_COMPRESSION_SUPERFAST);
1078 eet_close(icon_ef); 1154 eet_close(icon_ef);
1079 efreet_setowner(efreet_icon_cache_file(EFREET_CACHE_ICON_FALLBACK)); 1155 efreet_setowner(efreet_icon_cache_file(EFREET_CACHE_ICON_FALLBACK));
1080 free(icon_version); 1156 free(icon_version);
@@ -1082,7 +1158,7 @@ main(int argc, char **argv)
1082 eina_hash_free(icon_themes); 1158 eina_hash_free(icon_themes);
1083 1159
1084 /* save data */ 1160 /* save data */
1085 eet_data_write(theme_ef, efreet_version_edd(), EFREET_CACHE_VERSION, theme_version, 1); 1161 eet_data_write(theme_ef, efreet_version_edd(), EFREET_CACHE_VERSION, theme_version, EET_COMPRESSION_SUPERFAST);
1086 1162
1087 eet_close(theme_ef); 1163 eet_close(theme_ef);
1088 theme_ef = NULL; 1164 theme_ef = NULL;