Enlightenment CVS committal Author : dj2 Project : e17 Module : libs/efreet
Dir : e17/libs/efreet/src/lib Modified Files: efreet_mime.c Log Message: - update the magic parser to use mmap. fixes earlier hack =================================================================== RCS file: /cvs/e/e17/libs/efreet/src/lib/efreet_mime.c,v retrieving revision 1.10 retrieving revision 1.11 diff -u -3 -r1.10 -r1.11 --- efreet_mime.c 3 Jul 2007 14:12:12 -0000 1.10 +++ efreet_mime.c 3 Jul 2007 16:10:30 -0000 1.11 @@ -67,24 +67,25 @@ char *value; }; -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 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, unsigned int start, unsigned int end); -static int efreet_mime_init_files(void); +static int efreet_mime_init_files(void); static const char * efreet_mime_special_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_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, +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); @@ -268,7 +269,7 @@ IF_FREE_LIST(magics); magics = ecore_list_new(); ecore_list_set_free_cb(magics, efreet_mime_magic_free); - + datadir = datahome; ecore_list_goto_first(datadirs); while (datadir) @@ -627,8 +628,40 @@ /** * @internal * @param file: File to parse - * @return Returns number of digits - * @brief Parses a magic file and adds information to magics list + * @return Returns no value + * @brief Loads a magic file and adds information to magics list + */ +static void +efreet_mime_shared_mimeinfo_magic_load(const char *file) +{ + int fd = -1, size; + char *data = (void *)-1; + + if (!file) return; + + size = ecore_file_size(file); + if (size <= 0) return; + + fd = open(file, O_RDONLY); + if (fd == -1) return; + + data = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (data == (void *)-1) + { + close(fd); + return; + } + + efreet_mime_shared_mimeinfo_magic_parse(data, size); + + munmap(data, size); + close(fd); +} + +/** + * @param data: The data from the file + * @return Returns no value + * @brief Parses a magic file * @note Format: * * ---------------------------------------------------------------------- @@ -663,226 +696,178 @@ * quicker, uses less memory and will acheive the same exact effect. */ static void -efreet_mime_shared_mimeinfo_magic_load(const char *file) +efreet_mime_shared_mimeinfo_magic_parse(char *data, int size) { - FILE *f = NULL; - int priority = 0, i = 0; - char buf[4096], mimetype[4096]; Efreet_Mime_Magic *mime = NULL; Efreet_Mime_Magic_Entry *entry = NULL; - int bytes_read = 0, last_section = 0; - - f = fopen(file, "rb"); - if (!f) return; - - /* Check for magic string. Will also move us to first section */ - if (fread(buf, 1, 12, f)) - { - if (memcmp(buf, "MIME-Magic\0\n", 12)) - return; - } - - while ((bytes_read = fread(buf, 1, sizeof(buf), f))) + char *ptr; + + ptr = data; + + /* make sure we're a magic file */ + if (!ptr || strncmp(ptr, "MIME-Magic\0\n", 12)) + return; + + ptr += 12; + + for (; (ptr - data) < size; ) { - for (i = 0; i < bytes_read; ) + if (*ptr == '[') { - if (buf[i] == '[') + char *val, buf[512]; + + /* Append Mime to list of magics */ + if (mime) { - char *val; + ecore_list_append(magics, mime); + mime = NULL; + } - if (entry) - { - IF_FREE(entry->mask); - IF_FREE(entry->value); - FREE(entry); - } - - last_section = i; - i++; - val = strtok(&(buf[i]), ":"); - if (val) - { - priority = atoi(val); + mime = NEW(Efreet_Mime_Magic, 1); + mime->entries = ecore_list_new(); + ecore_list_set_free_cb(mime->entries, + efreet_mime_magic_entry_free); + + val = ++ptr; + while ((*val != ':')) val++; + memcpy(&buf, ptr, val - ptr); + buf[val - ptr] = '\0'; + + mime->priority = atoi(buf); + ptr = ++val; + + while ((*val != ']')) val++; + memcpy(&buf, ptr, val - ptr); + buf[val - ptr] = '\0'; - val = strtok(NULL, "]"); - if (val) - { - strncpy(mimetype, val, sizeof(mimetype)); - - mime = NEW(Efreet_Mime_Magic, 1); - mime->mime = ecore_string_instance(mimetype); - mime->priority = priority; - mime->entries = ecore_list_new(); - ecore_list_set_free_cb(mime->entries, - efreet_mime_magic_entry_free); + mime->mime = ecore_string_instance(buf); + ptr = ++val; - while (i < bytes_read && buf[i] != '\n') ++i; - } else - i = 4096; /* forward to force buffer to get filled again */ + while (*ptr != '\n') ptr++; + } + else + { + if (!mime) continue; + if (!entry) + { + if (!(entry = NEW(Efreet_Mime_Magic_Entry, 1))) + { + IF_FREE_LIST(magics); + return; } - else - i = 4096; /* forward to force buffer to get filled again */ - } - else - { - if (!mime) continue; + entry->indent = 0; + entry->offset = 0; + entry->value_len = 0; + entry->word_size = 1; + entry->range_len = 1; + entry->mask = NULL; + entry->value = NULL; + ptr++; + + ecore_list_append(mime->entries, entry); + } - i++; - switch(buf[i - 1]) - { - case '>': - entry->offset = atoi(&buf[i]); - i += efreet_mime_count_digits(entry->offset); - break; + switch(*ptr) + { + case '>': + ptr ++; + entry->offset = atoi(ptr); + ptr += efreet_mime_count_digits(entry->offset); + break; - case '=': - if (efreet_mime_endianess == EFREET_ENDIAN_LITTLE) - entry->value_len = ntohs(buf[i + 1] << 8 | (short)(buf[i])); - else - entry->value_len = ntohs((short)(buf[i + 1]) | buf[i] << 8); - - i += 2; + case '=': + ptr++; - entry->value = NEW(1, entry->value_len); - memcpy(entry->value, &(buf[i]), entry->value_len); - i += entry->value_len; - break; + if (efreet_mime_endianess == EFREET_ENDIAN_LITTLE) + entry->value_len = (*ptr) << 8 | (unsigned short)(*(ptr + 1)); + else + entry->value_len = (*(ptr + 1)) << 8 | (unsigned short)(*ptr); - case '&': - entry->mask = NEW(1, entry->value_len); - memcpy(entry->mask, &(buf[i]), entry->value_len); - i += entry->value_len; - break; + ptr += 2; - case '~': - entry->word_size = atoi(&(buf[i])); - if (((entry->word_size != 0) - && (entry->word_size != 1) - && (entry->word_size != 2) - && (entry->word_size != 4)) - || (entry->value_len % entry->word_size)) - { - /* Invalid, Destroy */ - FREE(entry->value); - FREE(entry->mask); - FREE(entry); - while ((i < bytes_read) && (buf[i] != '\n')) ++i; - break; - } + entry->value = NEW(1, entry->value_len); + memcpy(entry->value, ptr, entry->value_len); + ptr += entry->value_len; + break; + + case '&': + ptr++; + entry->mask = NEW(1, entry->value_len); + memcpy(entry->mask, ptr, entry->value_len); + ptr += entry->value_len; + break; + + case '~': + ptr++; + entry->word_size = atoi(ptr); + if (((entry->word_size != 0) + && (entry->word_size != 1) + && (entry->word_size != 2) + && (entry->word_size != 4)) + || (entry->value_len % entry->word_size)) + { + /* Invalid, Destroy */ + FREE(entry->value); + FREE(entry->mask); + FREE(entry); + + while (*ptr != '\n') ptr++; + break; + } - if (efreet_mime_endianess == EFREET_ENDIAN_LITTLE) + if (efreet_mime_endianess == EFREET_ENDIAN_LITTLE) + { + int j; + + for (j = 0; j < entry->value_len; j += entry->word_size) { - int j; - for (j = 0; j < entry->value_len; j += entry->word_size) - { - if (entry->word_size == 2) - { - ((short*)entry->value)[j] = + if (entry->word_size == 2) + { + ((short*)entry->value)[j] = ntohs(((short*)entry->value)[j]); - if (entry->mask) - ((short*)entry->mask)[j] = + if (entry->mask) + ((short*)entry->mask)[j] = ntohs(((short*)entry->mask)[j]); - } - else if (entry->word_size == 4) - { - ((long*)entry->value)[j] = + } + else if (entry->word_size == 4) + { + ((long*)entry->value)[j] = ntohl(((long*)entry->value)[j]); - if (entry->mask) - ((long*)entry->mask)[j] = + if (entry->mask) + ((long*)entry->mask)[j] = ntohl(((long*)entry->mask)[j]); - } } } + } - i += efreet_mime_count_digits(entry->word_size); - break; - - case '+': - entry->range_len = atoi(&(buf[i])); - i += efreet_mime_count_digits(entry->range_len); - break; - - default: - if (isdigit(buf[i])) - { - i--; - entry->indent = atoi(&buf[i]); - i += efreet_mime_count_digits(entry->indent); - } - break; - } - } - - /* - * Reached the end of the file. Need to go back to the last - * section. This can probably be elmiminated if the file is - * read another way which allows random access without having - * to read the file in chunks. This works fine for now though. - */ - if (i >= 4096) - { - /* If we have a mime, clean it up */ - if (mime) - { - Efreet_Mime_Magic *m; - - IF_FREE_LIST(mime->entries); - - m = ecore_list_goto_last(magics); - if (m && !(strcmp(m->mime,mimetype))) - ecore_list_remove_destroy(magics); - - FREE(mime); - } - - /* - * If we finished in the middle of an entry, make sure to - * clean it up as well. - */ - if (entry) - { - IF_FREE(entry->value); - IF_FREE(entry->mask); - FREE(entry); - } - - fseek(f, last_section - 4096, SEEK_CUR); - break; - } - - /* Create our new structure */ - if (buf[i] == '\n') - { - if (mime->mime && entry) - ecore_list_append(mime->entries, entry); + ptr += efreet_mime_count_digits(entry->word_size); + break; - if (!(entry = NEW(Efreet_Mime_Magic_Entry, 1))) - { - IF_FREE_LIST(magics); - return; - } + case '+': + ptr++; + entry->range_len = atoi(ptr); + ptr += efreet_mime_count_digits(entry->range_len); + break; + + case '\n': + ptr++; + entry = NULL; + break; - entry->indent = 0; - entry->offset = 0; - entry->value_len = 0; - entry->word_size = 1; - entry->range_len = 1; - entry->mask = NULL; - entry->value = NULL; - i++; - } - - /* Append Mime to list of magics */ - if (mime && ((buf[i] == '[') || (i >= bytes_read))) - { - ecore_list_append(magics, mime); - mime = NULL; + default: + if (isdigit(*ptr)) + { + entry->indent = atoi(ptr); + ptr += efreet_mime_count_digits(entry->indent); + } + break; } } - } + } + if (entry) { IF_FREE(entry->value); @@ -911,7 +896,7 @@ unsigned int i = 0, offset = 0,level = 0, match = 0, bytes_read = 0; const char *last_mime = NULL; char c, v, buf[EFREET_MIME_MAGIC_BUFFER_SIZE]; - + f = fopen(file, "rb"); if (!f) return NULL; @@ -926,7 +911,7 @@ { if ((start != 0) && (m->priority > start)) continue; - + if (m->priority < end) break; @@ -946,23 +931,29 @@ if (last_mime) return last_mime; } - for (offset = e->offset; offset < e->offset+e->range_len; ++offset) + for (offset = e->offset; offset < e->offset + e->range_len; offset++) { - if (((offset+e->value_len) > bytes_read) && + if (((offset + e->value_len) > bytes_read) && (fseek(f, offset, SEEK_SET) == -1)) break; - + match = 1; + + if (e->value_len == 0) + { + printf("0 value_len %s\n", m->mime); + match = 0; + } + for (i = 0; i < e->value_len; ++i) { - if (offset+e->value_len > bytes_read) + if (offset + e->value_len > bytes_read) c = fgetc(f); else c = buf[offset + i]; v = e->value[i]; - if (e->mask) - v &= e->mask[i]; + if (e->mask) v &= e->mask[i]; if (!(c == v)) { ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/ _______________________________________________ enlightenment-cvs mailing list enlightenment-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs