forked from enlightenment/efl
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:
parent
56c52311e5
commit
561f8eaa8f
|
@ -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
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/efreet_desktop_cache_create
|
||||
/efreet_icon_cache_create
|
||||
/efreetd
|
||||
/efreet_mime_cache_create
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue