]> Git Repo - u-boot.git/blame - fs/fdos/vfat.c
dts/Makefile: simplify dtc invocation
[u-boot.git] / fs / fdos / vfat.c
CommitLineData
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
16static 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
22static int unicode_read (char *in, char *out, int num);
23static int match (const char *s, const char *p);
24static unsigned char sum_shortname (char *name);
25static int check_vfat (struct vfat_state *v, Directory_t *dir);
26static char *conv_name (char *name, char *ext, char Case, char *ans);
27
28
29/*-----------------------------------------------------------------------------
8bde7f77 30 * clear_vfat --
2262cfee
WD
31 *-----------------------------------------------------------------------------
32 */
33static 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 */
43int 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 */
152static 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 */
211static 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 */
230static 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 */
252static 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 */
268static 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 */
296static 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}
This page took 0.21966 seconds and 4 git commands to generate.