12 #include <Ecore_File.h>
14 #define EFREET_MODULE_LOG_DOM _efreet_icon_cache_log_dom
15 static int _efreet_icon_cache_log_dom = -1;
18 #include "efreet_private.h"
19 #include "efreet_cache_private.h"
22 * - Need to handle programs using different exts
25 static Eina_Array *exts = NULL;
26 static Eina_Array *extra_dirs = NULL;
27 static Eina_Array *strs = NULL;
28 static Eina_Hash *icon_themes = NULL;
31 cache_directory_modified(Eina_Hash *dirs, const char *dir)
33 Efreet_Cache_Directory *dcache;
36 if (!dirs) return EINA_TRUE;
38 if (stat(dir, &st) < 0) return EINA_FALSE;
39 dcache = eina_hash_find(dirs, dir);
42 dcache = malloc(sizeof (Efreet_Cache_Directory));
43 if (!dcache) return EINA_TRUE;
45 dcache->modified_time = (long long) st.st_mtime;
46 eina_hash_add(dirs, dir, dcache);
48 else if (dcache->modified_time == (long long) st.st_mtime) return EINA_FALSE;
49 dcache->modified_time = st.st_mtime;
55 cache_extension_lookup(const char *ext)
59 for (i = 0; i < exts->count; ++i)
60 if (!strcmp(exts->data[i], ext))
66 cache_fallback_scan_dir(Eina_Hash *icons, Eina_Hash *dirs, const char *dir)
69 Eina_File_Direct_Info *entry;
71 if (!cache_directory_modified(dirs, dir)) return EINA_TRUE;
73 it = eina_file_stat_ls(dir);
74 if (!it) return EINA_TRUE;
76 EINA_ITERATOR_FOREACH(it, entry)
78 Efreet_Cache_Fallback_Icon *icon;
83 if (entry->type == EINA_FILE_DIR)
86 ext = strrchr(entry->path + entry->name_start, '.');
87 if (!ext || !cache_extension_lookup(ext))
90 /* icon with known extension */
91 name = entry->path + entry->name_start;
94 icon = eina_hash_find(icons, name);
97 icon = NEW(Efreet_Cache_Fallback_Icon, 1);
99 eina_hash_add(icons, name, icon);
104 for (i = 0; i < icon->icons_count; ++i)
105 if (!strcmp(icon->icons[i], entry->path))
108 if (i != icon->icons_count)
111 icon->icons = realloc(icon->icons, sizeof (char *) * (icon->icons_count + 1));
112 icon->icons[icon->icons_count] = eina_stringshare_add(entry->path);
113 eina_array_push(strs, icon->icons[icon->icons_count++]);
116 eina_iterator_free(it);
122 cache_fallback_scan(Eina_Hash *icons, Eina_Hash *dirs)
125 Eina_List *xdg_dirs, *l;
129 for (i = 0; i < extra_dirs->count; i++)
130 cache_fallback_scan_dir(icons, dirs, extra_dirs->data[i]);
132 cache_fallback_scan_dir(icons, dirs, efreet_icon_deprecated_user_dir_get());
133 cache_fallback_scan_dir(icons, dirs, efreet_icon_user_dir_get());
135 xdg_dirs = efreet_data_dirs_get();
136 EINA_LIST_FOREACH(xdg_dirs, l, dir)
138 snprintf(path, sizeof(path), "%s/icons", dir);
139 cache_fallback_scan_dir(icons, dirs, path);
143 EINA_LIST_FOREACH(xdg_dirs, l, dir)
145 snprintf(path, sizeof(path), "%s/pixmaps", dir);
146 cache_fallback_scan_dir(icons, dirs, path);
150 cache_fallback_scan_dir(icons, dirs, "/usr/share/pixmaps");
156 check_fallback_changed(Efreet_Cache_Icon_Theme *theme)
159 Eina_List *xdg_dirs, *l;
163 /* Check if the dirs we have cached are changed */
167 Eina_Bool changed = EINA_FALSE;
169 it = eina_hash_iterator_key_new(theme->dirs);
170 EINA_ITERATOR_FOREACH(it, dir)
172 changed = !ecore_file_exists(dir);
174 changed = cache_directory_modified(theme->dirs, dir);
177 eina_iterator_free(it);
178 if (changed) return EINA_TRUE;
181 /* Check if spec dirs have changed */
182 for (i = 0; i < extra_dirs->count; i++)
183 if (cache_directory_modified(theme->dirs, extra_dirs->data[i])) return EINA_TRUE;
185 if (cache_directory_modified(theme->dirs, efreet_icon_deprecated_user_dir_get())) return EINA_TRUE;
186 if (cache_directory_modified(theme->dirs, efreet_icon_user_dir_get())) return EINA_TRUE;
188 xdg_dirs = efreet_data_dirs_get();
189 EINA_LIST_FOREACH(xdg_dirs, l, dir)
191 snprintf(path, sizeof(path), "%s/icons", dir);
192 if (cache_directory_modified(theme->dirs, path)) return EINA_TRUE;
196 EINA_LIST_FOREACH(xdg_dirs, l, dir)
198 snprintf(path, sizeof(path), "%s/pixmaps", dir);
199 if (cache_directory_modified(theme->dirs, path)) return EINA_TRUE;
203 if (cache_directory_modified(theme->dirs, "/usr/share/pixmaps")) return EINA_TRUE;
208 cache_scan_path_dir(Efreet_Icon_Theme *theme,
210 Efreet_Icon_Theme_Directory *dir,
215 Eina_File_Direct_Info *entry;
217 snprintf(buf, sizeof(buf), "%s/%s", path, dir->name);
219 it = eina_file_stat_ls(buf);
220 if (!it) return EINA_TRUE;
222 EINA_ITERATOR_FOREACH(it, entry)
224 Efreet_Cache_Icon *icon;
229 if (entry->type == EINA_FILE_DIR)
232 ext = strrchr(entry->path + entry->name_start, '.');
233 if (!ext || !cache_extension_lookup(ext))
236 /* icon with known extension */
237 name = entry->path + entry->name_start;
240 icon = eina_hash_find(icons, name);
243 icon = NEW(Efreet_Cache_Icon, 1);
244 icon->theme = eina_stringshare_add(theme->name.internal);
245 eina_array_push(strs, icon->theme);
246 eina_hash_add(icons, name, icon);
248 else if (icon->theme && strcmp(icon->theme, theme->name.internal))
250 /* We got this icon from a parent theme */
254 /* find if we have the same icon in another type */
255 for (i = 0; i < icon->icons_count; ++i)
257 if ((icon->icons[i]->type == dir->type) &&
258 (icon->icons[i]->normal == dir->size.normal) &&
259 (icon->icons[i]->max == dir->size.max) &&
260 (icon->icons[i]->min == dir->size.min))
266 if (i != icon->icons_count)
270 /* check if the path already exist */
271 for (j = 0; j < icon->icons[i]->paths_count; ++j)
272 if (!strcmp(icon->icons[i]->paths[j], entry->path))
275 if (j != icon->icons[i]->paths_count)
278 /* no icon match so add a new one */
281 icon->icons = realloc(icon->icons,
282 sizeof (Efreet_Cache_Icon_Element*) * (++icon->icons_count));
283 icon->icons[i] = NEW(Efreet_Cache_Icon_Element, 1);
284 icon->icons[i]->type = dir->type;
285 icon->icons[i]->normal = dir->size.normal;
286 icon->icons[i]->min = dir->size.min;
287 icon->icons[i]->max = dir->size.max;
288 icon->icons[i]->paths = NULL;
289 icon->icons[i]->paths_count = 0;
292 /* and finally store the path */
293 icon->icons[i]->paths = realloc(icon->icons[i]->paths,
294 sizeof (char*) * (icon->icons[i]->paths_count + 1));
295 icon->icons[i]->paths[icon->icons[i]->paths_count] = eina_stringshare_add(entry->path);
296 eina_array_push(strs, icon->icons[i]->paths[icon->icons[i]->paths_count++]);
299 eina_iterator_free(it);
305 cache_scan_path(Efreet_Icon_Theme *theme, Eina_Hash *icons, const char *path)
308 Efreet_Icon_Theme_Directory *dir;
310 EINA_LIST_FOREACH(theme->directories, l, dir)
311 if (!cache_scan_path_dir(theme, path, dir, icons)) return EINA_FALSE;
317 cache_scan(Efreet_Icon_Theme *theme, Eina_Hash *themes, Eina_Hash *icons)
323 if (!theme) return EINA_TRUE;
324 if (eina_hash_find(themes, theme->name.internal)) return EINA_TRUE;
325 eina_hash_direct_add(themes, theme->name.internal, theme);
328 EINA_LIST_FOREACH(theme->paths, l, path)
329 if (!cache_scan_path(theme, icons, path)) return EINA_FALSE;
334 EINA_LIST_FOREACH(theme->inherits, l, name)
336 Efreet_Icon_Theme *inherit;
338 inherit = eina_hash_find(icon_themes, name);
340 INF("Theme `%s` not found for `%s`.",
341 name, theme->name.internal);
342 if (!cache_scan(inherit, themes, icons)) return EINA_FALSE;
345 else if (strcmp(theme->name.internal, "hicolor"))
347 theme = eina_hash_find(icon_themes, "hicolor");
348 if (!cache_scan(theme, themes, icons)) return EINA_FALSE;
355 check_changed(Efreet_Cache_Icon_Theme *theme)
360 if (!theme) return EINA_FALSE;
362 if (theme->changed) return EINA_TRUE;
363 if (theme->theme.inherits)
365 EINA_LIST_FOREACH(theme->theme.inherits, l, name)
367 Efreet_Cache_Icon_Theme *inherit;
369 inherit = eina_hash_find(icon_themes, name);
371 INF("Theme `%s` not found for `%s`.",
372 name, theme->theme.name.internal);
373 if (check_changed(inherit)) return EINA_TRUE;
376 else if (strcmp(theme->theme.name.internal, "hicolor"))
378 theme = eina_hash_find(icon_themes, "hicolor");
379 if (check_changed(theme)) return EINA_TRUE;
384 static Efreet_Icon_Theme_Directory *
385 icon_theme_directory_new(Efreet_Ini *ini, const char *name)
387 Efreet_Icon_Theme_Directory *dir;
391 if (!ini) return NULL;
393 dir = NEW(Efreet_Icon_Theme_Directory, 1);
394 if (!dir) return NULL;
395 dir->name = eina_stringshare_add(name);
396 eina_array_push(strs, dir->name);
398 efreet_ini_section_set(ini, name);
400 tmp = efreet_ini_string_get(ini, "Context");
403 if (!strcasecmp(tmp, "Actions"))
404 dir->context = EFREET_ICON_THEME_CONTEXT_ACTIONS;
406 else if (!strcasecmp(tmp, "Devices"))
407 dir->context = EFREET_ICON_THEME_CONTEXT_DEVICES;
409 else if (!strcasecmp(tmp, "FileSystems"))
410 dir->context = EFREET_ICON_THEME_CONTEXT_FILESYSTEMS;
412 else if (!strcasecmp(tmp, "MimeTypes"))
413 dir->context = EFREET_ICON_THEME_CONTEXT_MIMETYPES;
416 /* Threshold is fallback */
417 dir->type = EFREET_ICON_SIZE_TYPE_THRESHOLD;
419 tmp = efreet_ini_string_get(ini, "Type");
422 if (!strcasecmp(tmp, "Fixed"))
423 dir->type = EFREET_ICON_SIZE_TYPE_FIXED;
425 else if (!strcasecmp(tmp, "Scalable"))
426 dir->type = EFREET_ICON_SIZE_TYPE_SCALABLE;
429 dir->size.normal = efreet_ini_int_get(ini, "Size");
431 if (dir->type == EFREET_ICON_SIZE_TYPE_THRESHOLD)
433 val = efreet_ini_int_get(ini, "Threshold");
434 if (val < 0) val = 2;
435 dir->size.max = dir->size.normal + val;
436 dir->size.min = dir->size.normal - val;
438 else if (dir->type == EFREET_ICON_SIZE_TYPE_SCALABLE)
440 val = efreet_ini_int_get(ini, "MinSize");
441 if (val < 0) dir->size.min = dir->size.normal;
442 else dir->size.min = val;
444 val = efreet_ini_int_get(ini, "MaxSize");
445 if (val < 0) dir->size.max = dir->size.normal;
446 else dir->size.max = val;
453 icon_theme_index_read(Efreet_Cache_Icon_Theme *theme, const char *path)
456 Efreet_Icon_Theme_Directory *dir;
461 if (!theme || !path) return EINA_FALSE;
463 if (!realpath(path, rp)) return EINA_FALSE;
465 if (stat(rp, &st) < 0) return EINA_FALSE;
466 if (theme->path && !strcmp(theme->path, rp) && theme->last_cache_check >= (long long) st.st_mtime)
472 if (!theme->path || strcmp(theme->path, rp))
474 theme->path = eina_stringshare_add(rp);
475 eina_array_push(strs, theme->path);
477 if ((long long) st.st_mtime > theme->last_cache_check)
478 theme->last_cache_check = (long long) st.st_mtime;
481 ini = efreet_ini_new(path);
482 if (!ini) return EINA_FALSE;
485 efreet_ini_free(ini);
489 efreet_ini_section_set(ini, "Icon Theme");
490 tmp = efreet_ini_localestring_get(ini, "Name");
493 theme->theme.name.name = eina_stringshare_add(tmp);
494 eina_array_push(strs, theme->theme.name.name);
497 tmp = efreet_ini_localestring_get(ini, "Comment");
500 theme->theme.comment = eina_stringshare_add(tmp);
501 eina_array_push(strs, theme->theme.comment);
504 tmp = efreet_ini_string_get(ini, "Example");
507 theme->theme.example_icon = eina_stringshare_add(tmp);
508 eina_array_push(strs, theme->theme.example_icon);
511 theme->hidden = efreet_ini_boolean_get(ini, "Hidden");
515 /* Check the inheritance. If there is none we inherit from the hicolor theme */
516 tmp = efreet_ini_string_get(ini, "Inherits");
523 len = strlen(tmp) + 1;
533 i = eina_stringshare_add(s);
534 theme->theme.inherits = eina_list_append(theme->theme.inherits, i);
535 eina_array_push(strs, i);
539 i = eina_stringshare_add(s);
540 theme->theme.inherits = eina_list_append(theme->theme.inherits, i);
541 eina_array_push(strs, i);
544 /* make sure this one is done last as setting the directory will change
545 * the ini section ... */
546 tmp = efreet_ini_string_get(ini, "Directories");
552 len = strlen(tmp) + 1;
564 dir = icon_theme_directory_new(ini, s);
565 if (!dir) goto error;
566 theme->theme.directories = eina_list_append(theme->theme.directories, dir);
573 efreet_ini_free(ini);
579 cache_theme_scan(const char *dir)
582 Eina_File_Direct_Info *entry;
584 it = eina_file_stat_ls(dir);
585 if (!it) return EINA_TRUE;
587 EINA_ITERATOR_FOREACH(it, entry)
589 Efreet_Cache_Icon_Theme *theme;
595 if (stat(entry->path, &st) < 0) continue;
597 if ((entry->type != EINA_FILE_DIR) &&
598 (entry->type != EINA_FILE_LNK))
601 name = entry->path + entry->name_start;
602 theme = eina_hash_find(icon_themes, name);
606 theme = NEW(Efreet_Cache_Icon_Theme, 1);
607 theme->theme.name.internal = eina_stringshare_add(name);
608 eina_array_push(strs, theme->theme.name.internal);
609 eina_hash_direct_add(icon_themes,
610 (void *)theme->theme.name.internal, theme);
613 if ((long long) st.st_mtime > theme->last_cache_check)
615 theme->last_cache_check = (long long) st.st_mtime;
619 /* TODO: We need to handle change in order of included paths */
620 if (!eina_list_search_unsorted(theme->theme.paths, EINA_COMPARE_CB(strcmp), entry->path))
622 path = eina_stringshare_add(entry->path);
623 theme->theme.paths = eina_list_append(theme->theme.paths, path);
624 eina_array_push(strs, path);
628 /* we're already valid so no reason to check for an index.theme file */
629 if (theme->valid) continue;
631 /* if the index.theme file exists we parse it into the theme */
632 memcpy(buf, entry->path, entry->path_length);
633 memcpy(buf + entry->path_length, "/index.theme", sizeof("/index.theme"));
634 if (ecore_file_exists(buf))
636 if (!icon_theme_index_read(theme, buf))
640 eina_iterator_free(it);
645 cache_lock_file(void)
651 snprintf(file, sizeof(file), "%s/efreet/icon_data.lock", efreet_cache_home_get());
652 lockfd = open(file, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
653 if (lockfd < 0) return -1;
654 efreet_fsetowner(lockfd);
656 memset(&fl, 0, sizeof(struct flock));
658 fl.l_whence = SEEK_SET;
659 if (fcntl(lockfd, F_SETLK, &fl) < 0)
661 WRN("LOCKED! You may want to delete %s if this persists", file);
670 icon_theme_free(Efreet_Cache_Icon_Theme *theme)
674 eina_list_free(theme->theme.paths);
675 eina_list_free(theme->theme.inherits);
676 EINA_LIST_FREE(theme->theme.directories, data)
678 if (theme->dirs) efreet_hash_free(theme->dirs, free);
684 * @return EINA_TRUE if data adds new
687 add_data(Eet_File *ef, Eina_Array *data, const char *key)
689 Efreet_Cache_Array_String *add;
691 Eina_Bool added = EINA_FALSE;
693 add = eet_data_read(ef, efreet_array_string_edd(), key);
694 if (!add) return EINA_TRUE;
695 /* loop once to check added */
696 for (i = 0; i < data->count; i++)
699 for (j = 0; j < add->array_count; ++j)
701 if (!strcmp(add->array[j], data->data[i]))
713 /* loop again to add all data */
714 for (i = 0; i < add->array_count; i++)
717 for (j = 0; j < data->count; ++j)
719 if (!strcmp(add->array[i], data->data[j]))
726 eina_array_push(data, add->array[i]);
736 save_data(Eet_File *ef, Eina_Array *data, const char *key)
738 Efreet_Cache_Array_String *save;
741 if (!data || !data->count) return;
743 save = NEW(Efreet_Cache_Array_String, 1);
744 save->array = NEW(char *, data->count);
745 save->array_count = 0;
746 for (i = 0; i < data->count; ++i)
747 save->array[save->array_count++] = data->data[i];
748 eet_data_write(ef, efreet_array_string_edd(), key, save, 1);
749 IF_FREE(save->array);
754 main(int argc, char **argv)
757 * - Add file monitor on files, so that we catch changes on files
758 * during whilst this program runs.
759 * - Maybe linger for a while to reduce number of cache re-creates.
762 Efreet_Cache_Version *icon_version;
763 Efreet_Cache_Version *theme_version;
764 Efreet_Cache_Icon_Theme *theme;
765 Eet_Data_Descriptor *theme_edd;
766 Eet_Data_Descriptor *icon_edd;
767 Eet_Data_Descriptor *fallback_edd;
770 Eina_List *xdg_dirs = NULL;
775 Eina_Bool changed = EINA_FALSE;
776 Eina_Bool flush = EINA_FALSE;
782 /* init external subsystems */
783 if (!eina_init()) return -1;
784 _efreet_icon_cache_log_dom =
785 eina_log_domain_register("efreet_icon_cache", EFREET_DEFAULT_LOG_COLOR);
786 if (_efreet_icon_cache_log_dom < 0)
788 EINA_LOG_ERR("Efreet: Could not create a log domain for efreet_icon_cache.");
792 eina_log_domain_level_set("efreet_icon_cache", EINA_LOG_LEVEL_ERR);
794 exts = eina_array_new(10);
795 extra_dirs = eina_array_new(10);
797 for (i = 1; i < argc; i++)
799 if (!strcmp(argv[i], "-v"))
800 eina_log_domain_level_set("efreet_icon_cache", EINA_LOG_LEVEL_DBG);
801 else if ((!strcmp(argv[i], "-h")) ||
802 (!strcmp(argv[i], "-help")) ||
803 (!strcmp(argv[i], "--h")) ||
804 (!strcmp(argv[i], "--help")))
806 printf("Options:\n");
807 printf(" -v Verbose mode\n");
808 printf(" -e .ext1 .ext2 Extensions\n");
809 printf(" -d dir1 dir2 Extra dirs\n");
812 else if (!strcmp(argv[i], "-e"))
814 while ((i < (argc - 1)) && (argv[(i + 1)][0] != '-'))
815 eina_array_push(exts, argv[++i]);
817 else if (!strcmp(argv[i], "-d"))
819 while ((i < (argc - 1)) && (argv[(i + 1)][0] != '-'))
820 eina_array_push(extra_dirs, argv[++i]);
824 if (!eet_init()) return -1;
825 if (!ecore_init()) return -1;
827 efreet_cache_update = 0;
828 /* finish efreet init */
829 if (!efreet_init()) goto on_error;
831 strs = eina_array_new(32);
834 snprintf(file, sizeof(file), "%s/efreet", efreet_cache_home_get());
835 if (!ecore_file_exists(file))
837 if (!ecore_file_mkpath(file)) return -1;
838 efreet_setowner(file);
841 /* lock process, so that we only run one copy of this program */
842 lockfd = cache_lock_file();
843 if (lockfd == -1) goto on_error;
845 /* Need to init edd's, so they are like we want, not like userspace wants */
846 icon_edd = efreet_icon_edd();
847 fallback_edd = efreet_icon_fallback_edd();
848 theme_edd = efreet_icon_theme_edd(EINA_TRUE);
850 icon_themes = eina_hash_string_superfast_new(EINA_FREE_CB(icon_theme_free));
852 INF("opening theme cache");
853 /* open theme file */
854 theme_ef = eet_open(efreet_icon_theme_cache_file(), EET_FILE_MODE_READ_WRITE);
855 if (!theme_ef) goto on_error_efreet;
856 theme_version = eet_data_read(theme_ef, efreet_version_edd(), EFREET_CACHE_VERSION);
858 ((theme_version->major != EFREET_ICON_CACHE_MAJOR) ||
859 (theme_version->minor != EFREET_ICON_CACHE_MINOR)))
863 if (unlink(efreet_icon_theme_cache_file()) < 0)
865 if (errno != ENOENT) goto on_error_efreet;
867 theme_ef = eet_open(efreet_icon_theme_cache_file(), EET_FILE_MODE_READ_WRITE);
868 if (!theme_ef) goto on_error_efreet;
871 theme_version = NEW(Efreet_Cache_Version, 1);
873 theme_version->major = EFREET_ICON_CACHE_MAJOR;
874 theme_version->minor = EFREET_ICON_CACHE_MINOR;
876 if (add_data(theme_ef, exts, EFREET_CACHE_ICON_EXTENSIONS))
878 if (add_data(theme_ef, extra_dirs, EFREET_CACHE_ICON_EXTRA_DIRS))
883 if (exts->count == 0)
885 ERR("Need to pass extensions to icon cache create process");
886 goto on_error_efreet;
889 keys = eet_list(theme_ef, "*", &num);
892 for (i = 0; i < num; i++)
894 if (!strncmp(keys[i], "__efreet", 8)) continue;
895 theme = eet_data_read(theme_ef, theme_edd, keys[i]);
899 eina_hash_direct_add(icon_themes, theme->theme.name.internal, theme);
905 INF("scan for themes");
907 cache_theme_scan(efreet_icon_deprecated_user_dir_get());
908 cache_theme_scan(efreet_icon_user_dir_get());
910 xdg_dirs = efreet_data_dirs_get();
911 EINA_LIST_FOREACH(xdg_dirs, l, dir)
913 snprintf(file, sizeof(file), "%s/icons", dir);
914 cache_theme_scan(file);
918 EINA_LIST_FOREACH(xdg_dirs, l, dir)
920 snprintf(file, sizeof(file), "%s/pixmaps", dir);
921 cache_theme_scan(file);
925 cache_theme_scan("/usr/share/pixmaps");
928 it = eina_hash_iterator_data_new(icon_themes);
929 EINA_ITERATOR_FOREACH(it, theme)
931 if (!theme->valid) continue;
933 if (!theme->theme.name.name) continue;
935 INF("scan theme %s", theme->theme.name.name);
937 theme->changed = check_changed(theme);
939 theme->changed = EINA_TRUE;
941 INF("open icon file");
943 icon_ef = eet_open(efreet_icon_cache_file(theme->theme.name.internal), EET_FILE_MODE_READ_WRITE);
944 if (!icon_ef) goto on_error_efreet;
945 icon_version = eet_data_read(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION);
946 if (theme->changed || (icon_version &&
947 ((icon_version->major != EFREET_ICON_CACHE_MAJOR) ||
948 (icon_version->minor != EFREET_ICON_CACHE_MINOR))))
952 if (unlink(efreet_icon_cache_file(theme->theme.name.internal)) < 0)
954 if (errno != ENOENT) goto on_error_efreet;
956 icon_ef = eet_open(efreet_icon_cache_file(theme->theme.name.internal), EET_FILE_MODE_READ_WRITE);
957 if (!icon_ef) goto on_error_efreet;
958 theme->changed = EINA_TRUE;
970 icon_version = NEW(Efreet_Cache_Version, 1);
972 icon_version->major = EFREET_ICON_CACHE_MAJOR;
973 icon_version->minor = EFREET_ICON_CACHE_MINOR;
975 themes = eina_hash_string_superfast_new(NULL);
976 icons = eina_hash_string_superfast_new(NULL);
979 if (cache_scan(&(theme->theme), themes, icons))
981 Eina_Iterator *icons_it;
982 Eina_Hash_Tuple *tuple;
984 INF("generated: '%s' %i (%i)",
985 theme->theme.name.internal,
987 eina_hash_population(icons));
989 icons_it = eina_hash_iterator_tuple_new(icons);
990 EINA_ITERATOR_FOREACH(icons_it, tuple)
991 eet_data_write(icon_ef, icon_edd, tuple->key, tuple->data, 1);
992 eina_iterator_free(icons_it);
994 INF("theme change: %s %lld", theme->theme.name.internal, theme->last_cache_check);
995 eet_data_write(theme_ef, theme_edd, theme->theme.name.internal, theme, 1);
997 eina_hash_free(themes);
998 eina_hash_free(icons);
1001 eet_data_write(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION, icon_version, 1);
1003 efreet_setowner(efreet_icon_cache_file(theme->theme.name.internal));
1006 eina_iterator_free(it);
1008 INF("scan fallback icons");
1009 theme = eet_data_read(theme_ef, theme_edd, EFREET_CACHE_ICON_FALLBACK);
1012 theme = NEW(Efreet_Cache_Icon_Theme, 1);
1013 theme->changed = EINA_TRUE;
1016 theme->changed = EINA_TRUE;
1018 INF("open fallback file");
1019 /* open icon file */
1020 icon_ef = eet_open(efreet_icon_cache_file(EFREET_CACHE_ICON_FALLBACK), EET_FILE_MODE_READ_WRITE);
1021 if (!icon_ef) goto on_error_efreet;
1022 icon_version = eet_data_read(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION);
1023 if (theme->changed || (icon_version &&
1024 ((icon_version->major != EFREET_ICON_CACHE_MAJOR) ||
1025 (icon_version->minor != EFREET_ICON_CACHE_MINOR))))
1029 if (unlink(efreet_icon_cache_file(EFREET_CACHE_ICON_FALLBACK)) < 0)
1031 if (errno != ENOENT) goto on_error_efreet;
1033 icon_ef = eet_open(efreet_icon_cache_file(EFREET_CACHE_ICON_FALLBACK), EET_FILE_MODE_READ_WRITE);
1034 if (!icon_ef) goto on_error_efreet;
1035 theme->changed = EINA_TRUE;
1037 if (!theme->changed)
1038 theme->changed = check_fallback_changed(theme);
1039 if (theme->changed && theme->dirs)
1041 efreet_hash_free(theme->dirs, free);
1045 theme->dirs = eina_hash_string_superfast_new(NULL);
1048 changed = EINA_TRUE;
1055 icon_version = NEW(Efreet_Cache_Version, 1);
1057 icon_version->major = EFREET_ICON_CACHE_MAJOR;
1058 icon_version->minor = EFREET_ICON_CACHE_MINOR;
1060 icons = eina_hash_string_superfast_new(NULL);
1062 INF("scan fallback icons");
1063 /* Save fallback in the right part */
1064 if (cache_fallback_scan(icons, theme->dirs))
1066 Eina_Iterator *icons_it;
1067 Eina_Hash_Tuple *tuple;
1069 INF("generated: fallback %i (%i)", theme->changed, eina_hash_population(icons));
1071 icons_it = eina_hash_iterator_tuple_new(icons);
1072 EINA_ITERATOR_FOREACH(icons_it, tuple)
1073 eet_data_write(icon_ef, fallback_edd, tuple->key, tuple->data, 1);
1074 eina_iterator_free(icons_it);
1076 eina_hash_free(icons);
1078 eet_data_write(theme_ef, theme_edd, EFREET_CACHE_ICON_FALLBACK, theme, 1);
1081 icon_theme_free(theme);
1083 eet_data_write(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION, icon_version, 1);
1085 efreet_setowner(efreet_icon_cache_file(EFREET_CACHE_ICON_FALLBACK));
1088 eina_hash_free(icon_themes);
1091 eet_data_write(theme_ef, efreet_version_edd(), EFREET_CACHE_VERSION, theme_version, 1);
1092 save_data(theme_ef, exts, EFREET_CACHE_ICON_EXTENSIONS);
1093 save_data(theme_ef, extra_dirs, EFREET_CACHE_ICON_EXTRA_DIRS);
1095 eet_close(theme_ef);
1096 efreet_setowner(efreet_icon_theme_cache_file());
1097 free(theme_version);
1099 /* touch update file */
1100 snprintf(file, sizeof(file), "%s/efreet/icon_data.update", efreet_cache_home_get());
1101 tmpfd = open(file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1106 efreet_fsetowner(tmpfd);
1107 if (changed) c = 'c';
1108 if (write(tmpfd, &c, 1) != 1) perror("write");
1117 if (lockfd >= 0) close(lockfd);
1119 while ((path = eina_array_pop(strs)))
1120 eina_stringshare_del(path);
1121 eina_array_free(strs);
1122 eina_array_free(exts);
1123 eina_array_free(extra_dirs);
1127 eina_log_domain_unregister(_efreet_icon_cache_log_dom);