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,
29 #if defined(CONFIG_CMD_FDOS)
34 static int cache_sect
;
35 static unsigned char cache
[SZ_STD_SECTOR
];
38 #define min(x,y) ((x)<(y)?(x):(y))
40 static int descend (Slot_t
*parent
,
44 /*-----------------------------------------------------------------------------
46 *-----------------------------------------------------------------------------
48 void init_subdir (void)
52 /*-----------------------------------------------------------------------------
54 *-----------------------------------------------------------------------------
56 char *basename (char *name
)
60 if (!name
|| !*name
) {
64 for (cptr
= name
; *cptr
++; );
65 while (--cptr
>= name
) {
72 /*-----------------------------------------------------------------------------
74 *-----------------------------------------------------------------------------
76 static int root_map (Fs_t
*fs
, Slot_t
*file
, int where
, int *len
)
78 *len
= min (*len
, fs
-> dir_len
* SZ_STD_SECTOR
- where
);
83 return fs
-> dir_start
* SZ_STD_SECTOR
+ where
;
85 /*-----------------------------------------------------------------------------
87 *-----------------------------------------------------------------------------
89 static int normal_map (Fs_t
*fs
, Slot_t
*file
, int where
, int *len
)
93 unsigned short RelCluNr
;
94 unsigned short CurCluNr
;
95 unsigned short NewCluNr
;
96 unsigned short AbsCluNr
;
99 clus_size
= fs
-> cluster_size
* SZ_STD_SECTOR
;
100 offset
= where
% clus_size
;
102 *len
= min (*len
, file
-> FileSize
- where
);
109 if (file
-> FirstAbsCluNr
< 2){
114 RelCluNr
= where
/ clus_size
;
116 if (RelCluNr
>= file
-> PreviousRelCluNr
){
117 CurCluNr
= file
-> PreviousRelCluNr
;
118 AbsCluNr
= file
-> PreviousAbsCluNr
;
121 AbsCluNr
= file
-> FirstAbsCluNr
;
125 NrClu
= (offset
+ *len
- 1) / clus_size
;
126 while (CurCluNr
<= RelCluNr
+ NrClu
) {
127 if (CurCluNr
== RelCluNr
){
128 /* we have reached the beginning of our zone. Save
130 file
-> PreviousRelCluNr
= RelCluNr
;
131 file
-> PreviousAbsCluNr
= AbsCluNr
;
133 NewCluNr
= fat_decode (fs
, AbsCluNr
);
134 if (NewCluNr
== 1 || NewCluNr
== 0) {
135 PRINTF("Fat problem while decoding %d %x\n",
139 if (CurCluNr
== RelCluNr
+ NrClu
) {
143 if (CurCluNr
< RelCluNr
&& NewCluNr
== FAT12_END
) {
148 if (CurCluNr
>= RelCluNr
&& NewCluNr
!= AbsCluNr
+ 1)
154 *len
= min (*len
, (1 + CurCluNr
- RelCluNr
) * clus_size
- offset
);
156 return (((file
-> PreviousAbsCluNr
- 2) * fs
-> cluster_size
+
157 fs
-> dir_start
+ fs
-> dir_len
) *
158 SZ_STD_SECTOR
+ offset
);
160 /*-----------------------------------------------------------------------------
161 * open_subdir -- open the subdir containing the file
162 *-----------------------------------------------------------------------------
164 int open_subdir (File_t
*desc
)
167 char *tmp
, *s
, *path
;
170 if ((pathname
= (char *)malloc (MAX_PATH
)) == NULL
) {
174 strcpy (pathname
, desc
-> name
);
176 /* Suppress file name */
177 tmp
= basename (pathname
);
180 /* root directory init */
181 desc
-> subdir
.FirstAbsCluNr
= 0;
182 desc
-> subdir
.FileSize
= -1;
183 desc
-> subdir
.map
= root_map
;
184 desc
-> subdir
.dir
.attr
= ATTR_DIRECTORY
;
187 for (s
= tmp
; ; ++s
) {
188 if (*s
== '/' || *s
== '\0') {
192 if (s
!= tmp
&& strcmp (path
,".")) {
193 if (descend (&desc
-> subdir
, desc
-> fs
, path
) < 0) {
198 if (terminator
== 0) {
207 /*-----------------------------------------------------------------------------
209 *-----------------------------------------------------------------------------
211 static int descend (Slot_t
*parent
,
218 if(path
[0] == '\0' || strcmp (path
, ".") == 0) {
224 if (vfat_lookup (parent
,
230 ACCEPT_DIR
| SINGLE
| DO_OPEN
,
237 if (strcmp(path
, "..") == 0) {
238 parent
-> FileSize
= -1;
239 parent
-> FirstAbsCluNr
= 0;
240 parent
-> map
= root_map
;
245 /*-----------------------------------------------------------------------------
247 *-----------------------------------------------------------------------------
249 int open_file (Slot_t
*file
, Directory_t
*dir
)
254 first
= __le16_to_cpu (dir
-> start
);
257 (dir
-> attr
& ATTR_DIRECTORY
) != 0) {
258 file
-> FirstAbsCluNr
= 0;
259 file
-> FileSize
= -1;
260 file
-> map
= root_map
;
264 if ((dir
-> attr
& ATTR_DIRECTORY
) != 0) {
265 size
= (1UL << 31) - 1;
268 size
= __le32_to_cpu (dir
-> size
);
271 file
-> map
= normal_map
;
272 file
-> FirstAbsCluNr
= first
;
273 file
-> PreviousRelCluNr
= 0xffff;
274 file
-> FileSize
= size
;
277 /*-----------------------------------------------------------------------------
279 *-----------------------------------------------------------------------------
281 int read_file (Fs_t
*fs
,
288 int read
, nb
, sect
, offset
;
290 pos
= file
-> map (fs
, file
, where
, &len
);
298 /* Compute sector number */
299 sect
= pos
/ SZ_STD_SECTOR
;
300 offset
= pos
% SZ_STD_SECTOR
;
304 /* Read doesn't start at the sector beginning. We need to use our */
306 if (sect
!= cache_sect
) {
307 if (dev_read (cache
, sect
, 1) < 0) {
312 nb
= min (len
, SZ_STD_SECTOR
- offset
);
314 memcpy (buf
, cache
+ offset
, nb
);
320 if (len
> SZ_STD_SECTOR
) {
321 nb
= (len
- 1) / SZ_STD_SECTOR
;
322 if (dev_read (buf
+ read
, sect
, nb
) < 0) {
323 return ((read
) ? read
: -1);
325 /* update sector position */
328 /* Update byte position */
335 if (sect
!= cache_sect
) {
336 if (dev_read (cache
, sect
, 1) < 0) {
337 return ((read
) ? read
: -1);
343 memcpy (buf
+ read
, cache
, len
);