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