diff options
| -rw-r--r-- | mpq-file.c | 2 | ||||
| -rw-r--r-- | mpq-fs.c | 164 | ||||
| -rw-r--r-- | test-it.c | 21 | 
3 files changed, 184 insertions, 3 deletions
@@ -117,7 +117,7 @@ struct mpq_file_t * mpqlib_open_filename(struct mpq_archive_t * mpq_a, const cha      return mpqlib_open_file(mpq_a, e);  } -void mpqlib_close_file(struct mpq_file_t * mpq_f) { +void mpqlib_close(struct mpq_file_t * mpq_f) {      free(mpq_f->buffer);      free(mpq_f->offsets);      free(mpq_f->sizes); @@ -1,13 +1,173 @@  #include <stdlib.h> +#include <string.h> +#include <ctype.h>  #include "mpq-fs.h" +#define MAX_FNAME 2048 + +typedef struct directory_list_t { +    struct directory_list_t * child; +    char * name; +    struct mpq_archive_t * mpq_a; +    int entry; +    struct directory_list_t * next; +} directory_list; + +static directory_list root_dir = { +    NULL, "", NULL, -1, NULL +}; + +static directory_list * root = &root_dir; + +static char * strtoupper(char * _str) { +    char * str = _str; +    while (*str) { +        *str = toupper(*str); +        str++; +    } +    return _str; +} + +static directory_list * new_directory_list(directory_list * parent, struct mpq_archive_t * mpq_a, const char * name) { +    directory_list * r; +     +    for (r = parent->child; r; r = r->next) { +        if (!strcasecmp(r->name, name)) +            break; +    } +     +    if (!r) { +        r = (directory_list *) malloc(sizeof(directory_list)); +        r->child = NULL; +        r->next = parent->child; +        parent->child = r; +        r->name = strtoupper(strdup(name)); +        r->mpq_a = mpq_a; +        r->entry = -1; +    } +     +    return r; +} + +static directory_list * add_file_r(directory_list * parent, struct mpq_archive_t * mpq_a, char * fname, int entry) { +    char * bs; +    directory_list * r; +    int tail = 0; +     +    bs = strchr(fname, '\\'); +     +    if (bs) { +        *bs = 0; +    } else { +        tail = 1; +    } +    if (!(r = new_directory_list(parent, mpq_a, fname))) +        return NULL; +     +    if (tail) { +        r->entry = entry; +        return r; +    } +     +    return add_file_r(r, mpq_a, bs + 1, entry); +} + +static directory_list * add_file(struct mpq_archive_t * mpq_a, char * fname) { +    int entry; +     +    if ((entry = mpqlib_find_hash_entry_by_name(mpq_a, fname, 0, 0)) < 0) +        return NULL; +     +    return add_file_r(root, mpq_a, fname, entry); +} +  void mpqlib_fs_add_archive(struct mpq_archive_t * mpq_a) { +    struct mpq_file_t * listfile; +    char * buffer; +    int s; +     +    if (!(listfile = mpqlib_open_filename(mpq_a, "(listfile)"))) +        return; +     +    s = mpqlib_seek(listfile, 0, MPQLIB_SEEK_END); +    mpqlib_seek(listfile, 0, MPQLIB_SEEK_SET); + +    if (!(buffer = (char *) malloc(s + 1))) { +        mpqlib_close(listfile); +        return; +    } +     +    buffer[s] = 0; +    mpqlib_read(listfile, buffer, s); +    mpqlib_fs_attach_listfile(mpq_a, buffer); +     +    free(buffer); +    mpqlib_close(listfile);  }  void mpqlib_fs_attach_listfile(struct mpq_archive_t * mpq_a, const char * listfile) { -    mpqlib_fs_add_archive(mpq_a); +    char fname[MAX_FNAME]; +    const char * p; +    char * fnp; +     +    for (p = listfile, fnp = fname; *p; p++) { +        switch (*p) { +        case '\r': +        case '\n': +        case ';': +            *fnp = 0; +            if (fnp != fname) +                add_file(mpq_a, fname); +            fnp = fname; +            break; +        default: +            *(fnp++) = *p; +            break; +        } +    }  } -struct mpq_file_t * mpqlib_fs_open(const char * fname) { +static directory_list * find_file_r(directory_list * parent, char * fname) { +    char * bs; +    directory_list * r; +    int tail = 0; +     +    bs = strchr(fname, '\\'); +     +    if (bs) { +        *bs = 0; +    } else { +        tail = 1; +    } +     +    for (r = parent->child; r; r = r->next) { +        if (!strcmp(fname, r->name)) { +            if (tail) { +                return r; +            } else { +                return find_file_r(r, bs + 1); +            } +        } +    } +     +    return NULL; +} + +static directory_list * find_file(char * fname) { +    return find_file_r(root, fname); +} + +struct mpq_file_t * mpqlib_fs_open(const char * _fname) { +    char * fname = strtoupper(strdup(_fname)); +    directory_list * entry; +     +    entry = find_file(fname); +     +    free(fname); + +    if (entry) { +        return mpqlib_open_file(entry->mpq_a, entry->entry); +    } +          return NULL;  } @@ -2,6 +2,7 @@  #include <stdlib.h>  #include "mpq-bios.h"  #include "mpq-file.h" +#include "mpq-fs.h"  #include "mpq-errors.h"  int main(int argc, char ** argv) { @@ -38,6 +39,26 @@ int main(int argc, char ** argv) {          printf("Dumping:\n");          printf("%s", b);          printf("\nDone.\n"); +        mpqlib_close(f1); +    } +     +    mpqlib_fs_add_archive(t1); +    f1 = mpqlib_fs_open("Interface\\FrameXML\\WorldMapFrame.lua"); +     +    if (f1) { +        int size; +        char * b; +        printf("Found!\n"); +        size = mpqlib_seek(f1, 0, MPQLIB_SEEK_END); +        mpqlib_seek(f1, 0, MPQLIB_SEEK_SET); +        printf("Filesize seems to be: %d.\n", size); +        b = (char *) malloc(size + 1); +        b[size] = 0; +        mpqlib_read(f1, b, size); +        printf("Dumping:\n"); +        printf("%s", b); +        printf("\nDone.\n"); +        mpqlib_close(f1);      }      mpqlib_close_archive(t1);  | 
