]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - fs/fdos/subdir.c
karo: tx51: remove duplicate CONFIG_SYS_SDRAM_CLK definition
[karo-tx-uboot.git] / fs / fdos / subdir.c
1 /*
2  * (C) Copyright 2002
3  * Stäubli Faverges - <www.staubli.com>
4  * Pierre AUBERT  p.aubert@staubli.com
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <config.h>
11 #include <malloc.h>
12
13 #include "dos.h"
14 #include "fdos.h"
15
16 static int cache_sect;
17 static unsigned char cache [SZ_STD_SECTOR];
18
19
20 #define min(x,y) ((x)<(y)?(x):(y))
21
22 static int descend (Slot_t *parent,
23              Fs_t *fs,
24                     char *path);
25
26 /*-----------------------------------------------------------------------------
27  * init_subdir --
28  *-----------------------------------------------------------------------------
29  */
30 void init_subdir (void)
31 {
32     cache_sect = -1;
33 }
34 /*-----------------------------------------------------------------------------
35  * basename --
36  *-----------------------------------------------------------------------------
37  */
38 char *basename (char *name)
39 {
40     register char *cptr;
41
42     if (!name || !*name) {
43         return ("");
44     }
45
46     for (cptr= name; *cptr++; );
47     while (--cptr >= name) {
48         if (*cptr == '/')    {
49             return (cptr + 1);
50         }
51     }
52     return(name);
53 }
54 /*-----------------------------------------------------------------------------
55  * root_map --
56  *-----------------------------------------------------------------------------
57  */
58 static int root_map (Fs_t *fs, Slot_t *file, int where, int *len)
59 {
60     *len = min (*len, fs -> dir_len * SZ_STD_SECTOR - where);
61     if (*len < 0 ) {
62         *len = 0;
63         return (-1);
64     }
65     return fs -> dir_start * SZ_STD_SECTOR + where;
66 }
67 /*-----------------------------------------------------------------------------
68  * normal_map --
69  *-----------------------------------------------------------------------------
70  */
71 static int normal_map (Fs_t *fs, Slot_t *file, int where, int *len)
72 {
73     int offset;
74     int NrClu;
75     unsigned short RelCluNr;
76     unsigned short CurCluNr;
77     unsigned short NewCluNr;
78     unsigned short AbsCluNr;
79     int clus_size;
80
81     clus_size = fs -> cluster_size * SZ_STD_SECTOR;
82     offset = where % clus_size;
83
84     *len = min (*len, file -> FileSize - where);
85
86     if (*len < 0 ) {
87         *len = 0;
88         return (0);
89     }
90
91     if (file -> FirstAbsCluNr < 2){
92         *len = 0;
93         return (0);
94     }
95
96     RelCluNr = where / clus_size;
97
98     if (RelCluNr >= file -> PreviousRelCluNr){
99         CurCluNr = file -> PreviousRelCluNr;
100         AbsCluNr = file -> PreviousAbsCluNr;
101     } else {
102         CurCluNr = 0;
103         AbsCluNr = file -> FirstAbsCluNr;
104     }
105
106
107     NrClu = (offset + *len - 1) / clus_size;
108     while (CurCluNr <= RelCluNr + NrClu) {
109         if (CurCluNr == RelCluNr){
110             /* we have reached the beginning of our zone. Save
111              * coordinates */
112             file -> PreviousRelCluNr = RelCluNr;
113             file -> PreviousAbsCluNr = AbsCluNr;
114         }
115         NewCluNr = fat_decode (fs, AbsCluNr);
116         if (NewCluNr == 1 || NewCluNr == 0) {
117             PRINTF("Fat problem while decoding %d %x\n",
118                     AbsCluNr, NewCluNr);
119             return (-1);
120         }
121         if (CurCluNr == RelCluNr + NrClu) {
122             break;
123         }
124
125         if (CurCluNr < RelCluNr && NewCluNr == FAT12_END) {
126             *len = 0;
127             return 0;
128         }
129
130         if (CurCluNr >= RelCluNr && NewCluNr != AbsCluNr + 1)
131             break;
132         CurCluNr++;
133         AbsCluNr = NewCluNr;
134     }
135
136     *len = min (*len, (1 + CurCluNr - RelCluNr) * clus_size - offset);
137
138     return (((file -> PreviousAbsCluNr - 2) * fs -> cluster_size +
139              fs -> dir_start + fs -> dir_len) *
140             SZ_STD_SECTOR + offset);
141 }
142 /*-----------------------------------------------------------------------------
143  * open_subdir -- open the subdir containing the file
144  *-----------------------------------------------------------------------------
145  */
146 int open_subdir (File_t *desc)
147 {
148     char *pathname;
149     char *tmp, *s, *path;
150     char terminator;
151
152     if ((pathname = (char *)malloc (MAX_PATH)) == NULL) {
153         return (-1);
154     }
155
156     strcpy (pathname, desc -> name);
157
158     /* Suppress file name                                                    */
159     tmp = basename (pathname);
160     *tmp = '\0';
161
162     /* root directory  init                                                  */
163     desc -> subdir.FirstAbsCluNr = 0;
164     desc -> subdir.FileSize = -1;
165     desc -> subdir.map = root_map;
166     desc -> subdir.dir.attr = ATTR_DIRECTORY;
167
168     tmp = pathname;
169     for (s = tmp; ; ++s) {
170         if (*s == '/' || *s == '\0') {
171             path = tmp;
172             terminator = *s;
173             *s = '\0';
174             if (s != tmp && strcmp (path,".")) {
175                 if (descend (&desc -> subdir, desc -> fs, path) < 0) {
176                     free (pathname);
177                     return (-1);
178                 }
179             }
180             if (terminator == 0) {
181                 break;
182             }
183             tmp = s + 1;
184         }
185     }
186     free (pathname);
187     return (0);
188 }
189 /*-----------------------------------------------------------------------------
190  * descend --
191  *-----------------------------------------------------------------------------
192  */
193 static int descend (Slot_t *parent,
194              Fs_t *fs,
195              char *path)
196 {
197     int entry;
198     Slot_t SubDir;
199
200     if(path[0] == '\0' || strcmp (path, ".") == 0) {
201         return (0);
202     }
203
204
205     entry = 0;
206     if (vfat_lookup (parent,
207                      fs,
208                      &(SubDir.dir),
209                      &entry,
210                      0,
211                      path,
212                      ACCEPT_DIR | SINGLE | DO_OPEN,
213                      0,
214                      &SubDir) == 0) {
215         *parent = SubDir;
216         return (0);
217     }
218
219     if (strcmp(path, "..") == 0) {
220         parent -> FileSize = -1;
221         parent -> FirstAbsCluNr = 0;
222         parent -> map = root_map;
223         return (0);
224     }
225     return (-1);
226 }
227 /*-----------------------------------------------------------------------------
228  * open_file --
229  *-----------------------------------------------------------------------------
230  */
231 int open_file (Slot_t *file, Directory_t *dir)
232 {
233     int first;
234     unsigned long size;
235
236     first = __le16_to_cpu (dir -> start);
237
238     if(first == 0 &&
239        (dir -> attr & ATTR_DIRECTORY) != 0) {
240         file -> FirstAbsCluNr = 0;
241         file -> FileSize = -1;
242         file -> map = root_map;
243         return (0);
244     }
245
246     if ((dir -> attr & ATTR_DIRECTORY) != 0) {
247         size = (1UL << 31) - 1;
248     }
249     else {
250         size = __le32_to_cpu (dir -> size);
251     }
252
253     file -> map = normal_map;
254     file -> FirstAbsCluNr = first;
255     file -> PreviousRelCluNr = 0xffff;
256     file -> FileSize = size;
257     return (0);
258 }
259 /*-----------------------------------------------------------------------------
260  * read_file --
261  *-----------------------------------------------------------------------------
262  */
263 int read_file (Fs_t *fs,
264                Slot_t *file,
265                char *buf,
266                int where,
267                int len)
268 {
269     int pos;
270     int read, nb, sect, offset;
271
272     pos = file -> map (fs, file, where, &len);
273     if  (pos < 0) {
274         return -1;
275     }
276     if (len == 0) {
277         return (0);
278     }
279
280     /* Compute sector number                                                 */
281     sect = pos / SZ_STD_SECTOR;
282     offset = pos % SZ_STD_SECTOR;
283     read = 0;
284
285     if (offset) {
286         /* Read doesn't start at the sector beginning. We need to use our    */
287         /* cache                                                             */
288         if (sect != cache_sect) {
289             if (dev_read (cache, sect, 1) < 0) {
290                 return (-1);
291             }
292             cache_sect = sect;
293         }
294         nb = min (len, SZ_STD_SECTOR - offset);
295
296         memcpy (buf, cache + offset, nb);
297         read += nb;
298         len -= nb;
299         sect += 1;
300     }
301
302     if (len > SZ_STD_SECTOR) {
303         nb = (len - 1) / SZ_STD_SECTOR;
304         if (dev_read (buf + read, sect, nb) < 0) {
305             return ((read) ? read : -1);
306         }
307         /* update sector position                                            */
308         sect += nb;
309
310         /* Update byte position                                              */
311         nb *= SZ_STD_SECTOR;
312         read += nb;
313         len -= nb;
314     }
315
316     if (len) {
317         if (sect != cache_sect) {
318             if (dev_read (cache, sect, 1) < 0) {
319                 return ((read) ? read : -1);
320                 cache_sect = -1;
321             }
322             cache_sect = sect;
323         }
324
325         memcpy (buf + read, cache, len);
326         read += len;
327     }
328     return (read);
329 }