3 * Stäubli Faverges - <www.staubli.com>
6 * SPDX-License-Identifier: GPL-2.0+
11 #include <linux/ctype.h>
16 static int dir_read (Fs_t *fs,
20 struct vfat_state *v);
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);
29 /*-----------------------------------------------------------------------------
31 *-----------------------------------------------------------------------------
33 static void clear_vfat (struct vfat_state *v)
39 /*-----------------------------------------------------------------------------
41 *-----------------------------------------------------------------------------
43 int vfat_lookup (Slot_t *dir,
54 struct vfat_state vfat;
55 char newfile [VSE_NAMELEN];
65 if (dir_read (fs, dir, dirent, *entry, &vfat) < 0) {
74 if (dirent -> name[0] == '\0'){
75 if (vfat_start == 0) {
81 if (dirent -> attr == ATTR_VSE) {
82 /* VSE entry, continue */
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)) {
96 vfat_present = check_vfat (&vfat, dirent);
98 *vfat_start = *entry - 1;
100 *vfat_start -= vfat.subentries;
104 if (dirent -> attr & ATTR_VOLUME) {
105 strncpy (newfile, dirent -> name, 8);
107 strncat (newfile, dirent -> ext, 3);
111 conv_name (dirent -> name, dirent -> ext, dirent -> Case, newfile);
114 if (flags & MATCH_ANY) {
119 if ((vfat_present && match (vfat.name, filename)) ||
120 (match (newfile, filename))) {
128 if ((flags & DO_OPEN) && file) {
129 if (open_file (file, dirent) < 0) {
135 strcpy (outname, vfat.name);
138 strcpy (outname, newfile);
141 return (0); /* File found */
144 return -1; /* File not found */
148 /*-----------------------------------------------------------------------------
149 * dir_read -- Read one directory entry
150 *-----------------------------------------------------------------------------
152 static int dir_read (Fs_t *fs,
156 struct vfat_state *v)
159 /* read the directory entry */
164 MDIR_SIZE) != MDIR_SIZE) {
168 if (v && (dirent -> attr == ATTR_VSE)) {
169 struct vfat_subentry *vse;
170 unsigned char id, last_flag;
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 */
183 if(v -> sum != vse -> sum) {
185 v -> sum = vse -> sum;
189 v -> status |= 1 << (id - 1);
191 v -> subentries = id;
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);
200 *c = '\0'; /* Null terminate long name */
207 /*-----------------------------------------------------------------------------
209 *-----------------------------------------------------------------------------
211 static int unicode_read (char *in, char *out, int num)
215 for (j = 0; j < num; ++j) {
226 /*-----------------------------------------------------------------------------
228 *-----------------------------------------------------------------------------
230 static int match (const char *s, const char *p)
233 for (; *p != '\0'; ) {
234 if (toupper (*s) != toupper (*p)) {
248 /*-----------------------------------------------------------------------------
250 *-----------------------------------------------------------------------------
252 static unsigned char sum_shortname (char *name)
257 for (j = sum = 0; j < 11; ++j) {
258 sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) +
259 (name [j] ? name [j] : ' ');
263 /*-----------------------------------------------------------------------------
265 * Return 1 if long name is valid, 0 else
266 *-----------------------------------------------------------------------------
268 static int check_vfat (struct vfat_state *v, Directory_t *dir)
272 if (v -> subentries == 0) {
276 strncpy (name, dir -> name, 8);
277 strncpy (name + 8, dir -> ext, 3);
280 if (v -> sum != sum_shortname (name)) {
284 if( (v -> status & ((1 << v -> subentries) - 1)) !=
285 (1 << v -> subentries) - 1) {
288 v->name [VSE_NAMELEN * v -> subentries] = 0;
292 /*-----------------------------------------------------------------------------
294 *-----------------------------------------------------------------------------
296 static char *conv_name (char *name, char *ext, char Case, char *ans)
298 char tname [9], text [4];
302 while (i < 8 && name [i] != ' ' && name [i] != '\0') {
303 tname [i] = name [i];
308 if (Case & BASECASE) {
309 for (i = 0; i < 8 && tname [i]; i++) {
310 tname [i] = tolower (tname [i]);
315 while (i < 3 && ext [i] != ' ' && ext [i] != '\0') {
322 for (i = 0; i < 3 && text [i]; i++) {
323 text [i] = tolower (text [i]);