efreet - save about 240-300k or so of memory used by efreet mime

so efreet mime was loading a bunch of mime type info files, parsing
them on startup and allocating memory to store all this mime info -
globs, mimetype strings and more. all a big waste of memory as its
allocated on the heap per process where its the SAME data files loaded
every time.

so make an efreet mime cache file and a tool to create it from mime
files. mmap this file with all the hashes/strings in it so all that
data is mmaped once in memory and shared between all processes and it
is only paged in on demand - as actually read/needed so if your
process doesnt need to know about mime stuff.. it wont touch it anyway.

this saves about 240-300k or so of memory in my tests. this has not
covered the mime MAGIC files which still consume memory and are on the
heap. this is more complex so it will take more time to come up with a
nice file format for the data that is nicely mmaped etc.

@optimize
This commit is contained in:
Carsten Haitzler 2016-08-23 11:59:37 +09:00
parent 56c52311e5
commit 561f8eaa8f
11 changed files with 843 additions and 573 deletions

View File

@ -90,7 +90,8 @@ bin_efreet_efreetd_DEPENDENCIES = @USE_EFREET_INTERNAL_LIBS@
efreetinternal_bindir=$(libdir)/efreet/$(MODULE_ARCH)
efreetinternal_bin_PROGRAMS = \
bin/efreet/efreet_desktop_cache_create \
bin/efreet/efreet_icon_cache_create
bin/efreet/efreet_icon_cache_create \
bin/efreet/efreet_mime_cache_create
bin_efreet_efreet_desktop_cache_create_CPPFLAGS = -I$(top_builddir)/src/lib/efl $(EFREET_COMMON_CPPFLAGS)
bin_efreet_efreet_desktop_cache_create_LDADD = $(USE_EFREET_BIN_LIBS)
@ -102,6 +103,11 @@ bin_efreet_efreet_icon_cache_create_LDADD = $(USE_EFREET_BIN_LIBS)
bin_efreet_efreet_icon_cache_create_DEPENDENCIES = @USE_EFREET_INTERNAL_LIBS@
bin_efreet_efreet_icon_cache_create_SOURCES = bin/efreet/efreet_icon_cache_create.c
bin_efreet_efreet_mime_cache_create_CPPFLAGS = -I$(top_builddir)/src/lib/efl $(EFREET_COMMON_CPPFLAGS)
bin_efreet_efreet_mime_cache_create_LDADD = $(USE_EFREET_BIN_LIBS)
bin_efreet_efreet_mime_cache_create_DEPENDENCIES = @USE_EFREET_INTERNAL_LIBS@
bin_efreet_efreet_mime_cache_create_SOURCES = bin/efreet/efreet_mime_cache_create.c
### Unit tests
if EFL_ENABLE_TESTS

View File

@ -1,3 +1,4 @@
/efreet_desktop_cache_create
/efreet_icon_cache_create
/efreetd
/efreet_mime_cache_create

View File

