]>
git.ipfire.org Git - people/ms/u-boot.git/blob - fs/fdos/vfat.c
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
]);