3 * Stäubli Faverges - <www.staubli.com>
4 * Pierre AUBERT p.aubert@staubli.com
6 * See file CREDITS for list of people who contributed to this
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 #if defined(CONFIG_CMD_FDOS)
29 #include <linux/ctype.h>
34 static int dir_read (Fs_t *fs,
38 struct vfat_state *v);
40 static int unicode_read (char *in, char *out, int num);
41 static int match (const char *s, const char *p);
42 static unsigned char sum_shortname (char *name);
43 static int check_vfat (struct vfat_state *v, Directory_t *dir);
44 static char *conv_name (char *name, char *ext, char Case, char *ans);
47 /*-----------------------------------------------------------------------------
49 *-----------------------------------------------------------------------------
51 static void clear_vfat (struct vfat_state *v)
57 /*-----------------------------------------------------------------------------
59 *-----------------------------------------------------------------------------
61 int vfat_lookup (Slot_t *dir,
72 struct vfat_state vfat;
73 char newfile [VSE_NAMELEN];
83 if (dir_read (fs, dir, dirent, *entry, &vfat) < 0) {
92 if (dirent -> name[0] == '\0'){
93 if (vfat_start == 0) {
99 if (dirent -> attr == ATTR_VSE) {
100 /* VSE entry, continue */
103 if ( (dirent -> name [0] == DELMARK) ||
104 ((dirent -> attr & ATTR_DIRECTORY) != 0 &&
105 (flags & ACCEPT_DIR) == 0) ||
106 ((dirent -> attr & ATTR_VOLUME) != 0 &&
107 (flags & ACCEPT_LABEL) == 0) ||
108 (((dirent -> attr & (ATTR_DIRECTORY | ATTR_VOLUME)) == 0) &&
109 (flags & ACCEPT_PLAIN) == 0)) {
114 vfat_present = check_vfat (&vfat, dirent);
116 *vfat_start = *entry - 1;
118 *vfat_start -= vfat.subentries;
122 if (dirent -> attr & ATTR_VOLUME) {
123 strncpy (newfile, dirent -> name, 8);
125 strncat (newfile, dirent -> ext, 3);
129 conv_name (dirent -> name, dirent -> ext, dirent -> Case, newfile);
132 if (flags & MATCH_ANY) {
137 if ((vfat_present && match (vfat.name, filename)) ||
138 (match (newfile, filename))) {
146 if ((flags & DO_OPEN) && file) {
147 if (open_file (file, dirent) < 0) {
153 strcpy (outname, vfat.name);
156 strcpy (outname, newfile);
159 return (0); /* File found */
162 return -1; /* File not found */
166 /*-----------------------------------------------------------------------------
167 * dir_read -- Read one directory entry
168 *-----------------------------------------------------------------------------
170 static int dir_read (Fs_t *fs,
174 struct vfat_state *v)
177 /* read the directory entry */
182 MDIR_SIZE) != MDIR_SIZE) {
186 if (v && (dirent -> attr == ATTR_VSE)) {
187 struct vfat_subentry *vse;
188 unsigned char id, last_flag;
191 vse = (struct vfat_subentry *) dirent;
192 id = vse -> id & VSE_MASK;
193 last_flag = (vse -> id & VSE_LAST);
194 if (id > MAX_VFAT_SUBENTRIES) {
195 /* Invalid VSE entry */
201 if(v -> sum != vse -> sum) {
203 v -> sum = vse -> sum;
207 v -> status |= 1 << (id - 1);
209 v -> subentries = id;
212 c = &(v -> name [VSE_NAMELEN * (id - 1)]);
213 c += unicode_read (vse->text1, c, VSE1SIZE);
214 c += unicode_read (vse->text2, c, VSE2SIZE);
215 c += unicode_read (vse->text3, c, VSE3SIZE);
218 *c = '\0'; /* Null terminate long name */
225 /*-----------------------------------------------------------------------------
227 *-----------------------------------------------------------------------------
229 static int unicode_read (char *in, char *out, int num)
233 for (j = 0; j < num; ++j) {
244 /*-----------------------------------------------------------------------------
246 *-----------------------------------------------------------------------------
248 static int match (const char *s, const char *p)
251 for (; *p != '\0'; ) {
252 if (toupper (*s) != toupper (*p)) {
266 /*-----------------------------------------------------------------------------
268 *-----------------------------------------------------------------------------
270 static unsigned char sum_shortname (char *name)
275 for (j = sum = 0; j < 11; ++j) {
276 sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) +
277 (name [j] ? name [j] : ' ');
281 /*-----------------------------------------------------------------------------
283 * Return 1 if long name is valid, 0 else
284 *-----------------------------------------------------------------------------
286 static int check_vfat (struct vfat_state *v, Directory_t *dir)
290 if (v -> subentries == 0) {
294 strncpy (name, dir -> name, 8);
295 strncpy (name + 8, dir -> ext, 3);
298 if (v -> sum != sum_shortname (name)) {
302 if( (v -> status & ((1 << v -> subentries) - 1)) !=
303 (1 << v -> subentries) - 1) {
306 v->name [VSE_NAMELEN * v -> subentries] = 0;
310 /*-----------------------------------------------------------------------------
312 *-----------------------------------------------------------------------------
314 static char *conv_name (char *name, char *ext, char Case, char *ans)
316 char tname [9], text [4];
320 while (i < 8 && name [i] != ' ' && name [i] != '\0') {
321 tname [i] = name [i];
326 if (Case & BASECASE) {
327 for (i = 0; i < 8 && tname [i]; i++) {
328 tname [i] = tolower (tname [i]);
333 while (i < 3 && ext [i] != ' ' && ext [i] != '\0') {
340 for (i = 0; i < 3 && text [i]; i++) {
341 text [i] = tolower (text [i]);