@ -0,0 +1,453 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/time.h>
#include <sys/resource.h>
#endif
#ifdef _WIN32
# include <winsock2.h>
#endif
#include <libgen.h>
#include <ctype.h>
#include <Eina.h>
#include <Eet.h>
#include <Ecore.h>
#include <Ecore_File.h>
#ifndef O_BINARY
# define O_BINARY 0
#endif
#define EFREET_MODULE_LOG_DOM _efreet_mime_cache_log_dom
static int _efreet_mime_cache_log_dom = -1;
static Eina_List *extra_dirs = NULL;
static Eina_Hash *mimes = NULL;
static Eina_Hash *extn_mimes = NULL;
static Eina_Hash *glob_mimes = NULL;
static Eina_List *mimes_sorted = NULL;
static Eina_List *extn_mimes_sorted = NULL;
static Eina_List *glob_mimes_sorted = NULL;
#include "Efreet.h"
#include "efreet_private.h"
#include "efreet_cache_private.h"
static int
cache_lock_file(void)
{
char file[PATH_MAX];
struct flock fl;
int lockfd;
snprintf(file, sizeof(file), "%s/efreet/mime_data.lock", efreet_cache_home_get());
lockfd = open(file, O_CREAT | O_BINARY | O_RDWR, S_IRUSR | S_IWUSR);
if (lockfd < 0) return -1;
efreet_fsetowner(lockfd);
memset(&fl, 0, sizeof(struct flock));
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
if (fcntl(lockfd, F_SETLK, &fl) < 0)
{
INF("LOCKED! You may want to delete %s if this persists", file);
close(lockfd);
return -1;
}
return lockfd;
}
static int
hash_list_sort_insert_cmp(const char *key1, const char *key2)
{
return strcmp(key1, key2);
}
static Eina_Bool
hash_list_sort_each(const Eina_Hash *hash EINA_UNUSED, const void *key, void *value EINA_UNUSED, void *data)
{
Eina_List **list = data;
*list = eina_list_sorted_insert(*list,
EINA_COMPARE_CB(hash_list_sort_insert_cmp),
key);
return EINA_TRUE;
}
static void
hash_list_sort(Eina_Hash *hash, Eina_List **list)
{
eina_hash_foreach(hash, hash_list_sort_each, list);
}
static void
etc_mime_types_load(const char *file)
{
int len;
char buf[4096], buf2[4096], buf3[4096], *p, *p2;
const char *mime;
FILE *f = fopen(file, "r");
if (!f) return;
while (fgets(buf, sizeof(buf), f))
{
// remove newline at end of line string if there
buf[sizeof(buf) - 1] = 0;
len = strlen(buf);
if ((len > 0) && (buf[len - 1] == '\n')) buf[len - 1] = 0;
// buf: "# comment"
// or
// buf: "mime/type"
// buf: "mime/type "
// buf: "mime/type ext1"
// buf: "mime/type ext1 ext2"
// buf: "mime/type ext1 ext2 ext3"
// ...
p = buf;
// find first token in line
while ((*p) && isspace(*p)) p++;
// if comment - skip line
if (*p == '#') continue;
p2 = p;
while ((*p2) && !isspace(*p2)) p2++;
// token is between p and p2 (not including p2)
strncpy(buf2, p, p2 - p);
buf2[p2 - p] = 0;
mime = eina_stringshare_add(buf2);
// buf2 is now the mime type token
eina_hash_del(mimes, buf2, NULL);
eina_hash_add(mimes, buf2, mime);
// now lookf for all extension tokens;
p = p2;
// find next token in line
while ((*p) && isspace(*p)) p++;
while (*p)
{
// find end of token
p2 = p;
while ((*p2) && !isspace(*p2)) p2++;
// buf3 is now the extension token
strncpy(buf3, p, p2 - p);
buf3[p2 - p] = 0;
eina_hash_del(extn_mimes, buf3, NULL);
eina_hash_add(extn_mimes, buf3, mime);
// go to next token if any
p = p2;
while ((*p) && isspace(*p)) p++;
}
}
fclose(f);
}
static void
share_mime_globs_load(const char *file)
{
int len;
char buf[4096], buf2[4096], buf3[4096], *p, *p2;
const char *mime;
FILE *f = fopen(file, "r");
if (!f) return;
while (fgets(buf, sizeof(buf), f))
{
// remove newline at end of line string if there
buf[sizeof(buf) - 1] = 0;
len = strlen(buf);
if ((len > 0) && (buf[len - 1] == '\n')) buf[len - 1] = 0;
// buf: "# comment"
// or
// buf: "mime/type:glob"
// ...
p = buf;
// find first token in line
while ((*p) && isspace(*p)) p++;
// if comment - skip line
if (*p == '#') continue;
p2 = p;
while ((*p2) && (*p2 != ':')) p2++;
// token is between p and p2 (not including p2)
strncpy(buf2, p, p2 - p);
buf2[p2 - p] = 0;
mime = eina_stringshare_add(buf2);
// buf2 is now the mime type token
eina_hash_del(mimes, buf2, NULL);
eina_hash_add(mimes, buf2, mime);
// now lookf for all extension tokens;
p = p2;
// find next token in line
while ((*p) && (*p == ':')) p++;
// find end of token
p2 = p;
while ((*p2) && !isspace(*p2)) p2++;
// buf3 is now the extension token
strncpy(buf3, p, p2 - p);
buf3[p2 - p] = 0;
// for a shortcut a glob of "*.xxx" is the same as just an ext of "xxx"
// so if this is the case then put into the extn mimes not
// the globl mimes for speed of lookup later on
if ((buf3[0] == '*') && (buf3[1] == '.') &&
(!strchr(buf3 + 2, '*')) && (!strchr(buf3 + 2, '?')) &&
(!strchr(buf3 + 2, '[')) && (!strchr(buf3 + 2, ']')) &&
(!strchr(buf3 + 2, '\\')))
{
eina_hash_del(extn_mimes, buf3 + 2, NULL);
eina_hash_add(extn_mimes, buf3 + 2, mime);
}
else
{
eina_hash_del(glob_mimes, buf3, NULL);
eina_hash_add(glob_mimes, buf3, mime);
}
}
fclose(f);
}
static void *
find_off(const char *str, Eina_List *strlist, Eina_List *offlist)
{
Eina_List *l, *ll;
const char *s;
ll = offlist;
EINA_LIST_FOREACH(strlist, l, s)
{
if (!strcmp(str, s)) return ll->data;
ll = ll->next;
}
return (void *)-1;
}
static void
store_cache(const char *out)
{
char buf[PATH_MAX];
FILE *f;
size_t mimes_str_len = 0;
size_t extn_mimes_str_len = 0;
size_t glob_mimes_str_len = 0;
size_t str_start;
Eina_List *mimes_str_offsets = NULL;
Eina_List *extn_mimes_str_offsets = NULL;
Eina_List *glob_mimes_str_offsets = NULL;
Eina_List *l, *ll;
const char *s;
void *ptr;
unsigned int val;
snprintf(buf, sizeof(buf), "%s.tmp", out);
f = fopen(buf, "wb");
if (!f) return;
// write file magic - first 16 bytes
fwrite("EfrEeT-MiMeS-001", 16, 1, f);
// note: all offsets are in bytes from start of file
//
// "EfrEeT-MiMeS-001" <- magic 16 byte header
// [int] <- size of mimes array in number of entries
// [int] <- str byte offset of 1st mime string (sorted)
// [int] <- str byte offset of 2nd mime string
// ...
// [int] <- size of extn_mimes array in number of entries
// [int] <- str byte offset of 1st extn string (sorted)
// [int] <- str byte offset of 1st mime string
// [int] <- str byte offset of 2nd extn string
// [int] <- str byte offset of 2nd mine string
// ...
// [int] <- size of globs array in number of entries
// [int] <- str byte offset of 1st glob string (sorted)
// [int] <- str byte offset of 1st mime string
// [int] <- str byte offset of 2nd glob string
// [int] <- str byte offset of 2nd mime string
// ...
// strine1\0string2\0string3\0string4\0....
EINA_LIST_FOREACH(mimes_sorted, l, s)
{
mimes_str_offsets = eina_list_append(mimes_str_offsets,
(void *)mimes_str_len);
mimes_str_len += strlen(s) + 1;
}
EINA_LIST_FOREACH(extn_mimes_sorted, l, s)
{
extn_mimes_str_offsets = eina_list_append(extn_mimes_str_offsets,
(void *)extn_mimes_str_len);
extn_mimes_str_len += strlen(s) + 1;
}
EINA_LIST_FOREACH(glob_mimes_sorted, l, s)
{
glob_mimes_str_offsets = eina_list_append(glob_mimes_str_offsets,
(void *)glob_mimes_str_len);
glob_mimes_str_len += strlen(s) + 1;
}
str_start = 16 + // magic header
sizeof(int) +
(eina_list_count(mimes_sorted) * sizeof(int)) +
sizeof(int) +
(eina_list_count(extn_mimes_sorted) * sizeof(int) * 2) +
sizeof(int) +
(eina_list_count(glob_mimes_sorted) * sizeof(int) * 2);
val = eina_list_count(mimes_sorted);
fwrite(&val, sizeof(val), 1, f);
EINA_LIST_FOREACH(mimes_str_offsets, l, ptr)
{
val = (int)((long)ptr) + str_start;
fwrite(&val, sizeof(val), 1, f);
}
val = eina_list_count(extn_mimes_sorted);
fwrite(&val, sizeof(val), 1, f);
ll = extn_mimes_sorted;
EINA_LIST_FOREACH(extn_mimes_str_offsets, l, ptr)
{
val = (int)((long)ptr) + str_start + mimes_str_len;
fwrite(&val, sizeof(val), 1, f);
s = eina_hash_find(extn_mimes, ll->data);
ptr = find_off(s, mimes_sorted, mimes_str_offsets);
val = (int)((long)ptr) + str_start;
fwrite(&val, sizeof(val), 1, f);
ll = ll->next;
}
val = eina_list_count(glob_mimes_sorted);
fwrite(&val, sizeof(val), 1, f);
ll = glob_mimes_sorted;
EINA_LIST_FOREACH(glob_mimes_str_offsets, l, ptr)
{
val = (int)((long)ptr) + str_start + mimes_str_len + extn_mimes_str_len;
fwrite(&val, sizeof(val), 1, f);
s = eina_hash_find(glob_mimes, ll->data);
ptr = find_off(s, mimes_sorted, mimes_str_offsets);
val = (int)((long)ptr) + str_start;
fwrite(&val, sizeof(val), 1, f);
ll = ll->next;
}
EINA_LIST_FOREACH(mimes_sorted, l, s)
{
fwrite(s, strlen(s) + 1, 1, f);
}
EINA_LIST_FOREACH(extn_mimes_sorted, l, s)
{
fwrite(s, strlen(s) + 1, 1, f);
}
EINA_LIST_FOREACH(glob_mimes_sorted, l, s)
{
fwrite(s, strlen(s) + 1, 1, f);
}
fclose(f);
rename(buf, out);
}
int
main(int argc, char **argv)
{
char buf[PATH_MAX];
const char *s;
int i;
int ret = -1, lockfd = -1;
Eina_List *datadirs, *l;
if (!eina_init()) goto eina_error;
if (!eet_init()) goto eet_error;
if (!ecore_init()) goto ecore_error;
if (!ecore_file_init()) goto ecore_file_error;
if (!efreet_init()) goto efreet_error;
_efreet_mime_cache_log_dom =
eina_log_domain_register("efreet_mime_cache", EFREET_DEFAULT_LOG_COLOR);
if (_efreet_mime_cache_log_dom < 0)
{
EINA_LOG_ERR("Efreet: Could not create a log domain for efreet_mime_cache.");
return -1;
}
for (i = 1; i < argc; i++)
{
if (!strcmp(argv[i], "-v"))
eina_log_domain_level_set("efreet_mime_cache", EINA_LOG_LEVEL_DBG);
else if ((!strcmp(argv[i], "-h")) ||
(!strcmp(argv[i], "-help")) ||
(!strcmp(argv[i], "--h")) ||
(!strcmp(argv[i], "--help")))
{
printf("Options:\n");
printf(" -v Verbose mode\n");
printf(" -d dir1 dir2 Extra dirs\n");
exit(0);
}
else if (!strcmp(argv[i], "-d"))
{
while ((i < (argc - 1)) && (argv[(i + 1)][0] != '-'))
extra_dirs = eina_list_append(extra_dirs, argv[++i]);
}
}
extra_dirs = eina_list_sort(extra_dirs, -1, EINA_COMPARE_CB(strcmp));
/* create homedir */
snprintf(buf, sizeof(buf), "%s/efreet", efreet_cache_home_get());
if (!ecore_file_exists(buf))
{
if (!ecore_file_mkpath(buf)) goto error;
efreet_setowner(buf);
}
/* lock process, so that we only run one copy of this program */
lockfd = cache_lock_file();
if (lockfd == -1) goto error;
mimes = eina_hash_string_superfast_new(NULL);
extn_mimes = eina_hash_string_superfast_new(NULL);
glob_mimes = eina_hash_string_superfast_new(NULL);
etc_mime_types_load("/etc/mime.types");
share_mime_globs_load("/usr/share/mime/globs");
datadirs = efreet_data_dirs_get();
EINA_LIST_FOREACH(datadirs, l, s)
{
snprintf(buf, sizeof(buf), "%s/mime/globs", s);
share_mime_globs_load(buf);
}
EINA_LIST_FOREACH(extra_dirs, l, s)
{
snprintf(buf, sizeof(buf), "%s/mime/globs", s);
share_mime_globs_load(buf);
}
snprintf(buf, sizeof(buf), "%s/mime/globs", efreet_data_home_get());
share_mime_globs_load(buf);
// XXX: load user files and other dirs etc.
// XXX: load globs
hash_list_sort(mimes, &mimes_sorted);
hash_list_sort(extn_mimes, &extn_mimes_sorted);
hash_list_sort(glob_mimes, &glob_mimes_sorted);
#ifdef WORDS_BIGENDIAN
snprintf(buf, sizeof(buf), "%s/efreet/mime_cache_%s.be.dat",
efreet_cache_home_get(), efreet_hostname_get());
#else
snprintf(buf, sizeof(buf), "%s/efreet/mime_cache_%s.le.dat",
efreet_cache_home_get(), efreet_hostname_get());
#endif
store_cache(buf);
ret = 0;
close(lockfd);
error:
efreet_shutdown();
efreet_error:
ecore_file_shutdown();
ecore_file_error:
ecore_shutdown();
ecore_error:
eet_shutdown();
eet_error:
eina_list_free(extra_dirs);
eina_log_domain_unregister(_efreet_mime_cache_log_dom);
eina_shutdown();
eina_error:
return ret;
}

