3 * Stäubli Faverges - <www.staubli.com>
6 * SPDX-License-Identifier: GPL-2.0+
16 static int cache_sect;
17 static unsigned char cache [SZ_STD_SECTOR];
20 #define min(x,y) ((x)<(y)?(x):(y))
22 static int descend (Slot_t *parent,
26 /*-----------------------------------------------------------------------------
28 *-----------------------------------------------------------------------------
30 void init_subdir (void)
34 /*-----------------------------------------------------------------------------
36 *-----------------------------------------------------------------------------
38 char *basename (char *name)
42 if (!name || !*name) {
46 for (cptr= name; *cptr++; );
47 while (--cptr >= name) {
54 /*-----------------------------------------------------------------------------
56 *-----------------------------------------------------------------------------
58 static int root_map (Fs_t *fs, Slot_t *file, int where, int *len)
60 *len = min (*len, fs -> dir_len * SZ_STD_SECTOR - where);
65 return fs -> dir_start * SZ_STD_SECTOR + where;
67 /*-----------------------------------------------------------------------------
69 *-----------------------------------------------------------------------------
71 static int normal_map (Fs_t *fs, Slot_t *file, int where, int *len)
75 unsigned short RelCluNr;
76 unsigned short CurCluNr;
77 unsigned short NewCluNr;
78 unsigned short AbsCluNr;
81 clus_size = fs -> cluster_size * SZ_STD_SECTOR;
82 offset = where % clus_size;
84 *len = min (*len, file -> FileSize - where);
91 if (file -> FirstAbsCluNr < 2){
96 RelCluNr = where / clus_size;
98 if (RelCluNr >= file -> PreviousRelCluNr){
99 CurCluNr = file -> PreviousRelCluNr;
100 AbsCluNr = file -> PreviousAbsCluNr;
103 AbsCluNr = file -> FirstAbsCluNr;
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
112 file -> PreviousRelCluNr = RelCluNr;
113 file -> PreviousAbsCluNr = AbsCluNr;
115 NewCluNr = fat_decode (fs, AbsCluNr);
116 if (NewCluNr == 1 || NewCluNr == 0) {
117 PRINTF("Fat problem while decoding %d %x\n",
121 if (CurCluNr == RelCluNr + NrClu) {
125 if (CurCluNr < RelCluNr && NewCluNr == FAT12_END) {
130 if (CurCluNr >= RelCluNr && NewCluNr != AbsCluNr + 1)
136 *len = min (*len, (1 + CurCluNr - RelCluNr) * clus_size - offset);
138 return (((file -> PreviousAbsCluNr - 2) * fs -> cluster_size +
139 fs -> dir_start + fs -> dir_len) *
140 SZ_STD_SECTOR + offset);
142 /*-----------------------------------------------------------------------------
143 * open_subdir -- open the subdir containing the file
144 *-----------------------------------------------------------------------------
146 int open_subdir (File_t *desc)
149 char *tmp, *s, *path;
152 if ((pathname = (char *)malloc (MAX_PATH)) == NULL) {
156 strcpy (pathname, desc -> name);
158 /* Suppress file name */
159 tmp = basename (pathname);
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;
169 for (s = tmp; ; ++s) {
170 if (*s == '/' || *s == '\0') {
174 if (s != tmp && strcmp (path,".")) {
175 if (descend (&desc -> subdir, desc -> fs, path) < 0) {
180 if (terminator == 0) {
189 /*-----------------------------------------------------------------------------
191 *-----------------------------------------------------------------------------
193 static int descend (Slot_t *parent,
200 if(path[0] == '\0' || strcmp (path, ".") == 0) {
206 if (vfat_lookup (parent,
212 ACCEPT_DIR | SINGLE | DO_OPEN,
219 if (strcmp(path, "..") == 0) {
220 parent -> FileSize = -1;
221 parent -> FirstAbsCluNr = 0;
222 parent -> map = root_map;
227 /*-----------------------------------------------------------------------------
229 *-----------------------------------------------------------------------------
231 int open_file (Slot_t *file, Directory_t *dir)
236 first = __le16_to_cpu (dir -> start);
239 (dir -> attr & ATTR_DIRECTORY) != 0) {
240 file -> FirstAbsCluNr = 0;
241 file -> FileSize = -1;
242 file -> map = root_map;
246 if ((dir -> attr & ATTR_DIRECTORY) != 0) {
247 size = (1UL << 31) - 1;
250 size = __le32_to_cpu (dir -> size);
253 file -> map = normal_map;
254 file -> FirstAbsCluNr = first;
255 file -> PreviousRelCluNr = 0xffff;
256 file -> FileSize = size;
259 /*-----------------------------------------------------------------------------
261 *-----------------------------------------------------------------------------
263 int read_file (Fs_t *fs,
270 int read, nb, sect, offset;
272 pos = file -> map (fs, file, where, &len);
280 /* Compute sector number */
281 sect = pos / SZ_STD_SECTOR;
282 offset = pos % SZ_STD_SECTOR;
286 /* Read doesn't start at the sector beginning. We need to use our */
288 if (sect != cache_sect) {
289 if (dev_read (cache, sect, 1) < 0) {
294 nb = min (len, SZ_STD_SECTOR - offset);
296 memcpy (buf, cache + offset, nb);
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);
307 /* update sector position */
310 /* Update byte position */
317 if (sect != cache_sect) {
318 if (dev_read (cache, sect, 1) < 0) {
319 return ((read) ? read : -1);
325 memcpy (buf + read, cache, len);