summaryrefslogtreecommitdiff
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
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
-rw-r--r--src/bin/efreet/efreet_icon_cache_create.c204
-rw-r--r--src/lib/efreet/efreet_cache.c166
-rw-r--r--src/lib/efreet/efreet_cache_private.h28
3 files changed, 326 insertions, 72 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;
diff --git a/src/lib/efreet/efreet_cache.c b/src/lib/efreet/efreet_cache.c
index f859c630f0..2b5d0c9f5f 100644
--- a/src/lib/efreet/efreet_cache.c
+++ b/src/lib/efreet/efreet_cache.c
@@ -1,3 +1,4 @@
1
1#ifdef HAVE_CONFIG_H 2#ifdef HAVE_CONFIG_H
2# include <config.h> 3# include <config.h>
3#endif 4#endif
@@ -536,6 +537,137 @@ efreet_desktop_util_cache_file(void)
536/* 537/*
537 * Needs EAPI because of helper binaries 538 * Needs EAPI because of helper binaries
538 */ 539 */
540#define SHSH(n, v) ((((v) << (n)) & 0xffffffff) | ((v) >> (32 - (n))))
541
542static inline int
543int_to_bigendian(int in)
544{
545 static const unsigned char test[4] = { 0x11, 0x22, 0x33, 0x44 };
546 static const unsigned int *test_i = (const unsigned int *)test;
547 if (test_i[0] == 0x44332211) return eina_swap32(in);
548 return in;
549}
550
551static void
552sha1(unsigned char *data, int size, unsigned char *dst)
553{
554 unsigned int digest[5], word[80], wa, wb, wc, wd, we, t;
555 unsigned char buf[64], *d;
556 int idx, left, i;
557 const unsigned int magic[4] =
558 { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 };
559
560 idx = 0;
561 digest[0] = 0x67452301; digest[1] = 0xefcdab89; digest[2] = 0x98badcfe;
562 digest[3] = 0x10325476; digest[4] = 0xc3d2e1f0;
563
564 memset(buf, 0, sizeof(buf));
565 for (left = size, d = data; left > 0; left--, d++)
566 {
567 if ((idx == 0) && (left < 64))
568 {
569 memset(buf, 0, 60);
570 buf[60] = (size >> 24) & 0xff;
571 buf[61] = (size >> 16) & 0xff;
572 buf[62] = (size >> 8) & 0xff;
573 buf[63] = (size) & 0xff;
574 }
575 buf[idx] = *d;
576 idx++;
577 if ((idx == 64) || (left == 1))
578 {
579 if ((left == 1) && (idx < 64)) buf[idx] = 0x80;
580 for (i = 0; i < 16; i++)
581 {
582 word[i] = (unsigned int)buf[(i * 4) ] << 24;
583 word[i] |= (unsigned int)buf[(i * 4) + 1] << 16;
584 word[i] |= (unsigned int)buf[(i * 4) + 2] << 8;
585 word[i] |= (unsigned int)buf[(i * 4) + 3];
586 }
587 for (i = 16; i < 80; i++)
588 word[i] = SHSH(1,
589 word[i - 3 ] ^ word[i - 8 ] ^
590 word[i - 14] ^ word[i - 16]);
591 wa = digest[0]; wb = digest[1]; wc = digest[2];
592 wd = digest[3]; we = digest[4];
593 for (i = 0; i < 80; i++)
594 {
595 if (i < 20)
596 t = SHSH(5, wa) + ((wb & wc) | ((~wb) & wd)) +
597 we + word[i] + magic[0];
598 else if (i < 40)
599 t = SHSH(5, wa) + (wb ^ wc ^ wd) +
600 we + word[i] + magic[1];
601 else if (i < 60)
602 t = SHSH(5, wa) + ((wb & wc) | (wb & wd) | (wc & wd)) +
603 we + word[i] + magic[2];
604 else if (i < 80)
605 t = SHSH(5, wa) + (wb ^ wc ^ wd) +
606 we + word[i] + magic[3];
607 we = wd;
608 wd = wc;
609 wc = SHSH(30, wb);
610 wb = wa;
611 wa = t;
612 }
613 digest[0] += wa; digest[1] += wb; digest[2] += wc;
614 digest[3] += wd; digest[4] += we;
615 idx = 0;
616 }
617 }
618 t = int_to_bigendian(digest[0]); digest[0] = t;
619 t = int_to_bigendian(digest[1]); digest[1] = t;
620 t = int_to_bigendian(digest[2]); digest[2] = t;
621 t = int_to_bigendian(digest[3]); digest[3] = t;
622 t = int_to_bigendian(digest[4]); digest[4] = t;
623 memcpy(dst, digest, 5 * 4);
624}
625
626EAPI Eina_Bool
627efreet_file_cache_fill(const char *file, Efreet_Cache_Check *check)
628{
629 struct stat st;
630 ssize_t size = 0;
631 char link[PATH_MAX];
632
633 if (lstat(file, &st) != 0) return EINA_FALSE;
634 if (S_ISLNK(st.st_mode))
635 {
636 size = readlink(file, link, sizeof(link));
637 if ((size > 0) && ((size_t)size >= sizeof(link))) return EINA_FALSE;
638 if (stat(file, &st) != 0) return EINA_FALSE;
639 }
640
641 memset(check, 0, sizeof(Efreet_Cache_Check));
642 if (size > 0) sha1((unsigned char *)link, size, check->link_sha1);
643 else memset(check->link_sha1, 0, sizeof(check->link_sha1));
644 check->uid = st.st_uid;
645 check->gid = st.st_gid;
646 check->size = st.st_size;
647 check->blocks = st.st_blocks;
648 check->mtime = st.st_mtime;
649 check->chtime = st.st_ctime;
650 check->mode = st.st_mode;
651 return EINA_TRUE;
652}
653
654EAPI Eina_Bool // true if matches
655efreet_file_cache_check(const Efreet_Cache_Check *check1, const Efreet_Cache_Check *check2)
656{
657 if ((check1->mtime != check2->mtime ) ||
658 (check1->size != check2->size ) ||
659 (check1->chtime != check2->chtime ) ||
660 (check1->blocks != check2->blocks) ||
661 (check1->mode != check2->mode ) ||
662 (check1->uid != check2->uid ) ||
663 (check1->gid != check2->gid ) ||
664 (memcmp(check1->link_sha1, check2->link_sha1, 20) != 0))
665 {
666 return EINA_FALSE;
667 }
668 return EINA_TRUE; // matches
669}
670
539EAPI Eet_Data_Descriptor * 671EAPI Eet_Data_Descriptor *
540efreet_version_edd(void) 672efreet_version_edd(void)
541{ 673{
@@ -691,8 +823,22 @@ efreet_icon_directory_edd(void)
691 directory_edd = eet_data_descriptor_file_new(&eddc); 823 directory_edd = eet_data_descriptor_file_new(&eddc);
692 if (!directory_edd) return NULL; 824 if (!directory_edd) return NULL;
693 825
694 EET_DATA_DESCRIPTOR_ADD_BASIC(directory_edd, Efreet_Cache_Directory, 826 EET_DATA_DESCRIPTOR_ADD_BASIC(directory_edd, Efreet_Cache_Directory,
695 "modified_time", modified_time, EET_T_LONG_LONG); 827 "check.uid", check.uid, EET_T_LONG_LONG);
828 EET_DATA_DESCRIPTOR_ADD_BASIC(directory_edd, Efreet_Cache_Directory,
829 "check.gid", check.gid, EET_T_LONG_LONG);
830 EET_DATA_DESCRIPTOR_ADD_BASIC(directory_edd, Efreet_Cache_Directory,
831 "check.size", check.size, EET_T_LONG_LONG);
832 EET_DATA_DESCRIPTOR_ADD_BASIC(directory_edd, Efreet_Cache_Directory,
833 "check.blocks", check.blocks, EET_T_LONG_LONG);
834 EET_DATA_DESCRIPTOR_ADD_BASIC(directory_edd, Efreet_Cache_Directory,
835 "check.mtime", check.mtime, EET_T_LONG_LONG);
836 EET_DATA_DESCRIPTOR_ADD_BASIC(directory_edd, Efreet_Cache_Directory,
837 "check.chtime", check.chtime, EET_T_LONG_LONG);
838 EET_DATA_DESCRIPTOR_ADD_BASIC(directory_edd, Efreet_Cache_Directory,
839 "check.mode", check.mode, EET_T_INT);
840 EET_DATA_DESCRIPTOR_ADD_BASIC_ARRAY(directory_edd, Efreet_Cache_Directory,
841 "check.link_sha1", check.link_sha1, EET_T_CHAR);
696 842
697 return directory_edd; 843 return directory_edd;
698} 844}
@@ -790,7 +936,21 @@ efreet_icon_theme_edd(Eina_Bool cache)
790 if (cache) 936 if (cache)
791 { 937 {
792 EET_DATA_DESCRIPTOR_ADD_BASIC(icon_theme_edd, Efreet_Cache_Icon_Theme, 938 EET_DATA_DESCRIPTOR_ADD_BASIC(icon_theme_edd, Efreet_Cache_Icon_Theme,
793 "last_cache_check", last_cache_check, EET_T_LONG_LONG); 939 "check.uid", check.uid, EET_T_LONG_LONG);
940 EET_DATA_DESCRIPTOR_ADD_BASIC(icon_theme_edd, Efreet_Cache_Icon_Theme,
941 "check.gid", check.gid, EET_T_LONG_LONG);
942 EET_DATA_DESCRIPTOR_ADD_BASIC(icon_theme_edd, Efreet_Cache_Icon_Theme,
943 "check.size", check.size, EET_T_LONG_LONG);
944 EET_DATA_DESCRIPTOR_ADD_BASIC(icon_theme_edd, Efreet_Cache_Icon_Theme,
945 "check.blocks", check.blocks, EET_T_LONG_LONG);
946 EET_DATA_DESCRIPTOR_ADD_BASIC(icon_theme_edd, Efreet_Cache_Icon_Theme,
947 "check.mtime", check.mtime, EET_T_LONG_LONG);
948 EET_DATA_DESCRIPTOR_ADD_BASIC(icon_theme_edd, Efreet_Cache_Icon_Theme,
949 "check.chtime", check.chtime, EET_T_LONG_LONG);
950 EET_DATA_DESCRIPTOR_ADD_BASIC(icon_theme_edd, Efreet_Cache_Icon_Theme,
951 "check.mode", check.mode, EET_T_INT);
952 EET_DATA_DESCRIPTOR_ADD_BASIC_ARRAY(icon_theme_edd, Efreet_Cache_Icon_Theme,
953 "check.link_sha1", check.link_sha1, EET_T_CHAR);
794 954
795 EET_DATA_DESCRIPTOR_ADD_BASIC(icon_theme_edd, Efreet_Cache_Icon_Theme, 955 EET_DATA_DESCRIPTOR_ADD_BASIC(icon_theme_edd, Efreet_Cache_Icon_Theme,
796 "path", path, EET_T_STRING); 956 "path", path, EET_T_STRING);
diff --git a/src/lib/efreet/efreet_cache_private.h b/src/lib/efreet/efreet_cache_private.h
index 97dbd45a1e..1edbb3b5ff 100644
--- a/src/lib/efreet/efreet_cache_private.h
+++ b/src/lib/efreet/efreet_cache_private.h
@@ -38,11 +38,20 @@
38# endif 38# endif
39#endif 39#endif
40 40
41typedef struct _Efreet_Cache_Check Efreet_Cache_Check;
42
43typedef struct _Efreet_Cache_Icon_Theme Efreet_Cache_Icon_Theme;
44typedef struct _Efreet_Cache_Directory Efreet_Cache_Directory;
45typedef struct _Efreet_Cache_Desktop Efreet_Cache_Desktop;
46
41EAPI const char *efreet_desktop_util_cache_file(void); 47EAPI const char *efreet_desktop_util_cache_file(void);
42EAPI const char *efreet_desktop_cache_file(void); 48EAPI const char *efreet_desktop_cache_file(void);
43EAPI const char *efreet_icon_cache_file(const char *theme); 49EAPI const char *efreet_icon_cache_file(const char *theme);
44EAPI const char *efreet_icon_theme_cache_file(void); 50EAPI const char *efreet_icon_theme_cache_file(void);
45 51
52EAPI Eina_Bool efreet_file_cache_fill(const char *file, Efreet_Cache_Check *check);
53EAPI Eina_Bool efreet_file_cache_check(const Efreet_Cache_Check *check1, const Efreet_Cache_Check *check2);
54
46EAPI Eet_Data_Descriptor *efreet_version_edd(void); 55EAPI Eet_Data_Descriptor *efreet_version_edd(void);
47EAPI Eet_Data_Descriptor *efreet_desktop_edd(void); 56EAPI Eet_Data_Descriptor *efreet_desktop_edd(void);
48EAPI Eet_Data_Descriptor *efreet_hash_array_string_edd(void); 57EAPI Eet_Data_Descriptor *efreet_hash_array_string_edd(void);
@@ -52,15 +61,23 @@ EAPI Eet_Data_Descriptor *efreet_icon_theme_edd(Eina_Bool cache);
52EAPI Eet_Data_Descriptor *efreet_icon_edd(void); 61EAPI Eet_Data_Descriptor *efreet_icon_edd(void);
53EAPI Eet_Data_Descriptor *efreet_icon_fallback_edd(void); 62EAPI Eet_Data_Descriptor *efreet_icon_fallback_edd(void);
54 63
55typedef struct _Efreet_Cache_Icon_Theme Efreet_Cache_Icon_Theme; 64struct _Efreet_Cache_Check
56typedef struct _Efreet_Cache_Directory Efreet_Cache_Directory; 65{
57typedef struct _Efreet_Cache_Desktop Efreet_Cache_Desktop; 66 unsigned long long uid;
67 unsigned long long gid;
68 unsigned long long size;
69 unsigned long long blocks;
70 unsigned long long mtime;
71 unsigned long long chtime;
72 unsigned int mode;
73 unsigned char link_sha1[20];
74};
58 75
59struct _Efreet_Cache_Icon_Theme 76struct _Efreet_Cache_Icon_Theme
60{ 77{
61 Efreet_Icon_Theme theme; 78 Efreet_Icon_Theme theme;
62 79
63 long long last_cache_check; /**< Last time the cache was checked */ 80 Efreet_Cache_Check check; /**< relevant stat info from last check */
64 81
65 Eina_Hash *dirs; /**< All possible icon paths for this theme */ 82 Eina_Hash *dirs; /**< All possible icon paths for this theme */
66 83
@@ -73,13 +90,14 @@ struct _Efreet_Cache_Icon_Theme
73 90
74struct _Efreet_Cache_Directory 91struct _Efreet_Cache_Directory
75{ 92{
76 long long modified_time; 93 Efreet_Cache_Check check; /**< relevant stat info from last check */
77}; 94};
78 95
79struct _Efreet_Cache_Desktop 96struct _Efreet_Cache_Desktop
80{ 97{
81 Efreet_Desktop desktop; 98 Efreet_Desktop desktop;
82 99
100 Efreet_Cache_Check check; /**< relevant stat info from last check */
83 double check_time; /**< Last time we check for disk modification */ 101 double check_time; /**< Last time we check for disk modification */
84}; 102};
85 103