View File

@ -71,6 +71,13 @@ static Eet_Data_Descriptor *subdir_dir_edd = NULL;
static Subdir_Cache *subdir_cache = NULL;
static Eina_Bool subdir_need_save = EINA_FALSE;
static Eina_Hash *mime_monitors = NULL;
static Ecore_Timer *mime_update_timer = NULL;
static Ecore_Exe *mime_cache_exe = NULL;
static void mime_cache_init(void);
static void mime_cache_shutdown(void);
static void
subdir_cache_dir_free(Subdir_Cache_Dir *cd)
{
@ -756,6 +763,10 @@ cache_exe_data_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
if ((ev->lines) && (*ev->lines->line == 'c')) update = EINA_TRUE;
send_signal_icon_cache_update(update);
}
else if (ev->exe == mime_cache_exe)
{
// XXX: ZZZ: handle stdout here from cache updater... if needed
}
return ECORE_CALLBACK_RENEW;
}
@ -774,6 +785,11 @@ cache_exe_del_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
icon_cache_exe = NULL;
if (icon_queue) cache_icon_update(EINA_FALSE);
}
else if (ev->exe == mime_cache_exe)
{
mime_cache_exe = NULL;
send_signal_mime_cache_build();
}
return ECORE_CALLBACK_RENEW;
}
@ -838,6 +854,111 @@ cache_desktop_exists(void)
return desktop_exists;
}
static void
mime_update_launch(void)
{
char file[PATH_MAX];
snprintf(file, sizeof(file),
"%s/efreet/" MODULE_ARCH "/efreet_mime_cache_create",
eina_prefix_lib_get(pfx));
mime_cache_exe = ecore_exe_pipe_run(file,
ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_READ_LINE_BUFFERED,
NULL);
}
static Eina_Bool
mime_update_cache_cb(void *data EINA_UNUSED)
{
mime_update_timer = NULL;
if (mime_cache_exe)
{
ecore_exe_kill(mime_cache_exe);
ecore_exe_free(mime_cache_exe);
}
mime_update_launch();
return EINA_FALSE;
}
static void
mime_changes_cb(void *data EINA_UNUSED, Ecore_File_Monitor *em EINA_UNUSED,
Ecore_File_Event event, const char *path EINA_UNUSED)
{
switch (event)
{
case ECORE_FILE_EVENT_NONE:
/* noop */
break;
case ECORE_FILE_EVENT_CREATED_FILE:
case ECORE_FILE_EVENT_DELETED_FILE:
case ECORE_FILE_EVENT_MODIFIED:
case ECORE_FILE_EVENT_CLOSED:
case ECORE_FILE_EVENT_DELETED_DIRECTORY:
case ECORE_FILE_EVENT_CREATED_DIRECTORY:
case ECORE_FILE_EVENT_DELETED_SELF:
mime_cache_shutdown();
mime_cache_init();
if (mime_update_timer) ecore_timer_del(mime_update_timer);
mime_update_timer = ecore_timer_add(0.2, mime_update_cache_cb, NULL);
break;
}
}
static void
mime_cache_init(void)
{
Ecore_File_Monitor *mon;
Eina_List *datadirs, *l;
const char *s;
char buf[PATH_MAX];
mime_monitors = eina_hash_string_superfast_new(NULL);
mon = ecore_file_monitor_add("/etc/mime.types", mime_changes_cb, NULL);
if (mon) eina_hash_add(mime_monitors, "/etc/mime.types", mon);
mon = ecore_file_monitor_add("/usr/share/mime/globs", mime_changes_cb, NULL);
if (mon) eina_hash_add(mime_monitors, "/usr/share/mime/globs", mon);
datadirs = efreet_data_dirs_get();
EINA_LIST_FOREACH(datadirs, l, s)
{
snprintf(buf, sizeof(buf), "%s/mime/globs", s);
if (!eina_hash_find(mime_monitors, buf))
{
mon = ecore_file_monitor_add(buf, mime_changes_cb, NULL);
if (mon) eina_hash_add(mime_monitors, buf, mon);
}
}
}
static Eina_Bool
mime_cache_monitor_del(const Eina_Hash *hash EINA_UNUSED,
const void *key EINA_UNUSED, void *value,
void *data EINA_UNUSED)
{
Ecore_File_Monitor *mon = value;
ecore_file_monitor_del(mon);
return EINA_TRUE;
}
static void
mime_cache_shutdown(void)
{
if (mime_update_timer)
{
ecore_timer_del(mime_update_timer);
mime_update_timer = NULL;
}
if (mime_monitors)
{
eina_hash_foreach(mime_monitors, mime_cache_monitor_del, NULL);
eina_hash_free(mime_monitors);
mime_monitors = NULL;
}
}
Eina_Bool
cache_init(void)
{
@ -875,6 +996,8 @@ cache_init(void)
efreet_cache_update = 0;
if (!efreet_init()) goto error;
subdir_cache_init();
mime_cache_init();
mime_update_launch();
read_lists();
/* TODO: Should check if system dirs has changed and handles extra_dirs */
desktop_system_dirs = efreet_default_dirs_get(efreet_data_home_get(),
@ -906,6 +1029,7 @@ cache_shutdown(void)
eina_prefix_free(pfx);
pfx = NULL;
mime_cache_shutdown();
subdir_cache_shutdown();
efreet_shutdown();

View File

@ -190,6 +190,12 @@ send_signal_desktop_cache_build(void)
_broadcast(ipc, 1 /* desktop cache build */, 1, NULL, 0);
}
void
send_signal_mime_cache_build(void)
{
_broadcast(ipc, 4 /* mime cache build */, 1, NULL, 0);
}
Eina_Bool
ipc_init(void)
{

View File

@ -4,6 +4,7 @@
void send_signal_icon_cache_update(Eina_Bool update);
void send_signal_desktop_cache_update(Eina_Bool update);
void send_signal_desktop_cache_build(void);
void send_signal_mime_cache_build(void);
Eina_Bool ipc_init(void);
Eina_Bool ipc_shutdown(void);

View File

@ -1,132 +0,0 @@
#include "codegen_example_generated.h"
Evas_Object *
codegen_example_layout_add(Evas_Object *o, Elm_Theme *th, const char *edje_file)
{
Evas_Object *l;
if (edje_file)
elm_theme_extension_add(th, edje_file);
else
elm_theme_extension_add(th, "./codegen_example.edj");
l = elm_layout_add(o);
if (!l) return NULL;
if (!elm_layout_theme_set(l, "example", "mylayout", "default"))
{
evas_object_del(l);
return NULL;
}
return l;
}
void
codegen_example_title_set(Evas_Object *o, const char *value)
{
elm_layout_text_set(o, "example/title", value);
}
const char *
codegen_example_title_get(const Evas_Object *o)
{
return elm_layout_text_get(o, "example/title");
}
void
codegen_example_custom_set(Evas_Object *o, Evas_Object *value)
{
elm_layout_content_set(o, "example/custom", value);
}
Evas_Object *
codegen_example_custom_unset(Evas_Object *o)
{
return elm_layout_content_unset(o, "example/custom");
}
Evas_Object *
codegen_example_custom_get(const Evas_Object *o)
{
return elm_layout_content_get(o, "example/custom");
}
Eina_Bool
codegen_example_box_append(Evas_Object *o, Evas_Object *child)
{
return elm_layout_box_append(o, "example/box", child);
}
Eina_Bool
codegen_example_box_prepend(Evas_Object *o, Evas_Object *child)
{
return elm_layout_box_prepend(o, "example/box", child);
}
Eina_Bool
codegen_example_box_insert_before(Evas_Object *o, Evas_Object *child, const Evas_Object *reference)
{
return elm_layout_box_insert_before(o, "example/box", child, reference);
}
Eina_Bool
codegen_example_box_insert_at(Evas_Object *o, Evas_Object *child, unsigned int pos)
{
return elm_layout_box_insert_at(o, "example/box", child, pos);
}
Evas_Object *
codegen_example_box_remove(Evas_Object *o, Evas_Object *child)
{
return elm_layout_box_remove(o, "example/box", child);
}
Eina_Bool
codegen_example_box_remove_all(Evas_Object *o, Eina_Bool clear)
{
return elm_layout_box_remove_all(o, "example/box", clear);
}
Eina_Bool
codegen_example_table_pack(Evas_Object *o, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
{
return elm_layout_table_pack(o, "example/table", child, col, row, colspan, rowspan);
}
Evas_Object *
codegen_example_table_unpack(Evas_Object *o, Evas_Object *child)
{
return elm_layout_table_unpack(o, "example/table", child);
}
Eina_Bool
codegen_example_table_clear(Evas_Object *o, Eina_Bool clear)
{
return elm_layout_table_clear(o, "example/table", clear);
}
void
codegen_example_swallow_grow_emit(Evas_Object *o)
{
elm_layout_signal_emit(o, "button,enlarge", "");
}
void
codegen_example_swallow_shrink_emit(Evas_Object *o)
{
elm_layout_signal_emit(o, "button,reduce", "");
}
void
codegen_example_size_changed_callback_add(Evas_Object *o, Edje_Signal_Cb func, void *data)
{
elm_layout_signal_callback_add(o, "size,changed", "", func, data);
}
void
codegen_example_size_changed_callback_del(Evas_Object *o, Edje_Signal_Cb func)
{
elm_layout_signal_callback_del(o, "size,changed", "", func);
}

View File

@ -1,65 +0,0 @@
#ifndef _CODEGEN_EXAMPLE_GENERATED_H
#define _CODEGEN_EXAMPLE_GENERATED_H
#include <Edje.h>
#include <Elementary.h>
#include <Evas.h>
#include <stdlib.h>
/**
* @brief Creates the layout object and set the theme
* @param o The parent
* @param th The theme to add to, or if NULL, the default theme
* @param edje_file The path to edj, if NULL it's used the path given
* to elementary_codegen
*/
Evas_Object *codegen_example_layout_add(Evas_Object *o, Elm_Theme *th, const char *edje_file);
/**
* @brief The example title
*/
void codegen_example_title_set(Evas_Object *o, const char *value);
const char *codegen_example_title_get(const Evas_Object *o);
/**
* @brief The swallow part
*/
void codegen_example_custom_set(Evas_Object *o, Evas_Object *value);
Evas_Object *codegen_example_custom_unset(Evas_Object *o);
Evas_Object *codegen_example_custom_get(const Evas_Object *o);
/**
* @brief The box part
*/
Eina_Bool codegen_example_box_append(Evas_Object *o, Evas_Object *child);
Eina_Bool codegen_example_box_prepend(Evas_Object *o, Evas_Object *child);
Eina_Bool codegen_example_box_insert_before(Evas_Object *o, Evas_Object *child, const Evas_Object *reference);
Eina_Bool codegen_example_box_insert_at(Evas_Object *o, Evas_Object *child, unsigned int pos);
Evas_Object *codegen_example_box_remove(Evas_Object *o, Evas_Object *child);
Eina_Bool codegen_example_box_remove_all(Evas_Object *o, Eina_Bool clear);
/**
* @brief The table part
*/
Eina_Bool codegen_example_table_pack(Evas_Object *o, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan);
Evas_Object *codegen_example_table_unpack(Evas_Object *o, Evas_Object *child);
Eina_Bool codegen_example_table_clear(Evas_Object *o, Eina_Bool clear);
/**
* @brief Executed when the button enlarges
*/
void codegen_example_swallow_grow_emit(Evas_Object *o);
/**
* @brief Executed when the button reduces
*/
void codegen_example_swallow_shrink_emit(Evas_Object *o);
/**
* @brief Emit the signal size,changed
*/
void codegen_example_size_changed_callback_add(Evas_Object *o, Edje_Signal_Cb func, void *data);
void codegen_example_size_changed_callback_del(Evas_Object *o, Edje_Signal_Cb func);
#endif /* _CODEGEN_EXAMPLE_GENERATED_H */

View File

@ -203,6 +203,8 @@ _icon_desktop_cache_update_event_add(int event_type)
ecore_event_add(event_type, ev, icon_cache_update_free, l);
}
EAPI void (*_efreet_mime_update_func) (void) = NULL;
static Eina_Bool
_cb_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
@ -223,6 +225,10 @@ _cb_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
_icon_desktop_cache_update_event_add(EFREET_EVENT_DESKTOP_CACHE_UPDATE);
}
else if (e->major == 4) // mime cache update
{
if (_efreet_mime_update_func) _efreet_mime_update_func();
}
return ECORE_CALLBACK_DONE;
}

