1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "lookupa.h"
#include "hashtab.h"
#include "mpq-fs.h"
#include "mpq-misc.h"
#define MAX_FNAME 2048
#define INITIAL_HASH_SIZE 10
typedef struct hash_entry_t {
struct mpq_archive_t * mpq_a;
int entry;
} hash_entry;
static char * strnormalize(char * _str) {
char * str = _str;
while (*str) {
*str = toupper(*str);
if (*str == '/')
*str = '\\';
str++;
}
return _str;
}
htab * hash_table = 0;
static void add_file(struct mpq_archive_t * mpq_a, char * fname) {
int entry;
char * nfname;
if ((entry = mpqlib_find_hash_entry_by_name(mpq_a, fname, 0, 0)) < 0)
return;
if (!hash_table)
hash_table = hcreate(INITIAL_HASH_SIZE);
nfname = strnormalize(strdup(fname));
hadd(hash_table, (uint8_t *) nfname, strlen(nfname), NULL);
if (!hstuff(hash_table)) {
hstuff(hash_table) = malloc(sizeof(hash_entry));
}
((hash_entry *) hstuff(hash_table))->mpq_a = mpq_a;
((hash_entry *) hstuff(hash_table))->entry = entry;
}
/*
* Adds an opened archive file into the system, and try to automagically import the list file.
*/
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);
}
/*
* Generalistic function to add an archive to the directory structure using a custom listfile.
*/
void mpqlib_fs_attach_listfile(struct mpq_archive_t * mpq_a, const char * listfile) {
char fname[MAX_FNAME];
const char * p;
char * fnp;
for (p = listfile, fnp = fname; *p; p++) {
switch (*p) {
/* Each entry in the listfile may be separated by CR, LF, and/or ';'. */
case '\r':
case '\n':
case ';':
*fnp = 0;
if (fnp != fname)
add_file(mpq_a, fname);
fnp = fname;
break;
default:
*(fnp++) = *p;
break;
}
}
}
/*
* Recursively find a file.
*/
static hash_entry * find_file(char * fname) {
if (!hfind(hash_table, (uint8_t *) fname, strlen(fname)))
return NULL;
return (hash_entry *) hstuff(hash_table);
}
struct mpq_file_t * mpqlib_fs_open(const char * _fname) {
char * fname = strnormalize(strdup(_fname));
hash_entry * entry;
entry = find_file(fname);
free(fname);
if (entry) {
return mpqlib_open_file(entry->mpq_a, entry->entry);
}
return NULL;
}
|