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#include <common.h>
26#include <config.h>
27#include <linux/ctype.h>
28
29#include "dos.h"
30#include "fdos.h"
31
32static int dir_read (Fs_t *fs,
33 Slot_t *dir,
34 Directory_t *dirent,
35 int num,
36 struct vfat_state *v);
37
38static int unicode_read (char *in, char *out, int num);
39static int match (const char *s, const char *p);
40static unsigned char sum_shortname (char *name);
41static int check_vfat (struct vfat_state *v, Directory_t *dir);
42static char *conv_name (char *name, char *ext, char Case, char *ans);
43
44
45
46
47
48
49static void clear_vfat (struct vfat_state *v)
50{
51 v -> subentries = 0;
52 v -> status = 0;
53}
54
55
56
57
58
59int vfat_lookup (Slot_t *dir,
60 Fs_t *fs,
61 Directory_t *dirent,
62 int *entry,
63 int *vfat_start,
64 char *filename,
65 int flags,
66 char *outname,
67 Slot_t *file)
68{
69 int found;
70 struct vfat_state vfat;
71 char newfile [VSE_NAMELEN];
72 int vfat_present = 0;
73
74 if (*entry == -1) {
75 return -1;
76 }
77
78 found = 0;
79 clear_vfat (&vfat);
80 while (1) {
81 if (dir_read (fs, dir, dirent, *entry, &vfat) < 0) {
82 if (vfat_start) {
83 *vfat_start = *entry;
84 }
85 break;
86 }
87 (*entry)++;
88
89
90 if (dirent -> name[0] == '\0'){
91 if (vfat_start == 0) {
92 break;
93 }
94 continue;
95 }
96
97 if (dirent -> attr == ATTR_VSE) {
98
99 continue;
100 }
101 if ( (dirent -> name [0] == DELMARK) ||
102 ((dirent -> attr & ATTR_DIRECTORY) != 0 &&
103 (flags & ACCEPT_DIR) == 0) ||
104 ((dirent -> attr & ATTR_VOLUME) != 0 &&
105 (flags & ACCEPT_LABEL) == 0) ||
106 (((dirent -> attr & (ATTR_DIRECTORY | ATTR_VOLUME)) == 0) &&
107 (flags & ACCEPT_PLAIN) == 0)) {
108 clear_vfat (&vfat);
109 continue;
110 }
111
112 vfat_present = check_vfat (&vfat, dirent);
113 if (vfat_start) {
114 *vfat_start = *entry - 1;
115 if (vfat_present) {
116 *vfat_start -= vfat.subentries;
117 }
118 }
119
120 if (dirent -> attr & ATTR_VOLUME) {
121 strncpy (newfile, dirent -> name, 8);
122 newfile [8] = '\0';
123 strncat (newfile, dirent -> ext, 3);
124 newfile [11] = '\0';
125 }
126 else {
127 conv_name (dirent -> name, dirent -> ext, dirent -> Case, newfile);
128 }
129
130 if (flags & MATCH_ANY) {
131 found = 1;
132 break;
133 }
134
135 if ((vfat_present && match (vfat.name, filename)) ||
136 (match (newfile, filename))) {
137 found = 1;
138 break;
139 }
140 clear_vfat (&vfat);
141 }
142
143 if (found) {
144 if ((flags & DO_OPEN) && file) {
145 if (open_file (file, dirent) < 0) {
146 return (-1);
147 }
148 }
149 if (outname) {
150 if (vfat_present) {
151 strcpy (outname, vfat.name);
152 }
153 else {
154 strcpy (outname, newfile);
155 }
156 }
157 return (0);
158 } else {
159 *entry = -1;
160 return -1;
161 }
162}
163
164
165
166
167
168static int dir_read (Fs_t *fs,
169 Slot_t *dir,
170 Directory_t *dirent,
171 int num,
172 struct vfat_state *v)
173{
174
175
176 if (read_file (fs,
177 dir,
178 (char *)dirent,
179 num * MDIR_SIZE,
180 MDIR_SIZE) != MDIR_SIZE) {
181 return (-1);
182 }
183
184 if (v && (dirent -> attr == ATTR_VSE)) {
185 struct vfat_subentry *vse;
186 unsigned char id, last_flag;
187 char *c;
188
189 vse = (struct vfat_subentry *) dirent;
190 id = vse -> id & VSE_MASK;
191 last_flag = (vse -> id & VSE_LAST);
192 if (id > MAX_VFAT_SUBENTRIES) {
193
194 return (-1);
195 }
196
197
198
199 if(v -> sum != vse -> sum) {
200 clear_vfat (v);
201 v -> sum = vse -> sum;
202 }
203
204
205 v -> status |= 1 << (id - 1);
206 if (last_flag) {
207 v -> subentries = id;
208 }
209
210 c = &(v -> name [VSE_NAMELEN * (id - 1)]);
211 c += unicode_read (vse->text1, c, VSE1SIZE);
212 c += unicode_read (vse->text2, c, VSE2SIZE);
213 c += unicode_read (vse->text3, c, VSE3SIZE);
214
215 if (last_flag) {
216 *c = '\0';
217 }
218
219 }
220 return (0);
221}
222
223
224
225
226
227static int unicode_read (char *in, char *out, int num)
228{
229 int j;
230
231 for (j = 0; j < num; ++j) {
232 if (in [1])
233 *out = '_';
234 else
235 *out = in [0];
236 out ++;
237 in += 2;
238 }
239 return num;
240}
241
242
243
244
245
246static int match (const char *s, const char *p)
247{
248
249 for (; *p != '\0'; ) {
250 if (toupper (*s) != toupper (*p)) {
251 return (0);
252 }
253 p++;
254 s++;
255 }
256
257 if (*s != '\0') {
258 return (0);
259 }
260 else {
261 return (1);
262 }
263}
264
265
266
267
268static unsigned char sum_shortname (char *name)
269{
270 unsigned char sum;
271 int j;
272
273 for (j = sum = 0; j < 11; ++j) {
274 sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) +
275 (name [j] ? name [j] : ' ');
276 }
277 return (sum);
278}
279
280
281
282
283
284static int check_vfat (struct vfat_state *v, Directory_t *dir)
285{
286 char name[12];
287
288 if (v -> subentries == 0) {
289 return 0;
290 }
291
292 strncpy (name, dir -> name, 8);
293 strncpy (name + 8, dir -> ext, 3);
294 name [11] = '\0';
295
296 if (v -> sum != sum_shortname (name)) {
297 return 0;
298 }
299
300 if( (v -> status & ((1 << v -> subentries) - 1)) !=
301 (1 << v -> subentries) - 1) {
302 return 0;
303 }
304 v->name [VSE_NAMELEN * v -> subentries] = 0;
305
306 return 1;
307}
308
309
310
311
312static char *conv_name (char *name, char *ext, char Case, char *ans)
313{
314 char tname [9], text [4];
315 int i;
316
317 i = 0;
318 while (i < 8 && name [i] != ' ' && name [i] != '\0') {
319 tname [i] = name [i];
320 i++;
321 }
322 tname [i] = '\0';
323
324 if (Case & BASECASE) {
325 for (i = 0; i < 8 && tname [i]; i++) {
326 tname [i] = tolower (tname [i]);
327 }
328 }
329
330 i = 0;
331 while (i < 3 && ext [i] != ' ' && ext [i] != '\0') {
332 text [i] = ext [i];
333 i++;
334 }
335 text [i] = '\0';
336
337 if (Case & EXTCASE){
338 for (i = 0; i < 3 && text [i]; i++) {
339 text [i] = tolower (text [i]);
340 }
341 }
342
343 if (*text) {
344 strcpy (ans, tname);
345 strcat (ans, ".");
346 strcat (ans, text);
347 }
348 else {
349 strcpy(ans, tname);
350 }
351 return (ans);
352}
353