PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
fat_driver.c
1//---------------------------------------------------------------------------
2// File name: fat_driver.c
3//---------------------------------------------------------------------------
4#include <stdio.h>
5#include <errno.h>
6#include <limits.h>
7
8#ifdef WIN32
9#include <stdlib.h>
10#include <memory.h>
11#include <string.h>
12#else
13#include <sysclib.h>
14// #include <sys/stat.h>
15
16#include <thbase.h>
17#include <sysmem.h>
18#endif
19
20#ifdef BUILDING_USBHDFSD
21#include <usbhdfsd.h>
22#endif /* BUILDING_USBHDFSD */
23#include "usbhd_common.h"
24#include "scache.h"
25#include "fat_driver.h"
26#include "fat.h"
27#ifdef BUILDING_USBHDFSD
28#include "mass_stor.h"
29#endif /* BUILDING_USBHDFSD */
30#ifdef BUILDING_IEEE1394_DISK
31#include "sbp2_disk.h"
32#include "scsi.h"
33#endif /* BUILDING_IEEE1394_DISK */
34
35// #define DEBUG //comment out this line when not debugging
36
37#include "mass_debug.h"
38
39#define READ_SECTOR(d, a, b) scache_readSector((d)->cache, (a), (void **)&b)
40#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
41#define DEV_ACCESSOR(d) (d)
42#else
43#define DEV_ACCESSOR(d) ((d)->dev)
44#endif
45#ifdef BUILDING_USBHDFSD
46#define READ_SECTORS_RAW(d, a, c, b) mass_stor_readSector((d), a, b, c);
47#define INVALIDATE_SECTORS(d, s, c) scache_invalidate((d)->cache, s, c)
48#endif /* BUILDING_USBHDFSD */
49
50#define NUM_DRIVES 10
51static fat_driver *g_fatd[NUM_DRIVES];
52
53//---------------------------------------------------------------------------
54int InitFAT(void)
55{
56 int i;
57
58 M_DEBUG("%s\n", __func__);
59
60 for (i = 0; i < NUM_DRIVES; ++i)
61 g_fatd[i] = NULL;
62
63 return 0;
64}
65
66//---------------------------------------------------------------------------
67int strEqual(const char *s1, const char *s2)
68{
69 M_DEBUG("%s\n", __func__);
70
71 for (;;) {
72 char u1, u2;
73
74 u1 = *s1++;
75 u2 = *s2++;
76 if (u1 > 64 && u1 < 91)
77 u1 += 32;
78 if (u2 > 64 && u2 < 91)
79 u2 += 32;
80
81 if (u1 != u2) {
82 return -1;
83 }
84 if (u1 == '\0') {
85 return 0;
86 }
87 }
88}
89
90/*
91
92 0x321, 0xABC
93
94 byte| byte| byte|
95 +--+--+--+--+--+--+
96 |2 |1 |C |3 |A |B |
97 +--+--+--+--+--+--+
98
99*/
100
101//---------------------------------------------------------------------------
102unsigned int fat_getClusterRecord12(const unsigned char *buf, int type)
103{
104 M_DEBUG("%s\n", __func__);
105
106 if (type) { // 1
107 return ((buf[1] << 4) + (buf[0] >> 4));
108 } else { // 0
109 return (((buf[1] & 0x0F) << 8) + buf[0]);
110 }
111}
112
113//---------------------------------------------------------------------------
114// Get Cluster chain into <buf> buffer
115// returns:
116// 0 :if buf is full (bufSize entries) and more chain entries exist
117// 1-n :number of filled entries of the buf
118// -1 :error
119//---------------------------------------------------------------------------
120// for fat12
121/* fat12 cluster records can overlap the edge of the sector so we need to detect and maintain
122 these cases
123*/
124static int fat_getClusterChain12(fat_driver *fatd, unsigned int cluster, unsigned int *buf, unsigned int bufSize, int startFlag)
125{
126 int ret;
127 unsigned int i, lastFatSector;
128 unsigned char xbuf[4], cont;
129 unsigned char *sbuf = NULL; // sector buffer
130
131 M_DEBUG("%s\n", __func__);
132
133 cont = 1;
134 lastFatSector = -1;
135 i = 0;
136 if (startFlag) {
137 buf[i] = cluster; // store first cluster
138 i++;
139 }
140 while (i < bufSize && cont) {
141 unsigned int recordOffset, fatSector;
142 unsigned char sectorSpan;
143
144 recordOffset = (cluster * 3) / 2; // offset of the cluster record (in bytes) from the FAT start
145 fatSector = recordOffset / fatd->partBpb.sectorSize;
146 sectorSpan = 0;
147 if ((recordOffset % fatd->partBpb.sectorSize) == (fatd->partBpb.sectorSize - 1)) {
148 sectorSpan = 1;
149 }
150 if (lastFatSector != fatSector || sectorSpan) {
151 ret = READ_SECTOR(DEV_ACCESSOR(fatd), fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector, sbuf);
152 if (ret < 0) {
153 XPRINTF("Read fat12 sector failed! sector=%u! \n", fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector);
154 return -EIO;
155 }
156 lastFatSector = fatSector;
157
158 if (sectorSpan) {
159 xbuf[0] = sbuf[fatd->partBpb.sectorSize - 2];
160 xbuf[1] = sbuf[fatd->partBpb.sectorSize - 1];
161 ret = READ_SECTOR(DEV_ACCESSOR(fatd), fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector + 1, sbuf);
162 if (ret < 0) {
163 XPRINTF("Read fat12 sector failed sector=%u! \n", fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector + 1);
164 return -EIO;
165 }
166 xbuf[2] = sbuf[0];
167 xbuf[3] = sbuf[1];
168 }
169 }
170 if (sectorSpan) { // use xbuf as source buffer
171 cluster = fat_getClusterRecord12(xbuf + (recordOffset % fatd->partBpb.sectorSize) - (fatd->partBpb.sectorSize - 2), cluster % 2);
172 } else { // use sector buffer as source buffer
173 cluster = fat_getClusterRecord12(sbuf + (recordOffset % fatd->partBpb.sectorSize), cluster % 2);
174 }
175
176 if ((cluster & 0xFFF) >= 0xFF8) {
177 cont = 0; // continue = false
178 } else {
179 buf[i] = cluster & 0xFFF;
180 i++;
181 }
182 }
183 return i;
184}
185
186
187//---------------------------------------------------------------------------
188// for fat16
189static int fat_getClusterChain16(fat_driver *fatd, unsigned int cluster, unsigned int *buf, unsigned int bufSize, int startFlag)
190{
191 int ret;
192 unsigned int i, indexCount, lastFatSector;
193 unsigned char cont;
194 unsigned char *sbuf = NULL; // sector buffer
195
196 M_DEBUG("%s\n", __func__);
197
198 cont = 1;
199 indexCount = fatd->partBpb.sectorSize / 2; // FAT16->2, FAT32->4
200 lastFatSector = -1;
201 i = 0;
202 if (startFlag) {
203 buf[i] = cluster; // store first cluster
204 i++;
205 }
206 while (i < bufSize && cont) {
207 unsigned int fatSector;
208
209 fatSector = cluster / indexCount;
210 if (lastFatSector != fatSector) {
211 ret = READ_SECTOR(DEV_ACCESSOR(fatd), fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector, sbuf);
212 if (ret < 0) {
213 XPRINTF("Read fat16 sector failed! sector=%u! \n", fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector);
214 return -EIO;
215 }
216
217 lastFatSector = fatSector;
218 }
219 cluster = getUI16(sbuf + ((cluster % indexCount) * 2));
220 if ((cluster & 0xFFFF) >= 0xFFF8) {
221 cont = 0; // continue = false
222 } else {
223 buf[i] = cluster & 0xFFFF;
224 i++;
225 }
226 }
227 return i;
228}
229
230//---------------------------------------------------------------------------
231// for fat32
232static int fat_getClusterChain32(fat_driver *fatd, unsigned int cluster, unsigned int *buf, unsigned int bufSize, int startFlag)
233{
234 int ret;
235 unsigned int i, indexCount, lastFatSector;
236 unsigned char cont;
237 unsigned char *sbuf = NULL; // sector buffer
238
239 M_DEBUG("%s\n", __func__);
240
241 cont = 1;
242 indexCount = fatd->partBpb.sectorSize / 4; // FAT16->2, FAT32->4
243 lastFatSector = -1;
244 i = 0;
245 if (startFlag) {
246 buf[i] = cluster; // store first cluster
247 i++;
248 }
249 while (i < bufSize && cont) {
250 unsigned int fatSector;
251
252 fatSector = cluster / indexCount;
253 if (lastFatSector != fatSector) {
254 ret = READ_SECTOR(DEV_ACCESSOR(fatd), fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector, sbuf);
255 if (ret < 0) {
256 XPRINTF("Read fat32 sector failed sector=%u! \n", fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector);
257 return -EIO;
258 }
259
260 lastFatSector = fatSector;
261 }
262 cluster = getUI32(sbuf + ((cluster % indexCount) * 4));
263 if ((cluster & 0xFFFFFFF) >= 0xFFFFFF8) {
264 cont = 0; // continue = false
265 } else {
266 buf[i] = cluster & 0xFFFFFFF;
267 i++;
268 }
269 }
270 return i;
271}
272
273//---------------------------------------------------------------------------
274int fat_getClusterChain(fat_driver *fatd, unsigned int cluster, unsigned int *buf, unsigned int bufSize, int startFlag)
275{
276 M_DEBUG("%s\n", __func__);
277
278 if (cluster == fatd->lastChainCluster) {
279 return fatd->lastChainResult;
280 }
281
282 switch (fatd->partBpb.fatType) {
283 case FAT12:
284 fatd->lastChainResult = fat_getClusterChain12(fatd, cluster, buf, bufSize, startFlag);
285 break;
286 case FAT16:
287 fatd->lastChainResult = fat_getClusterChain16(fatd, cluster, buf, bufSize, startFlag);
288 break;
289 case FAT32:
290 fatd->lastChainResult = fat_getClusterChain32(fatd, cluster, buf, bufSize, startFlag);
291 break;
292 }
293 fatd->lastChainCluster = cluster;
294 return fatd->lastChainResult;
295}
296
297//---------------------------------------------------------------------------
298#ifndef BUILDING_IEEE1394_DISK
299int fat_CheckChain(fat_driver *fatd, unsigned int cluster)
300{
301 int i, nextChain = 1;
302 int clusterChainStart = 1;
303
304 if (cluster < 2)
305 return 0;
306
307 while (nextChain) {
308 int chainSize;
309
310 chainSize = fat_getClusterChain(fatd, cluster, fatd->cbuf, MAX_DIR_CLUSTER, clusterChainStart);
311 clusterChainStart = 0;
312 if (chainSize >= MAX_DIR_CLUSTER) { // the chain is full, but more chain parts exist
313 cluster = fatd->cbuf[MAX_DIR_CLUSTER - 1];
314 } else { // chain fits in the chain buffer completely - no next chain needed
315 nextChain = 0;
316 }
317
318 // process the cluster chain (fatd->cbuf) and skip leading clusters if needed
319 for (i = 0; i < (chainSize - 1); i++) {
320 if ((fatd->cbuf[i] + 1) != fatd->cbuf[i + 1])
321 return 0;
322 }
323 }
324
325 return 1;
326}
327#endif /* BUILDING_IEEE1394_DISK */
328
329//---------------------------------------------------------------------------
330void fat_invalidateLastChainResult(fat_driver *fatd)
331{
332 fatd->lastChainCluster = 0;
333}
334
335//---------------------------------------------------------------------------
336static void fat_determineFatType(fat_bpb *partBpb)
337{
338 unsigned int sector, clusterCount;
339
340 M_DEBUG("%s\n", __func__);
341
342 // get sector of cluster 0
343 sector = fat_cluster2sector(partBpb, 0);
344 // remove partition start sector to get BR+FAT+ROOT_DIR sector count
345 sector -= partBpb->partStart;
346 sector = partBpb->sectorCount - sector;
347 clusterCount = sector / partBpb->clusterSize;
348 // XPRINTF("Data cluster count = %u \n", clusterCount);
349
350 if (clusterCount < 4085) {
351 partBpb->fatType = FAT12;
352 } else if (clusterCount < 65525) {
353 partBpb->fatType = FAT16;
354 } else {
355 partBpb->fatType = FAT32;
356 }
357}
358
359//---------------------------------------------------------------------------
360#if defined(BUILDING_USBHDFSD)
361static int fat_getPartitionBootSector(mass_dev *dev, unsigned int sector, fat_bpb *partBpb)
362#elif defined(BUILDING_IEEE1394_DISK)
363static int fat_getPartitionBootSector(struct SBP2Device *dev, unsigned int sector, fat_bpb *partBpb)
364#else
365static int fat_getPartitionBootSector(struct block_device *bd, unsigned int sector, fat_bpb *partBpb)
366#endif
367{
368 fat_raw_bpb *bpb_raw; // fat16, fat12
369 fat32_raw_bpb *bpb32_raw; // fat32
370 int ret;
371 unsigned char *sbuf = NULL; // sector buffer
372
373 M_DEBUG("%s\n", __func__);
374
375#if !defined(BUILDING_USBHDFSD) && !defined(BUILDING_IEEE1394_DISK)
376 sbuf = malloc(bd->sectorSize);
377 ret = bd->read(bd, sector, sbuf, 1); // read partition boot sector (first sector on partition)
378#else
379 ret = READ_SECTOR(dev, sector, sbuf); // read partition boot sector (first sector on partition)
380#endif
381
382 if (ret < 0) {
383 XPRINTF("Read partition boot sector failed sector=%u! \n", sector);
384#if !defined(BUILDING_USBHDFSD) && !defined(BUILDING_IEEE1394_DISK)
385 free(sbuf);
386#endif
387 return -EIO;
388 }
389
390 bpb_raw = (fat_raw_bpb *)sbuf;
391 bpb32_raw = (fat32_raw_bpb *)sbuf;
392
393#if !defined(BUILDING_USBHDFSD) && !defined(BUILDING_IEEE1394_DISK)
394 if ((bpb32_raw->bootSignature[0] != 0x55) || (bpb32_raw->bootSignature[1] != 0xAA)) {
395 M_DEBUG("Invalid bootSignature (0x%x - 0x%x)\n", bpb32_raw->bootSignature[0], bpb32_raw->bootSignature[1]);
396 free(sbuf);
397 return -EIO;
398 }
399#endif
400
401 // set fat common properties
402 partBpb->sectorSize = getUI16(bpb_raw->sectorSize);
403 partBpb->clusterSize = bpb_raw->clusterSize;
404 partBpb->resSectors = getUI16(bpb_raw->resSectors);
405 partBpb->fatCount = bpb_raw->fatCount;
406 partBpb->rootSize = getUI16(bpb_raw->rootSize);
407 partBpb->fatSize = getUI16(bpb_raw->fatSize);
408 partBpb->trackSize = getUI16(bpb_raw->trackSize);
409 partBpb->headCount = getUI16(bpb_raw->headCount);
410 partBpb->sectorCount = getUI16(bpb_raw->sectorCountO);
411 if (partBpb->sectorCount == 0) {
412 partBpb->sectorCount = getUI32(bpb_raw->sectorCount); // large partition
413 }
414 partBpb->partStart = sector;
415 partBpb->rootDirStart = partBpb->partStart + (partBpb->fatCount * partBpb->fatSize) + partBpb->resSectors;
416 for (ret = 0; ret < 8; ret++) {
417 partBpb->fatId[ret] = bpb_raw->fatId[ret];
418 }
419 partBpb->fatId[ret] = 0;
420 partBpb->rootDirCluster = 0;
421 partBpb->dataStart = partBpb->rootDirStart + (partBpb->rootSize / (partBpb->sectorSize >> 5));
422
423 fat_determineFatType(partBpb);
424
425 // fat32 specific info
426 if (partBpb->fatType == FAT32 && partBpb->fatSize == 0) {
427 partBpb->fatSize = getUI32(bpb32_raw->fatSize32);
428 partBpb->activeFat = getUI16(bpb32_raw->fatStatus);
429 if (partBpb->activeFat & 0x80) { // fat not synced
430 partBpb->activeFat = (partBpb->activeFat & 0xF);
431 } else {
432 partBpb->activeFat = 0;
433 }
434 partBpb->rootDirStart = partBpb->partStart + (partBpb->fatCount * partBpb->fatSize) + partBpb->resSectors;
435 partBpb->rootDirCluster = getUI32(bpb32_raw->rootDirCluster);
436 for (ret = 0; ret < 8; ret++) {
437 partBpb->fatId[ret] = bpb32_raw->fatId[ret];
438 }
439 partBpb->fatId[ret] = 0;
440 partBpb->dataStart = partBpb->rootDirStart;
441 }
442
443 M_PRINTF("Fat type %u Id %s \n", partBpb->fatType, partBpb->fatId);
444#if !defined(BUILDING_USBHDFSD) && !defined(BUILDING_IEEE1394_DISK)
445 free(sbuf);
446#endif
447 return 1;
448}
449
450//---------------------------------------------------------------------------
451/*
452 returns:
453 0 - no more dir entries
454 1 - short name dir entry found
455 2 - long name dir entry found
456 3 - deleted dir entry found
457*/
458int fat_getDirentry(unsigned char fatType, fat_direntry *dir_entry, fat_direntry_summary *dir)
459{
460 int i;
461
462 u16 character;
463
464 M_DEBUG("%s\n", __func__);
465
466 // detect last entry - all zeros (slight modification by radad)
467 if (dir_entry->sfn.name[0] == 0) {
468 return 0;
469 }
470 // detect deleted entry - it will be ignored
471 if (dir_entry->sfn.name[0] == 0xE5) {
472 return 3;
473 }
474
475 // detect long filename
476 if (dir_entry->lfn.rshv == 0x0F && dir_entry->lfn.reserved1 == 0x00 && dir_entry->lfn.reserved2[0] == 0x00) {
477 unsigned int offset;
478 unsigned char cont;
479
480 // long filename - almost whole direntry is unicode string - extract it
481 offset = dir_entry->lfn.entrySeq & 0x3f;
482 offset--;
483 offset = offset * 13;
484 // name - 1st part
485 cont = 1;
486 for (i = 0; i < 10 && cont; i += 2) {
487 character = dir_entry->lfn.name1[i] | (dir_entry->lfn.name1[i + 1] << 8);
488
489 if (character == 0 || offset >= (FAT_MAX_NAME - 1)) {
490 dir->name[offset] = 0; // terminate
491 cont = 0; // stop
492 } else {
493 // Handle characters that we don't support.
494 dir->name[offset] = character <= UCHAR_MAX ? dir_entry->lfn.name1[i] : '?';
495 offset++;
496 }
497 }
498 // name - 2nd part
499 for (i = 0; i < 12 && cont; i += 2) {
500 character = dir_entry->lfn.name2[i] | (dir_entry->lfn.name2[i + 1] << 8);
501
502 if (character == 0 || offset >= (FAT_MAX_NAME - 1)) {
503 dir->name[offset] = 0; // terminate
504 cont = 0; // stop
505 } else {
506 // Handle characters that we don't support.
507 dir->name[offset] = character <= UCHAR_MAX ? dir_entry->lfn.name2[i] : '?';
508 offset++;
509 }
510 }
511 // name - 3rd part
512 for (i = 0; i < 4 && cont; i += 2) {
513 character = dir_entry->lfn.name3[i] | (dir_entry->lfn.name3[i + 1] << 8);
514
515 if (character == 0 || offset >= (FAT_MAX_NAME - 1)) {
516 dir->name[offset] = 0; // terminate
517 cont = 0; // stop
518 } else {
519 // Handle characters that we don't support.
520 dir->name[offset] = character <= UCHAR_MAX ? dir_entry->lfn.name3[i] : '?';
521 offset++;
522 }
523 }
524 if ((dir_entry->lfn.entrySeq & 0x40)) { // terminate string flag
525 dir->name[offset] = 0;
526 }
527 return 2;
528 } else {
529 int j;
530
531 // short filename
532 // copy name
533 for (i = 0; i < 8 && dir_entry->sfn.name[i] != ' '; i++) {
534 dir->sname[i] = dir_entry->sfn.name[i];
535 // NT-adaption for LaunchELF
536 if (dir_entry->sfn.reservedNT & 0x08 &&
537 dir->sname[i] >= 'A' && dir->sname[i] <= 'Z') {
538 dir->sname[i] += 0x20; // Force standard letters in name to lower case
539 }
540 }
541 for (j = 0; j < 3 && dir_entry->sfn.ext[j] != ' '; j++) {
542 if (j == 0) {
543 dir->sname[i] = '.';
544 i++;
545 }
546 dir->sname[i + j] = dir_entry->sfn.ext[j];
547 // NT-adaption for LaunchELF
548 if (dir_entry->sfn.reservedNT & 0x10 &&
549 dir->sname[i + j] >= 'A' && dir->sname[i + j] <= 'Z') {
550 dir->sname[i + j] += 0x20; // Force standard letters in ext to lower case
551 }
552 }
553 dir->sname[i + j] = 0; // terminate
554 if (dir->name[0] == 0) { // long name desn't exit
555 for (i = 0; dir->sname[i] != 0; i++)
556 dir->name[i] = dir->sname[i];
557 dir->name[i] = 0;
558 }
559 dir->attr = dir_entry->sfn.attr;
560 dir->size = getUI32(dir_entry->sfn.size);
561 dir->cluster = (fatType == FAT32) ? getUI32_2(dir_entry->sfn.clusterL, dir_entry->sfn.clusterH) : getUI16(dir_entry->sfn.clusterL);
562
563 return 1;
564 }
565}
566
567//---------------------------------------------------------------------------
568// Set chain info (cluster/offset) cache
569void fat_setFatDirChain(fat_driver *fatd, fat_dir *fatDir)
570{
571 int i, j;
572 unsigned int index, clusterChainStart, fileCluster, fileSize, blockSize;
573 unsigned char nextChain;
574 int chainSize;
575
576 M_DEBUG("%s\n", __func__);
577 XPRINTF("reading cluster chain \n");
578 fileCluster = fatDir->chain[0].cluster;
579
580 if (fileCluster < 2) {
581 XPRINTF(" early exit... \n");
582 return;
583 }
584
585 fileSize = fatDir->size;
586 blockSize = fileSize / DIR_CHAIN_SIZE;
587
588 nextChain = 1;
589 clusterChainStart = 0;
590 j = 1;
591 fileSize = 0;
592 index = 0;
593
594 while (nextChain) {
595 if ((chainSize = fat_getClusterChain(fatd, fileCluster, fatd->cbuf, MAX_DIR_CLUSTER, 1)) >= 0) {
596 if (chainSize >= MAX_DIR_CLUSTER) { // the chain is full, but more chain parts exist
597 fileCluster = fatd->cbuf[MAX_DIR_CLUSTER - 1];
598 } else { // chain fits in the chain buffer completely - no next chain exist
599 nextChain = 0;
600 }
601 } else {
602 XPRINTF("fat_setFatDirChain(): fat_getClusterChain() failed: %d\n", chainSize);
603 return;
604 }
605
606 // process the cluster chain (fatd->cbuf)
607 for (i = clusterChainStart; i < chainSize; i++) {
608 fileSize += (fatd->partBpb.clusterSize * fatd->partBpb.sectorSize);
609 while (fileSize >= (j * blockSize) && j < DIR_CHAIN_SIZE) {
610 fatDir->chain[j].cluster = fatd->cbuf[i];
611 fatDir->chain[j].index = index;
612 j++;
613 } // ends "while"
614 index++;
615 } // ends "for"
616 clusterChainStart = 1;
617 } // ends "while"
618 fatDir->lastCluster = fatd->cbuf[i - 1];
619
620#ifdef DEBUG_EXTREME // dlanor: I patched this because this bloat hid important stuff
621 // debug
622 XPRINTF("SEEK CLUSTER CHAIN CACHE fileSize=%u blockSize=%u \n", fatDir->size, blockSize);
623 for (i = 0; i < DIR_CHAIN_SIZE; i++) {
624 XPRINTF("index=%u cluster=%u offset= %u - %u start=%u \n",
625 fatDir->chain[i].index, fatDir->chain[i].cluster,
626 fatDir->chain[i].index * fatd->partBpb.clusterSize * fatd->partBpb.sectorSize,
627 (fatDir->chain[i].index + 1) * fatd->partBpb.clusterSize * fatd->partBpb.sectorSize,
628 i * blockSize);
629 }
630#endif /* debug */
631 XPRINTF("read cluster chain done!\n");
632}
633
634//---------------------------------------------------------------------------
635/* Set base attributes of direntry */
636static void fat_setFatDir(fat_driver *fatd, fat_dir *fatDir, unsigned int parentDirCluster, fat_direntry_sfn *dsfn, fat_direntry_summary *dir, int getClusterInfo)
637{
638 unsigned int i;
639 char *srcName;
640
641 M_DEBUG("%s\n", __func__);
642 XPRINTF("setting fat dir...\n");
643 srcName = dir->sname;
644 if (dir->name[0] != 0) { // long filename not empty
645 srcName = dir->name;
646 }
647 // copy name
648 for (i = 0; srcName[i] != 0; i++)
649 fatDir->name[i] = srcName[i];
650 fatDir->name[i] = 0; // terminate
651
652 fatDir->attr = dir->attr;
653 fatDir->size = dir->size;
654
655 // created Date: Day, Month, Year-low, Year-high
656 fatDir->cdate[0] = (dsfn->dateCreate[0] & 0x1F);
657 fatDir->cdate[1] = (dsfn->dateCreate[0] >> 5) + ((dsfn->dateCreate[1] & 0x01) << 3);
658 i = 1980 + (dsfn->dateCreate[1] >> 1);
659 fatDir->cdate[2] = (i & 0xFF);
660 fatDir->cdate[3] = ((i & 0xFF00) >> 8);
661
662 // created Time: Hours, Minutes, Seconds
663 fatDir->ctime[0] = ((dsfn->timeCreate[1] & 0xF8) >> 3);
664 fatDir->ctime[1] = ((dsfn->timeCreate[1] & 0x07) << 3) + ((dsfn->timeCreate[0] & 0xE0) >> 5);
665 fatDir->ctime[2] = ((dsfn->timeCreate[0] & 0x1F) << 1);
666
667 // accessed Date: Day, Month, Year-low, Year-high
668 fatDir->adate[0] = (dsfn->dateAccess[0] & 0x1F);
669 fatDir->adate[1] = (dsfn->dateAccess[0] >> 5) + ((dsfn->dateAccess[1] & 0x01) << 3);
670 i = 1980 + (dsfn->dateAccess[1] >> 1);
671 fatDir->adate[2] = (i & 0xFF);
672 fatDir->adate[3] = ((i & 0xFF00) >> 8);
673
674 // modified Date: Day, Month, Year-low, Year-high
675 fatDir->mdate[0] = (dsfn->dateWrite[0] & 0x1F);
676 fatDir->mdate[1] = (dsfn->dateWrite[0] >> 5) + ((dsfn->dateWrite[1] & 0x01) << 3);
677 i = 1980 + (dsfn->dateWrite[1] >> 1);
678 fatDir->mdate[2] = (i & 0xFF);
679 fatDir->mdate[3] = ((i & 0xFF00) >> 8);
680
681 // modified Time: Hours, Minutes, Seconds
682 fatDir->mtime[0] = ((dsfn->timeWrite[1] & 0xF8) >> 3);
683 fatDir->mtime[1] = ((dsfn->timeWrite[1] & 0x07) << 3) + ((dsfn->timeWrite[0] & 0xE0) >> 5);
684 fatDir->mtime[2] = ((dsfn->timeWrite[0] & 0x1F) << 1);
685
686 fatDir->chain[0].cluster = dir->cluster;
687 fatDir->chain[0].index = 0;
688 if (getClusterInfo) {
689 fat_setFatDirChain(fatd, fatDir);
690 }
691
692 fatDir->parentDirCluster = parentDirCluster;
693 fatDir->startCluster = dir->cluster;
694}
695
696//---------------------------------------------------------------------------
697int fat_getDirentrySectorData(fat_driver *fatd, unsigned int *startCluster, unsigned int *startSector, unsigned int *dirSector)
698{
699 unsigned int chainSize;
700
701 M_DEBUG("%s\n", __func__);
702
703 if (*startCluster == 0 && fatd->partBpb.fatType < FAT32) { // Root directory
704 *startSector = fatd->partBpb.rootDirStart;
705 *dirSector = fatd->partBpb.rootSize / (fatd->partBpb.sectorSize / 32);
706 return 0;
707 }
708 // other directory or fat 32
709 if (*startCluster == 0 && fatd->partBpb.fatType == FAT32) {
710 *startCluster = fatd->partBpb.rootDirCluster;
711 }
712 *startSector = fat_cluster2sector(&fatd->partBpb, *startCluster);
713 chainSize = fat_getClusterChain(fatd, *startCluster, fatd->cbuf, MAX_DIR_CLUSTER, 1);
714 if (chainSize >= MAX_DIR_CLUSTER) {
715 XPRINTF("Chain too large\n");
716 return -EFAULT;
717 } else if (chainSize > 0) {
718 *dirSector = chainSize * fatd->partBpb.clusterSize;
719 } else {
720 XPRINTF("Error getting cluster chain! startCluster=%u \n", *startCluster);
721 return -EFAULT;
722 }
723
724 return chainSize;
725}
726
727//---------------------------------------------------------------------------
728static int fat_getDirentryStartCluster(fat_driver *fatd, char *dirName, unsigned int *startCluster, fat_dir *fatDir)
729{
730#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
731 static fat_direntry_summary dir; // TOO BIG FOR STACK!
732#else
734#endif
735 unsigned int i, dirSector, startSector;
736 unsigned char cont;
737 int ret;
738#ifdef DEBUG
739#ifdef BUILDING_USBHDFSD
740 mass_dev *mass_device = fatd->dev;
741#endif /* BUILDING_USBHDFSD */
742#ifdef BUILDING_IEEE1394_DISK
743 struct SBP2Device *mass_device = fatd->dev;
744#endif /* BUILDING_IEEE1394_DISK */
745#endif
746
747 M_DEBUG("%s(%s)\n", __func__, dirName);
748
749 cont = 1;
750 XPRINTF("getting cluster for dir entry: %s \n", dirName);
751 // clear name strings
752 dir.sname[0] = 0;
753 dir.name[0] = 0;
754
755 ret = fat_getDirentrySectorData(fatd, startCluster, &startSector, &dirSector);
756 if (ret < 0)
757 return ret;
758
759 XPRINTF("dirCluster=%u startSector=%u (%u) dirSector=%u \n", *startCluster, startSector, startSector
760#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
761 * fatd->bd->sectorSize,
762#else
763 * mass_device->sectorSize,
764#endif
765 dirSector);
766
767 // go through first directory sector till the max number of directory sectors
768 // or stop when no more direntries detected
769 for (i = 0; i < dirSector && cont; i++) {
770 unsigned int dirPos;
771 unsigned char *sbuf = NULL; // sector buffer
772
773 // At cluster borders, get correct sector from cluster chain buffer
774 if ((*startCluster != 0) && (i % fatd->partBpb.clusterSize == 0)) {
775 startSector = fat_cluster2sector(&fatd->partBpb, fatd->cbuf[(i / fatd->partBpb.clusterSize)]) - i;
776 }
777
778 ret = READ_SECTOR(DEV_ACCESSOR(fatd), startSector + i, sbuf);
779 if (ret < 0) {
780 XPRINTF("read directory sector failed ! sector=%u\n", startSector + i);
781 return -EIO;
782 }
783 XPRINTF("read sector ok, scanning sector for direntries...\n");
784 dirPos = 0;
785
786 // go through start of the sector till the end of sector
787 while (cont && dirPos < fatd->partBpb.sectorSize) {
788 fat_direntry *dir_entry = (fat_direntry *)(sbuf + dirPos);
789 cont = fat_getDirentry(fatd->partBpb.fatType, dir_entry, &dir); // get single directory entry from sector buffer
790 if (cont == 1) { // when short file name entry detected
791 if (!(dir.attr & FAT_ATTR_VOLUME_LABEL)) { // not volume label
792 if ((strEqual(dir.sname, dirName) == 0) ||
793 (strEqual(dir.name, dirName) == 0)) {
794 XPRINTF("found! %s\n", dir.name);
795 if (fatDir != NULL) { // fill the directory properties
796 fat_setFatDir(fatd, fatDir, *startCluster, &dir_entry->sfn, &dir, 1);
797 }
798 *startCluster = dir.cluster;
799 XPRINTF("direntry %s found at cluster: %u \n", dirName, dir.cluster);
800 return dir.attr; // returns file or directory attr
801 }
802 } // ends "if(!(dir.attr & FAT_ATTR_VOLUME_LABEL))"
803 // clear name strings
804 dir.sname[0] = 0;
805 dir.name[0] = 0;
806 } // ends "if (cont == 1)"
807 dirPos += sizeof(fat_direntry);
808 } // ends "while"
809 } // ends "for"
810 XPRINTF("direntry %s not found! \n", dirName);
811 return -ENOENT;
812}
813
814//---------------------------------------------------------------------------
815// start cluster should be 0 - if we want to search from root directory
816// otherwise the start cluster should be correct cluster of directory
817// to search directory - set fatDir as NULL
818int fat_getFileStartCluster(fat_driver *fatd, const char *fname, unsigned int *startCluster, fat_dir *fatDir)
819{
820#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
821 static char tmpName[FAT_MAX_NAME + 1]; // TOO BIG FOR STACK!
822#else
823 char tmpName[FAT_MAX_NAME + 1];
824#endif
825 unsigned int i, offset;
826 int ret;
827
828 M_DEBUG("%s\n", __func__);
829 XPRINTF("Entering fat_getFileStartCluster\n");
830
831 offset = 0;
832 i = 0;
833
834 *startCluster = 0;
835 if (fatDir != NULL) {
836 memset(fatDir, 0, sizeof(fat_dir));
837 fatDir->attr = FAT_ATTR_DIRECTORY;
838 }
839 if (fname[i] == '/') {
840 i++;
841 }
842
843 for (; fname[i] != 0; i++) {
844 if (fname[i] == '/') { // directory separator
845 tmpName[offset] = 0; // terminate string
846 ret = fat_getDirentryStartCluster(fatd, tmpName, startCluster, fatDir);
847 if (ret < 0) {
848 return -ENOENT;
849 }
850 offset = 0;
851 } else {
852 tmpName[offset] = fname[i];
853 offset++;
854 }
855 } // ends "for"
856 // and the final file
857 tmpName[offset] = 0; // terminate string
858 XPRINTF("Ready to get cluster for file \"%s\"\n", tmpName);
859 if (fatDir != NULL) {
860 // if the last char of the name was slash - the name was already found -exit
861 if (offset == 0) {
862 XPRINTF("Exiting from fat_getFileStartCluster with a folder\n");
863 return 2;
864 }
865 ret = fat_getDirentryStartCluster(fatd, tmpName, startCluster, fatDir);
866 if (ret < 0) {
867 XPRINTF("Exiting from fat_getFileStartCluster with error %i\n", ret);
868 return ret;
869 }
870 XPRINTF("file's startCluster found. Name=%s, cluster=%u \n", fname, *startCluster);
871 }
872 XPRINTF("Exiting from fat_getFileStartCluster with no error.\n");
873 return 1;
874}
875
876//---------------------------------------------------------------------------
877void fat_getClusterAtFilePos(fat_driver *fatd, fat_dir *fatDir, unsigned int filePos, unsigned int *cluster, unsigned int *clusterPos)
878{
879 unsigned int i, j, blockSize;
880
881 M_DEBUG("%s\n", __func__);
882
883 blockSize = fatd->partBpb.clusterSize * fatd->partBpb.sectorSize;
884
885 for (i = 0, j = (DIR_CHAIN_SIZE - 1); i < (DIR_CHAIN_SIZE - 1); i++) {
886 if (fatDir->chain[i].index * blockSize <= filePos &&
887 fatDir->chain[i + 1].index * blockSize > filePos) {
888 j = i;
889 break;
890 }
891 }
892 *cluster = fatDir->chain[j].cluster;
893 *clusterPos = (fatDir->chain[j].index * blockSize);
894}
895
896//---------------------------------------------------------------------------
897#ifdef BUILDING_USBHDFSD
898static int fat_readSingleSector(mass_dev *dev, unsigned int sector, void *buffer, int size, int dataSkip)
899{
900 unsigned char *sbuf = NULL; // sector buffer
901 int ret;
902
903 ret = READ_SECTOR(dev, sector, sbuf);
904 if (ret < 0) {
905 XPRINTF("Read sector failed ! sector=%u\n", sector);
906 return 0;
907 }
908
909 memcpy(buffer, sbuf + dataSkip, size);
910
911 return 1;
912}
913#endif /* BUILDING_USBHDFSD */
914
915int fat_readFile(fat_driver *fatd, fat_dir *fatDir, unsigned int filePos, unsigned char *buffer, unsigned int size)
916{
917 int ret;
918#ifdef BUILDING_USBHDFSD
919 unsigned int toRead;
920#endif
921 unsigned int i, j, startSector, clusterChainStart, bufSize, sectorSkip, clusterSkip, dataSkip;
922 unsigned char nextChain;
923#ifdef BUILDING_USBHDFSD
924 // cppcheck-suppress unreadVariable
925 mass_dev *mass_device = fatd->dev;
926#endif /* BUILDING_USBHDFSD */
927#ifdef BUILDING_IEEE1394_DISK
928 struct SBP2Device *mass_device = fatd->dev;
929#endif /* BUILDING_IEEE1394_DISK */
930
931 unsigned int bufferPos, fileCluster, clusterPos;
932
933 M_DEBUG("%s\n", __func__);
934
935 fat_getClusterAtFilePos(fatd, fatDir, filePos, &fileCluster, &clusterPos);
936 sectorSkip = (filePos - clusterPos) / fatd->partBpb.sectorSize;
937 clusterSkip = sectorSkip / fatd->partBpb.clusterSize;
938 sectorSkip %= fatd->partBpb.clusterSize;
939 dataSkip = filePos % fatd->partBpb.sectorSize;
940 bufferPos = 0;
941
942 XPRINTF("fileCluster = %u, clusterPos= %u clusterSkip=%u, sectorSkip=%u dataSkip=%u \n",
943 fileCluster, clusterPos, clusterSkip, sectorSkip, dataSkip);
944
945 if (fileCluster < 2) {
946 return 0;
947 }
948
949#ifdef BUILDING_IEEE1394_DISK
950 // cppcheck-suppress unreadVariable
951 bufSize = mass_device->sectorSize;
952#endif /* BUILDING_IEEE1394_DISK */
953#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
954 bufSize = fatd->bd->sectorSize;
955#endif
956 nextChain = 1;
957 clusterChainStart = 1;
958
959 while (nextChain && size > 0) {
960 int chainSize;
961
962 if ((chainSize = fat_getClusterChain(fatd, fileCluster, fatd->cbuf, MAX_DIR_CLUSTER, clusterChainStart)) < 0) {
963 return chainSize;
964 }
965
966 clusterChainStart = 0;
967 if (chainSize >= MAX_DIR_CLUSTER) { // the chain is full, but more chain parts exist
968 fileCluster = fatd->cbuf[MAX_DIR_CLUSTER - 1];
969 } else { // chain fits in the chain buffer completely - no next chain needed
970 nextChain = 0;
971 }
972 while (clusterSkip >= MAX_DIR_CLUSTER) {
973 chainSize = fat_getClusterChain(fatd, fileCluster, fatd->cbuf, MAX_DIR_CLUSTER, clusterChainStart);
974 clusterChainStart = 0;
975 if (chainSize >= MAX_DIR_CLUSTER) { // the chain is full, but more chain parts exist
976 fileCluster = fatd->cbuf[MAX_DIR_CLUSTER - 1];
977 } else { // chain fits in the chain buffer completely - no next chain needed
978 nextChain = 0;
979 }
980 clusterSkip -= MAX_DIR_CLUSTER;
981 }
982
983 // process the cluster chain (fatd->cbuf) and skip leading clusters if needed
984 for (i = 0 + clusterSkip; i < (unsigned int)chainSize && size > 0; i++) {
985 // read cluster and save cluster content
986 startSector = fat_cluster2sector(&fatd->partBpb, fatd->cbuf[i]);
987
988#ifdef BUILDING_USBHDFSD
989 // Calculate how long we can continuously read for.
990 j = (size + dataSkip) / fatd->partBpb.sectorSize + sectorSkip;
991 toRead = 0;
992 while (1) {
993 if (j >= fatd->partBpb.clusterSize) {
994 toRead += fatd->partBpb.clusterSize;
995 j -= fatd->partBpb.clusterSize;
996 } else {
997 toRead += j;
998 j = 0;
999 }
1000
1001 // Check that the next cluster is adjacent to this one, so we can read across.
1002 if ((i >= (unsigned int)(chainSize - 1)) || (fatd->cbuf[i] != (fatd->cbuf[i + 1] - 1)))
1003 break;
1004 if (j == 0)
1005 break;
1006 i++; // Advance to the next cluster.
1007 }
1008
1009 // Consider the number of sectors within the cluster to skip.
1010 startSector += sectorSkip;
1011 toRead -= sectorSkip;
1012#endif /* BUILDING_USBHDFSD */
1013
1014 // process all sectors of the cluster (and skip leading sectors if needed)
1015#ifndef BUILDING_USBHDFSD
1016 for (j = 0 + sectorSkip; j < fatd->partBpb.clusterSize && size > 0; j++) {
1017 unsigned char *sbuf = NULL; // sector buffer
1018
1019 ret = READ_SECTOR(DEV_ACCESSOR(fatd), startSector + j, sbuf);
1020 if (ret < 0) {
1021 XPRINTF("Read sector failed ! sector=%u\n", startSector + j);
1022 return bufferPos;
1023 }
1024
1025 // compute exact size of transfered bytes
1026 if (size < bufSize) {
1027 bufSize = size + dataSkip;
1028 }
1029#ifdef BUILDING_IEEE1394_DISK
1030 if (bufSize > mass_device->sectorSize) {
1031 bufSize = mass_device->sectorSize;
1032 }
1033#else
1034 if (bufSize > fatd->bd->sectorSize) {
1035 bufSize = fatd->bd->sectorSize;
1036 }
1037#endif
1038 XPRINTF("memcopy dst=%u, src=%u, size=%u bufSize=%u \n", bufferPos, dataSkip, bufSize - dataSkip, bufSize);
1039 memcpy(buffer + bufferPos, sbuf + dataSkip, bufSize - dataSkip);
1040 size -= (bufSize - dataSkip);
1041 bufferPos += (bufSize - dataSkip);
1042 dataSkip = 0;
1043#ifdef BUILDING_IEEE1394_DISK
1044 bufSize = mass_device->sectorSize;
1045#else
1046 bufSize = fatd->bd->sectorSize;
1047#endif
1048 }
1049#endif /* BUILDING_USBHDFSD */
1050
1051#ifdef BUILDING_USBHDFSD
1052 if (dataSkip > 0) {
1053 bufSize = mass_device->sectorSize - dataSkip;
1054 if (size < bufSize)
1055 bufSize = size;
1056
1057 ret = fat_readSingleSector(fatd->dev, startSector, buffer + bufferPos, bufSize, dataSkip);
1058 if (ret != 1) {
1059 return bufferPos;
1060 }
1061
1062 if (size + dataSkip >= mass_device->sectorSize)
1063 toRead--;
1064
1065 size -= bufSize;
1066 bufferPos += bufSize;
1067 dataSkip = 0;
1068 startSector++;
1069 }
1070
1071 if (toRead > 0) {
1072 INVALIDATE_SECTORS(DEV_ACCESSOR(fatd), startSector, toRead);
1073 ret = READ_SECTORS_RAW(DEV_ACCESSOR(fatd), startSector, toRead, buffer + bufferPos);
1074 if (ret != 0) {
1075 XPRINTF("Read sectors failed ! sector=%u (%u)\n", startSector, toRead);
1076 return bufferPos;
1077 }
1078
1079 bufSize = toRead * mass_device->sectorSize;
1080 size -= bufSize;
1081 bufferPos += bufSize;
1082 startSector += toRead;
1083 }
1084
1085 if (size > 0 && size <= mass_device->sectorSize) {
1086 bufSize = size;
1087
1088 ret = fat_readSingleSector(fatd->dev, startSector, buffer + bufferPos, bufSize, 0);
1089 if (ret != 1) {
1090 return bufferPos;
1091 }
1092
1093 size -= bufSize;
1094 bufferPos += bufSize;
1095 }
1096#endif /* BUILDING_USBHDFSD */
1097
1098 sectorSkip = 0;
1099 }
1100 clusterSkip = 0;
1101 }
1102 return bufferPos;
1103}
1104
1105//---------------------------------------------------------------------------
1106int fat_getNextDirentry(fat_driver *fatd, fat_dir_list *fatdlist, fat_dir *fatDir)
1107{
1108#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
1109 static fat_direntry_summary dir; // TOO BIG FOR STACK!
1110#else
1112#endif
1113 int i, ret;
1114 unsigned int startSector, dirSector, dirPos, dirCluster;
1115 unsigned char cont, new_entry;
1116#ifdef DEBUG
1117#ifdef BUILDING_USBHDFSD
1118 mass_dev *mass_device = fatd->dev;
1119#endif /* BUILDING_USBHDFSD */
1120#ifdef BUILDING_IEEE1394_DISK
1121 struct SBP2Device *mass_device = fatd->dev;
1122#endif /* BUILDING_IEEE1394_DISK */
1123#endif
1124
1125 M_DEBUG("%s\n", __func__);
1126
1127 // the getFirst function was not called
1128 if (fatdlist->direntryCluster == 0xFFFFFFFF || fatDir == NULL) {
1129 return -EFAULT;
1130 }
1131
1132 dirCluster = fatdlist->direntryCluster;
1133
1134 // clear name strings
1135 dir.sname[0] = 0;
1136 dir.name[0] = 0;
1137
1138 ret = fat_getDirentrySectorData(fatd, &dirCluster, &startSector, &dirSector);
1139 if (ret < 0)
1140 return ret;
1141
1142 XPRINTF("dirCluster=%u startSector=%u (%u) dirSector=%u \n", dirCluster, startSector, startSector
1143#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
1144 * fatd->bd->sectorSize,
1145#else
1146 * mass_device->sectorSize,
1147#endif
1148 dirSector);
1149
1150 // go through first directory sector till the max number of directory sectors
1151 // or stop when no more direntries detected
1152 // dlanor: but avoid rescanning same areas redundantly (if possible)
1153 cont = 1;
1154 new_entry = 1;
1155 dirPos = (fatdlist->direntryIndex * 32) % fatd->partBpb.sectorSize;
1156 for (i = ((fatdlist->direntryIndex * 32) / fatd->partBpb.sectorSize); ((unsigned int)i < dirSector) && cont; i++) {
1157 unsigned char *sbuf = NULL; // sector buffer
1158
1159 // At cluster borders, get correct sector from cluster chain buffer
1160 if ((dirCluster != 0) && (new_entry || (i % fatd->partBpb.clusterSize == 0))) {
1161 startSector = fat_cluster2sector(&fatd->partBpb, fatd->cbuf[(i / fatd->partBpb.clusterSize)]) - i + (i % fatd->partBpb.clusterSize);
1162 new_entry = 0;
1163 }
1164 ret = READ_SECTOR(DEV_ACCESSOR(fatd), startSector + i, sbuf);
1165 if (ret < 0) {
1166 XPRINTF("Read directory sector failed ! sector=%u\n", startSector + i);
1167 return -EIO;
1168 }
1169
1170 // go through sector from current pos till its end
1171 while (cont && (dirPos < fatd->partBpb.sectorSize)) {
1172 fat_direntry *dir_entry = (fat_direntry *)(sbuf + dirPos);
1173 cont = fat_getDirentry(fatd->partBpb.fatType, dir_entry, &dir); // get a directory entry from sector
1174 fatdlist->direntryIndex++; // Note current entry processed
1175 if (cont == 1) { // when short file name entry detected
1176 fat_setFatDir(fatd, fatDir, dirCluster, &dir_entry->sfn, &dir, 0);
1177#if 0
1178 XPRINTF("fat_getNextDirentry %c%c%c%c%c%c %x %s %s\n",
1179 (dir.attr & FAT_ATTR_VOLUME_LABEL) ? 'v' : '-',
1180 (dir.attr & FAT_ATTR_DIRECTORY) ? 'd' : '-',
1181 (dir.attr & FAT_ATTR_READONLY) ? 'r' : '-',
1182 (dir.attr & FAT_ATTR_ARCHIVE) ? 'a' : '-',
1183 (dir.attr & FAT_ATTR_SYSTEM) ? 's' : '-',
1184 (dir.attr & FAT_ATTR_HIDDEN) ? 'h' : '-',
1185 dir.attr,
1186 dir.sname,
1187 dir.name);
1188#endif
1189 return 1;
1190 }
1191 dirPos += sizeof(fat_direntry);
1192 } // ends "while"
1193 dirPos = 0;
1194 } // ends "for"
1195 // when we get this far - reset the direntry cluster
1196 fatdlist->direntryCluster = 0xFFFFFFFF; // no more files
1197 return 0; // indicate that no direntry is avalable
1198}
1199
1200//---------------------------------------------------------------------------
1201int fat_getFirstDirentry(fat_driver *fatd, const char *dirName, fat_dir_list *fatdlist, fat_dir *fatDir_host, fat_dir *fatDir)
1202{
1203 int ret;
1204 unsigned int startCluster = 0;
1205
1206 M_DEBUG("%s\n", __func__);
1207
1208 ret = fat_getFileStartCluster(fatd, dirName, &startCluster, fatDir_host);
1209 if (ret < 0) { // dir name not found
1210 return -ENOENT;
1211 }
1212 // check that direntry is directory
1213 if (!(fatDir_host->attr & FAT_ATTR_DIRECTORY)) {
1214 return -ENOTDIR; // it's a file - exit
1215 }
1216 fatdlist->direntryCluster = startCluster;
1217 fatdlist->direntryIndex = 0;
1218 return fat_getNextDirentry(fatd, fatdlist, fatDir);
1219}
1220
1221//---------------------------------------------------------------------------
1222#if defined(BUILDING_USBHDFSD)
1223int fat_mount(mass_dev *dev, unsigned int start, unsigned int count)
1224#elif defined(BUILDING_IEEE1394_DISK)
1225int fat_mount(struct SBP2Device *dev, unsigned int start, unsigned int count)
1226#else
1227int fat_mount(struct block_device *bd)
1228#endif
1229{
1230 fat_driver *fatd = NULL;
1231 unsigned int i;
1232
1233 M_DEBUG("%s\n", __func__);
1234
1235#if defined(BUILDING_USBHDFSD) || defined(BUILDING_IEEE1394_DISK)
1236 (void)count;
1237#endif
1238
1239 // Filter for supported partition IDs:
1240 // - 0x0b = FAT32 with CHS addressing
1241 // - 0x0c = FAT32 with LBA addressing
1242 // AKuHAK: dont filter partition, fat_getPartitionBootSector() will care about
1243 // that, this is filtering too much if (bd->parId != 0x0b && bd->parId !=
1244 // 0x0c)
1245 // return -1;
1246
1247 for (i = 0; i < NUM_DRIVES && fatd == NULL; ++i) {
1248 if (g_fatd[i] == NULL) {
1249 XPRINTF("usb fat: allocate fat_driver %d!\n", sizeof(fat_driver));
1250 g_fatd[i] = malloc(sizeof(fat_driver));
1251 if (g_fatd[i] != NULL) {
1252#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
1253 g_fatd[i]->bd = NULL;
1254 g_fatd[i]->cache = NULL;
1255#else
1256 g_fatd[i]->dev = NULL;
1257#endif
1258 }
1259 fatd = g_fatd[i];
1260 } else if (
1261#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
1262 g_fatd[i]->bd
1263#else
1264 g_fatd[i]->dev
1265#endif
1266 == NULL) {
1267 fatd = g_fatd[i];
1268 }
1269 }
1270
1271 if (fatd == NULL) {
1272 M_PRINTF("unable to allocate drive!\n");
1273 return -1;
1274 }
1275
1276#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
1277 if (fatd->bd != NULL) {
1278 M_PRINTF("mount ERROR: alread mounted\n");
1279 fat_forceUnmount(fatd->bd);
1280 }
1281#else
1282 if (fatd->dev != NULL) {
1283 M_PRINTF("mount ERROR: alread mounted\n");
1284 fat_forceUnmount(fatd->dev);
1285 }
1286#endif
1287
1288#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
1289 if (fatd->cache != NULL) {
1290 M_PRINTF("ERROR: cache already created\n");
1291 scache_kill(fatd->cache);
1292 fatd->cache = NULL;
1293 }
1294#endif
1295
1296#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
1297 if (fat_getPartitionBootSector(bd, bd->sectorOffset, &fatd->partBpb) < 0)
1298 return -1;
1299#else
1300 if (fat_getPartitionBootSector(dev, start, &fatd->partBpb) < 0)
1301 return -1;
1302#endif
1303
1304#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
1305 fatd->cache = scache_init(bd);
1306 if (fatd->cache == NULL) {
1307 M_PRINTF("Error - scache_init failed\n");
1308 return -1;
1309 }
1310#endif
1311
1312#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
1313 fatd->bd = bd;
1314#else
1315 fatd->dev = dev;
1316#endif
1317 fatd->deIdx = 0;
1318 fatd->clStackIndex = 0;
1319 fatd->clStackLast = 0;
1320 fatd->lastChainCluster = 0xFFFFFFFF;
1321 fatd->lastChainResult = -1;
1322 return 0;
1323}
1324
1325//---------------------------------------------------------------------------
1326#if defined(BUILDING_USBHDFSD)
1327void fat_forceUnmount(mass_dev *dev)
1328#elif defined(BUILDING_IEEE1394_DISK)
1329void fat_forceUnmount(struct SBP2Device *dev)
1330#else
1331void fat_forceUnmount(struct block_device *bd)
1332#endif
1333{
1334 unsigned int i;
1335
1336 M_DEBUG("%s\n", __func__);
1337
1338#ifdef BUILDING_USBHDFSD
1339 XPRINTF("usb fat: forceUnmount devId %i \n", dev->devId);
1340#endif /* BUILDING_USBHDFSD */
1341#ifdef BUILDING_IEEE1394_DISK
1342 XPRINTF("usb fat: forceUnmount devId %i \n", dev->nodeID);
1343#endif /* BUILDING_IEEE1394_DISK */
1344
1345 for (i = 0; i < NUM_DRIVES; ++i) {
1346#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
1347 if (g_fatd[i] != NULL && g_fatd[i]->bd == bd)
1348#else
1349 if (g_fatd[i] != NULL && g_fatd[i]->dev == dev)
1350#endif
1351 {
1352#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
1353 scache_kill(g_fatd[i]->cache);
1354 free(g_fatd[i]);
1355#endif
1356 g_fatd[i] = NULL;
1357 }
1358 }
1359}
1360
1361//---------------------------------------------------------------------------
1362fat_driver *fat_getData(int device)
1363{
1364 M_DEBUG("%s(%d)\n", __func__, device);
1365
1366 if (device >= NUM_DRIVES)
1367 return NULL;
1368
1369#ifdef BUILDING_USBHDFSD
1370 while (g_fatd[device] == NULL || g_fatd[device]->dev == NULL) {
1371 if (mass_stor_configureNextDevice() <= 0)
1372 break;
1373 // Do not block USBD by busy-looping here, if the device is not ready. This function call will carry the priority of the calling thread.
1374 DelayThread(5000);
1375 }
1376#endif /* BUILDING_USBHDFSD */
1377
1378#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
1379 if (g_fatd[device] == NULL || g_fatd[device]->bd == NULL)
1380#else
1381 if (g_fatd[device] == NULL || g_fatd[device]->dev == NULL)
1382#endif
1383 return NULL;
1384 return g_fatd[device];
1385}
1386
1387//---------------------------------------------------------------------------
1388#if !defined(BUILDING_IEEE1394_DISK) && !defined(BUILDING_USBHDFSD)
1389int fat_stopUnit(int device)
1390{
1391 fat_driver *fatd;
1392
1393 fatd = fat_getData(device);
1394 return (fatd != NULL) ? fatd->bd->stop(fatd->bd) : -ENODEV;
1395}
1396
1397void fat_stopAll(void)
1398{
1399 int i;
1400
1401 for (i = 0; i < NUM_DRIVES; i++) {
1402 fat_driver *fatd;
1403
1404 fatd = fat_getData(i);
1405 if (fatd != NULL)
1406 fatd->bd->stop(fatd->bd);
1407 }
1408}
1409#endif
1410
1411//---------------------------------------------------------------------------
1412// End of file: fat_driver.c
1413//---------------------------------------------------------------------------
#define ENOENT
Definition errno.h:23
#define EFAULT
Definition errno.h:47
#define EIO
Definition errno.h:29
#define ENOTDIR
Definition errno.h:59
#define ENODEV
Definition errno.h:57
u32 count
start sector of fragmented bd/file