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