View File

@ -32,11 +32,8 @@ static int _efreet_mime_log_dom = -1;
#include "Efreet_Mime.h"
#include "efreet_private.h"
static Eina_List *globs = NULL; /* contains Efreet_Mime_Glob structs */
static Eina_List *magics = NULL; /* contains Efreet_Mime_Magic structs */
static Eina_Hash *wild = NULL; /* contains *.ext and mime.types globs*/
static Eina_Hash *monitors = NULL; /* contains file monitors */
static Eina_Hash *mime_icons = NULL; /* contains cache with mime->icons */
static Eina_List *magics = NULL; // contains Efreet_Mime_Magic structs
static Eina_Hash *mime_icons = NULL; // contains cache with mime->icons
static Eina_Inlist *mime_icons_lru = NULL;
static unsigned int _efreet_mime_init_count = 0;
@ -89,13 +86,6 @@ static enum
*/
//#define EFREET_MIME_ICONS_DEBUG
typedef struct Efreet_Mime_Glob Efreet_Mime_Glob;
struct Efreet_Mime_Glob
{
const char *glob;
const char *mime;
};
typedef struct Efreet_Mime_Magic Efreet_Mime_Magic;
struct Efreet_Mime_Magic
{
@ -134,9 +124,6 @@ struct Efreet_Mime_Icon_Entry
unsigned int size;
};
static int efreet_mime_glob_remove(const char *glob);
static void efreet_mime_mime_types_load(const char *file);
static void efreet_mime_shared_mimeinfo_globs_load(const char *file);
static void efreet_mime_shared_mimeinfo_magic_load(const char *file);
static void efreet_mime_shared_mimeinfo_magic_parse(char *data, int size);
static const char *efreet_mime_magic_check_priority(const char *file,
@ -145,19 +132,12 @@ static const char *efreet_mime_magic_check_priority(const char *file,
static int efreet_mime_init_files(void);
static const char *efreet_mime_special_check(const char *file);
static const char *efreet_mime_fallback_check(const char *file);
static void efreet_mime_glob_free(void *data);
static void efreet_mime_magic_free(void *data);
static void efreet_mime_magic_entry_free(void *data);
static int efreet_mime_glob_match(const char *str, const char *glob);
static int efreet_mime_glob_case_match(char *str, const char *glob);
static int efreet_mime_endian_check(void);
static void efreet_mime_monitor_add(const char *file);
static void efreet_mime_cb_update_file(void *data,
Ecore_File_Monitor *monitor,
Ecore_File_Event event,
const char *path);
static void efreet_mime_icons_flush(double now);
static void efreet_mime_icon_entry_head_free(Efreet_Mime_Icon_Entry_Head *entry);
static void efreet_mime_icon_entry_add(const char *mime,
@ -169,6 +149,218 @@ static const char *efreet_mime_icon_entry_find(const char *mime,
unsigned int size);
static void efreet_mime_icons_debug(void);
static Eina_File *mimedb = NULL;
static unsigned char *mimedb_ptr = NULL;
static size_t mimedb_size = 0;
static void
_efreet_mimedb_shutdown(void)
{
if (mimedb)
{
if (mimedb_ptr) eina_file_map_free(mimedb, mimedb_ptr);
eina_file_close(mimedb);
mimedb = NULL;
mimedb_ptr = NULL;
mimedb_size = 0;
}
}
static void
_efreet_mimedb_update(void)
{
char buf[PATH_MAX];
if (mimedb)
{
if (mimedb_ptr) eina_file_map_free(mimedb, mimedb_ptr);
eina_file_close(mimedb);
mimedb = NULL;
mimedb_ptr = NULL;
mimedb_size = 0;
}
#ifdef WORDS_BIGENDIAN
snprintf(buf, sizeof(buf), "%s/efreet/mime_cache_%s.be.dat",
efreet_cache_home_get(), efreet_hostname_get());
#else
snprintf(buf, sizeof(buf), "%s/efreet/mime_cache_%s.le.dat",
efreet_cache_home_get(), efreet_hostname_get());
#endif
mimedb = eina_file_open(buf, EINA_FALSE);
if (mimedb)
{
mimedb_ptr = eina_file_map_all(mimedb, EINA_FILE_POPULATE);
if (mimedb_ptr)
{
mimedb_size = eina_file_size_get(mimedb);
if ((mimedb_size > (16 + 4 + 4 + 4) &&
(!strncmp((char *)mimedb_ptr, "EfrEeT-MiMeS-001", 16))))
{
// load ok - magic fine. more sanity checks?
}
else
{
eina_file_map_free(mimedb, mimedb_ptr);
mimedb_ptr = NULL;
eina_file_close(mimedb);
mimedb = NULL;
mimedb_size = 0;
}
}
else
{
eina_file_close(mimedb);
mimedb = NULL;
}
}
}
static const char *
_efreet_mimedb_str_get(unsigned int offset)
{
if (offset < (16 + 4 + 4 + 4)) return NULL;
if (offset >= mimedb_size) return NULL;
return (const char *)(mimedb_ptr + offset);
}
static unsigned int
_efreet_mimedb_uint_get(unsigned int index)
// index is the unit NUMBER AFTER the header
{
unsigned int *ptr;
ptr = ((unsigned int *)(mimedb_ptr + 16)) + index;
if ((size_t)(((unsigned char *)ptr) - mimedb_ptr) >= (mimedb_size - 4))
return 0;
return *ptr;
}
static unsigned int
_efreet_mimedb_mime_count(void)
{
return _efreet_mimedb_uint_get(0);
}
/**** currently unused - here for symmetry and future use
static const char *
_efreet_mimedb_mime_get(unsigned int num)
{
unsigned int offset = _efreet_mimedb_uint_get
(1 + num);
return _efreet_mimedb_str_get(offset);
}
*/
static unsigned int
_efreet_mimedb_extn_count(void)
{
return _efreet_mimedb_uint_get(1 + _efreet_mimedb_mime_count());
}
static const char *
_efreet_mimedb_extn_get(unsigned int num)
{
unsigned int offset = _efreet_mimedb_uint_get
(1 + _efreet_mimedb_mime_count() + 1 + (num * 2));
return _efreet_mimedb_str_get(offset);
}
static const char *
_efreet_mimedb_extn_mime_get(unsigned int num)
{
unsigned int offset = _efreet_mimedb_uint_get
(1 + _efreet_mimedb_mime_count() + 1 + (num * 2) + 1);
return _efreet_mimedb_str_get(offset);
}
static const char *
_efreet_mimedb_extn_find(const char *extn)
{
unsigned int i, begin, end;
const char *s;
// binary search keys to get value
begin = 0;
end = _efreet_mimedb_extn_count();
i = (begin + end) / 2;
for (;;)
{
s = _efreet_mimedb_extn_get(i);
if (s)
{
int v = strcmp(extn, s);
if (v < 0)
{
end = i;
i = (begin + end) / 2;
if ((end - begin) == 0) break;
}
else if (v > 0)
{
if ((end - begin) > 1)
{
begin = i;
i = (begin + end) / 2;
if (i == end) break;
}
else
{
if ((end - begin) == 0) break;
begin = end;
i = end;
}
}
else if (v == 0)
return _efreet_mimedb_extn_mime_get(i);
}
else
{
break;
}
}
return NULL;
}
static unsigned int
_efreet_mimedb_glob_count(void)
{
return _efreet_mimedb_uint_get
(1 + _efreet_mimedb_mime_count() +
1 + (_efreet_mimedb_extn_count() * 2));
}
static const char *
_efreet_mimedb_glob_get(unsigned int num)
{
unsigned int offset = _efreet_mimedb_uint_get
(1 + _efreet_mimedb_mime_count() +
1 + (_efreet_mimedb_extn_count() * 2) +
1 + (num * 2));
return _efreet_mimedb_str_get(offset);
}
static const char *
_efreet_mimedb_glob_mime_get(unsigned int num)
{
unsigned int offset = _efreet_mimedb_uint_get
(1 + _efreet_mimedb_mime_count() +
1 + (_efreet_mimedb_extn_count() * 2) +
1 + (num * 2) + 1);
return _efreet_mimedb_str_get(offset);
}
/** --------------------------------- **/
EAPI int
efreet_mime_init(void)
{
@ -194,14 +386,15 @@ efreet_mime_init(void)
}
efreet_mime_endianess = efreet_mime_endian_check();
monitors = eina_hash_string_superfast_new(EINA_FREE_CB(ecore_file_monitor_del));
efreet_mime_type_cache_clear();
_efreet_mimedb_update();
if (!efreet_mime_init_files())
goto unregister_log_domain;
_efreet_mime_update_func = _efreet_mimedb_update;
return _efreet_mime_init_count;
unregister_log_domain:
@ -228,6 +421,9 @@ efreet_mime_shutdown(void)
if (--_efreet_mime_init_count != 0)
return _efreet_mime_init_count;
_efreet_mimedb_shutdown();
_efreet_mime_update_func = NULL;
efreet_mime_icons_debug();
IF_RELEASE(_mime_inode_symlink);
@ -241,10 +437,7 @@ efreet_mime_shutdown(void)
IF_RELEASE(_mime_application_octet_stream);
IF_RELEASE(_mime_text_plain);
IF_FREE_LIST(globs, efreet_mime_glob_free);
IF_FREE_LIST(magics, efreet_mime_magic_free);
IF_FREE_HASH(monitors);
IF_FREE_HASH(wild);
IF_FREE_HASH(mime_icons);
eina_log_domain_unregister(_efreet_mime_log_dom);
_efreet_mime_log_dom = -1;
@ -387,11 +580,10 @@ efreet_mime_magic_type_get(const char *file)
EAPI const char *
efreet_mime_globs_type_get(const char *file)
{
Eina_List *l;
Efreet_Mime_Glob *g;
char *sl, *p;
const char *s;
char *ext, *mime;
const char *s, *mime;
char *ext;
unsigned int i, n;
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
@ -406,25 +598,27 @@ efreet_mime_globs_type_get(const char *file)
while (p)
{
p++;
if (p && (mime = eina_hash_find(wild, p))) return mime;
if (p && (mime = _efreet_mimedb_extn_find(p))) return mime;
p = strchr(p, '.');
}
}
/* Fallback to the other globs if not found */
EINA_LIST_FOREACH(globs, l, g)
// Fallback to the other globs if not found
n = _efreet_mimedb_glob_count();
for (i = 0; i < n; i++)
{
if (efreet_mime_glob_match(file, g->glob))
return g->mime;
s = _efreet_mimedb_glob_get(i);
if (efreet_mime_glob_match(file, s))
return _efreet_mimedb_glob_mime_get(i);
}
ext = alloca(strlen(file) + 1);
for (s = file, p = ext; *s; s++, p++) *p = tolower(*s);
*p = 0;
EINA_LIST_FOREACH(globs, l, g)
for (i = 0; i < n; i++)
{
if (efreet_mime_glob_case_match(ext, g->glob))
return g->mime;
s = _efreet_mimedb_glob_get(i);
if (efreet_mime_glob_case_match(ext, s))
return _efreet_mimedb_glob_mime_get(i);
}
return NULL;
}
@ -455,72 +649,6 @@ efreet_mime_endian_check(void)
return (*((char*)(&test)));
}
/**
* @internal
* @param file File to monitor
* @return Returns no value.
* @brief Creates a new file monitor if we aren't already monitoring the
* given file
*/
static void
efreet_mime_monitor_add(const char *file)
{
Ecore_File_Monitor *fm = NULL;
/* if this is already in our hash then we're already monitoring so no
* reason to re-monitor */
if (eina_hash_find(monitors, file))
return;
if ((fm = ecore_file_monitor_add(file, efreet_mime_cb_update_file, NULL)))
{
eina_hash_del(monitors, file, NULL);
eina_hash_add(monitors, file, fm);
}
}
/**
* @internal
* @param datadirs List of XDG data dirs
* @param datahome Path to XDG data home directory
* @return Returns no value
* @brief Read all glob files in XDG data/home dirs.
* Also reads the /etc/mime.types file.
*/
static void
efreet_mime_load_globs(Eina_List *datadirs, const char *datahome)
{
Eina_List *l;
char buf[4096];
const char *datadir = NULL;
IF_FREE_HASH(wild);
wild = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
while (globs)
{
efreet_mime_glob_free(eina_list_data_get(globs));
globs = eina_list_remove_list(globs, globs);
}
/*
* This is here for legacy reasons. It is mentioned briefly
* in the spec and seems to still be quite valid. It is
* loaded first so the globs files will override anything
* in here.
*/
efreet_mime_mime_types_load("/etc/mime.types");
datadir = datahome;
snprintf(buf, sizeof(buf), "%s/mime/globs", datadir);
efreet_mime_shared_mimeinfo_globs_load(buf);
EINA_LIST_FOREACH(datadirs, l, datadir)
{
snprintf(buf, sizeof(buf), "%s/mime/globs", datadir);
efreet_mime_shared_mimeinfo_globs_load(buf);
}
}
/**
* @internal
* @param datadirs List of XDG data dirs
@ -552,39 +680,6 @@ efreet_mime_load_magics(Eina_List *datadirs, const char *datahome)
}
}
/**
* @internal
* @param data Data pointer passed to monitor_add
* @param monitor Ecore_File_Monitor associated with this event
* @param event The type of event
* @param path Path to the file that was updated
* @return Returns no value
* @brief Callback for all file monitors. Just reloads the appropriate
* list depending on which file changed. If it was a magic file
* only the magic list is updated. If it was a glob file or /etc/mime.types,
* the globs are updated.
*/
static void
efreet_mime_cb_update_file(void *data EINA_UNUSED,
Ecore_File_Monitor *monitor EINA_UNUSED,
Ecore_File_Event event EINA_UNUSED,
const char *path)
{
Eina_List *datadirs = NULL;
const char *datahome = NULL;
if (!(datahome = efreet_data_home_get()))
return;
if (!(datadirs = efreet_data_dirs_get()))
return;
if (strstr(path, "magic"))
efreet_mime_load_magics(datadirs, datahome);
else
efreet_mime_load_globs(datadirs, datahome);
}
/**
* @internal
* @param datadirs List of XDG data dirs
@ -595,10 +690,8 @@ efreet_mime_cb_update_file(void *data EINA_UNUSED,
static int
efreet_mime_init_files(void)
{
Eina_List *l;
Eina_List *datadirs = NULL;
char buf[PATH_MAX];
const char *datahome, *datadir = NULL;
const char *datahome;
if (!(datahome = efreet_data_home_get()))
return 0;
@ -606,32 +699,15 @@ efreet_mime_init_files(void)
if (!(datadirs = efreet_data_dirs_get()))
return 0;
/*
* Add our file monitors
* We watch the directories so we can watch for new files
*/
datadir = datahome;
snprintf(buf, sizeof(buf), "%s/mime", datadir);
efreet_mime_monitor_add(buf);
EINA_LIST_FOREACH(datadirs, l, datadir)
{
snprintf(buf, sizeof(buf), "%s/mime", datadir);
efreet_mime_monitor_add(buf);
}
efreet_mime_monitor_add("/etc/mime.types");
/* Load our mime information */
efreet_mime_load_globs(datadirs, datahome);
efreet_mime_load_magics(datadirs, datahome);
_mime_inode_symlink = eina_stringshare_add("inode/symlink");
_mime_inode_fifo = eina_stringshare_add("inode/fifo");
_mime_inode_chardevice = eina_stringshare_add("inode/chardevice");
_mime_inode_blockdevice = eina_stringshare_add("inode/blockdevice");
_mime_inode_socket = eina_stringshare_add("inode/socket");
_mime_inode_mountpoint = eina_stringshare_add("inode/mountpoint");
_mime_inode_directory = eina_stringshare_add("inode/directory");
_mime_inode_symlink = eina_stringshare_add("inode/symlink");
_mime_inode_fifo = eina_stringshare_add("inode/fifo");
_mime_inode_chardevice = eina_stringshare_add("inode/chardevice");
_mime_inode_blockdevice = eina_stringshare_add("inode/blockdevice");
_mime_inode_socket = eina_stringshare_add("inode/socket");
_mime_inode_mountpoint = eina_stringshare_add("inode/mountpoint");
_mime_inode_directory = eina_stringshare_add("inode/directory");
_mime_application_x_executable = eina_stringshare_add("application/x-executable");
_mime_application_octet_stream = eina_stringshare_add("application/octet-stream");
_mime_text_plain = eina_stringshare_add("text/plain");
@ -779,198 +855,6 @@ efreet_mime_fallback_check(const char *file)
return _mime_text_plain;
}
/**
* @internal
* @param glob Glob to search for
* @return Returns 1 on success, 0 on failure
* @brief Removes a glob from the list
*/
static int
efreet_mime_glob_remove(const char *glob)
{
Efreet_Mime_Glob *mime = NULL;
if ((mime = eina_list_search_unsorted(globs, EINA_COMPARE_CB(strcmp), glob)))
{
globs = eina_list_remove(globs, mime);
IF_RELEASE(mime->glob);
IF_RELEASE(mime->mime);
FREE(mime);
return 1;
}
return 0;
}
static inline const char *
efreet_eat_space(const char *head, const Eina_File_Line *ln, Eina_Bool not)
{
if (not)
{
while (!isspace(*head) && (head < ln->end))
head++;
}
else
{
while (isspace(*head) && (head < ln->end))
head++;
}
return head;
}
/**
* @internal
* @param file mime.types file to load
* @return Returns no value
* @brief Loads values from a mime.types style file
* into the globs list.
* @note Format:
* application/msaccess mdb
* application/msword doc dot
*/
static void
efreet_mime_mime_types_load(const char *file)
{
const Eina_File_Line *ln;
Eina_Iterator *it;
Eina_File *f;
const char *head_line;
const char *word_start;
const char *mimetype;
EINA_SAFETY_ON_NULL_RETURN(file);
f = eina_file_open(file, 0);
if (!f) return;
it = eina_file_map_lines(f);
if (it)
{
Eina_Strbuf *ext;
ext = eina_strbuf_new();
EINA_ITERATOR_FOREACH(it, ln)
{
head_line = efreet_eat_space(ln->start, ln, EINA_FALSE);
if (head_line == ln->end) continue ;
if (*head_line == '#') continue ;
word_start = head_line;
head_line = efreet_eat_space(head_line, ln, EINA_TRUE);
if (head_line == ln->end) continue ;
mimetype = eina_stringshare_add_length(word_start, head_line - word_start);
do
{
head_line = efreet_eat_space(head_line, ln, EINA_FALSE);
if (head_line == ln->end) break ;
word_start = head_line;
head_line = efreet_eat_space(head_line, ln, EINA_TRUE);
eina_strbuf_append_length(ext, word_start, head_line - word_start);
eina_hash_del(wild,
eina_strbuf_string_get(ext),
NULL);
eina_hash_add(wild,
eina_strbuf_string_get(ext),
eina_stringshare_ref(mimetype));
eina_strbuf_reset(ext);
}
while (head_line < ln->end);
eina_stringshare_del(mimetype);
}
eina_strbuf_free(ext);
eina_iterator_free(it);
}
eina_file_close(f);
}
/**
* @internal
* @param file globs file to load
* @return Returns no value
* @brief Loads values from a mime.types style file
* into the globs list.
* @note Format:
* text/vnd.wap.wml:*.wml
* application/x-7z-compressed:*.7z
* application/vnd.corel-draw:*.cdr
* text/spreadsheet:*.sylk
*/
static void
efreet_mime_shared_mimeinfo_globs_load(const char *file)
{
FILE *f = NULL;
char buf[4096], mimetype[4096], ext[4096], *p, *pp;
Efreet_Mime_Glob *mime = NULL;
f = fopen(file, "rb");
if (!f) return;
while (fgets(buf, sizeof(buf), f))
{
p = buf;
while (isspace(*p) && (*p != 0) && (*p != '\n')) p++;
if (*p == '#') continue;
if ((*p == '\n') || (*p == 0)) continue;
pp = p;
while ((*p != ':') && (*p != 0) && (*p != '\n')) p++;
if ((*p == '\n') || (*p == 0)) continue;
strncpy(mimetype, pp, (p - pp));
mimetype[p - pp] = 0;
p++;
pp = ext;
while ((*p != 0) && (*p != '\n'))
{
*pp = *p;
pp++;
p++;
}
*pp = 0;
if (ext[0] == '*' && ext[1] == '.')
{
eina_hash_del(wild, &(ext[2]), NULL);
eina_hash_add(wild, &(ext[2]),
(void*)eina_stringshare_add(mimetype));
}
else
{
mime = NEW(Efreet_Mime_Glob, 1);
if (mime)
{
mime->mime = eina_stringshare_add(mimetype);
mime->glob = eina_stringshare_add(ext);
if ((!mime->mime) || (!mime->glob))
{
IF_RELEASE(mime->mime);
IF_RELEASE(mime->glob);
FREE(mime);
}
else
{
efreet_mime_glob_remove(ext);
globs = eina_list_append(globs, mime);
}
}
}
}
fclose(f);
}
/**
* @internal
* @param in Number to count the digits
@ -1337,22 +1221,6 @@ efreet_mime_magic_check_priority(const char *file,
return NULL;
}
/**
* @internal
* @param data Data pointer that is being destroyed
* @return Returns no value
* @brief Callback for globs destroy
*/
static void
efreet_mime_glob_free(void *data)
{
Efreet_Mime_Glob *m = data;
IF_RELEASE(m->mime);
IF_RELEASE(m->glob);
IF_FREE(m);
}
/**
* @internal
* @param data Data pointer that is being destroyed

View File

@ -251,6 +251,8 @@ EAPI void efreet_fsetowner(int fd);
EAPI extern int efreet_cache_update;
EAPI extern void (*_efreet_mime_update_func) (void);
#undef EAPI
#define EAPI