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: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45:
46:
47: 48: 49: 50:
51:
52: #include "fimp_fat.h"
53: #include "fimp_fat_local.h"
54:
55: 56: 57:
58: LOCAL INT MaxOpenF = DEFAULT_MaxOpenF;
59: LOCAL INT TaskPriority = DEFAULT_TaskPriority;
60: LOCAL INT TaskStackSize = DEFAULT_TaskStackSize;
61: LOCAL INT CacheFATMemorySize = DEFAULT_CacheFATMemorySize;
62: LOCAL INT CacheFATRatio = DEFAULT_CacheFATRatio;
63: LOCAL INT CacheRootMemorySize = DEFAULT_CacheRootMemorySize;
64: LOCAL INT CacheRootRatio = DEFAULT_CacheRootRatio;
65: LOCAL INT CacheDataMemorySize = DEFAULT_CacheDataMemorySize;
66: LOCAL INT CacheDataRatio = DEFAULT_CacheDataRatio;
67: LOCAL INT LastAccess = DEFAULT_LastAccess;
68:
69: 70: 71:
72: LOCAL ER fatfs_service(fimp_t *req);
73: LOCAL ER fatfs_registfn(fimpinf_t *fimpinf, void *exinf);
74: LOCAL ER fatfs_unregistfn(fimpinf_t *fimpinf);
75: LOCAL ER fatfs_attachfn(coninf_t *coninf, void *exinf);
76: LOCAL ER fatfs_detachfn(coninf_t *coninf);
77: LOCAL ER fatfs_breakfn(coninf_t *coninf, ID tskid, BOOL set);
78:
79: EXPORT const fs_fimp_t fimp_fatfs_entry = {
80: fatfs_service,
81: fatfs_registfn,
82: fatfs_unregistfn,
83: fatfs_attachfn,
84: fatfs_detachfn,
85: NULL,
86: NULL,
87: fatfs_breakfn,
88: FIMP_FLAG_64BIT | FIMP_FLAG_USEABORT,
89: 0,
90: };
91:
92:
93: LOCAL TaskSts *tskStsTab;
94:
95:
96: #define isSET(flags, value) (((UW)(flags) & (UW)(value)) != 0)
97: #define isFAT_SUBDIR(typ) isSET(typ, FAT_SUBDIR)
98: #define isFAT_VOLUME(typ) isSET(typ, FAT_VOLUME)
99: #define isFAT_RDONLY(typ) isSET(typ, FAT_RDONLY)
100: #define isNOT_RDONLY(md) (((UW)(md) & O_ACCMODE) != O_RDONLY)
101: #define isDEV_RDONLY(flg) isSET(flg, DEV_FLAG_READONLY)
102:
103:
104: #define isDE_TERM(de) ((de)->de_fname[0] == DE_B0_END)
105: #define isDE_FREE(de) ((de)->de_fname[0] == DE_B0_FREE)
106: #define isDE_LFN(de) ((de)->de_ftype == FAT_LONGNAME)
107: #define isDE_VOL(de) isFAT_VOLUME((de)->de_ftype)
108:
109:
110: #define CHK_BREAK_AND_SET_ERR(fs, perr) \
111: { if (((FS*)(fs))->fs_tsksts->c.break_done != 0) {*(perr) = EX_INTR;} }
112:
113:
114: #define SetErr2(er,er2) {if ((er) >= E_OK) (er) = (er2);}
115:
116:
117: #define DIRENTSZ (sizeof(FAT_DIRENT))
118:
119:
120: #define ROOTENT (fs->ff_rootent)
121: #define ROOTSZ (ROOTENT * DIRENTSZ)
122:
123:
124: #define CNtoBN(cn) (fs->ff_clstart + (((cn) - 2) * fs->ff_ratio))
125: #define BNtoCN(bn) ((((bn) - fs->ff_clstart) / fs->ff_ratio) + 2)
126:
127:
128: #define DEpSEC ((fs->ff_clsz / fs->ff_ratio) / DIRENTSZ)
129: #define DEpCL (fs->ff_clsz / DIRENTSZ)
130:
131:
132: #define BYTEtoCL(b) (((b) + (fs->ff_clsz - 1)) / fs->ff_clsz)
133:
134:
135: #define IsRootINODE(fs, inode) \
136: (((INODE*)(inode))->ino_ino == ((FS*)(fs))->fs_rootino)
137:
138:
139: #define DSECSZ(fs) ((fs)->ff_c.fs_diskinfo.blocksize)
140:
141:
142: #define OFFSETinPAGE(fs, page, secno, offset) \
143: ( ((secno) - (page)->dcp_secno) * DSECSZ(fs) + (offset) % DSECSZ(fs) )
144:
145:
146: #define isFAT32(fstype) ((fstype) == FAT32)
147:
148:
149: typedef union {
150: UB *b;
151: UH *h;
152: UW *w;
153: } GPTR;
154:
155:
156: LOCAL const struct {
157: UB ofs;
158: UB cnt;
159: } LDE_NMPOS[3] = {
160: {offsetof(FAT_DIRENT_LFN, lde_fname1), 10},
161: {offsetof(FAT_DIRENT_LFN, lde_fname2), 12},
162: {offsetof(FAT_DIRENT_LFN, lde_fname3), 4}
163: };
164:
165:
166: LOCAL const UB nmDOT[BASE_EXTLEN + 1] = ". ";
167: LOCAL const UB nmDOT2[BASE_EXTLEN + 1] = ".. ";
168:
169:
170: LOCAL const UB inode_root_path[] = "/";
171:
172: 173: 174:
175:
176: 177: 178:
179: Inline UD dirINO(FATFS *fs, UW fclno)
180: {
181: return (fclno == fs->ff_rootcl) ? CLSTART : CNtoBN(fclno) * DEpSEC;
182: }
183:
184: 185: 186:
187: Inline UD fileINO(FATFS *fs, UW clno, UW offset)
188: {
189: return (CNtoBN(clno) * DEpSEC) + offset;
190: }
191:
192: 193: 194:
195: Inline UD rootINO(FATFS *fs, UW offset)
196: {
197: return ((fs->ff_rootsc * DEpSEC) + offset);
198: }
199:
200: 201: 202:
203: Inline UW dirCLNO(FATFS *fs, UD ino)
204: {
205: return ((ino == CLSTART) ? fs->ff_rootcl : BNtoCN(ino / DEpSEC));
206: }
207:
208: 209: 210:
211: LOCAL UW dirent_to_fcl(FATFS *fs, FAT_DIRENT *dirent)
212: {
213: UW fcl;
214:
215: fcl = (UW)CEH(dirent->de_clno_lo);
216: if (isFAT32(fs->ff_fstype)) {
217: fcl |= (UW)CEH(dirent->de_clno_hi) << DE_SHIFT_CLNO_HI;
218: }
219: if (fcl == 0 && isFAT_SUBDIR(dirent->de_ftype)) {
220: fcl = fs->ff_rootcl;
221: }
222: return fcl;
223: }
224:
225: 226: 227:
228: LOCAL void fcl_to_dirent(FATFS *fs, FAT_DIRENT *dirent, UW fcl)
229: {
230:
231: if (fcl == fs->ff_rootcl) fcl = 0;
232:
233: dirent->de_clno_lo = CEH((UH)fcl);
234: dirent->de_clno_hi = isFAT32(fs->ff_fstype) ?
235: (CEH((UH)(fcl >> DE_SHIFT_CLNO_HI))) : 0;
236: }
237:
238: 239: 240:
241:
242: 243: 244:
245: LOCAL ER fatDiskRead(FATFS *fs, D start, void *buf, W size)
246: {
247: W asize;
248: ER err;
249:
250: err = tk_srea_dev_d(fs->ff_c.fs_devid, start, buf, size, &asize);
251: return (err >= E_OK && asize != size) ? EX_IO : err;
252: }
253:
254: 255: 256:
257: LOCAL ER fatDiskWrite(FATFS *fs, D start, void *buf, W size)
258: {
259: W asize;
260: ER err;
261:
262: err = tk_swri_dev_d(fs->ff_c.fs_devid, start, buf, size, &asize);
263: return (err >= E_OK && asize != size) ? EX_IO : err;
264: }
265:
266: 267: 268:
269: LOCAL ER fatDiskOpen(const coninf_t *coninf, FATFS *fs)
270: {
271: ER err;
272: UINT omode;
273: W sz;
274: #define OPEN_MODE(n) ((n) | TD_WEXCL | TD_NOLOCK)
275:
276:
277: if (coninf->devnm[0] == '\0') {
278: err = EX_INVAL;
279: goto exit0;
280: }
281:
282:
283: if (isDEV_RDONLY(coninf->dflags)) {
284: omode = OPEN_MODE(TD_READ);
285: fs->ff_c.fs_rdonly = TRUE;
286: } else {
287: omode = OPEN_MODE(TD_UPDATE);
288: fs->ff_c.fs_rdonly = FALSE;
289: }
290: err = tk_opn_dev((UB*)coninf->devnm, omode);
291: if (err == E_RONLY) {
292:
293: fs->ff_c.fs_rdonly = TRUE;
294: err = tk_opn_dev((UB *)coninf->devnm, OPEN_MODE(TD_READ));
295: }
296: if (err < E_OK) goto exit0;
297: fs->ff_c.fs_devid = err;
298:
299:
300: err = tk_srea_dev(fs->ff_c.fs_devid, DN_DISKINFO,
301: &fs->ff_c.fs_diskinfo, sizeof(DiskInfo), &sz);
302: if (err < E_OK) goto exit0;
303:
304: if (DSECSZ(fs) == 0) {
305: err = EX_NXIO;
306: } else if (fs->ff_c.fs_diskinfo.protect != 0) {
307: fs->ff_c.fs_rdonly = TRUE;
308: }
309: exit0:
310: return err;
311: }
312:
313: 314: 315:
316: LOCAL void fatDiskClose(const coninf_t *coninf, FATFS *fs)
317: {
318: (void)tk_cls_dev(fs->ff_c.fs_devid, 0);
319: }
320:
321: 322: 323:
324: LOCAL ER fatGetDeviceNumber(UB *devnm, W *devnum)
325: {
326: ID devid;
327:
328: devid = tk_ref_dev(devnm, NULL);
329: if (devid >= E_OK) {
330: *devnum = (W)devid;
331: }
332: return devid;
333: }
334:
335: 336: 337:
338:
339: 340: 341:
342: LOCAL ER fatDCacheSyncPage(FATFS *fs, DCachePage *page, VW info)
343: {
344: ER err;
345:
346: err = E_OK;
347: if (info == 0 || page->dcp_info == 0 || page->dcp_info == info) {
348: if (page->dcp_update != FALSE) {
349: err = fatDiskWrite(fs, page->dcp_secno,
350: page->dcp_buf, page->dcp_seclen);
351: page->dcp_update = FALSE;
352: page->dcp_dcinf->dci_updatecnt--;
353: }
354: page->dcp_info = 0;
355: }
356: return err;
357: }
358:
359: 360: 361:
362: LOCAL ER fatDCacheInfoInit(FATFS *fs, DCacheInfo *dcinf, D secno,
363: D seclen, UW memsz, UW ratio)
364: {
365: DCachePage *page;
366: UB *buf;
367: UW pagememsz;
368: W i;
369: ER err;
370:
371: err = E_OK;
372:
373:
374: if (ratio != 1 && (ratio % 2) != 0) {
375: err = EX_INVAL;
376: goto exit0;
377: }
378: pagememsz = ratio * DSECSZ(fs);
379:
380: dcinf->dci_secno = secno;
381: dcinf->dci_endsec = secno + seclen;
382: dcinf->dci_ratio = ratio;
383: dcinf->dci_pagelen = memsz / pagememsz;
384: if (dcinf->dci_pagelen == 0) {
385: err = EX_INVAL;
386: goto exit0;
387: }
388:
389:
390: buf = (UB *)fimp_calloc(dcinf->dci_pagelen, sizeof(DCachePage));
391: if (buf == NULL) {
392: err = EX_NOMEM;
393: goto exit0;
394: }
395: dcinf->dci_pages = (DCachePage *)buf;
396:
397:
398: buf = (UB *)fimp_malloc(dcinf->dci_pagelen * pagememsz);
399: if (buf == NULL) {
400: fimp_free(dcinf->dci_pages);
401: dcinf->dci_pages = NULL;
402: err = EX_NOMEM;
403: goto exit0;
404: }
405: dcinf->dci_bufs = buf;
406:
407:
408: for (i = 0; i < DCI_NHSQUE; i++) {
409: QueInit(&dcinf->dci_hsque[i]);
410: }
411: QueInit(&dcinf->dci_freeque);
412: QueInit(&dcinf->dci_useque);
413: QueInit(&dcinf->dci_actque);
414:
415:
416: for (i = 0; i < dcinf->dci_pagelen; i++) {
417: page = &dcinf->dci_pages[i];
418: page->dcp_dcinf = dcinf;
419: page->dcp_secno = SECVOID;
420:
421:
422:
423:
424: page->dcp_buf = &dcinf->dci_bufs[pagememsz * i];
425:
426: QueInsert(&page->dcp_q, &dcinf->dci_freeque);
427: }
428: exit0:
429: return err;
430: }
431:
432: 433: 434:
435: LOCAL void fatDCacheInfoCleanup(FATFS *fs, DCacheInfo *dcinf)
436: {
437: QUEUE *q;
438:
439:
440: for (q = dcinf->dci_actque.next;
441: q != &dcinf->dci_actque; q = q->next) {
442: (void)fatDCacheSyncPage(fs, PageFromActque(q), 0);
443: }
444:
445:
446: for (q = dcinf->dci_useque.next;
447: q != &dcinf->dci_useque; q = q->next) {
448: (void)fatDCacheSyncPage(fs, PageFromUseque(q), 0);
449: }
450:
451:
452: fimp_free(dcinf->dci_pages);
453: fimp_free(dcinf->dci_bufs);
454: memset(dcinf, 0, sizeof(DCacheInfo));
455: }
456:
457: 458: 459:
460: LOCAL ER fatDCacheRead(FATFS *fs, DCachePage ** pagep)
461: {
462: ER err;
463: DCachePage *page;
464:
465: page = *pagep;
466: err = E_OK;
467:
468: if (page->dcp_read == FALSE) {
469: err = fatDiskRead(fs, page->dcp_secno, page->dcp_buf,
470: page->dcp_seclen);
471: if (err < E_OK) {
472:
473: QueRemove(&page->dcp_uq);
474: QueRemove(&page->dcp_q);
475: QueInsert(&page->dcp_q, &page->dcp_dcinf->dci_freeque);
476: *pagep = NULL;
477: } else {
478: page->dcp_read = TRUE;
479: }
480: }
481: return err;
482: }
483:
484: 485: 486:
487: LOCAL ER fatDCacheSearchUsedPage(FATFS *fs, DCacheInfo *dcinf, D sec,
488: DCachePage ** pagep)
489: {
490: DCachePage *page;
491: QUEUE *q, *hsq;
492: D secno;
493: ER err;
494:
495: page = NULL;
496:
497:
498: if (sec < dcinf->dci_secno || sec >= dcinf->dci_endsec) {
499: err = EX_INVAL;
500: goto exit0;
501: }
502:
503:
504: secno = sec - ((sec - dcinf->dci_secno) % dcinf->dci_ratio);
505: hsq = &dcinf->dci_hsque[(secno / dcinf->dci_ratio) & DCI_HSQUEMSK];
506:
507: err = E_OK;
508: if (isQueEmpty(hsq) == FALSE) {
509: for (q = hsq->next; q != hsq; q = q->next) {
510: if (PageFromHsque(q)->dcp_secno != secno) continue;
511:
512: page = PageFromHsque(q);
513: if (page->dcp_accnt++ == 0) {
514:
515: QueRemove(&page->dcp_uq);
516: QueInsert(&page->dcp_uq, &dcinf->dci_actque);
517: }
518: break;
519: }
520: }
521: exit0:
522: *pagep = page;
523: return err;
524: }
525:
526: 527: 528:
529: LOCAL ER fatDCacheSearchPage(FATFS *fs, DCacheInfo *dcinf, D sec,
530: DCachePage ** pagep, BOOL read)
531: {
532: DCachePage *page;
533: D secno;
534: UW seclen;
535: ER err;
536:
537:
538: err = fatDCacheSearchUsedPage(fs, dcinf, sec, &page);
539: if (err < E_OK || page != NULL) goto exit0;
540:
541:
542: if (isQueEmpty(&dcinf->dci_freeque) == FALSE) {
543:
544: page = PageFromFreeque(dcinf->dci_freeque.next);
545: QueRemove(&page->dcp_q);
546:
547: } else if (isQueEmpty(&dcinf->dci_useque) == FALSE) {
548: 549:
550: page = PageFromUseque(dcinf->dci_useque.next);
551: err = fatDCacheSyncPage(fs, page, 0);
552: if (err >= E_OK) {
553:
554: QueRemove(&page->dcp_uq);
555: QueRemove(&page->dcp_q);
556: }
557: } else {
558:
559: err = EX_NOMEM;
560: goto exit0;
561: }
562:
563:
564: page->dcp_accnt = 1;
565: page->dcp_read = FALSE;
566: page->dcp_update = FALSE;
567: page->dcp_info = 0;
568: secno = sec - ((sec - dcinf->dci_secno) % dcinf->dci_ratio);
569: seclen = dcinf->dci_ratio;
570: if (secno + seclen > dcinf->dci_endsec) {
571: seclen = dcinf->dci_endsec - secno;
572: }
573: page->dcp_secno = secno;
574: page->dcp_seclen = seclen;
575:
576: QueInsert(&page->dcp_uq, &dcinf->dci_actque);
577: QueInsert(&page->dcp_q,
578: &dcinf->dci_hsque[(secno / dcinf->dci_ratio) & DCI_HSQUEMSK]);
579: exit0:
580: *pagep = page;
581: if (err >= E_OK && read != FALSE) {
582:
583: err = fatDCacheRead(fs, pagep);
584: }
585: return err;
586: }
587:
588: 589: 590:
591: LOCAL void fatDCacheGetDcinf(FATFS *fs, D sec, DCacheInfo ** dcinf)
592: {
593: if ( sec >= fs->ff_dc_fat.dci_secno &&
594: sec < fs->ff_dc_fat.dci_endsec) {
595:
596: *dcinf = &fs->ff_dc_fat;
597:
598: } else if (! isFAT32(fs->ff_fstype) &&
599: sec >= fs->ff_dc_rootdir.dci_secno &&
600: sec < fs->ff_dc_rootdir.dci_endsec) {
601:
602: *dcinf = &fs->ff_dc_rootdir;
603:
604: } else if (sec >= fs->ff_dc_data.dci_secno &&
605: sec < fs->ff_dc_data.dci_endsec) {
606:
607: *dcinf = &fs->ff_dc_data;
608:
609: } else {
610:
611: *dcinf = &fs->ff_dc_other;
612: }
613: }
614:
615: 616: 617:
618: LOCAL ER fatDCacheStart(FATFS *fs, D sec, DCachePage ** page)
619: {
620: DCacheInfo *dcinf;
621:
622: *page = NULL;
623: fatDCacheGetDcinf(fs, sec, &dcinf);
624: return fatDCacheSearchPage(fs, dcinf, sec, page, TRUE);
625: }
626:
627: 628: 629:
630: LOCAL ER fatDCacheEnd(FATFS *fs, DCachePage *page)
631: {
632: ER err;
633:
634: err = E_OK;
635:
636: if (--page->dcp_accnt <= 0) {
637: #if FAT_SYNC_WITH_CACHEEND
638: err = fatDCacheSyncPage(fs, page, 0);
639: #endif
640: page->dcp_info = 0;
641: page->dcp_accnt = 0;
642:
643:
644: QueRemove(&page->dcp_uq);
645: QueInsert(&page->dcp_uq, &page->dcp_dcinf->dci_useque);
646: }
647: return err;
648: }
649:
650: 651: 652:
653: LOCAL ER fatDCacheUpdate(FATFS *fs, DCachePage *page, VW info)
654: {
655: if (page->dcp_update == FALSE) {
656: page->dcp_dcinf->dci_updatecnt++;
657: page->dcp_update = TRUE;
658: }
659: page->dcp_read = TRUE;
660: page->dcp_info = info;
661: return E_OK;
662: }
663:
664: 665: 666:
667: LOCAL ER fatDCacheSyncInfo(FATFS *fs, DCacheInfo *dcinf, VW info)
668: {
669: QUEUE *q;
670: ER err, err2;
671:
672: err = E_OK;
673: CHK_BREAK_AND_SET_ERR(fs, &err);
674: if (err < E_OK) goto exit0;
675:
676:
677: for (q = dcinf->dci_actque.next; q != &dcinf->dci_actque &&
678: dcinf->dci_updatecnt > 0 && err != EX_INTR; q = q->next) {
679: err2 = fatDCacheSyncPage(fs, PageFromActque(q), info);
680: SetErr2(err, err2);
681: CHK_BREAK_AND_SET_ERR(fs, &err);
682: }
683:
684:
685: for (q = dcinf->dci_useque.next; q != &dcinf->dci_useque &&
686: dcinf->dci_updatecnt > 0 && err != EX_INTR; q = q->next) {
687: err2 = fatDCacheSyncPage(fs, PageFromUseque(q), info);
688: SetErr2(err, err2);
689: CHK_BREAK_AND_SET_ERR(fs, &err);
690: }
691: exit0:
692: return err;
693: }
694:
695: 696: 697:
698: LOCAL ER fatDCacheSyncFS(FATFS *fs, VW info)
699: {
700: ER err, err2;
701:
702: err = E_OK;
703: if (fs->ff_c.fs_rdonly != FALSE) goto exit0;
704:
705:
706: err2 = fatDCacheSyncInfo(fs, &fs->ff_dc_other, info);
707: SetErr2(err, err2);
708:
709:
710: err2 = fatDCacheSyncInfo(fs, &fs->ff_dc_fat, info);
711: SetErr2(err, err2);
712:
713:
714: if (! isFAT32(fs->ff_fstype)) {
715: err2 = fatDCacheSyncInfo(fs, &fs->ff_dc_rootdir, info);
716: SetErr2(err, err2);
717: }
718:
719:
720: err2 = fatDCacheSyncInfo(fs, &fs->ff_dc_data, info);
721: SetErr2(err, err2);
722: exit0:
723: return err;
724: }
725:
726: 727: 728:
729: LOCAL ER fatDCacheInit(FATFS *fs)
730: {
731: ER err;
732:
733:
734: err = fatDCacheInfoInit(fs, &fs->ff_dc_fat, fs->ff_fat, fs->ff_fatsz,
735: CacheFATMemorySize, CacheFATRatio);
736: if (err < E_OK) goto exit0;
737:
738:
739: if (! isFAT32(fs->ff_fstype)) {
740: err = fatDCacheInfoInit(fs, &fs->ff_dc_rootdir, fs->ff_rootsc,
741: ROOTSZ / DSECSZ(fs),
742: CacheRootMemorySize, CacheRootRatio);
743: if (err < E_OK) goto exit0;
744: }
745:
746:
747: err = fatDCacheInfoInit(fs, &fs->ff_dc_data, fs->ff_clstart,
748: CNtoBN(fs->ff_lastcl + 1) - fs->ff_clstart,
749: CacheDataMemorySize,
750: (CacheDataRatio == 0) ? fs->ff_ratio : CacheDataRatio);
751: if (err < E_OK) goto exit0;
752:
753:
754: err = fatDCacheInfoInit(fs, &fs->ff_dc_other, 1, fs->ff_fat - 1,
755: DSECSZ(fs) * 2, 1);
756: exit0:
757: return err;
758: }
759:
760: 761: 762:
763: LOCAL void fatDCacheCleanup(FATFS *fs)
764: {
765:
766: fatDCacheInfoCleanup(fs, &fs->ff_dc_other);
767:
768:
769: fatDCacheInfoCleanup(fs, &fs->ff_dc_fat);
770:
771:
772: if (! isFAT32(fs->ff_fstype)) {
773: fatDCacheInfoCleanup(fs, &fs->ff_dc_rootdir);
774: }
775:
776:
777: fatDCacheInfoCleanup(fs, &fs->ff_dc_data);
778: }
779:
780: 781: 782:
783: LOCAL ER fatFDSync(FD *fd)
784: {
785: return isSET(fd->fd_omode, O_SYNC) ?
786: fatDCacheSyncFS((FATFS*)fd->fd_fs, (VW)fd->fd_inode) : E_OK;
787: }
788:
789: 790: 791:
792:
793: 794: 795:
796: LOCAL ER fatMapEnd(MapInfo *map)
797: {
798: return (map->m_page == NULL) ? E_OK :
799: fatDCacheEnd(map->m_fs, map->m_page);
800: }
801:
802: 803: 804:
805: LOCAL void fatUnmapDisk(MapInfo *map)
806: {
807: memset(map, 0, sizeof(MapInfo));
808: }
809:
810: 811: 812: 813:
814: LOCAL ER fatMapGetCache(MapInfo *map, D offset, UW *bufofs, BOOL isread)
815: {
816: FATFS *fs;
817: D sec;
818: UW off, toff, secsz;
819: CLAD *clp, *cle;
820: ER err;
821:
822: fs = map->m_fs;
823: secsz = DSECSZ(fs);
824:
825:
826: off = offset / (isSET(map->m_flags, MAP_C) ? fs->ff_clsz : secsz);
827:
828:
829: clp = map->m_clad;
830: cle = clp + map->m_clen;
831:
832:
833: if ((toff = map->m_lastoff) <= off) {
834: clp += map->m_lastix;
835: } else {
836: toff = 0;
837: }
838:
839: for ( ; clp < cle && (toff += clp->ca_len) <= off; clp++);
840: if (clp >= cle) {
841: err = EX_INVAL;
842: goto exit0;
843: }
844:
845: map->m_btop = CLVOID;
846: map->m_bend = 0;
847: map->m_lastix = clp - map->m_clad;
848: map->m_lastoff = toff - clp->ca_len;
849: sec = clp->ca_no + (off - map->m_lastoff);
850:
851: if (isSET(map->m_flags, MAP_C)) {
852:
853: sec = CNtoBN(sec);
854:
855: sec += offset / secsz - (off * fs->ff_ratio);
856: }
857:
858:
859: if (map->m_page == NULL ||
860: sec < map->m_page->dcp_secno ||
861: sec >= map->m_page->dcp_secno + map->m_page->dcp_seclen) {
862: if (map->m_page != NULL) {
863: err = fatDCacheEnd(fs, map->m_page);
864: if (err < E_OK) goto exit0;
865: }
866:
867: err = fatDCacheSearchPage(fs, map->m_dcinf, sec,
868: &map->m_page, isread);
869: if (err < E_OK) goto exit0;
870: }
871:
872:
873: *bufofs = (sec - map->m_page->dcp_secno) * secsz + (offset % secsz);
874: return E_OK;
875: exit0:
876: return err;
877: }
878:
879: 880: 881:
882: LOCAL ER fatMapRead(MapInfo *map, D *offset, UB **sp, UW *len, UB **ep)
883: {
884: FATFS *fs;
885: UW bufofs, sz;
886: ER err;
887:
888: fs = map->m_fs;
889: err = fatMapGetCache(map, *offset, &bufofs, TRUE);
890: if (err < E_OK) goto exit0;
891:
892: sz = map->m_bpp - bufofs;
893: *offset += sz;
894: *sp = &map->m_page->dcp_buf[bufofs];
895: if (sz > *len) sz = *len;
896: *len -= sz;
897: *ep = *sp + sz;
898: exit0:
899: return err;
900: }
901:
902: 903: 904:
905: LOCAL ER fatMapReadBytes(MapInfo *map, D offset, UB *buf, UW len)
906: {
907: FATFS *fs;
908: UW bufofs, dofs, sz;
909: ER err;
910:
911: err = E_OK;
912: fs = map->m_fs;
913: for (dofs = 0; len > 0; len -= sz, dofs += sz) {
914: err = fatMapGetCache(map, offset, &bufofs, TRUE);
915: if (err < E_OK) break;
916:
917: sz = map->m_bpp - bufofs;
918: if (sz > len) sz = len;
919:
920: memcpy(&buf[dofs], &map->m_page->dcp_buf[bufofs], sz);
921: offset += sz;
922: }
923: if (len > 0) {
924: CHK_BREAK_AND_SET_ERR(fs, &err);
925: }
926: return err;
927: }
928:
929: 930: 931:
932: LOCAL ER fatMapWriteBytes(MapInfo *map, D offset, const UB *buf, D len)
933: {
934: FATFS *fs;
935: DCachePage *page;
936: UW bufofs, dofs, sz;
937: ER err;
938:
939: err = E_OK;
940: fs = map->m_fs;
941: for (dofs = 0; len > 0; len -= sz, dofs += sz) {
942: err = fatMapGetCache(map, offset, &bufofs, FALSE);
943: if (err < E_OK) break;
944:
945: page = map->m_page;
946: if (bufofs != 0 || len < map->m_bpp) {
947: err = fatDCacheRead(fs, &page);
948: if (err < E_OK) break;
949: }
950: sz = map->m_bpp - bufofs;
951: if (sz > len) sz = len;
952:
953: if (buf == NULL) {
954: memset(&page->dcp_buf[bufofs], 0, sz);
955: } else {
956: memcpy(&page->dcp_buf[bufofs], &buf[dofs], sz);
957: }
958:
959: offset += sz;
960: err = fatDCacheUpdate(fs, page, map->m_info);
961: if (err < E_OK) break;
962: }
963: if (len > 0) {
964: CHK_BREAK_AND_SET_ERR(fs, &err);
965: }
966: return err;
967: }
968:
969: 970: 971:
972: LOCAL ER fatMapDisk(FATFS *fs, CLAD *clad, W len, MapInfo *map,
973: W flags, VW info)
974: {
975: DCacheInfo *dcinf;
976: D sec, sa, ea;
977: W i, secsz;
978: UW cnt;
979: ER err, err2;
980:
981:
982: memset(map, 0, sizeof(MapInfo));
983:
984:
985: if (isSET(flags, MAP_C)) {
986: sec = CNtoBN(clad[0].ca_no);
987: fatDCacheGetDcinf(fs, sec, &dcinf);
988: sa = BNtoCN(dcinf->dci_secno);
989: ea = BNtoCN(dcinf->dci_endsec);
990: } else {
991: sec = clad[0].ca_no;
992: fatDCacheGetDcinf(fs, sec, &dcinf);
993: sa = dcinf->dci_secno;
994: ea = dcinf->dci_endsec - 1;
995: }
996:
997:
998: err = E_OK;
999: for (i = 0; i < len; i++) {
1000: if (sa > clad[i].ca_no ||
1001: ea < (clad[i].ca_no + clad[i].ca_len - 1)) {
1002: err = EX_INVAL;
1003: break;
1004: }
1005: }
1006: if (err < E_OK) goto exit0;
1007:
1008:
1009: map->m_fs = fs;
1010: map->m_dcinf = dcinf;
1011: map->m_flags = flags;
1012: map->m_info = info;
1013: map->m_clad = clad;
1014: map->m_clen = len;
1015:
1016:
1017:
1018: secsz = DSECSZ(fs);
1019: map->m_bpp = dcinf->dci_ratio * secsz;
1020: map->m_btop = CLVOID;
1021:
1022:
1023: if (isSET(flags, MAP_CLR)) {
1024: for (cnt = 0, i = 0; i < len; i++) {
1025: cnt += clad[i].ca_len;
1026: }
1027: if (cnt > 0) {
1028: err = fatMapWriteBytes(map, 0, NULL, (D)cnt *
1029: (isSET(flags, MAP_C) ? fs->ff_clsz : secsz));
1030: err2 = fatMapEnd(map);
1031: SetErr2(err, err2);
1032: }
1033: } else if (isSET(flags, MAP_READ)) {
1034:
1035: err = fatDCacheSearchPage(fs, dcinf, sec, &map->m_page, TRUE);
1036: }
1037: exit0:
1038: return err;
1039: }
1040:
1041: 1042: 1043:
1044: LOCAL ER fatMapFATInit(FATFS *fs)
1045: {
1046: fs->ff_fatmap_s[0].ca_no = fs->ff_fat;
1047: fs->ff_fatmap_s[0].ca_len = fs->ff_fatsz;
1048:
1049: return fatMapDisk(fs, fs->ff_fatmap_s, NUM_FATMAP_S,
1050: &fs->ff_fatmap, MAP_S, 0);
1051: }
1052:
1053: 1054: 1055:
1056: LOCAL void fatMapFATCleanup(FATFS *fs)
1057: {
1058: fatUnmapDisk(&fs->ff_fatmap);
1059: }
1060:
1061: 1062: 1063:
1064:
1065: 1066: 1067:
1068: LOCAL void fatInodeQueInit(FS *fs)
1069: {
1070: W i;
1071:
1072: for (i = 0; i < FS_NIQUE; i++) {
1073: QueInit(&fs->fs_ique[i]);
1074: }
1075: }
1076:
1077: 1078: 1079:
1080: LOCAL ER fatInodeCheckEmpty(FS *fs, INODE *ignorenode)
1081: {
1082: QUEUE *q;
1083: W i;
1084:
1085: for (i = 0; i < FS_NIQUE; i++) {
1086: if (isQueEmpty(&fs->fs_ique[i]) != FALSE) continue;
1087: for (q = fs->fs_ique[i].next;
1088: q != &fs->fs_ique[i]; q = q->next) {
1089: if ((INODE *)q != ignorenode) {
1090: return EX_BUSY;
1091: }
1092: }
1093: }
1094: return E_OK;
1095: }
1096:
1097: 1098: 1099:
1100: LOCAL void fatInodeRegister(FS *fs, INODE *inode, UB omode)
1101: {
1102:
1103: if (inode != NULL) {
1104:
1105: if (isNOT_RDONLY(omode)) {
1106: inode->ino_wrefcnt++;
1107: }
1108: if (inode->ino_refcnt++ <= 0) {
1109:
1110: QueInsert(&inode->ino_q,
1111: &fs->fs_ique[(UW)inode->ino_ino & FS_IQUEMSK]);
1112: }
1113: }
1114: }
1115:
1116: 1117: 1118:
1119: LOCAL void fatInodeFree(FS *fs, INODE *inode)
1120: {
1121:
1122: if (inode != NULL) {
1123:
1124: if (inode->ino_refcnt <= 0) {
1125: if (inode->ino_path != NULL &&
1126: inode->ino_path != inode_root_path) {
1127: fimp_free(inode->ino_path);
1128: }
1129: if (inode->ino_info != NULL) {
1130: fimp_free(inode->ino_info);
1131: }
1132: if (inode != (INODE*)&((FATFS*)fs)->ff_rootnode) {
1133: fimp_free(inode);
1134: } else {
1135: memset(inode, 0, sizeof(INODE));
1136: }
1137: }
1138: }
1139: }
1140:
1141: 1142: 1143:
1144: LOCAL void fatInodeRelease(FS *fs, INODE *inode, UB omode)
1145: {
1146:
1147: if (inode != NULL) {
1148:
1149: if (isNOT_RDONLY(omode)) {
1150: if (--inode->ino_wrefcnt <= 0) {
1151: (void)fatDCacheSyncFS((FATFS *)fs, (VW)inode);
1152: }
1153: }
1154:
1155: if (--inode->ino_refcnt <= 0) {
1156:
1157: QueRemove(&inode->ino_q);
1158:
1159:
1160: fatInodeFree(fs, inode);
1161: }
1162: }
1163: }
1164:
1165: 1166: 1167:
1168: LOCAL INODE *fatInodeSearch(FS *fs, UD ino)
1169: {
1170: QUEUE *iq, *q;
1171:
1172:
1173: iq = &fs->fs_ique[(UW)ino & FS_IQUEMSK];
1174: for (q = iq->next; q != iq; q = q->next) {
1175: if (((INODE *)q)->ino_ino == ino) return (INODE *)q;
1176: }
1177: return NULL;
1178: }
1179:
1180: 1181: 1182:
1183: LOCAL void fatInodeChangeQue(FS *fs, INODE *inode)
1184: {
1185: if (inode->ino_refcnt > 0) {
1186:
1187: QueRemove(&inode->ino_q);
1188: QueInsert(&inode->ino_q,
1189: &fs->fs_ique[(UW)inode->ino_ino & FS_IQUEMSK]);
1190: }
1191: }
1192:
1193: 1194: 1195:
1196:
1197: 1198: 1199:
1200: LOCAL ER fatSearchFileDesc(FS *fs, FD **fdp, W fildes)
1201: {
1202: FD *fd;
1203:
1204: if (fs->fs_uxinfo.uxi_fdtbl != NULL) {
1205: if (fildes >= 0 && fildes < MaxOpenF) {
1206: fd = fs->fs_uxinfo.uxi_fdtbl[fildes];
1207: if (fd != NULL && fd->fd_fs == fs) {
1208: *fdp = fd;
1209: return E_OK;
1210: }
1211: }
1212: }
1213: *fdp = NULL;
1214: return EX_BADF;
1215: }
1216:
1217: 1218: 1219:
1220: LOCAL ER fatNewFileDesc(FS *fs, FD **fdp, W *fdno)
1221: {
1222: FD *fd;
1223: W i;
1224: ER err;
1225:
1226: if (fs->fs_uxinfo.uxi_fdtbl == NULL) {
1227: err = EX_NOBUFS;
1228: goto exit0;
1229: }
1230:
1231: for (i = 0; i < MaxOpenF && fs->fs_uxinfo.uxi_fdtbl[i] != NULL; i++);
1232:
1233: if (i >= MaxOpenF) {
1234: err = EX_NFILE;
1235: } else {
1236: fd = (FD *)fimp_calloc(1, sizeof(FD));
1237: if (fd == NULL) {
1238: err = EX_NOMEM;
1239: } else {
1240: fd->fd_fs = fs;
1241: fd->fd_inode = NULL;
1242: fd->fd_fpos = 0;
1243: fd->fd_refcnt = 1;
1244:
1245:
1246: fs->fs_uxinfo.uxi_fdtbl[i] = fd;
1247:
1248: *fdp = fd;
1249: *fdno = i;
1250: err = E_OK;
1251: }
1252: }
1253: exit0:
1254: return err;
1255: }
1256:
1257: 1258: 1259:
1260: LOCAL void fatDelFileDesc(FS *fs, FD *fd, W fdno)
1261: {
1262: fs->fs_uxinfo.uxi_fdtbl[fdno] = NULL;
1263:
1264: if (--fd->fd_refcnt <= 0) {
1265:
1266: fatInodeRelease(fd->fd_fs, fd->fd_inode, fd->fd_omode);
1267: fimp_free(fd);
1268: }
1269: }
1270:
1271: 1272: 1273:
1274:
1275: 1276: 1277:
1278: LOCAL ER alloc_clbuf(CLAD **clbufp, UH *maxcl)
1279: {
1280: CLAD *clbuf;
1281: UH ncl;
1282: VP tmp;
1283:
1284: if ((clbuf = *clbufp) == NULL) {
1285:
1286: clbuf = (CLAD *)fimp_malloc(sizeof(CLAD) * MAX_CLEN);
1287: ncl = 1;
1288: } else {
1289:
1290: ncl = *maxcl + 1;
1291: tmp = fimp_realloc(clbuf, sizeof(CLAD) * ncl * MAX_CLEN);
1292: if (tmp == NULL) {
1293: fimp_free(clbuf);
1294: }
1295: clbuf = tmp;
1296: }
1297: *clbufp = clbuf;
1298: if (clbuf == NULL) {
1299: *maxcl = 0;
1300: return EX_NOMEM;
1301: }
1302: *maxcl = ncl;
1303: return E_OK;
1304: }
1305:
1306: 1307: 1308:
1309: LOCAL ER fatGetCluster(MapInfo *map, UW clno, UW *ncl)
1310: {
1311: UW cl, bufofs, n;
1312: ER err;
1313:
1314: cl = CLEND;
1315: err = E_OK;
1316:
1317: switch (map->m_fs->ff_fstype) {
1318: case FAT12:
1319: {
1320: UB buf[2];
1321:
1322: err = fatMapReadBytes(map, clno + clno / 2, buf, 2);
1323: if (err < E_OK) break;
1324:
1325: cl = CEH(GetMisalignH(buf));
1326: if ((clno & 1) != 0) cl >>= 4;
1327: cl &= FAT12_MASK_VALID_CLST;
1328: if (cl >= FAT12_EOC) cl = CLEND;
1329: }
1330: break;
1331:
1332: case FAT16:
1333: if (clno >= map->m_btop && clno < map->m_bend) {
1334:
1335: n = clno - map->m_btop;
1336: } else {
1337: err = fatMapGetCache(map, clno * sizeof(UH),
1338: &bufofs, TRUE);
1339: if (err < E_OK) break;
1340: map->m_btop = clno - (n = bufofs / sizeof(UH));
1341: map->m_bend = map->m_btop + (map->m_bpp / sizeof(UH));
1342: }
1343: cl = CEH(((UH *)map->m_page->dcp_buf)[n]);
1344: if (cl >= FAT16_EOC) cl = CLEND;
1345: break;
1346:
1347: case FAT32:
1348: default:
1349: if (clno >= map->m_btop && clno < map->m_bend) {
1350:
1351: n = clno - map->m_btop;
1352: } else {
1353: err = fatMapGetCache(map, clno * sizeof(UW),
1354: &bufofs, TRUE);
1355: if (err < E_OK) break;
1356: map->m_btop = clno - (n = bufofs / sizeof(UW));
1357: map->m_bend = map->m_btop + (map->m_bpp / sizeof(UW));
1358: }
1359: cl = CEW(((UW *)map->m_page->dcp_buf)[n]);
1360: cl &= FAT32_MASK_VALID_CLST;
1361: if (cl >= FAT32_EOC) cl = CLEND;
1362: break;
1363: }
1364: *ncl = cl;
1365:
1366:
1367: if (err >= E_OK) {
1368: if (cl < CLSTART || cl > map->m_fs->ff_lastcl) {
1369: if (cl != CLEND) err = EX_IO;
1370:
1371: }
1372: }
1373: return err;
1374: }
1375:
1376: 1377: 1378:
1379: LOCAL ER fatSetCluster(MapInfo *map, UW clno, UW new, UW *old)
1380: {
1381: FATFS *fs;
1382: UW offset, cl, bufofs, n;
1383: ER err;
1384: GPTR dp;
1385:
1386: err = E_OK;
1387: fs = map->m_fs;
1388: switch (fs->ff_fstype) {
1389: case FAT12:
1390: {
1391: UB buf[2];
1392:
1393: offset = clno + (clno / 2);
1394: err = fatMapReadBytes(map, offset, buf, 2);
1395: if (err < E_OK) break;
1396:
1397: cl = CEH(GetMisalignH(buf));
1398: new &= FAT12_MASK_VALID_CLST;
1399: if ((clno & 1) != 0) {
1400: new = (new << 4) | (cl & 0x0F);
1401: cl >>= 4;
1402: } else {
1403: new |= (cl & 0xF000);
1404: }
1405: if (old != NULL) {
1406: cl &= FAT12_MASK_VALID_CLST;
1407: *old = (cl >= FAT12_EOC) ? CLEND : cl;
1408: }
1409: SetMisalignH(buf, (UH)CEH(new));
1410: err = fatMapWriteBytes(map, offset, buf, 2);
1411: break;
1412: }
1413:
1414: case FAT16:
1415: if (clno >= map->m_btop && clno < map->m_bend) {
1416:
1417: n = clno - map->m_btop;
1418: } else {
1419: err = fatMapGetCache(map, clno * sizeof(UH),
1420: &bufofs, TRUE);
1421: if (err < E_OK) break;
1422: map->m_btop = clno - (n = bufofs / sizeof(UH));
1423: map->m_bend = map->m_btop + (map->m_bpp / sizeof(UH));
1424: }
1425: dp.b = &map->m_page->dcp_buf[n * sizeof(UH)];
1426: if (old != NULL) {
1427: cl = CEH(*dp.h);
1428: *old = (cl >= FAT16_EOC) ? CLEND : cl;
1429: }
1430: *dp.h = CEH(new);
1431: err = fatDCacheUpdate(fs, map->m_page, map->m_info);
1432: break;
1433:
1434: case FAT32:
1435: default:
1436: if (clno >= map->m_btop && clno < map->m_bend) {
1437:
1438: n = clno - map->m_btop;
1439: } else {
1440: err = fatMapGetCache(map, clno * sizeof(UW),
1441: &bufofs, TRUE);
1442: if (err < E_OK) break;
1443: map->m_btop = clno - (n = bufofs / sizeof(UW));
1444: map->m_bend = map->m_btop + (map->m_bpp / sizeof(UW));
1445: }
1446: dp.b = &map->m_page->dcp_buf[n * sizeof(UW)];
1447: if (old != NULL) {
1448: cl = CEW(*dp.w) & FAT32_MASK_VALID_CLST;
1449: *old = (cl >= FAT32_EOC) ? CLEND : cl;
1450: }
1451: new &= FAT32_MASK_VALID_CLST;
1452: *dp.w = CEW(new);
1453: err = fatDCacheUpdate(fs, map->m_page, map->m_info);
1454: break;
1455: }
1456: return err;
1457: }
1458:
1459: 1460: 1461: 1462:
1463: LOCAL ER fatGetClusterList(FATFS *fs, CLAD clad[], W cllen,
1464: UW clno, UW offset, W *len)
1465: {
1466: MapInfo *map;
1467: UW ncl, pos;
1468: W n;
1469: ER err;
1470:
1471: if (clno < CLSTART || clno > fs->ff_lastcl) {
1472: err = EX_INVAL;
1473: goto exit0;
1474: }
1475:
1476: pos = fs->ff_clsz;
1477: if (offset == OFSNEXT) {
1478: offset = 0;
1479: n = -1;
1480: } else {
1481: n = (pos > offset) ? 0 : -1;
1482: }
1483:
1484: clad[0].ca_no = clno;
1485: clad[0].ca_len = 1;
1486:
1487: map = &fs->ff_fatmap;
1488:
1489: for (err = E_OK; err >= E_OK; clno = ncl) {
1490: err = fatGetCluster(map, clno, &ncl);
1491: if (err < E_OK || ncl == CLEND) break;
1492:
1493: if (offset == 0 || (pos += fs->ff_clsz) > offset) {
1494: if (ncl == clno + 1 && n >= 0) {
1495: clad[n].ca_len++;
1496: } else {
1497: if (n + 1 >= cllen) break;
1498: clad[++n].ca_no = ncl;
1499: clad[n].ca_len = 1;
1500: }
1501: }
1502: CHK_BREAK_AND_SET_ERR(fs, &err);
1503: }
1504: if (err >= E_OK) {
1505: *len = n + 1;
1506: }
1507: (void)fatMapEnd(map);
1508: exit0:
1509: return err;
1510: }
1511:
1512: 1513: 1514:
1515: LOCAL ER fatGetPrevCluster(FATFS *fs, CLAD *clad, UW stcl, UW clno)
1516: {
1517: MapInfo *map;
1518: UW ncl, cl;
1519: W len;
1520: ER err;
1521:
1522: if (stcl < CLSTART || stcl > fs->ff_lastcl) {
1523: err = EX_INVAL;
1524: goto exit0;
1525: }
1526: err = E_OK;
1527: if (stcl == CLEND || stcl == clno) goto exit0;
1528:
1529: map = &fs->ff_fatmap;
1530:
1531: for (cl = stcl, len = 1; ; stcl = ncl) {
1532: err = fatGetCluster(map, stcl, &ncl);
1533: if (err < E_OK) break;
1534: if (ncl == CLEND) {
1535: len = 0;
1536: break;
1537: }
1538: if (ncl == clno) break;
1539: if (ncl == stcl + 1) {
1540: len++;
1541: } else {
1542: cl = ncl;
1543: len = 1;
1544: }
1545: }
1546: if (err >= E_OK) {
1547: clad->ca_no = cl;
1548: clad->ca_len = (UW)len;
1549: }
1550: (void)fatMapEnd(map);
1551: exit0:
1552: return err;
1553: }
1554:
1555: 1556: 1557:
1558: LOCAL ER fatGetClusterCount(FATFS *fs, UW clno, FATNODE *inode, W *num)
1559: {
1560: MapInfo *map;
1561: W n;
1562: UW ncl;
1563: ER err;
1564:
1565: if (clno < CLSTART || clno > fs->ff_lastcl) {
1566: err = EX_INVAL;
1567: goto exit0;
1568: }
1569:
1570: map = &fs->ff_fatmap;
1571:
1572: for (n = 1; ; n++, clno = ncl) {
1573: err = fatGetCluster(map, clno, &ncl);
1574: if (err < E_OK || ncl == CLEND) break;
1575: }
1576: if (err >= E_OK) {
1577: if (inode != NULL) {
1578:
1579: inode->fino_filsz = n * fs->ff_clsz;
1580: if (inode->fino_filsz > FILE_SIZE_MAX) {
1581: inode->fino_filsz = FILE_SIZE_MAX;
1582: }
1583: }
1584: if (num != NULL) {
1585: *num = n;
1586: }
1587: }
1588: (void)fatMapEnd(map);
1589: exit0:
1590: return err;
1591: }
1592:
1593: 1594: 1595: 1596:
1597: LOCAL ER fatGetNewCluster(FATFS *fs, CLAD *clad, UW clno, D nbyte)
1598: {
1599: MapInfo *map;
1600: UW reqlen, ccl, ncl, stcl, encl;
1601: W n;
1602: ER err;
1603:
1604: stcl = (clno < CLSTART || clno > fs->ff_lastcl) ? CLSTART : clno;
1605: encl = fs->ff_lastcl + 1;
1606: reqlen = (nbyte + fs->ff_clsz - 1) / fs->ff_clsz;
1607:
1608: clad->ca_no = CLVOID;
1609: clad->ca_len = 0;
1610:
1611: map = &fs->ff_fatmap;
1612:
1613: for (err = E_OK; ; ) {
1614:
1615: ncl = CLVOID;
1616: for (ccl = stcl; ccl < encl; ccl++) {
1617: err = fatGetCluster(map, ccl, &ncl);
1618: if (err < E_OK) {
1619: if (ncl == 0) err = E_OK;
1620: break;
1621: }
1622: CHK_BREAK_AND_SET_ERR(fs, &err);
1623: if (err < E_OK) break;
1624: }
1625: if (err < E_OK) break;
1626:
1627: if (ncl == 0) {
1628:
1629: clad->ca_no = ccl;
1630: n = 1;
1631: if (reqlen > 1) {
1632: while(++ccl < encl) {
1633: err = fatGetCluster(map, ccl, &ncl);
1634: if (ncl != 0) break;
1635: err = E_OK;
1636: if (++n >= reqlen) break;
1637: CHK_BREAK_AND_SET_ERR(fs, &err);
1638: if (err < E_OK) break;
1639: }
1640: }
1641: if (err >= E_OK) clad->ca_len = n;
1642: break;
1643: }
1644: if (stcl == CLSTART) break;
1645:
1646:
1647: stcl = CLSTART;
1648: encl = clno;
1649: }
1650: (void)fatMapEnd(map);
1651: return err;
1652: }
1653:
1654: 1655: 1656:
1657: LOCAL ER fatCountFreeCluster(FATFS *fs, UW *freecl)
1658: {
1659: MapInfo *map;
1660: D offset;
1661: UW free, totalcl, len, rem, dt;
1662: ER err;
1663: UB *ep;
1664: GPTR dp;
1665:
1666:
1667: map = &fs->ff_fatmap;
1668:
1669:
1670: free = 0;
1671: offset = 0;
1672: totalcl = fs->ff_lastcl + 1;
1673:
1674:
1675: switch (fs->ff_fstype) {
1676: case FAT12:
1677: for (len = (totalcl * 3 + 1) / 2, rem = 0; len > 0; ) {
1678: err = fatMapRead(map, &offset, &dp.b, &len, &ep);
1679: if (err < E_OK) break;
1680: while (dp.b + 3 <= ep) {
1681: switch(rem) {
1682: case 0: dt = *dp.b++;
1683: case 1: dt |= *dp.b++ << 8;
1684: case 2: dt |= *dp.b++ << 16;
1685: }
1686: if (dt == 0) free += 2;
1687: else if ((dt & 0x000FFF) == 0) free++;
1688: else if ((dt & 0xFFF000) == 0) free++;
1689: rem = 0;
1690: }
1691: rem = ep - dp.b;
1692: if (rem == 0) continue;
1693: dt = *dp.b++;
1694: if (rem <= 1) continue;
1695: dt |= *dp.b++ << 8;
1696: if (len <= 0 && (dt & 0x000FFF) == 0) free++;
1697: }
1698: break;
1699:
1700: case FAT16:
1701: for (len = totalcl * sizeof(UH); len > 0; ) {
1702: err = fatMapRead(map, &offset, &dp.b, &len, &ep);
1703: if (err < E_OK) break;
1704: while (dp.b < ep) {
1705: if (*dp.h++ == 0) free++;
1706: }
1707: }
1708: break;
1709:
1710: case FAT32:
1711: default:
1712: for (len = totalcl * sizeof(UW); len > 0; ) {
1713: err = fatMapRead(map, &offset, &dp.b, &len, &ep);
1714: if (err < E_OK) break;
1715: while (dp.b < ep) {
1716: if (*dp.w++ == 0) free++;
1717: }
1718: }
1719: break;
1720: }
1721: if (err >= E_OK) {
1722: *freecl = free;
1723: }
1724: (void)fatMapEnd(map);
1725: return err;
1726: }
1727:
1728: 1729: 1730:
1731: LOCAL ER fatChainCluster(FATFS *fs, UW clno, CLAD *clad, VW info)
1732: {
1733: MapInfo *map;
1734: UW ccl, ncl, endcl;
1735: VW oldinfo;
1736: ER err;
1737:
1738: endcl = clad->ca_no + clad->ca_len - 1;
1739: if (clno < CLSTART || clno > fs->ff_lastcl ||
1740: clad->ca_no < CLSTART || endcl > fs->ff_lastcl) {
1741: err = EX_INVAL;
1742: goto exit0;
1743: }
1744:
1745:
1746: map = &fs->ff_fatmap;
1747: oldinfo = map->m_info;
1748: map->m_info = info;
1749:
1750:
1751: err = E_OK;
1752: for (ccl = clad->ca_no; ccl < endcl && err >= E_OK; ccl++) {
1753: err = fatSetCluster(map, ccl, ccl + 1, NULL);
1754: }
1755: if (err < E_OK) goto exit1;
1756:
1757:
1758: err = fatSetCluster(map, ccl, CLEND, NULL);
1759: if (err < E_OK) goto exit1;
1760:
1761:
1762: for (ccl = clno; ccl != clad->ca_no; ccl = ncl) {
1763: err = fatGetCluster(map, ccl, &ncl);
1764: if (err < E_OK) break;
1765: if (ncl == CLEND) {
1766: err = fatSetCluster(map, ccl, clad->ca_no, NULL);
1767: break;
1768: }
1769: }
1770:
1771:
1772: if (err >= E_OK) {
1773: fs->ff_freecl -= clad->ca_len;
1774: fs->ff_nextfree = clad->ca_no + clad->ca_len;
1775: }
1776: exit1:
1777: (void)fatMapEnd(map);
1778:
1779:
1780: map->m_info = oldinfo;
1781: exit0:
1782: return err;
1783: }
1784:
1785: 1786: 1787: 1788:
1789: LOCAL ER fatUnchainCluster(FATFS *fs, UW clno, BOOL next, VW info)
1790: {
1791: MapInfo *map;
1792: UW clofs, ncl;
1793: W cnt;
1794: VW oldinfo;
1795: ER err;
1796:
1797:
1798: map = &fs->ff_fatmap;
1799: oldinfo = map->m_info;
1800: map->m_info = info;
1801:
1802: for (cnt = 0, ncl = clno; ncl != CLEND;) {
1803:
1804: if (ncl < CLSTART || ncl > fs->ff_lastcl) {
1805: err = EX_IO;
1806: break;
1807: }
1808:
1809: clofs = ncl;
1810: if (ncl == clno && next != FALSE) {
1811:
1812: err = fatSetCluster(map, clofs, CLEND, &ncl);
1813: } else {
1814:
1815: err = fatSetCluster(map, clofs, 0, &ncl);
1816: cnt++;
1817: }
1818: if (err < E_OK) break;
1819: }
1820: if (err >= E_OK) {
1821:
1822: fs->ff_freecl += cnt;
1823:
1824:
1825: }
1826: (void)fatMapEnd(map);
1827:
1828:
1829: map->m_info = oldinfo;
1830: return err;
1831: }
1832:
1833: 1834: 1835:
1836: LOCAL ER fatExtendClusterList(FATFS *fs, CLAD *clad, FATNODE *inode)
1837: {
1838: UW clno;
1839: CLAD *clbuf, *clp;
1840: ER err;
1841:
1842: clbuf = inode->fino_c.ino_info;
1843: clp = NULL;
1844:
1845:
1846: if (clbuf != NULL && inode->fino_cllen > 0) {
1847:
1848: clp = &clbuf[inode->fino_cllen - 1];
1849: clno = clp->ca_no + clp->ca_len - 1;
1850: } else if (inode->fino_fclno == 0) {
1851:
1852: inode->fino_fclno = clad->ca_no;
1853: clno = clad->ca_no;
1854: } else {
1855:
1856: clno = inode->fino_fclno;
1857: }
1858:
1859:
1860: err = fatChainCluster(fs, clno, clad, (VW)inode);
1861: if (err < E_OK) goto exit0;
1862:
1863: if (clbuf == NULL) goto exit0;
1864:
1865:
1866: if (clp != NULL && clad->ca_no == clno + 1) {
1867:
1868: clp->ca_len += clad->ca_len;
1869: } else {
1870:
1871: if (inode->fino_maxcl <= inode->fino_cllen) {
1872: err = alloc_clbuf(&clbuf, &inode->fino_maxcl);
1873: inode->fino_c.ino_info = clbuf;
1874: if (err < E_OK) goto exit0;
1875: }
1876:
1877: clbuf[inode->fino_cllen] = *clad;
1878: inode->fino_cllen++;
1879: }
1880: exit0:
1881: return err;
1882: }
1883:
1884: 1885: 1886:
1887: LOCAL ER fatApdNewCluster(FATFS *fs, CLAD *clad, D size, FATNODE *inode)
1888: {
1889: ER err;
1890:
1891:
1892: err = fatGetNewCluster(fs, clad, fs->ff_nextfree, size);
1893: if (err >= E_OK) {
1894:
1895: err = fatExtendClusterList(fs, clad, inode);
1896: }
1897: return err;
1898: }
1899:
1900: 1901: 1902:
1903: LOCAL ER fatTruncClusterList(FATFS *fs, D newsz, FATNODE *inode)
1904: {
1905: UW clno, ofs;
1906: W len;
1907: CLAD *clbuf, clad;
1908: ER err;
1909:
1910: err = E_OK;
1911:
1912:
1913: ofs = (newsz > 0) ? newsz - 1 : 0;
1914:
1915: clbuf = (CLAD *)inode->fino_c.ino_info;
1916: if (clbuf != NULL) {
1917:
1918: if (inode->fino_cllen == 0) goto exit0;
1919:
1920:
1921: ofs /= fs->ff_clsz;
1922:
1923:
1924: for (len = 0; len < (W)inode->fino_cllen; len++) {
1925: if (ofs < clbuf[len].ca_len) break;
1926: ofs -= clbuf[len].ca_len;
1927: }
1928: if (len >= (W)inode->fino_cllen) len--;
1929: clno = clbuf[len].ca_no + ofs;
1930: } else {
1931:
1932: if (inode->fino_fclno == 0) goto exit0;
1933:
1934:
1935: err = fatGetClusterList(fs, &clad, 1, inode->fino_fclno,
1936: ofs, &len);
1937: if (err < E_OK) goto exit0;
1938:
1939:
1940: clno = clad.ca_no;
1941: }
1942:
1943:
1944: err = fatUnchainCluster(fs, clno, (newsz > 0)? TRUE : FALSE, (VW)inode);
1945: if (err < E_OK) goto exit0;
1946:
1947:
1948: if ((inode->fino_filsz = newsz) > 0) {
1949: if (clbuf != NULL) {
1950: clbuf[len].ca_len = ofs + 1;
1951: inode->fino_cllen = (UW)len + 1;
1952: }
1953: } else {
1954: inode->fino_fclno = 0;
1955: inode->fino_cllen = 0;
1956: }
1957: exit0:
1958: return err;
1959: }
1960:
1961: 1962: 1963:
1964: LOCAL ER fatMakeClusterList(FATFS *fs, FATNODE *inode)
1965: {
1966: UW clno, cllen;
1967: UH maxcl;
1968: W len;
1969: CLAD *clbuf,*clp;
1970: ER err;
1971:
1972: err = E_OK;
1973:
1974:
1975: if (inode->fino_c.ino_info != NULL ||
1976: (IsRootINODE(fs, inode) && ! isFAT32(fs->ff_fstype))) {
1977: goto exit0;
1978: }
1979:
1980:
1981: cllen = 0;
1982: clbuf = NULL;
1983: err = alloc_clbuf(&clbuf, &maxcl);
1984: if (err < E_OK) goto exit1;
1985:
1986:
1987: if ((clno = inode->fino_fclno) == 0 &&
1988: inode->fino_filsz == 0) goto exit1;
1989:
1990:
1991: for ( ; ; ) {
1992:
1993: clp = &clbuf[cllen];
1994:
1995:
1996: err = fatGetClusterList(fs, clp, MAX_CLEN, clno,
1997: (cllen == 0) ? 0 : OFSNEXT, &len);
1998: if (err < E_OK) break;
1999:
2000: cllen += (UW)len;
2001:
2002:
2003: if (len < MAX_CLEN) break;
2004:
2005:
2006: clno = clbuf[cllen - 1].ca_no + clbuf[cllen - 1].ca_len - 1;
2007:
2008:
2009: err = alloc_clbuf(&clbuf, &maxcl);
2010: if (err < E_OK) break;
2011: }
2012: exit1:
2013: if (err < E_OK) {
2014: if (clbuf != NULL) {
2015: fimp_free(clbuf);
2016: }
2017: clbuf = NULL;
2018: maxcl = cllen = 0;
2019: }
2020: inode->fino_c.ino_info = clbuf;
2021: inode->fino_maxcl = maxcl;
2022: inode->fino_cllen = cllen;
2023: exit0:
2024: return err;
2025: }
2026:
2027: 2028: 2029: 2030:
2031: LOCAL ER fatCopyClusterList(FATFS *fs, CLAD clad[], D offset,
2032: D nbyte, FATNODE *inode, W *lenp)
2033: {
2034: CLAD *clp, *cle;
2035: UW cllen, clofs, clend, len;
2036: W n;
2037: ER err;
2038:
2039: err = E_OK;
2040:
2041:
2042: if (inode->fino_c.ino_info == NULL) {
2043: err = fatMakeClusterList(fs, inode);
2044: if (err < E_OK) goto exit0;
2045: }
2046:
2047:
2048: clofs = offset / fs->ff_clsz;
2049: clend = (nbyte <= 0) ? 0 :
2050: (offset + nbyte + (fs->ff_clsz - 1)) / fs->ff_clsz;
2051:
2052:
2053: clp = (CLAD *)inode->fino_c.ino_info;
2054: cle = clp + (W)inode->fino_cllen;
2055:
2056: for (cllen = 0, n = 0; n < MAX_CLEN && clp < cle; clp++) {
2057: cllen += (len = clp->ca_len);
2058: if (len <= clofs) {
2059:
2060: clofs -= len;
2061: } else {
2062:
2063: clad[n].ca_no = clp->ca_no + clofs;
2064: clad[n++].ca_len = len - clofs;
2065: if (clend > 0 && cllen >= clend) {
2066:
2067: clad[n - 1].ca_len -= cllen - clend;
2068: break;
2069: }
2070: clofs = 0;
2071: }
2072: }
2073: *lenp = n;
2074: exit0:
2075: return err;
2076: }
2077:
2078: 2079: 2080:
2081:
2082: 2083: 2084:
2085: LOCAL W fatGetSFN(UB sfname[BASE_EXTLEN], UB smallcaps,
2086: UH utf16nm[BASE_EXTLEN + 2])
2087: {
2088: UB c, nm[BASE_EXTLEN + 2];
2089: W i, n, sflg;
2090:
2091:
2092: sflg = SMALL_BASE;
2093: for (i = n = 0; n < BASE_EXTLEN; n++) {
2094: if ((c = sfname[n]) == ' ') {
2095: if (n == BASELEN) break;
2096: } else {
2097: if (n == BASELEN) {
2098: nm[i++] = '.';
2099: sflg = SMALL_EXT;
2100: }
2101: nm[i++] = isSET(smallcaps, sflg) ? AsciiToLOW(c) : c;
2102: }
2103: }
2104: nm[i] = '\0';
2105:
2106: if (nm[0] == DE_B0_KANJI_ESC) nm[0] = DE_B0_FREE;
2107:
2108:
2109: for (i = n = 0; nm[i] != '\0'; n++) {
2110: #ifdef FAT_ASCII_FN_ONLY
2111: utf16nm[n] = (nm[i] <= ASCII_MAX) ? (UH)nm[i] : (UH)'_';
2112: i++;
2113: #else
2114: UW unicode;
2115: i += fatEncLocalToUnicode(&nm[i], &unicode);
2116: if (UnicodeIsNormal(unicode)) {
2117: utf16nm[n] = (UH)unicode;
2118: } else if (UnicodeIsSurrogate(unicode)) {
2119: utf16nm[n++] = UnicodeToUtf16UpSurrogate(unicode);
2120: utf16nm[n] = UnicodeToUtf16LowSurrogate(unicode);
2121: } else {
2122: utf16nm[n] = (UH)'_';
2123: }
2124: #endif
2125: }
2126: utf16nm[n] = (UH)'\0';
2127: return n;
2128: }
2129:
2130: 2131: 2132:
2133: LOCAL W fatSetSFN(const UB *utf8nm, W utf8len,
2134: UB sfname[BASE_EXTLEN], UB *smallcaps, W gen)
2135: {
2136: W n, i, kind, stat;
2137: UW unicode, cbit;
2138: UB *e_utf8nm, *cp;
2139:
2140:
2141: memset(sfname, ' ', BASE_EXTLEN);
2142: *smallcaps = 0x0;
2143: e_utf8nm = (UB*)utf8nm + utf8len;
2144:
2145: cbit = 0;
2146: stat = FAT_SAME_NAME;
2147:
2148:
2149: if (utf8nm[0] == '.') {
2150: if (utf8len == 1) {
2151: sfname[0] = '.';
2152: goto exit0;
2153: }
2154: if (utf8nm[1] == '.' && utf8len == 2) {
2155: sfname[0] = sfname[1] = '.';
2156: goto exit0;
2157: }
2158:
2159: sfname[0] = '_';
2160: cbit |= 1 << 0;
2161: stat = FAT_CHG_WITH_N;
2162: }
2163:
2164:
2165: for (kind = n = 0; n < BASELEN &&
2166: utf8nm < e_utf8nm && *utf8nm != '.'; ) {
2167:
2168: cbit |= 1 << n;
2169: utf8nm += fatEncUtf8ToUnicode(utf8nm, &unicode);
2170: if (UnicodeIsAscii(unicode)) {
2171: if (AsciiIsSFN(unicode)) {
2172:
2173: sfname[n++] = AsciiToUP(unicode);
2174: kind |= 1 << getAsciiKind(unicode);
2175: continue;
2176: }
2177: #ifndef FAT_ASCII_FN_ONLY
2178: } else if (! UnicodeIsInvalid(unicode)) {
2179: W cnt;
2180: UB buf[ENC_CHAR_MAX];
2181:
2182: cnt = fatEncUnicodeToLocal(unicode, buf);
2183: if (cnt > 0) {
2184:
2185: if (n + cnt > BASELEN) {
2186: n = BASELEN;
2187: stat = FAT_CHG_WITH_N;
2188: break;
2189: }
2190: for (i = 0; i < cnt; i++) {
2191: sfname[n++] = buf[i];
2192: }
2193: kind |= 1 << ASCII_CON;
2194: continue;
2195: }
2196: #endif
2197: }
2198:
2199: sfname[n++] = '_';
2200: stat = FAT_CHG_WITH_N;
2201: }
2202:
2203: if (stat != FAT_CHG_WITH_N) {
2204:
2205: if ((kind & (1 << ASCII_LOW)) != 0) {
2206: if ((kind & (1 << ASCII_UP)) != 0) {
2207:
2208: stat = FAT_CHG_WITHOUT_N;
2209: } else if ((kind & (1 << ASCII_CON)) == 0) {
2210:
2211: *smallcaps |= SMALL_BASE;
2212: }
2213: }
2214: }
2215:
2216:
2217: if (utf8nm < e_utf8nm) {
2218: if (*utf8nm != '.') {
2219: stat = FAT_CHG_WITH_N;
2220: }
2221:
2222: for (cp = e_utf8nm; --cp >= utf8nm; ) {
2223: if (*cp == '.') break;
2224: }
2225: utf8nm = (cp < utf8nm) ? e_utf8nm : cp + 1;
2226:
2227:
2228: for (n = BASELEN, kind = 0;
2229: n < BASE_EXTLEN && utf8nm < e_utf8nm; ) {
2230: utf8nm += fatEncUtf8ToUnicode(utf8nm, &unicode);
2231: if (UnicodeIsAscii(unicode)) {
2232: if (AsciiIsSFN(unicode)) {
2233:
2234: sfname[n++] = AsciiToUP(unicode);
2235: kind |= 1 << getAsciiKind(unicode);
2236: continue;
2237: }
2238: #ifndef FAT_ASCII_FN_ONLY
2239: } else if (! UnicodeIsInvalid(unicode)) {
2240: W cnt;
2241: UB buf[ENC_CHAR_MAX];
2242:
2243: cnt = fatEncUnicodeToLocal(unicode, buf);
2244: if (cnt > 0) {
2245:
2246: if (n + cnt > BASE_EXTLEN) {
2247: n = BASE_EXTLEN;
2248: stat = FAT_CHG_WITH_N;
2249: break;
2250: }
2251: for (i = 0; i < cnt; i++) {
2252: sfname[n++] = buf[i];
2253: }
2254: kind |= 1 << ASCII_CON;
2255: continue;
2256: }
2257: #endif
2258: }
2259:
2260: sfname[n++] = '_';
2261: stat = FAT_CHG_WITH_N;
2262: }
2263: if (utf8nm < e_utf8nm) {
2264: stat = FAT_CHG_WITH_N;
2265:
2266: } else if (stat != FAT_CHG_WITH_N) {
2267:
2268: if ((kind & (1 << ASCII_LOW)) != 0) {
2269: if ((kind & (1 << ASCII_UP)) != 0) {
2270:
2271: stat = FAT_CHG_WITHOUT_N;
2272: } else if ((kind & (1 << ASCII_CON)) == 0) {
2273:
2274: *smallcaps |= SMALL_EXT;
2275: }
2276: }
2277: }
2278: }
2279:
2280: if (sfname[0] == DE_B0_FREE) sfname[0] = DE_B0_KANJI_ESC;
2281:
2282: if (stat != FAT_SAME_NAME) {
2283: *smallcaps = 0x0;
2284:
2285:
2286: if (stat == FAT_CHG_WITH_N && gen > 0) {
2287: UB numstr[BASELEN];
2288:
2289:
2290: for (i = BASELEN; --i > 0 && gen > 0; gen /= 10) {
2291: numstr[i] = '0' + (gen % 10);
2292: }
2293:
2294:
2295: while (i > 0 && ! isSET(cbit, 1 << i)) i--;
2296:
2297:
2298: sfname[i] = '~';
2299: while (++i < BASELEN) sfname[i] = numstr[i];
2300: }
2301: }
2302: exit0:
2303: return stat;
2304: }
2305:
2306: 2307: 2308:
2309: LOCAL W fatGetLFN(FAT_DIRENT_LFN *lde, W *ldenum, W *chksum,
2310: UH *utf16nm)
2311: {
2312: W i, num;
2313: UB *cp, *ep;
2314:
2315: if ((num = lde->lde_index & LFN_CNT) > LFN_MAXENT) goto exit0;
2316:
2317: if (*chksum == CKSVOID) {
2318: if (! isSET(lde->lde_index, LFN_LAST)) goto exit0;
2319: *chksum = lde->lde_checksum;
2320: utf16nm[num * LFN_CHARS] = (UH)'\0';
2321: } else {
2322: if (num != *ldenum ||
2323: lde->lde_checksum != *chksum) goto exit0;
2324: }
2325: *ldenum = --num;
2326:
2327:
2328: for (utf16nm += num * LFN_CHARS, i = 0; i < 3; i++) {
2329: cp = (UB*)lde + LDE_NMPOS[i].ofs;
2330: ep = cp + LDE_NMPOS[i].cnt;
2331: for ( ; cp < ep; cp += 2) {
2332: *utf16nm++ = CEH(GetMisalignH(cp));
2333: }
2334: }
2335: return 0;
2336: exit0:
2337: return -1;
2338: }
2339:
2340: 2341: 2342: 2343:
2344: LOCAL W fatChkLFN(UH *utf16nm, W utf16len, FAT_DIRENT_LFN *lde,
2345: W chksum, UH *realnm)
2346: {
2347: UB *cp, *ep;
2348: W n, i, cks;
2349: UH utf16;
2350:
2351: cks = CKSVOID;
2352:
2353:
2354: n = (W)(((lde->lde_index & LFN_CNT) - 1) * LFN_CHARS);
2355: if ((utf16len -= n) <= 0) goto exit0;
2356:
2357:
2358: if (isSET(lde->lde_index, LFN_LAST)) {
2359: if (utf16len > (W)LFN_CHARS) goto exit0;
2360: chksum = (W)lde->lde_checksum;
2361: } else {
2362: if (chksum != lde->lde_checksum) goto exit0;
2363: }
2364:
2365:
2366: for (utf16nm += n, i = 0; i < 3; i++) {
2367: cp = (UB*)lde + LDE_NMPOS[i].ofs;
2368: ep = cp + LDE_NMPOS[i].cnt;
2369: for ( ; cp < ep; cp += 2) {
2370: utf16 = CEH(GetMisalignH(cp));
2371: if (--utf16len < 0) {
2372: if (utf16 != 0) goto exit0;
2373: if (realnm != NULL) realnm[n] = (UH)'\0';
2374: goto exit1;
2375: }
2376: if (*utf16nm++ != (CharIsAscii(utf16) ?
2377: AsciiToUP(utf16) : utf16)) goto exit0;
2378: if (realnm != NULL) realnm[n++] = utf16;
2379: }
2380: }
2381: exit1:
2382: cks = chksum;
2383: exit0:
2384: return cks;
2385: }
2386:
2387: 2388: 2389:
2390: LOCAL void fatSetLFN(UH *utf16nm, W utf16len, FAT_DIRENT_LFN *lde,
2391: W lfnidx, UB chksum)
2392: {
2393: UB *cp, *ep;
2394: UH *utf16end;
2395: W i;
2396:
2397:
2398: memset(lde, 0xFF, sizeof(FAT_DIRENT_LFN));
2399: lde->lde_index = (UB)lfnidx;
2400: lde->lde_ftype = FAT_LONGNAME;
2401: lde->lde_smallcaps = 0;
2402: lde->lde_checksum = chksum;
2403: lde->lde_clno = 0;
2404:
2405:
2406: utf16end = utf16nm + utf16len;
2407: utf16nm += (lfnidx - 1) * LFN_CHARS;
2408:
2409: for (i = 0; i < 3; i++) {
2410: cp = (UB*)lde + LDE_NMPOS[i].ofs;
2411: ep = cp + LDE_NMPOS[i].cnt;
2412: for ( ; cp < ep && utf16nm < utf16end; cp += 2, utf16nm++) {
2413: SetMisalignH(cp, *utf16nm);
2414: }
2415: if (utf16nm < utf16end) continue;
2416:
2417:
2418: if (cp < ep) cp[0] = cp[1] = 0;
2419: else if (i < 2) continue;
2420: lde->lde_index |= LFN_LAST;
2421: break;
2422: }
2423: }
2424:
2425: 2426: 2427:
2428:
2429: 2430: 2431:
2432: LOCAL UB fatCalcChksum(UB *name)
2433: {
2434: W i;
2435: UB s;
2436:
2437: for (s = 0, i = BASE_EXTLEN; --i >= 0; s += *name++) {
2438: s = (s << 7) | (s >> 1);
2439: }
2440: return s;
2441: }
2442:
2443: 2444: 2445:
2446: LOCAL ER fatReadCurDIR(FATFS *fs, DIRINF *dir)
2447: {
2448: W d_ofs;
2449: UW ofs;
2450: ER err;
2451:
2452: if ((d_ofs = dir->di_dirent_ofs) == OFSVOID) return EX_INVAL;
2453:
2454: if (d_ofs >= dir->di_map.m_btop && d_ofs < dir->di_map.m_bend) {
2455:
2456: ofs = (d_ofs - dir->di_map.m_btop) * DIRENTSZ;
2457: } else {
2458: err = fatMapGetCache(&dir->di_map, d_ofs * DIRENTSZ, &ofs,TRUE);
2459: if (err < E_OK) return err;
2460:
2461: dir->di_map.m_btop = d_ofs - (ofs / DIRENTSZ);
2462: dir->di_map.m_bend = dir->di_map.m_btop +
2463: ( ((fs->ff_clsz < dir->di_map.m_bpp) ?
2464: fs->ff_clsz : dir->di_map.m_bpp) / DIRENTSZ );
2465: }
2466: dir->di_dirent = (FAT_DIRENT *)&dir->di_map.m_page->dcp_buf[ofs];
2467: return E_OK;
2468: }
2469:
2470: 2471: 2472:
2473: LOCAL ER fatWriteCurDIR(FATFS *fs, DIRINF *dir, VW info)
2474: {
2475: if (dir->di_map.m_page == NULL || dir->di_access != AC_WRITE ||
2476: dir->di_dirent_ofs == OFSVOID) return EX_INVAL;
2477:
2478: return fatDCacheUpdate(fs, dir->di_map.m_page,
2479: (info == 0) ? dir->di_map.m_info : info);
2480: }
2481:
2482: 2483: 2484:
2485: LOCAL ER fatOpenDIR(FATFS *fs, DIRINF *dir, UW dircl, W offset,
2486: UW mode, FATNODE *inode)
2487: {
2488: UW dirofs;
2489: W cllen;
2490: div_t dv;
2491: ER err;
2492:
2493:
2494: memset(dir, 0, sizeof(DIRINF));
2495: dir->di_dircl = dircl;
2496: dir->di_access = mode;
2497: dir->di_dirent_ofs = OFSVOID;
2498:
2499: dirofs = 0;
2500: dv.quot = dv.rem = 0;
2501: err = E_OK;
2502:
2503: if (offset >= 0) {
2504: dv = div((dircl > 0)? (offset % fs->ff_clsz):offset, DIRENTSZ);
2505: if (dv.rem != 0) {
2506: err = EX_INVAL;
2507: goto exit0;
2508: }
2509:
2510: dir->di_offset = (UW)offset;
2511: dirofs = (UW)offset;
2512: }
2513:
2514: if (inode == NULL) {
2515: inode = (FATNODE *)fatInodeSearch((FS*)fs, dirINO(fs, dircl));
2516: }
2517: dir->di_inode = inode;
2518:
2519: if (dircl > 0) {
2520:
2521: if (inode != NULL && inode->fino_c.ino_info != NULL) {
2522: err = fatCopyClusterList(fs, dir->di_clno,
2523: dirofs, 0, inode, &cllen);
2524: } else {
2525: err = fatGetClusterList(fs, dir->di_clno, MAX_CLEN,
2526: dircl, dirofs, &cllen);
2527: }
2528: if (err < E_OK) goto exit0;
2529:
2530:
2531: if (cllen == 0) {
2532: if (offset < 0) {
2533: err = EX_INVAL;
2534: goto exit0;
2535: }
2536: offset = OFSVOID;
2537: goto exit1;
2538: }
2539:
2540:
2541: dir->di_len = cllen;
2542: err = fatMapDisk(fs, dir->di_clno, cllen, &dir->di_map,
2543: MAP_C | MAP_READ, (VW)inode);
2544: if (err < E_OK) goto exit0;
2545:
2546:
2547: while (--cllen >= 0) {
2548: dir->di_nent += dir->di_clno[cllen].ca_len;
2549: }
2550: dir->di_nent *= DEpCL;
2551:
2552: } else {
2553:
2554: if (dirofs >= ROOTSZ) {
2555: offset = OFSVOID;
2556: goto exit1;
2557: }
2558:
2559:
2560: dir->di_secno[0].ca_no = fs->ff_rootsc;
2561: dir->di_secno[0].ca_len = ROOTSZ / DSECSZ(fs);
2562:
2563: err = fatMapDisk(fs, dir->di_secno, ROOT_SLEN, &dir->di_map,
2564: MAP_S | MAP_READ, (VW)inode);
2565: if (err < E_OK) goto exit0;
2566:
2567:
2568: dir->di_nent = ROOTENT;
2569: }
2570: exit1:
2571:
2572: if (offset >= 0) {
2573: if (dv.quot >= (W)dir->di_nent) {
2574: err = EX_INVAL;
2575: } else {
2576: dir->di_dirent_ofs = dv.quot;
2577: err = fatReadCurDIR(fs, dir);
2578: }
2579: }
2580: exit0:
2581: return err;
2582: }
2583:
2584: 2585: 2586:
2587: LOCAL ER fatCloseDIR(FATFS *fs, DIRINF *dir, ER err)
2588: {
2589: (void)fs;
2590:
2591: if (dir->di_dirent_ofs != OFSVOID) {
2592: if (err < E_OK) {
2593: dir->di_access = AC_RDONLY;
2594: }
2595: (void)fatMapEnd(&dir->di_map);
2596: fatUnmapDisk(&dir->di_map);
2597: dir->di_dirent_ofs = OFSVOID;
2598: dir->di_dirent = NULL;
2599: }
2600: return err;
2601: }
2602:
2603: 2604: 2605:
2606: LOCAL ER fatMapNextDIR(FATFS *fs, DIRINF *dir, UW mode)
2607: {
2608: UW clno;
2609: W n;
2610: ER err;
2611:
2612:
2613: (void)fatCloseDIR(fs, dir, E_OK);
2614:
2615: err = E_OK;
2616: if (dir->di_dircl == 0) goto exit0;
2617:
2618:
2619: clno = dir->di_clno[dir->di_len - 1].ca_no +
2620: dir->di_clno[dir->di_len - 1].ca_len - 1;
2621:
2622: err = fatGetClusterList(fs, dir->di_clno, MAX_CLEN, clno, OFSNEXT,
2623: &dir->di_len);
2624: if (err < E_OK) goto exit0;
2625:
2626: if ((n = dir->di_len) > 0) {
2627:
2628: err = fatMapDisk(fs, dir->di_clno, n, &dir->di_map,
2629: MAP_C | MAP_READ, (VW)dir->di_inode);
2630: if (err < E_OK) goto exit0;
2631:
2632:
2633: for (dir->di_nent = 0; --n >= 0; ) {
2634: dir->di_nent += dir->di_clno[n].ca_len;
2635: }
2636: dir->di_nent *= DEpCL;
2637:
2638:
2639: dir->di_access = mode;
2640: dir->di_dirent_ofs = 0;
2641: err = fatReadCurDIR(fs, dir);
2642: }
2643: exit0:
2644: return err;
2645: }
2646:
2647: 2648: 2649:
2650: LOCAL ER fatMapPrevDIR(FATFS *fs, DIRINF *dir, UW mode)
2651: {
2652: ER err;
2653:
2654:
2655: (void)fatCloseDIR(fs, dir, E_OK);
2656:
2657:
2658: err = fatGetPrevCluster(fs, &dir->di_clno[0], dir->di_dircl,
2659: dir->di_clno[0].ca_no);
2660: if (err < E_OK) goto exit0;
2661:
2662: if (dir->di_clno[0].ca_len == 0) {
2663: err = EX_INVAL;
2664: goto exit0;
2665: }
2666:
2667:
2668: dir->di_len = 1;
2669: err = fatMapDisk(fs, dir->di_clno, 1, &dir->di_map,
2670: MAP_C | MAP_READ, (VW)dir->di_inode);
2671: if (err < E_OK) goto exit0;
2672:
2673:
2674: dir->di_nent = dir->di_clno[0].ca_len * DEpCL;
2675:
2676:
2677: dir->di_access = mode;
2678: dir->di_dirent_ofs = dir->di_nent - 1;
2679: err = fatReadCurDIR(fs, dir);
2680: exit0:
2681: return err;
2682: }
2683:
2684: 2685: 2686:
2687: LOCAL ER fatNextDIR(FATFS *fs, DIRINF *dir, UW mode)
2688: {
2689: ER err;
2690:
2691: if (dir->di_dirent == NULL) {
2692: dir->di_dirent_ofs = 0;
2693: dir->di_offset = 0;
2694: return fatReadCurDIR(fs, dir);
2695: }
2696:
2697:
2698: dir->di_dirent_ofs++;
2699:
2700: if (dir->di_dirent_ofs >= dir->di_nent) {
2701:
2702: err = fatMapNextDIR(fs, dir, mode);
2703: } else {
2704:
2705: err = fatReadCurDIR(fs, dir);
2706: }
2707: if (err >= E_OK) {
2708: if (dir->di_dirent != NULL) {
2709: dir->di_offset += DIRENTSZ;
2710: }
2711:
2712: }
2713: return err;
2714: }
2715:
2716: 2717: 2718:
2719: LOCAL ER fatPrevDIR(FATFS *fs, DIRINF *dir, UW mode)
2720: {
2721: ER err;
2722:
2723: if (dir->di_dirent == NULL) {
2724: err = EX_INVAL;
2725:
2726:
2727: } else {
2728: if (dir->di_dirent_ofs <= 0) {
2729: if (dir->di_offset > 0) {
2730:
2731: err = fatMapPrevDIR(fs, dir, mode);
2732: if (err >= E_OK) {
2733: dir->di_offset -= DIRENTSZ;
2734: }
2735: } else {
2736: err = EX_INVAL;
2737: }
2738: } else {
2739: dir->di_dirent_ofs--;
2740: err = fatReadCurDIR(fs, dir);
2741: if (err >= E_OK) {
2742: dir->di_offset -= DIRENTSZ;
2743: }
2744: }
2745: }
2746: return err;
2747: }
2748:
2749: 2750: 2751:
2752: LOCAL ER fatSetEndDIR(FATFS *fs, DIRINF *dir)
2753: {
2754: MapInfo map;
2755: UW clno;
2756: W len, bufofs;
2757: CLAD clad;
2758: FAT_DIRENT *de;
2759: ER err, err2;
2760:
2761: if (dir->di_dirent == NULL) {
2762: err = EX_INVAL;
2763: goto exit0;
2764: }
2765:
2766: if (dir->di_dirent_ofs + 1 >= dir->di_nent) {
2767:
2768: if (dir->di_dircl == 0) {
2769: err = E_OK;
2770: goto exit0;
2771: }
2772:
2773:
2774: clno = dir->di_clno[dir->di_len - 1].ca_no
2775: + dir->di_clno[dir->di_len - 1].ca_len - 1;
2776: err = fatGetClusterList(fs, &clad, 1, clno, OFSNEXT, &len);
2777: if (err < E_OK) goto exit0;
2778:
2779: if (len <= 0) goto exit0;
2780:
2781:
2782: err = fatMapDisk(fs, &clad, 1, &map,
2783: MAP_C | MAP_READ, (VW)dir->di_inode);
2784: if (err >= E_OK) {
2785:
2786: bufofs = OFFSETinPAGE(fs, map.m_page,
2787: CNtoBN(clad.ca_no), 0);
2788: de = (FAT_DIRENT*)&map.m_page->dcp_buf[bufofs];
2789: de->de_fname[0] = DE_B0_END;
2790: err = fatDCacheUpdate(fs,map.m_page, (VW)dir->di_inode);
2791: (void)fatMapEnd(&map);
2792: }
2793: fatUnmapDisk(&map);
2794: } else {
2795: dir->di_dirent_ofs++;
2796: err = fatReadCurDIR(fs, dir);
2797: if (err >= E_OK) {
2798:
2799: dir->di_dirent->de_fname[0] = DE_B0_END;
2800: err = fatWriteCurDIR(fs, dir, 0);
2801:
2802: dir->di_dirent_ofs--;
2803: err2 = fatReadCurDIR(fs, dir);
2804: SetErr2(err, err2);
2805: }
2806: }
2807: exit0:
2808: return err;
2809: }
2810:
2811: 2812: 2813: 2814:
2815: LOCAL ER fatSearchDIR_cl(FATFS *fs, DIRINF *dir, UW fclno, UW mode)
2816: {
2817: FAT_DIRENT *dirent;
2818: ER err;
2819:
2820: for (;;) {
2821:
2822: err = fatNextDIR(fs, dir, mode);
2823: if (err < E_OK) break;
2824:
2825: dirent = dir->di_dirent;
2826: if (dirent == NULL ||
2827: isDE_TERM(dirent)) {
2828: dir->di_dirent = NULL;
2829: err = EX_NOENT;
2830: break;
2831: }
2832: if (isDE_FREE(dirent) ||
2833: isDE_LFN(dirent)) {
2834: continue;
2835: }
2836: if (isFAT_SUBDIR(dirent->de_ftype)) {
2837:
2838: if (dirent_to_fcl(fs, dirent) == fclno) break;
2839: }
2840: }
2841: return err;
2842: }
2843:
2844: 2845: 2846:
2847: LOCAL ER fatSearchDIR_nm(FATFS *fs, DIRINF *dir, UB *utf8nm, W len,
2848: UW mode, UH *realname)
2849: {
2850: FAT_DIRENT *dirent;
2851: UB sfname[BASE_EXTLEN];
2852: W utf16len, enc, cks;
2853: UB smallcaps;
2854: ER err;
2855:
2856:
2857: utf16len = fatEncUtf8strToUtf16str(utf8nm, len,
2858: fs->ff_nmwk, LFN_MAXBUF, TRUE);
2859: if (utf16len <= 0) {
2860: err = EX_INVAL;
2861: goto exit0;
2862: }
2863: if (utf16len > LFN_MAXLEN) {
2864: err = EX_NAMETOOLONG;
2865: goto exit0;
2866: }
2867:
2868:
2869: enc = fatSetSFN(utf8nm, len, sfname, &smallcaps, 0);
2870:
2871:
2872: for (cks = CKSVOID; ; ) {
2873:
2874:
2875: err = fatNextDIR(fs, dir, mode);
2876: if (err < E_OK) break;
2877:
2878: dirent = dir->di_dirent;
2879: if (dirent == NULL ||
2880: isDE_TERM(dirent)) {
2881: dir->di_dirent = NULL;
2882: err = EX_NOENT;
2883: break;
2884: }
2885: if (isDE_FREE(dirent)) {
2886: goto next0;
2887: }
2888: if (isDE_LFN(dirent)) {
2889:
2890: cks = fatChkLFN(fs->ff_nmwk, utf16len,
2891: (FAT_DIRENT_LFN *)dirent, cks, realname);
2892: goto next1;
2893: }
2894: if (isDE_VOL(dirent)) {
2895: goto next0;
2896: }
2897:
2898:
2899: if (fatCalcChksum(dirent->de_fname) == cks) {
2900:
2901: break;
2902: }
2903: if (enc != FAT_CHG_WITH_N &&
2904: memcmp((B*)dirent->de_fname,
2905: (B*)sfname, BASE_EXTLEN) == 0) {
2906:
2907: if (realname != NULL) {
2908: (void)fatGetSFN(dirent->de_fname,
2909: dirent->de_smallcaps, realname);
2910: }
2911: break;
2912: }
2913: next0:
2914: cks = CKSVOID;
2915: next1:
2916: CHK_BREAK_AND_SET_ERR(fs, &err);
2917: if (err < E_OK) break;
2918: }
2919: exit0:
2920: return err;
2921: }
2922:
2923: 2924: 2925:
2926: LOCAL UD fatGetInoDIR(FATFS *fs, DIRINF *dir)
2927: {
2928: W i, ofs, offset;
2929:
2930: if (isFAT_SUBDIR(dir->di_dirent->de_ftype)) {
2931: return dirINO(fs, dirent_to_fcl(fs, dir->di_dirent));
2932: }
2933:
2934: if (dir->di_dircl > 0) {
2935: for (i = 0, ofs = dir->di_dirent_ofs; ;) {
2936: offset = ofs;
2937: ofs -= (W)(dir->di_clno[i].ca_len * DEpCL);
2938: if (++i >= dir->di_len || ofs <= 0) break;
2939: }
2940: return fileINO(fs, dir->di_clno[i - 1].ca_no, offset);
2941: }
2942:
2943: return rootINO(fs, dir->di_dirent_ofs);
2944: }
2945:
2946: 2947: 2948:
2949: LOCAL ER fatGetRootINODE(FATFS *fs, FATNODE ** inodep)
2950: {
2951: FATNODE *inode;
2952: ER err;
2953:
2954: err = E_OK;
2955:
2956: inode = &fs->ff_rootnode;
2957: if (inode->fino_ftype != FAT_SUBDIR) {
2958: inode->fino_c.ino_ino = fs->ff_c.fs_rootino;
2959: inode->fino_c.ino_path = (UB*)inode_root_path;
2960: inode->fino_c.ino_type = DT_DIR;
2961: inode->fino_d_ronly = TRUE;
2962: inode->fino_fclno = fs->ff_rootcl;
2963: inode->fino_ftype = FAT_SUBDIR;
2964:
2965: if (! isFAT32(fs->ff_fstype)) {
2966: inode->fino_filsz = ROOTSZ;
2967: } else {
2968: err = fatGetClusterCount(fs, inode->fino_fclno,
2969: inode, NULL);
2970: if (err < E_OK) inode = NULL;
2971: }
2972: }
2973: *inodep = inode;
2974: return err;
2975: }
2976:
2977: 2978: 2979:
2980: LOCAL ER fatGetINODE(FATFS *fs, DIRINF *dir, UB dtype,
2981: UB *abspath, W len, FATNODE ** inodep)
2982: {
2983: FATNODE *inode;
2984: UD ino;
2985: UB *path;
2986: FAT_DIRENT *dirent;
2987: ER err;
2988:
2989: err = E_OK;
2990: if ((dirent = dir->di_dirent) != NULL) {
2991: ino = fatGetInoDIR(fs, dir);
2992: inode = (FATNODE *)fatInodeSearch((FS *)fs, ino);
2993: } else {
2994: inode = NULL;
2995: ino = NOEXS_INO;
2996: }
2997: if (inode == NULL) {
2998: inode = fimp_calloc(1, sizeof(FATNODE));
2999: if (inode == NULL) {
3000: err = EX_NOMEM;
3001: goto exit0;
3002: }
3003: if (dirent != NULL) {
3004: inode->fino_dirofs = dir->di_offset;
3005: inode->fino_fclno = dirent_to_fcl(fs, dirent);
3006: inode->fino_ftype = dirent->de_ftype;
3007:
3008: if (isFAT_SUBDIR(dirent->de_ftype)) {
3009: inode->fino_c.ino_type = DT_DIR;
3010:
3011: err = fatGetClusterCount(fs, inode->fino_fclno,
3012: inode, NULL);
3013: if (err < E_OK) {
3014: fimp_free(inode);
3015: goto exit0;
3016: }
3017: } else {
3018: inode->fino_c.ino_type = DT_REG;
3019: inode->fino_filsz = (D)
3020: ((UW)CEW(dirent->de_fsize));
3021: }
3022: }
3023: inode->fino_dircl = dir->di_dircl;
3024: inode->fino_d_ronly = isFAT_RDONLY(dtype) ? TRUE : FALSE;
3025: inode->fino_c.ino_ino = ino;
3026: }
3027:
3028:
3029: if (inode->fino_c.ino_type == DT_DIR &&
3030: inode->fino_c.ino_path == NULL) {
3031: path = fimp_malloc(len + 1);
3032: if (path == NULL) {
3033: fimp_free(inode);
3034: err = EX_NOMEM;
3035: goto exit0;
3036: }
3037: inode->fino_c.ino_path = path;
3038: while (--len >= 0) {
3039: *path++ = *abspath++;
3040: }
3041: *path = '\0';
3042: }
3043: if (inode != NULL) {
3044: *inodep = inode;
3045: }
3046: exit0:
3047: return err;
3048: }
3049:
3050: 3051: 3052:
3053:
3054: 3055: 3056:
3057: LOCAL void fatGetDateTime(FAT_DIRENT *dirent, struct stat64_us *sb)
3058: {
3059: struct tm mtim, atim;
3060:
3061: memset(&mtim, 0, sizeof(struct tm));
3062: mtim.tm_sec = (CEH(dirent->de_mtime) & FAT_TIME_MASK_SEC) << 1;
3063: mtim.tm_min = (CEH(dirent->de_mtime) & FAT_TIME_MASK_MIN) >>
3064: FAT_TIME_SHIFT_MIN;
3065: mtim.tm_hour = (CEH(dirent->de_mtime) & FAT_TIME_MASK_HOUR) >>
3066: FAT_TIME_SHIFT_HOUR;
3067: mtim.tm_mday = CEH(dirent->de_mdate) & FAT_TIME_MASK_SEC;
3068: mtim.tm_mon = ((CEH(dirent->de_mdate) & FAT_DATE_MASK_MON) >>
3069: FAT_DATE_SHIFT_MON) - 1;
3070: mtim.tm_year = ((CEH(dirent->de_mdate) & FAT_DATE_MAS_YEAR) >>
3071: FAT_DATE_SHIFT_YEAR) + FATYEAR_TO_TMYEAR;
3072:
3073: memset(&atim, 0, sizeof(struct tm));
3074: atim.tm_mday = CEH(dirent->de_adate) & FAT_TIME_MASK_SEC;
3075: atim.tm_mon = ((CEH(dirent->de_adate) & FAT_DATE_MASK_MON) >>
3076: FAT_DATE_SHIFT_MON) -1;
3077: atim.tm_year = ((CEH(dirent->de_adate) & FAT_DATE_MAS_YEAR) >>
3078: FAT_DATE_SHIFT_YEAR) + FATYEAR_TO_TMYEAR;
3079:
3080: 3081: 3082:
3083:
3084: (void)dt_mktime_us(&mtim, NULL, &sb->st_mtime_u);
3085: (void)dt_mktime_us(&mtim, NULL, &sb->st_ctime_u);
3086: (void)dt_mktime_us(&atim, NULL, &sb->st_atime_u);
3087: }
3088:
3089: 3090: 3091:
3092: LOCAL ER fatSetDateTime(UH *date, UH *time, const SYSTIM_U *stime_u)
3093: {
3094: SYSTIM_U tim_u;
3095: struct tm tm;
3096: UH de_date, de_time;
3097: ER err;
3098:
3099: if (stime_u == NULL) {
3100: (void)tk_get_tim_u(&tim_u, 0);
3101: } else {
3102: tim_u = *stime_u;
3103: }
3104: err = dt_localtime_us(tim_u, NULL, &tm);
3105: if (err >= E_OK) {
3106:
3107: de_date = (UH)( ((tm.tm_year - FATYEAR_TO_TMYEAR) <<
3108: FAT_DATE_SHIFT_YEAR) |
3109: ((tm.tm_mon + 1) << FAT_DATE_SHIFT_MON) |
3110: tm.tm_mday );
3111: de_time = (UH)( (tm.tm_hour << FAT_TIME_SHIFT_HOUR) |
3112: (tm.tm_min << FAT_TIME_SHIFT_MIN) |
3113: (tm.tm_sec >> 1));
3114: *date = CEH(de_date);
3115: *time = CEH(de_time);
3116: }
3117: return err;
3118: }
3119:
3120: 3121: 3122:
3123:
3124: 3125: 3126:
3127: LOCAL ER fatCheckDirent(FATFS *fs, UW dircl, UB *sfname, UW nent)
3128: {
3129: DIRINF dir;
3130: FAT_DIRENT *dirent;
3131: UB nm[BASE_EXTLEN];
3132: W i, exist, existall, gnpos;
3133: ER err;
3134:
3135:
3136: err = fatOpenDIR(fs, &dir, dircl, OFSVOID, AC_RDONLY, NULL);
3137: if (err < E_OK) goto exit0;
3138:
3139:
3140: for (gnpos = BASELEN; sfname[--gnpos] == ' '; );
3141:
3142:
3143: existall = (1 << nent) - 1;
3144: for (exist = 0; exist != existall; ) {
3145:
3146:
3147: err = fatNextDIR(fs, &dir, AC_RDONLY);
3148: if (err < E_OK) break;
3149:
3150: dirent = dir.di_dirent;
3151: if (dirent == NULL ||
3152: isDE_TERM(dirent) ) {
3153: break;
3154: }
3155: if (isDE_FREE(dirent) ||
3156: isDE_LFN(dirent) ||
3157: isDE_VOL(dirent) ) {
3158: continue;
3159: }
3160:
3161:
3162: memcpy(nm, sfname, BASE_EXTLEN);
3163: for (i = 0; i < nent; i++, nm[gnpos] += 1) {
3164: if (isSET(exist, (1 << i)) ||
3165: memcmp(dirent->de_fname, nm, BASE_EXTLEN) != 0)
3166: continue;
3167: exist |= (1 << i);
3168: break;
3169: }
3170: }
3171:
3172:
3173: err = fatCloseDIR(fs, &dir, err);
3174: if (err < E_OK) goto exit0;
3175:
3176: err = E_OK;
3177: if (exist != existall) {
3178: for (i = 0; i < nent && isSET(exist, 1); i++, exist >>= 1);
3179: sfname[gnpos] += i;
3180: err = E_OK + 1;
3181: }
3182: exit0:
3183: return err;
3184: }
3185:
3186: 3187: 3188: 3189: 3190: 3191: 3192:
3193: LOCAL ER fatSearchFreeDirent(FATFS *fs, UW dircl, UW nent, W *ofs)
3194: {
3195: DIRINF dir;
3196: FAT_DIRENT *dirent;
3197: W end, free, offset, freeofs, num, nbyte;
3198: FATNODE *inode;
3199: BOOL found;
3200: CLAD clad;
3201: MapInfo map;
3202: ER err;
3203:
3204:
3205: err = fatOpenDIR(fs, &dir, dircl, 0, AC_WRITE, NULL);
3206: if (err < E_OK) goto exit0;
3207:
3208: for (end = free = 0, freeofs = OFSVOID, found = FALSE;;) {
3209: offset = (W)dir.di_offset;
3210:
3211: dirent = dir.di_dirent;
3212: if (dirent == NULL) {
3213: if (freeofs != OFSVOID) {
3214: offset = freeofs;
3215: found = TRUE;
3216: }
3217: break;
3218: }
3219: if (end > 0 || isDE_TERM(dirent)) {
3220: if (++end >= nent) {
3221: err = fatSetEndDIR(fs, &dir);
3222: if (err >= E_OK) found = TRUE;
3223: break;
3224: }
3225: } else if (isDE_FREE(dirent) && freeofs == OFSVOID) {
3226:
3227: if (++free >= nent) {
3228: freeofs = offset;
3229: #ifdef USE_1ST_FREEENT
3230: found = TRUE;
3231: break;
3232: #endif
3233: }
3234: } else {
3235:
3236: free = 0;
3237: }
3238:
3239: err = fatNextDIR(fs, &dir, AC_WRITE);
3240: if (err < E_OK) break;
3241: }
3242:
3243:
3244: err = fatCloseDIR(fs, &dir, err);
3245: if (err < E_OK) goto exit0;
3246:
3247: if (found != FALSE) goto exit1;
3248:
3249:
3250: inode = dir.di_inode;
3251: if (dircl > 0) {
3252: nbyte = ((W)nent - end) * DIRENTSZ;
3253:
3254:
3255: err = fatGetNewCluster(fs, &clad, fs->ff_nextfree, nbyte);
3256: if (err < E_OK) goto exit0;
3257:
3258:
3259: err = fatGetClusterCount(fs, dircl, NULL, &num);
3260: if (err < E_OK) goto exit0;
3261:
3262: if (((num + clad.ca_len) * fs->ff_clsz) > DIR_SIZE_MAX) {
3263: err = EX_FBIG;
3264: goto exit0;
3265: }
3266:
3267:
3268: if (inode != NULL) {
3269: err = fatExtendClusterList(fs, &clad, inode);
3270: if (err < E_OK) goto exit0;
3271:
3272: inode->fino_filsz += (fs->ff_clsz * clad.ca_len);
3273: if (inode->fino_filsz > FILE_SIZE_MAX) {
3274: inode->fino_filsz = FILE_SIZE_MAX;
3275: }
3276: } else {
3277: err = fatChainCluster(fs, dircl, &clad, NULL);
3278: }
3279:
3280:
3281: err = fatMapDisk(fs, &clad, 1, &map, MAP_C | MAP_CLR,(VW)inode);
3282: fatUnmapDisk(&map);
3283:
3284:
3285: offset += nbyte;
3286:
3287: } else {
3288: 3289:
3290: err = EX_NOSPC;
3291: goto exit0;
3292: }
3293: exit1:
3294: *ofs = offset;
3295: exit0:
3296: return err;
3297: }
3298:
3299: 3300: 3301:
3302: LOCAL ER fatInitDirent(FATFS *fs, FAT_DIRENT *dirent, FATNODE *inode)
3303: {
3304: UH date, time;
3305: MapInfo map;
3306: CLAD clad;
3307: FAT_DIRENT *de;
3308: ER err;
3309:
3310:
3311: err = fatSetDateTime(&date, &time, NULL);
3312: if (err < E_OK) goto exit0;
3313:
3314:
3315: memset(dirent, 0, sizeof(FAT_DIRENT));
3316: dirent->de_ftype = inode->fino_ftype | FAT_ARCHIV;
3317:
3318: dirent->de_adate = date;
3319: dirent->de_ctime = time;
3320: dirent->de_cdate = date;
3321: dirent->de_mdate = date;
3322: dirent->de_mtime = time;
3323:
3324:
3325: if (! isFAT_SUBDIR(inode->fino_ftype)) goto exit0;
3326:
3327:
3328: err = fatApdNewCluster(fs, &clad, fs->ff_clsz, inode);
3329: if (err < E_OK) goto exit0;
3330:
3331: inode->fino_filsz = fs->ff_clsz;
3332: inode->fino_fclno = clad.ca_no;
3333: fcl_to_dirent(fs, dirent, inode->fino_fclno);
3334:
3335:
3336: err = fatMapDisk(fs, &clad, 1, &map, MAP_C | MAP_CLR, (VW)inode);
3337: if (err < E_OK) goto exit1;
3338:
3339:
3340: de = (FAT_DIRENT *)&map.m_page->dcp_buf[
3341: OFFSETinPAGE(fs, map.m_page, CNtoBN(clad.ca_no), 0)];
3342: memcpy(de->de_fname, nmDOT, BASE_EXTLEN);
3343: de->de_ftype = FAT_SUBDIR;
3344: de->de_smallcaps = 0;
3345: de->de_rsv[0] = 0;
3346: de->de_adate = date;
3347: de->de_ctime = time;
3348: de->de_cdate = date;
3349: de->de_mtime = time;
3350: de->de_mdate = date;
3351: de->de_fsize = 0;
3352: fcl_to_dirent(fs, de, inode->fino_fclno);
3353:
3354:
3355: de++;
3356: memcpy(de->de_fname, nmDOT2, BASE_EXTLEN);
3357: de->de_ftype = FAT_SUBDIR;
3358: de->de_smallcaps = 0;
3359: de->de_rsv[0] = 0;
3360: de->de_adate = date;
3361: de->de_ctime = time;
3362: de->de_cdate = date;
3363: de->de_mtime = time;
3364: de->de_mdate = date;
3365: de->de_fsize = 0;
3366: fcl_to_dirent(fs, de, inode->fino_dircl);
3367:
3368: err = fatDCacheUpdate(fs, map.m_page, (VW)inode);
3369: (void)fatMapEnd(&map);
3370: exit1:
3371: fatUnmapDisk(&map);
3372: exit0:
3373: return err;
3374: }
3375:
3376: 3377: 3378:
3379: LOCAL ER fatCopyDirent(FATFS *fs, FAT_DIRENT *from, FAT_DIRENT *to,
3380: FATNODE *inode)
3381: {
3382: DIRINF dir;
3383: ER err;
3384:
3385: err = E_OK;
3386:
3387:
3388: memset(to, 0, sizeof(FAT_DIRENT));
3389: to->de_ftype = from->de_ftype | FAT_ARCHIV;
3390: to->de_adate = from->de_adate;
3391: to->de_ctime = from->de_ctime;
3392: to->de_cdate = from->de_cdate;
3393: to->de_mtime = from->de_mtime;
3394: to->de_mdate = from->de_mdate;
3395: to->de_clno_hi = from->de_clno_hi;
3396: to->de_clno_lo = from->de_clno_lo;
3397: to->de_fsize = from->de_fsize;
3398:
3399:
3400: if (! isFAT_SUBDIR(inode->fino_ftype)) goto exit0;
3401:
3402:
3403: err = fatOpenDIR(fs, &dir, inode->fino_fclno, OFSVOID, AC_WRITE, inode);
3404: if (err < E_OK) goto exit0;
3405:
3406:
3407: err = fatSearchDIR_nm(fs, &dir, (UB*)nmDOT2, 2, AC_WRITE, NULL);
3408: if (err >= E_OK) {
3409: fcl_to_dirent(fs, dir.di_dirent, inode->fino_dircl);
3410: err = fatWriteCurDIR(fs, &dir, 0);
3411: }
3412:
3413:
3414: err = fatCloseDIR(fs, &dir, err);
3415: exit0:
3416: return err;
3417: }
3418:
3419: 3420: 3421:
3422: LOCAL ER fatUpdateFileSystem(FATFS *fs)
3423: {
3424: FAT_FSINFO *fsi;
3425: DCachePage *page;
3426: ER err;
3427:
3428: err = E_OK;
3429:
3430:
3431: if (fs->ff_fsinfo > 0) {
3432:
3433:
3434: err = fatDCacheStart(fs, fs->ff_fsinfo, &page);
3435: if (err < E_OK) goto exit0;
3436:
3437: fsi = (FAT_FSINFO *)&page->dcp_buf[
3438: OFFSETinPAGE(fs, page, fs->ff_fsinfo, 0)];
3439:
3440:
3441: if ( fsi->fsi_freecl != CEW(fs->ff_freecl) ||
3442: fsi->fsi_nextfree != CEW(fs->ff_nextfree) ) {
3443:
3444:
3445: fsi->fsi_freecl = CEW(fs->ff_freecl);
3446:
3447:
3448: fsi->fsi_nextfree = CEW(fs->ff_nextfree);
3449:
3450: (void)fatDCacheUpdate(fs, page, 0);
3451: err = fatDCacheEnd(fs, page);
3452: }
3453: }
3454: exit0:
3455: return err;
3456: }
3457:
3458: 3459: 3460:
3461: LOCAL ER fatUpdateFile(FATFS *fs, FATNODE *inode)
3462: {
3463: DIRINF dir;
3464: UH date, time;
3465: ER err;
3466:
3467:
3468: err = fatSetDateTime(&date, &time, NULL);
3469: if (err < E_OK) goto exit0;
3470:
3471:
3472: err = fatOpenDIR(fs, &dir, inode->fino_dircl,
3473: (W)inode->fino_dirofs, AC_WRITE, NULL);
3474: if (err < E_OK) goto exit0;
3475:
3476: if (dir.di_dirent == NULL) {
3477: err = EX_NOENT;
3478: } else {
3479: dir.di_dirent->de_fsize = (W)CEW(inode->fino_filsz);
3480: dir.di_dirent->de_ftype |= FAT_ARCHIV;
3481: fcl_to_dirent(fs, dir.di_dirent, inode->fino_fclno);
3482: dir.di_dirent->de_mdate = date;
3483: dir.di_dirent->de_mtime = time;
3484: err = fatWriteCurDIR(fs, &dir, (VW)inode);
3485: }
3486:
3487: err = fatCloseDIR(fs, &dir, err);
3488: if (err >= E_OK) {
3489:
3490: (void)fatUpdateFileSystem(fs);
3491: }
3492: exit0:
3493: return err;
3494: }
3495:
3496: 3497: 3498:
3499: LOCAL ER fatGetParentDirectory(FATFS *fs, W *dircl, FATNODE *inode)
3500: {
3501: ER err;
3502: DIRINF dir;
3503:
3504:
3505: err = fatOpenDIR(fs, &dir, *dircl, OFSVOID, AC_RDONLY, inode);
3506: if (err < E_OK) return err;
3507:
3508:
3509: err = fatSearchDIR_nm(fs, &dir, (UB*)nmDOT2, 2, AC_RDONLY, NULL);
3510: if (err >= E_OK) {
3511:
3512: *dircl = (W)dirent_to_fcl(fs, dir.di_dirent);
3513: }
3514:
3515: return fatCloseDIR(fs, &dir, err);
3516: }
3517:
3518: 3519: 3520:
3521: LOCAL ER fatUpdateDirectory(FATFS *fs, FATNODE *inode)
3522: {
3523: DIRINF dir;
3524: FATNODE *din;
3525: W dircl;
3526: UH date, time;
3527: ER err;
3528:
3529: dircl = 0;
3530:
3531:
3532: if (inode->fino_dircl == fs->ff_rootcl) goto exit0;
3533:
3534:
3535: din = (FATNODE *)fatInodeSearch((FS*)fs, dirINO(fs, inode->fino_dircl));
3536:
3537:
3538: err = fatSetDateTime(&date, &time, NULL);
3539: if (err < E_OK) goto exit0;
3540:
3541:
3542: dircl = inode->fino_dircl;
3543: err = fatGetParentDirectory(fs, &dircl, din);
3544: if (err < E_OK) goto exit0;
3545:
3546:
3547: err = fatOpenDIR(fs, &dir, (UW)dircl, OFSVOID, AC_WRITE, NULL);
3548: if (err < E_OK) goto exit0;
3549:
3550:
3551: err = fatSearchDIR_cl(fs, &dir, inode->fino_dircl, AC_WRITE);
3552: if (err >= E_OK) {
3553: dir.di_dirent->de_mdate = date;
3554: dir.di_dirent->de_mtime = time;
3555: err = fatWriteCurDIR(fs, &dir, (VW)inode);
3556: }
3557:
3558: err = fatCloseDIR(fs, &dir, err);
3559: exit0:
3560:
3561: (void)fatUpdateFileSystem(fs);
3562: return E_OK;
3563: }
3564:
3565: 3566: 3567:
3568: LOCAL ER fatCheckSubDirectory(FATFS *fs, FATNODE *from, FATNODE *to)
3569: {
3570: W dircl;
3571: ER err;
3572:
3573: err = E_OK;
3574:
3575: if (isFAT_SUBDIR(from->fino_ftype)) {
3576: for (dircl = to->fino_dircl; ;) {
3577:
3578: if (dircl == from->fino_fclno) {
3579: err = EX_INVAL;
3580: break;
3581: }
3582:
3583: if (dircl == fs->ff_rootcl) break;
3584:
3585:
3586: err = fatGetParentDirectory(fs, &dircl, NULL);
3587: if (err < E_OK) break;
3588: }
3589: }
3590: return err;
3591: }
3592:
3593: 3594: 3595: 3596:
3597: LOCAL ER fatCreateFile(FATFS *fs, FATNODE *inode, UB *utf8nm,
3598: FAT_DIRENT *rename)
3599: {
3600: UB sfname[BASE_EXTLEN];
3601: W utf8len, utf16len, ofs;
3602: W gen, idx, nent, enc;
3603: UB smallcaps, chksum;
3604: DIRINF dir;
3605: FAT_DIRENT *dirent;
3606: ER err;
3607:
3608: err = E_OK;
3609:
3610:
3611: utf8len = strlen((B*)utf8nm);
3612: while (utf8nm[utf8len - 1] == ' ' ||
3613: utf8nm[utf8len - 1] == '.') utf8len--;
3614:
3615:
3616: utf16len = fatEncUtf8strToUtf16str(utf8nm, utf8len,
3617: fs->ff_nmbf, LFN_MAXBUF, FALSE);
3618: if (utf16len <= 0) {
3619: err = EX_INVAL;
3620: goto exit1;
3621: }
3622: if (utf16len > LFN_MAXLEN) {
3623: err = EX_NAMETOOLONG;
3624: goto exit1;
3625: }
3626:
3627:
3628: smallcaps = 0x00;
3629: for (nent = 1, gen = 1; ; ) {
3630:
3631:
3632: enc = fatSetSFN(utf8nm, utf8len, sfname, &smallcaps, gen);
3633: if (enc == FAT_SAME_NAME) break;
3634:
3635: smallcaps = 0x00;
3636:
3637: 3638:
3639: err = fatCheckDirent(fs, inode->fino_dircl, sfname,
3640: (enc == FAT_CHG_WITH_N) ? 9 : 1);
3641: if (err < E_OK) break;
3642: if (err > E_OK) {
3643: nent += (utf16len + LFN_CHARS - 1) / LFN_CHARS;
3644: break;
3645: }
3646:
3647: gen += 10;
3648: }
3649:
3650:
3651: err = fatSearchFreeDirent(fs, inode->fino_dircl, (UW)nent, &ofs);
3652: if (err < E_OK) goto exit1;
3653:
3654:
3655: inode->fino_dirofs = (UW)ofs;
3656:
3657:
3658: err = fatOpenDIR(fs, &dir, inode->fino_dircl, (W)inode->fino_dirofs,
3659: AC_WRITE, NULL);
3660: if (err < E_OK) goto exit1;
3661:
3662: if (dir.di_dirent == NULL) {
3663: err = EX_NOENT;
3664: goto exit2;
3665: }
3666:
3667:
3668: dirent = dir.di_dirent;
3669: if (rename != NULL) {
3670: err = fatCopyDirent(fs, rename, dirent, inode);
3671: } else {
3672: err = fatInitDirent(fs, dirent, inode);
3673: }
3674: if (err < E_OK) goto exit2;
3675:
3676: dirent->de_smallcaps = smallcaps;
3677: memcpy(dirent->de_fname, sfname, BASE_EXTLEN);
3678: inode->fino_c.ino_ino = fatGetInoDIR(fs, &dir);
3679: inode->fino_c.ino_type =
3680: isFAT_SUBDIR(inode->fino_ftype) ? DT_DIR : DT_REG;
3681: err = fatWriteCurDIR(fs, &dir, (VW)inode);
3682: if (err < E_OK) goto exit2;
3683:
3684:
3685: if (nent > 1) {
3686:
3687: chksum = fatCalcChksum(sfname);
3688:
3689: for (idx = 1; idx < nent; idx++) {
3690:
3691: err = fatPrevDIR(fs, &dir, AC_WRITE);
3692: if (err < E_OK) break;
3693:
3694: fatSetLFN(fs->ff_nmbf, utf16len,
3695: (FAT_DIRENT_LFN *)dir.di_dirent, idx, chksum);
3696: err = fatWriteCurDIR(fs, &dir, (VW)inode);
3697: if (err < E_OK) break;
3698: }
3699: }
3700: exit2:
3701:
3702: err = fatCloseDIR(fs, &dir, err);
3703: exit1:
3704: return err;
3705: }
3706:
3707: 3708: 3709:
3710: LOCAL ER fatRemoveFile(FATFS *fs, FATNODE *inode)
3711: {
3712: DIRINF dir;
3713: ER err;
3714:
3715:
3716: err = fatOpenDIR(fs, &dir, inode->fino_dircl, (W)inode->fino_dirofs,
3717: AC_WRITE, NULL);
3718: if (err < E_OK) goto exit0;
3719:
3720: if (dir.di_dirent == NULL) {
3721: err = EX_NOENT;
3722: goto exit0;
3723: }
3724:
3725:
3726: dir.di_dirent->de_fname[0] = DE_B0_FREE;
3727: err = fatWriteCurDIR(fs, &dir, (VW)inode);
3728: if (err < E_OK) goto exit0;
3729:
3730:
3731: for (;;) {
3732: if (dir.di_offset == 0) break;
3733:
3734:
3735: err = fatPrevDIR(fs, &dir, AC_WRITE);
3736: if (err < E_OK) break;
3737:
3738: if (! isDE_LFN(dir.di_dirent)) break;
3739:
3740:
3741: dir.di_dirent->de_fname[0] = DE_B0_FREE;
3742: err = fatWriteCurDIR(fs, &dir, (VW)inode);
3743: if (err < E_OK) break;
3744: }
3745:
3746:
3747: err = fatCloseDIR(fs, &dir, err);
3748: if (err >= E_OK) {
3749:
3750: err = fatTruncClusterList(fs, 0, inode);
3751: }
3752: exit0:
3753: return err;
3754: }
3755:
3756: 3757: 3758:
3759: LOCAL ER fatExtendFile(FATFS *fs, FATNODE *inode, D size)
3760: {
3761: CLAD clad[MAX_CLEN];
3762: MapInfo map;
3763: D fsz, incsz;
3764: W cllen, ofs, i;
3765: UW clsz;
3766: ER err;
3767:
3768: err = E_OK;
3769:
3770:
3771: fsz = (UW)inode->fino_filsz;
3772: if (fsz >= size) goto exit0;
3773:
3774:
3775: if (BYTEtoCL(size) - BYTEtoCL(fsz) > fs->ff_freecl) {
3776: err = EX_NOSPC;
3777: goto exit0;
3778: }
3779:
3780:
3781: for (ofs = fsz % fs->ff_clsz; (incsz = size - fsz) > 0; ofs = 0) {
3782:
3783:
3784: err = fatCopyClusterList(fs, clad, fsz, incsz, inode, &cllen);
3785: if (err < E_OK) goto exit0;
3786:
3787:
3788:
3789: if (cllen <= 0) {
3790: err = fatApdNewCluster(fs, &clad[0], incsz, inode);
3791: if (err < E_OK) goto exit0;
3792: cllen = 1;
3793: }
3794:
3795:
3796: err = fatMapDisk(fs, clad, cllen, &map, MAP_C |
3797: ((ofs > 0) ? 0 : MAP_CLR), (VW)inode);
3798: if (err >= E_OK && ofs > 0) {
3799:
3800: err = fatMapWriteBytes(&map, ofs, NULL,
3801: (incsz < fs->ff_clsz - ofs) ?
3802: incsz : fs->ff_clsz - ofs);
3803: (void)fatMapEnd(&map);
3804: }
3805: fatUnmapDisk(&map);
3806: if (err < E_OK) break;
3807:
3808:
3809: for (clsz = 0, i = 0; i < cllen; i++) clsz += clad[i].ca_len;
3810: fsz += clsz * fs->ff_clsz - ofs;
3811: }
3812:
3813:
3814: inode->fino_filsz = size;
3815: err = fatUpdateFile(fs, inode);
3816: exit0:
3817: return err;
3818: }
3819:
3820: 3821: 3822:
3823: LOCAL ER fatTruncateFile(FATFS *fs, FATNODE *inode, D size)
3824: {
3825: ER err;
3826:
3827: err = E_OK;
3828: if (size < inode->fino_filsz) {
3829:
3830: err = fatTruncClusterList(fs, size, inode);
3831: if (err >= E_OK) {
3832:
3833: err = fatUpdateFile(fs, inode);
3834: }
3835: }
3836: return err;
3837: }
3838:
3839: 3840: 3841:
3842: LOCAL ER fatChkEmptyDirectory(FATFS *fs, FATNODE *inode)
3843: {
3844: DIRINF dir;
3845: FAT_DIRENT *dirent;
3846: ER err;
3847:
3848:
3849: err = fatOpenDIR(fs, &dir, inode->fino_fclno, OFSVOID,
3850: AC_RDONLY, inode);
3851: if (err < E_OK) goto exit0;
3852:
3853: for (;;) {
3854:
3855: err = fatNextDIR(fs, &dir, AC_RDONLY);
3856: if (err < E_OK) break;
3857:
3858: dirent = dir.di_dirent;
3859: if (dirent == NULL ||
3860: isDE_TERM(dirent)) {
3861: break;
3862: }
3863: if (isDE_FREE(dirent) ||
3864: isDE_LFN(dirent) ||
3865: isDE_VOL(dirent) ) {
3866: continue;
3867: }
3868:
3869: if (memcmp(dirent->de_fname, nmDOT, BASE_EXTLEN) != 0 &&
3870: memcmp(dirent->de_fname, nmDOT2, BASE_EXTLEN) != 0) {
3871: err = EX_NOTEMPTY;
3872: break;
3873: }
3874: }
3875:
3876:
3877: err = fatCloseDIR(fs, &dir, err);
3878: exit0:
3879: return err;
3880: }
3881:
3882: 3883: 3884:
3885: LOCAL ER fatGetAttr64us(FATFS *fs, FATNODE *inode,
3886: struct stat64_us *sb)
3887: {
3888: ER err;
3889: UB ftyp;
3890:
3891: err = E_OK;
3892: memset(sb, 0, sizeof(struct stat64_us));
3893:
3894:
3895: sb->st_dev = (dev_t)fs->ff_c.fs_devnum;
3896:
3897: 3898:
3899: sb->st_ino = (ino_t)inode->fino_c.ino_ino;
3900:
3901:
3902: ftyp = inode->fino_ftype;
3903: sb->st_mode = DEFAULT_FILMODE;
3904: if (! isFAT_RDONLY(ftyp)) {
3905: sb->st_mode |= FILMODE_WRITE;
3906: }
3907: sb->st_mode |= isFAT_SUBDIR(ftyp) ? S_IFDIR : S_IFREG;
3908:
3909:
3910: sb->st_nlink = 1;
3911:
3912:
3913:
3914:
3915:
3916: sb->st_size = inode->fino_filsz;
3917:
3918:
3919: if (! IsRootINODE(fs, inode)) {
3920: DIRINF dir;
3921:
3922: err = fatOpenDIR(fs, &dir, inode->fino_dircl,
3923: (W)inode->fino_dirofs, AC_RDONLY, NULL);
3924: if (err >= E_OK) {
3925: if (dir.di_dirent == NULL) {
3926: err = EX_NOENT;
3927: } else {
3928: fatGetDateTime(dir.di_dirent, sb);
3929: }
3930:
3931: err = fatCloseDIR(fs, &dir, err);
3932: }
3933: }
3934:
3935:
3936:
3937:
3938: sb->st_blksize = fs->ff_clsz;
3939:
3940:
3941: if (inode->fino_fclno > 0) {
3942: W num = 0;
3943:
3944: if (isFAT_SUBDIR(ftyp)) {
3945: err = fatGetClusterCount(fs, inode->fino_fclno,
3946: NULL, &num);
3947: } else {
3948: num = BYTEtoCL(inode->fino_filsz);
3949: }
3950: sb->st_blocks = (blkcnt_t)num;
3951: }
3952: return err;
3953: }
3954:
3955: 3956: 3957:
3958: LOCAL ER fatCheckPartitionID(FATFS *fs, FATFSType *fstype)
3959: {
3960: DiskPartInfo inf;
3961: ER err;
3962:
3963: *fstype = 0;
3964:
3965:
3966: err = fatDiskRead(fs, DN_DISKPARTINFO, (B*)&inf, sizeof(inf));
3967: if (err < E_OK) {
3968: if (err == E_NOSPT || err == E_PAR) err = E_OK;
3969: } else {
3970: switch (inf.systemid) {
3971: case DSID_DOS1:
3972:
3973: break;
3974: case DSID_DOS2:
3975:
3976: break;
3977: case DSID_DOS3:
3978:
3979: break;
3980: case DSID_DOS3L:
3981:
3982: break;
3983: case DSID_WIN95:
3984: *fstype = FAT32;
3985: break;
3986: case DSID_WIN95L:
3987: *fstype = FAT32;
3988: break;
3989: default:
3990: err = EX_NOTSUP;
3991: break;
3992: }
3993: }
3994: return err;
3995: }
3996:
3997: 3998: 3999:
4000: LOCAL ER fatCheckFileSystem(FATFS *fs)
4001: {
4002: FAT_BOOTSEC *boot;
4003: FAT_FSINFO *fsi;
4004: FATFSType fstype;
4005: UB *blkbuf;
4006: UW dsksz, secsz, rsvsc, nfat;
4007: UH fsinfo;
4008: ER err;
4009:
4010:
4011: if ((blkbuf = fimp_malloc(DSECSZ(fs))) == NULL) {
4012: err = EX_NOMEM;
4013: goto exit0;
4014: }
4015:
4016:
4017: err = fatCheckPartitionID(fs, &fstype);
4018: if (err < E_OK) goto exit1;
4019:
4020:
4021: boot = (FAT_BOOTSEC *)blkbuf;
4022: err = fatDiskRead(fs, 0, boot, BPB_READ_SIZE);
4023: if (err < E_OK) goto exit1;
4024:
4025:
4026: err = EX_NOTSUP;
4027: if ( (((UB *)boot)[BPB_TAILSIGN_OFS1] != BPB_TAILSIGN_VAL1) ||
4028: (((UB *)boot)[BPB_TAILSIGN_OFS2] != BPB_TAILSIGN_VAL2)) {
4029: goto exit1;
4030: }
4031:
4032:
4033: secsz = CEH(GetMisalignH(boot->bo_scsz));
4034: fs->ff_ratio = boot->bo_clsz;
4035: fs->ff_clsz = (UH)(secsz * fs->ff_ratio);
4036: rsvsc = CEH(GetMisalignH(boot->bo_rsvsc));
4037: nfat = boot->bo_nfat;
4038: fs->ff_fatsz = CEH(boot->bo_fatsz);
4039: if (fs->ff_fatsz == 0) {
4040: fs->ff_fatsz = ((UW)CEH(boot-> bo_fatsz_hi) << BPB_SHIFT_FATSZ)
4041: | (UW)CEH(boot->bo_fatsz_lo);
4042: }
4043: dsksz = CEH(GetMisalignH(boot->bo_dsksz));
4044: if (dsksz == 0) {
4045: dsksz = ((UW)CEH(boot->bo_dsksz_hi) << BPB_SHIFT_DSKSZ) |
4046: (UW)CEH(boot->bo_dsksz_lo);
4047: }
4048:
4049: if (secsz <= 0 || (W)secsz != DSECSZ(fs) ||
4050: fs->ff_ratio <= 0 || (W)dsksz > fs->ff_c.fs_diskinfo.blockcont) {
4051: goto exit1;
4052: }
4053:
4054: fs->ff_rootent = CEH(GetMisalignH(boot->bo_rootent));
4055: fs->ff_fat = rsvsc;
4056:
4057: CHK_AGAIN:
4058:
4059: if (isFAT32(fstype)) {
4060: fs->ff_rootcl = ((UW)CEH(boot->bo_root_hi) <<
4061: BPB_SHIFT_ROOT_HI) | (UW)CEH(boot->bo_root_lo);
4062: if ((boot->bo_extflg & FAT_NoFATMirror) != 0) {
4063: fs->ff_fat += (boot->bo_extflg & FAT_ActiveFAT) *
4064: fs->ff_fatsz;
4065: fs->ff_nfat = 1;
4066: } else {
4067: fs->ff_nfat = (UB)nfat;
4068: }
4069: fsinfo = CEH(boot->bo_fsinfo);
4070: }
4071:
4072: else {
4073: fs->ff_rootcl = 0;
4074: fs->ff_nfat = (UB)nfat;
4075: fsinfo = 0;
4076: }
4077:
4078:
4079: if (isFAT32(fstype)) {
4080: fs->ff_rootsc = 0;
4081: fs->ff_clstart = rsvsc + (fs->ff_fatsz * nfat);
4082: } else {
4083: fs->ff_rootsc = rsvsc + (fs->ff_fatsz * nfat);
4084: fs->ff_clstart = (UW)(fs->ff_rootsc +
4085: (ROOTSZ + secsz - 1) / secsz);
4086: }
4087:
4088:
4089: fs->ff_lastcl = ((dsksz - fs->ff_clstart) / fs->ff_ratio) + 1;
4090:
4091:
4092: if (fstype == 0) {
4093: if (fs->ff_lastcl < FAT12_EOC) {
4094: fstype = FAT12;
4095: } else if (fs->ff_lastcl < FAT16_EOC) {
4096: fstype = FAT16;
4097: } else {
4098: fstype = FAT32;
4099: goto CHK_AGAIN;
4100: }
4101: }
4102:
4103: fs->ff_fstype = fstype;
4104: fs->ff_fsinfo = 0;
4105:
4106:
4107: if (fsinfo > 0) {
4108:
4109: fsi = (FAT_FSINFO *)blkbuf;
4110: err = fatDiskRead(fs, fsinfo, fsi, FSINFO_READ_SIZE);
4111: if (err < E_OK) goto exit1;
4112:
4113:
4114: if ( fsi->fsi_leadsig == CEW(FSINFO_LEADSIGN_VAL) &&
4115: fsi->fsi_structsig == CEW(FSINFO_STRUCTSIGN_VAL) &&
4116: fsi->fsi_trailsig == CEW(FSINFO_TAILSIGN_VAL)) {
4117: fs->ff_fsinfo = fsinfo;
4118:
4119: 4120:
4121:
4122:
4123: fs->ff_nextfree = fsi->fsi_nextfree;
4124: }
4125: }
4126: err = E_OK;
4127: exit1:
4128: fimp_free(blkbuf);
4129: exit0:
4130: return err;
4131: }
4132:
4133: 4134: 4135:
4136: LOCAL void fatResetCurdir(FS *fs)
4137: {
4138: CDINF *curdir;
4139: INODE *rootinode;
4140:
4141: curdir = &fs->fs_uxinfo.uxi_curdir;
4142:
4143: if (! IsRootINODE(fs, curdir->cd_inode)) {
4144:
4145: (void)fatGetRootINODE((FATFS *)fs, (FATNODE **)&rootinode);
4146: fatInodeRegister(fs, rootinode, O_RDONLY);
4147: 4148:
4149: fs->fs_uxinfo.uxi_relino = curdir->cd_inode;
4150: curdir->cd_inode = rootinode;
4151: }
4152: }
4153:
4154: 4155: 4156:
4157: LOCAL BOOL fatCheckIsInodeBusy(FS *fs, INODE *inode)
4158: {
4159: if (inode->ino_refcnt <= 0) return FALSE;
4160:
4161: if (inode == fs->fs_uxinfo.uxi_curdir.cd_inode &&
4162: inode->ino_refcnt == 1) {
4163:
4164: fatResetCurdir(fs);
4165: return FALSE;
4166: }
4167: return TRUE;
4168: }
4169:
4170: 4171: 4172:
4173: LOCAL ER fatUpdateAccessDate(FATFS *fs, FATNODE *inode)
4174: {
4175: DIRINF dir;
4176: UH date, time;
4177: ER err;
4178:
4179: err = E_OK;
4180: if (LastAccess != FALSE && fs->ff_c.fs_rdonly == FALSE &&
4181: ! IsRootINODE(fs, inode)) {
4182:
4183: err = fatSetDateTime(&date, &time, NULL);
4184: if (err < E_OK) goto exit0;
4185:
4186:
4187: err = fatOpenDIR(fs, &dir, inode->fino_dircl,
4188: (W)inode->fino_dirofs, AC_WRITE, NULL);
4189: if (err < E_OK) goto exit0;
4190:
4191:
4192: if (dir.di_dirent != NULL && dir.di_dirent->de_adate != date){
4193: dir.di_dirent->de_adate = date;
4194: err = fatWriteCurDIR(fs, &dir, (VW)inode);
4195: }
4196:
4197:
4198: err = fatCloseDIR(fs, &dir, err);
4199: }
4200: exit0:
4201: return err;
4202: }
4203:
4204: 4205: 4206:
4207:
4208: 4209: 4210:
4211: LOCAL ER fat_lookup(FATFS *fs, LPINF *lp, const B *r_path)
4212: {
4213: CDINF *curdir;
4214: FATNODE *inode;
4215: DIRINF dir;
4216: UB *path, *cpath, *npath;
4217: UW len, dcl;
4218: UB dtp;
4219: ER err;
4220:
4221: err = E_OK;
4222: cpath = path = (UB*)&r_path[fs->ff_c.fs_conlen];
4223:
4224:
4225: if (path[0] == '\0') {
4226: (void)fatGetRootINODE(fs, &inode);
4227: goto exit1;
4228: }
4229:
4230:
4231: curdir = &fs->ff_c.fs_uxinfo.uxi_curdir;
4232: len = strlen((B*)curdir->cd_inode->ino_path);
4233:
4234: if (fat_strncasecmp(curdir->cd_inode->ino_path, path, len) == 0
4235: && (path[len] == '\0' || path[len] == '/')) {
4236:
4237: if (path[len] == '\0') {
4238:
4239: if ((cpath = (UB*)strrchr((B*)path, '/')) != NULL) cpath++;
4240: else cpath = path;
4241: inode = (FATNODE*)curdir->cd_inode;
4242: goto exit1;
4243: }
4244:
4245: dcl = dirCLNO(fs, curdir->cd_inode->ino_ino);
4246: cpath += len + 1;
4247: } else {
4248:
4249: dcl = fs->ff_rootcl;
4250: cpath += 1;
4251: }
4252:
4253:
4254: dtp = FAT_SUBDIR;
4255: dir.di_dirent = NULL;
4256: for ( ; (npath = (UB*)strchr((B*)cpath, '/')) != NULL; cpath = npath + 1) {
4257:
4258:
4259: err = fatOpenDIR(fs, &dir, dcl, OFSVOID, AC_RDONLY, NULL);
4260: if (err < E_OK) break;
4261:
4262:
4263: err = fatSearchDIR_nm(fs, &dir, cpath,
4264: npath - cpath, AC_RDONLY, NULL);
4265: if (err >= E_OK) {
4266: if (isFAT_SUBDIR(dir.di_dirent->de_ftype)) {
4267:
4268: dcl = dirent_to_fcl(fs, dir.di_dirent);
4269: dtp = dir.di_dirent->de_ftype;
4270: } else {
4271: dir.di_dirent = NULL;
4272: err = EX_NOTDIR;
4273: }
4274: }
4275:
4276: err = fatCloseDIR(fs, &dir, err);
4277:
4278: CHK_BREAK_AND_SET_ERR(fs, &err);
4279: if (err < E_OK) break;
4280: }
4281: if (err < E_OK) goto exit0;
4282:
4283: if (dir.di_dirent != NULL) {
4284: err = fatGetINODE(fs, &dir, dtp, path, cpath - path -1, &inode);
4285: if (err >= E_OK && curdir->cd_inode != (INODE*)inode) {
4286:
4287: fatInodeRegister((FS*)fs, (INODE*)inode, O_RDONLY);
4288: fatInodeRelease((FS*)fs, curdir->cd_inode, O_RDONLY);
4289: curdir->cd_inode = (INODE*)inode;
4290: }
4291: CHK_BREAK_AND_SET_ERR(fs, &err);
4292: }
4293: if (err < E_OK) goto exit0;
4294:
4295:
4296: err = fatOpenDIR(fs, &dir, dcl, OFSVOID, AC_RDONLY, NULL);
4297: if (err < E_OK) goto exit0;
4298:
4299:
4300: inode = NULL;
4301: err = fatSearchDIR_nm(fs, &dir, cpath, strlen((B*)cpath), AC_RDONLY, NULL);
4302: if (err >= E_OK || err == EX_NOENT) {
4303: err = fatGetINODE(fs, &dir, dtp, path, strlen((B*)path), &inode);
4304: }
4305:
4306:
4307: err = fatCloseDIR(fs, &dir, err);
4308: if (err < E_OK) {
4309:
4310: if (inode != NULL && inode->fino_c.ino_refcnt == 0) {
4311: fatInodeFree((FS*)fs, (INODE*)inode);
4312: }
4313: } else {
4314: exit1:
4315: lp->lp_inode = (INODE*)inode;
4316: lp->lp_path = cpath;
4317: }
4318: CHK_BREAK_AND_SET_ERR(fs, &err);
4319: exit0:
4320: return err;
4321: }
4322:
4323: 4324: 4325:
4326: LOCAL ER fat_truncate64(FATFS *fs, FATNODE *inode, D size)
4327: {
4328: ER err;
4329:
4330: if (isFAT_RDONLY(inode->fino_ftype)) {
4331: err = EX_ACCES;
4332: } else if (size > FILE_SIZE_MAX) {
4333: err = EX_FBIG;
4334: } else if (size < 0) {
4335: err = EX_INVAL;
4336: } else if (size > inode->fino_filsz) {
4337: err = fatExtendFile(fs, inode, size);
4338: } else {
4339: err = fatTruncateFile(fs, inode, size);
4340: }
4341: return err;
4342: }
4343:
4344: 4345: 4346:
4347: LOCAL ER fat_ftruncate64(FD *fd, D size)
4348: {
4349: return fat_truncate64((FATFS*)fd->fd_fs, (FATNODE*)fd->fd_inode, size);
4350: }
4351:
4352: 4353: 4354:
4355: LOCAL ER fat_utimes_us(FATFS *fs, FATNODE *inode,
4356: const SYSTIM_U times_u[2])
4357: {
4358: DIRINF dir;
4359: UH date[2], time[2];
4360: ER err;
4361:
4362: err = E_OK;
4363:
4364: if (IsRootINODE(fs, inode)) goto exit0;
4365:
4366:
4367: err = fatSetDateTime(&date[0], &time[0], ×_u[0]);
4368: if (err >= E_OK) {
4369: err = fatSetDateTime(&date[1], &time[1], ×_u[1]);
4370: }
4371: if (err < E_OK) goto exit0;
4372:
4373:
4374: err = fatOpenDIR(fs, &dir, inode->fino_dircl,
4375: (W)inode->fino_dirofs, AC_WRITE, NULL);
4376: if (err >= E_OK) {
4377: if (dir.di_dirent == NULL) {
4378: err = EX_NOENT;
4379: } else {
4380:
4381: dir.di_dirent->de_adate = date[0];
4382: dir.di_dirent->de_mdate = date[1];
4383: dir.di_dirent->de_mtime = time[1];
4384: err = fatWriteCurDIR(fs, &dir, (VW)inode);
4385: }
4386:
4387: err = fatCloseDIR(fs, &dir, err);
4388: }
4389: exit0:
4390: return err;
4391: }
4392:
4393: 4394: 4395:
4396: LOCAL ER fat_chmod(FATFS *fs, FATNODE *inode, mode_t mode)
4397: {
4398: DIRINF dir;
4399: ER err;
4400:
4401: if (IsRootINODE(fs, inode)) {
4402: err = isSET(mode, FILMODE_WRITE) ? E_OK : EX_INVAL;
4403: } else {
4404:
4405: err = fatOpenDIR(fs, &dir, inode->fino_dircl,
4406: (W)inode->fino_dirofs, AC_WRITE, NULL);
4407: if (err >= E_OK) {
4408: if (dir.di_dirent == NULL) {
4409: err = EX_NOENT;
4410: } else {
4411:
4412: if (isSET(mode, FILMODE_WRITE)) {
4413: dir.di_dirent->de_ftype &= ~FAT_RDONLY;
4414: } else {
4415: dir.di_dirent->de_ftype |= FAT_RDONLY;
4416: }
4417: err = fatWriteCurDIR(fs, &dir, (VW) inode);
4418: inode->fino_ftype = dir.di_dirent->de_ftype;
4419: }
4420:
4421: err = fatCloseDIR(fs, &dir, err);
4422: }
4423: }
4424: return err;
4425: }
4426:
4427: 4428: 4429:
4430: LOCAL ER fat_fchmod(FD *fd, mode_t mode)
4431: {
4432: return fat_chmod((FATFS*)fd->fd_fs, (FATNODE*)fd->fd_inode, mode);
4433: }
4434:
4435: 4436: 4437:
4438: LOCAL ER fat_rename(FATFS *fs, FATNODE *from,
4439: FATNODE *to, const UB *fname)
4440: {
4441: DIRINF dir;
4442: FAT_DIRENT de;
4443: UW dircl, dirofs;
4444: ER err;
4445:
4446:
4447: if (from->fino_d_ronly || to->fino_d_ronly) {
4448: err = EX_ACCES;
4449: goto exit0;
4450: }
4451:
4452:
4453: err = fatCheckSubDirectory(fs, from, to);
4454: if (err < E_OK) goto exit0;
4455:
4456:
4457: if (isFAT_SUBDIR(from->fino_ftype) && isFAT_RDONLY(from->fino_ftype)
4458: && to->fino_dircl != from->fino_dircl) {
4459: err = EX_ACCES;
4460: goto exit0;
4461: }
4462:
4463:
4464: err = fatOpenDIR(fs, &dir, from->fino_dircl,
4465: (W)from->fino_dirofs, AC_RDONLY, NULL);
4466: if (err >= E_OK) {
4467:
4468: memcpy(&de, dir.di_dirent, DIRENTSZ);
4469:
4470:
4471: err = fatCloseDIR(fs, &dir, E_OK);
4472: }
4473: if (err < E_OK) goto exit0;
4474:
4475: if (to->fino_c.ino_ino != NOEXS_INO) {
4476:
4477: if (isFAT_SUBDIR(to->fino_ftype)) {
4478:
4479: err = fatChkEmptyDirectory(fs, to);
4480: if (err == EX_NOTEMPTY) err = EX_EXIST;
4481: }
4482: if (err < E_OK) goto exit0;
4483:
4484:
4485: err = fatOpenDIR(fs, &dir, to->fino_dircl,
4486: (W)to->fino_dirofs, AC_WRITE, NULL);
4487: if (err < E_OK) goto exit0;
4488:
4489: if (dir.di_dirent == NULL) {
4490: err = EX_NOENT;
4491: } else {
4492:
4493: dir.di_dirent->de_ftype = de.de_ftype | FAT_ARCHIV;
4494: dir.di_dirent->de_ctime = de.de_ctime;
4495: dir.di_dirent->de_cdate = de.de_cdate;
4496: dir.di_dirent->de_adate = de.de_adate;
4497: dir.di_dirent->de_clno_hi = de.de_clno_hi;
4498: dir.di_dirent->de_mtime = de.de_mtime;
4499: dir.di_dirent->de_mdate = de.de_mdate;
4500: dir.di_dirent->de_clno_lo = de.de_clno_lo;
4501: dir.di_dirent->de_fsize = de.de_fsize;
4502:
4503: err = fatWriteCurDIR(fs, &dir, (VW)to);
4504: }
4505:
4506: err = fatCloseDIR(fs, &dir, err);
4507: if (err < E_OK) goto exit0;
4508:
4509:
4510: dircl = to->fino_dircl;
4511: dirofs = to->fino_dirofs;
4512: to->fino_dircl = from->fino_dircl;
4513: to->fino_dirofs = from->fino_dirofs;
4514:
4515: err = fatRemoveFile(fs, to);
4516: if (err < E_OK) goto exit0;
4517:
4518:
4519: err = fatUpdateDirectory(fs, to);
4520: if (err < E_OK) goto exit0;
4521:
4522:
4523: if (! isFAT_SUBDIR(to->fino_ftype)) {
4524: from->fino_c.ino_ino = to->fino_c.ino_ino;
4525: }
4526: from->fino_dircl = dircl;
4527: from->fino_dirofs = dirofs;
4528:
4529: } else {
4530: dircl = from->fino_dircl;
4531: dirofs = from->fino_dirofs;
4532: from->fino_dircl = to->fino_dircl;
4533:
4534:
4535: err = fatCreateFile(fs, from, (UB*)fname, &de);
4536: if (err < E_OK) goto exit0;
4537:
4538:
4539: to->fino_dircl = dircl;
4540: to->fino_dirofs = dirofs;
4541:
4542: err = fatRemoveFile(fs, to);
4543: if (err < E_OK) goto exit0;
4544:
4545:
4546: err = fatUpdateDirectory(fs, from);
4547: if (err < E_OK) goto exit0;
4548:
4549:
4550: if (from->fino_dircl != to->fino_dircl) {
4551: err = fatUpdateDirectory(fs, to);
4552: }
4553: }
4554: if (err >= E_OK) {
4555:
4556: fatInodeChangeQue((FS *)fs, (INODE *)from);
4557: }
4558: exit0:
4559: return err;
4560: }
4561:
4562: 4563: 4564:
4565: LOCAL ER fat_unlink(FATFS *fs, FATNODE *inode)
4566: {
4567: ER err;
4568:
4569: if (inode->fino_d_ronly != FALSE) {
4570: err = EX_ACCES;
4571: } else {
4572:
4573: err = fatRemoveFile(fs, inode);
4574: if (err >= E_OK) {
4575: err = fatUpdateDirectory(fs, inode);
4576: }
4577: }
4578: return err;
4579: }
4580:
4581: 4582: 4583:
4584: LOCAL ER fat_mkdir(FATFS *fs, FATNODE *inode,
4585: const UB *fname, mode_t mode)
4586: {
4587: ER err;
4588:
4589: if (inode->fino_d_ronly != FALSE) {
4590: err = EX_ACCES;
4591: } else {
4592:
4593: inode->fino_ftype = FAT_SUBDIR;
4594: if (! isSET(mode, FILMODE_WRITE)) {
4595: inode->fino_ftype |= FAT_RDONLY;
4596: }
4597:
4598:
4599: err = fatCreateFile(fs, inode, (UB*)fname, NULL);
4600: if (err >= E_OK) {
4601: err = fatUpdateDirectory(fs, inode);
4602: }
4603: }
4604: return err;
4605: }
4606:
4607: 4608: 4609:
4610: LOCAL ER fat_rmdir(FATFS *fs, CDINF *curdir, FATNODE *inode)
4611: {
4612: ER err;
4613:
4614: if (inode->fino_d_ronly != FALSE) {
4615: err = EX_ACCES;
4616: goto exit0;
4617: }
4618:
4619: if (inode == (FATNODE*)curdir->cd_inode) {
4620:
4621: fatResetCurdir((FS*)fs);
4622: }
4623:
4624:
4625: err = fatChkEmptyDirectory(fs, inode);
4626: if (err >= E_OK) {
4627: err = fatRemoveFile(fs, inode);
4628: if (err >= E_OK) {
4629: err = fatUpdateDirectory(fs, inode);
4630: }
4631: }
4632: exit0:
4633: return err;
4634: }
4635:
4636: 4637: 4638:
4639: LOCAL ER fat_stat64_us(FATFS *fs, FATNODE *inode, struct stat64_us *sb)
4640: {
4641: return fatGetAttr64us(fs, inode, sb);
4642: }
4643:
4644: 4645: 4646:
4647: LOCAL ER fat_fstat64_us(FD *fd, struct stat64_us *sb)
4648: {
4649: return fatGetAttr64us((FATFS*)fd->fd_fs, (FATNODE*)fd->fd_inode, sb);
4650: }
4651:
4652: 4653: 4654:
4655: LOCAL ER fat_read64(FD *fd, UB *buf, UW len, UW *alen, D *aoffset)
4656: {
4657: FATFS *fs;
4658: FATNODE *inode;
4659: CLAD clad[MAX_CLEN];
4660: D offset;
4661: UW actual, ofs, sz;
4662: W cllen, i;
4663: MapInfo map;
4664: ER err;
4665:
4666: fs = (FATFS *)fd->fd_fs;
4667: inode = (FATNODE *)fd->fd_inode;
4668: offset = fd->fd_fpos;
4669: err = E_OK;
4670:
4671: *alen = 0;
4672: *aoffset = offset;
4673:
4674:
4675: if (offset >= inode->fino_filsz) {
4676: if (offset > inode->fino_filsz) {
4677: err = EX_OVERFLOW;
4678: }
4679: goto exit0;
4680: }
4681:
4682:
4683: if (offset + len > inode->fino_filsz) {
4684: len = inode->fino_filsz - offset;
4685: }
4686:
4687:
4688: ofs = offset % fs->ff_clsz;
4689:
4690: for (actual = 0; len > 0; actual += sz, len -= sz, ofs = 0) {
4691:
4692:
4693: err = fatCopyClusterList(fs, clad, offset + actual,
4694: len, inode, &cllen);
4695: if (err < E_OK) break;
4696:
4697:
4698: for (sz = 0, i = 0; i < cllen; i++) {
4699: sz += clad[i].ca_len;
4700: }
4701: sz *= fs->ff_clsz;
4702:
4703:
4704: if ((sz -= ofs) > len) sz = len;
4705:
4706:
4707: err = fatMapDisk(fs, clad, cllen, &map, MAP_C, (VW)inode);
4708: if (err < E_OK) break;
4709:
4710:
4711: err = fatMapReadBytes(&map, ofs, &buf[actual], sz);
4712:
4713: (void)fatMapEnd(&map);
4714: fatUnmapDisk(&map);
4715: if (err < E_OK) break;
4716: }
4717: if (err == EX_INTR && actual > 0) err = E_OK;
4718:
4719:
4720: if (err >= E_OK) {
4721: err = fatUpdateAccessDate(fs, inode);
4722: }
4723:
4724: if (err >= E_OK) {
4725: *aoffset = (fd->fd_fpos += actual);
4726: *alen = actual;
4727: }
4728: exit0:
4729: return err;
4730: }
4731:
4732: 4733: 4734:
4735: LOCAL ER fat_write64(FD *fd, const UB *buf, UW len,
4736: UW *alen, D *aoffset)
4737: {
4738: FATFS *fs;
4739: FATNODE *inode;
4740: CLAD clad[MAX_CLEN];
4741: D offset;
4742: UW actual, gapsz, ofs, sz, gsz, dsz;
4743: W i, cllen;
4744: MapInfo map;
4745: ER err;
4746:
4747: fs = (FATFS *)fd->fd_fs;
4748: inode = (FATNODE *)fd->fd_inode;
4749: err = E_OK;
4750:
4751:
4752: if ((fd->fd_omode & O_APPEND) != 0) {
4753: fd->fd_fpos = inode->fino_filsz;
4754: }
4755: offset = fd->fd_fpos;
4756:
4757: *alen = 0;
4758: *aoffset = offset;
4759:
4760: if (len <= 0) goto exit0;
4761:
4762:
4763: gapsz = 0;
4764: if (offset > inode->fino_filsz) {
4765: gapsz = offset - inode->fino_filsz;
4766: offset -= gapsz;
4767: }
4768:
4769:
4770: len += gapsz;
4771: if (offset + len > FILE_SIZE_MAX) {
4772: err = EX_FBIG;
4773: goto exit0;
4774: }
4775:
4776:
4777: ofs = offset % fs->ff_clsz;
4778:
4779: for (actual = 0; len > 0; len -= sz, offset += sz, gapsz -= gsz,
4780: actual += dsz, ofs = 0) {
4781:
4782:
4783: err = fatCopyClusterList(fs, clad, offset, len, inode, &cllen);
4784: if (err >= E_OK && cllen == 0) {
4785:
4786: err = fatApdNewCluster(fs, &clad[0], (W)len, inode);
4787: if (err >= E_OK) cllen = 1;
4788: }
4789: if (err < E_OK) break;
4790:
4791:
4792: for (sz = i = 0; i < cllen; i++) {
4793: sz += clad[i].ca_len;
4794: }
4795: sz *= fs->ff_clsz;
4796:
4797:
4798: if ((sz -= ofs) > len) sz = len;
4799:
4800:
4801: if ((gsz = gapsz) > sz) gsz = sz;
4802:
4803:
4804: dsz = sz - gsz;
4805:
4806:
4807: err = fatMapDisk(fs, clad, cllen, &map, MAP_C, (VW)inode);
4808: if (err < E_OK) break;
4809:
4810:
4811: if (gsz > 0) {
4812: err = fatMapWriteBytes(&map, ofs, NULL, gsz);
4813: }
4814:
4815:
4816: if (err >= E_OK && dsz > 0) {
4817: err = fatMapWriteBytes(&map, ofs + gsz,
4818: &buf[actual], dsz);
4819: }
4820: (void)fatMapEnd(&map);
4821: fatUnmapDisk(&map);
4822: if (err < E_OK) break;
4823: }
4824:
4825: if (err == EX_INTR && actual > 0) err = E_OK;
4826:
4827:
4828: if (inode->fino_filsz < fd->fd_fpos + actual) {
4829: inode->fino_filsz = fd->fd_fpos + actual;
4830: }
4831:
4832:
4833: err = fatUpdateFile(fs, inode);
4834: if (err >= E_OK) {
4835: *aoffset = (fd->fd_fpos += actual);
4836: *alen = actual;
4837: }
4838: exit0:
4839: return err;
4840: }
4841:
4842: 4843: 4844:
4845: LOCAL ER set_dirent(FATFS *fs, UD ino, void *nm,
4846: struct dirent *ent, W *alen, W bflen)
4847: {
4848: W nmlen, nmsz;
4849: struct dirent *e;
4850:
4851:
4852: bflen -= *alen;
4853: nmsz = bflen - offsetof(struct dirent, d_name) - 1;
4854: if (nmsz <= 0) goto nospace;
4855: if (nmsz > NAME_MAX) nmsz = NAME_MAX;
4856:
4857:
4858: e = (struct dirent *)((UB*)ent + *alen);
4859: if (ino <= CLSTART) {
4860: nmlen = strlen((B*)nm);
4861: if (nmlen <= nmsz) strcpy(e->d_name, (B*)nm);
4862: } else {
4863: nmlen = fatEncUtf16strToUtf8str((UH*)nm,
4864: fat_strlen16((UH*)nm), (UB*)e->d_name, nmsz + 1);
4865: }
4866: if (bflen < RECLEN_DIRENT(nmlen)) goto nospace;
4867:
4868: 4869:
4870: e->d_ino = (ino_t)ino;
4871: e->d_reclen = RECLEN_DIRENT(nmlen);
4872: *alen += e->d_reclen;
4873: return E_OK + 1;
4874: nospace:
4875: return (nmsz == NAME_MAX) ? EX_NAMETOOLONG :
4876: ((*alen == 0) ? EX_INVAL : E_OK);
4877: }
4878:
4879: 4880: 4881:
4882: LOCAL ER fat_getdents(FD *fd, struct dirent *ent, W *len, W *retofs)
4883: {
4884: FATFS *fs;
4885: FATNODE *inode;
4886: DIRINF dir;
4887: FAT_DIRENT *dirent;
4888: W ofs, ofsbias, ldenum, cks, bflen, alen;
4889: ER err;
4890:
4891: 4892: 4893: 4894:
4895: #define GetOnlyOneEnt (bflen == sizeof(struct dirent))
4896:
4897: fs = (FATFS *)fd->fd_fs;
4898: inode = (FATNODE *)fd->fd_inode;
4899: ofs = (W)fd->fd_fpos;
4900:
4901: bflen = *len;
4902: *len = alen = 0;
4903: ofsbias = 0;
4904: err = E_OK;
4905:
4906:
4907: if ((ofs % DIRENTSZ) != 0) {
4908: err = EX_NOENT;
4909: goto exit0;
4910: }
4911:
4912:
4913: if (IsRootINODE(fs, inode)) {
4914:
4915: if (ofs == 0) {
4916: err = set_dirent(fs, CLSTART, ".", ent, &alen, bflen);
4917: if (err <= E_OK) goto exit1;
4918: ofs = DIRENTSZ;
4919: if (GetOnlyOneEnt) goto exit1;
4920: }
4921:
4922: if (ofs == DIRENTSZ) {
4923: err = set_dirent(fs, 0, "..", ent, &alen, bflen);
4924: if (err <= 0) goto exit1;
4925: ofs = DIRENTSZ * 2;
4926: if (GetOnlyOneEnt) goto exit1;
4927: }
4928: ofs -= (ofsbias = DIRENTSZ * 2);
4929: }
4930:
4931:
4932: err = fatOpenDIR(fs, &dir, inode->fino_fclno, ofs, AC_RDONLY, inode);
4933: if (err < E_OK) goto exit0;
4934:
4935:
4936: for (ldenum = 0, cks = CKSVOID; err >= E_OK;
4937: err = fatNextDIR(fs, &dir, AC_RDONLY) ) {
4938:
4939: dirent = dir.di_dirent;
4940: if (dirent == NULL ||
4941: isDE_TERM(dirent)) {
4942: break;
4943: }
4944: if (isDE_FREE(dirent)) {
4945: ;
4946: } else if (isDE_LFN(dirent)) {
4947: if (fatGetLFN((FAT_DIRENT_LFN *)dirent,
4948: &ldenum, &cks, fs->ff_nmbf) >= 0) continue;
4949:
4950: } else if (isDE_VOL(dirent)) {
4951: ;
4952: } else if (cks == fatCalcChksum(dirent->de_fname) ||
4953: cks == CKSVOID ) {
4954:
4955: if (cks == CKSVOID) {
4956:
4957: (void)fatGetSFN(dirent->de_fname,
4958: dirent->de_smallcaps, fs->ff_nmbf);
4959: }
4960:
4961: err = set_dirent(fs, fatGetInoDIR(fs, &dir),
4962: fs->ff_nmbf, ent, &alen, bflen);
4963: if (err <= E_OK) break;
4964:
4965: ofs = dir.di_offset + DIRENTSZ;
4966: if (GetOnlyOneEnt) break;
4967: }
4968: cks = CKSVOID;
4969: ldenum = 0;
4970: }
4971:
4972:
4973: err = fatCloseDIR(fs, &dir, err);
4974: if (err >= E_OK) {
4975:
4976: err = fatUpdateAccessDate(fs, inode);
4977: }
4978: exit1:
4979: if (err >= E_OK) {
4980: *retofs = fd->fd_fpos = ofs + ofsbias;
4981: *len = alen;
4982: }
4983: exit0:
4984: return err;
4985: }
4986:
4987: 4988: 4989:
4990: LOCAL ER fat_open(FD *fd, const UB *fname, W oflag, mode_t mode)
4991: {
4992: FATFS *fs;
4993: FATNODE *inode;
4994: ER err;
4995:
4996: fs = (FATFS *)fd->fd_fs;
4997: inode = (FATNODE *)fd->fd_inode;
4998: err = E_OK;
4999:
5000: fd->fd_omode = (UB)oflag;
5001:
5002: if (inode->fino_c.ino_ino == NOEXS_INO) {
5003:
5004:
5005: if (inode->fino_d_ronly != FALSE) {
5006: err = EX_ACCES;
5007: goto exit0;
5008: }
5009:
5010: if (! isSET(mode, FILMODE_WRITE)) {
5011: inode->fino_ftype = FAT_RDONLY;
5012: }
5013:
5014: err = fatCreateFile(fs, inode, (UB*)fname, NULL);
5015: if (err < E_OK) goto exit0;
5016:
5017: err = fatUpdateDirectory(fs, inode);
5018:
5019: } else {
5020:
5021: if (isFAT_RDONLY(inode->fino_ftype) &&
5022: isNOT_RDONLY(fd->fd_omode)) {
5023: err = EX_ACCES;
5024: goto exit0;
5025: }
5026:
5027:
5028: if (isSET(oflag, O_TRUNC) &&
5029: ! isFAT_SUBDIR(inode->fino_ftype)) {
5030:
5031: if (isFAT_RDONLY(inode->fino_ftype)) {
5032: err = EX_ACCES;
5033: goto exit0;
5034: }
5035:
5036: if (isNOT_RDONLY(fd->fd_omode)) {
5037:
5038: err = fatTruncateFile(fs, inode, 0);
5039: }
5040: }
5041: }
5042: if (err >= E_OK) {
5043:
5044: err = fatMakeClusterList(fs, inode);
5045: }
5046: exit0:
5047: return err;
5048: }
5049:
5050: 5051: 5052:
5053: LOCAL ER fat_close(FD *fd)
5054: {
5055:
5056: (void)fd;
5057: return E_OK;
5058: }
5059:
5060: 5061: 5062:
5063: LOCAL ER fat_statvfs(FATFS *fs, struct statvfs *buf)
5064: {
5065: buf->f_bsize = DSECSZ(fs);
5066: buf->f_frsize = fs->ff_clsz;
5067: buf->f_blocks = fs->ff_lastcl;
5068: buf->f_bfree = fs->ff_freecl;
5069: buf->f_bavail = buf->f_bfree;
5070: buf->f_files = 0;
5071: buf->f_ffree = 0;
5072: buf->f_favail = buf->f_ffree;
5073: buf->f_fsid = 0;
5074: buf->f_flag = ST_NOSUID;
5075: if (fs->ff_c.fs_rdonly != FALSE) {
5076: buf->f_flag |= ST_RDONLY;
5077: }
5078: if (fs->ff_c.fs_diskinfo.removable != 0) {
5079: buf->f_flag |= ST_REMOVABLE;
5080: }
5081: buf->f_namemax = LFN_MAXLEN;
5082: return E_OK;
5083: }
5084:
5085: 5086: 5087:
5088: LOCAL ER fat_ioctl(FD *fd, UW dcmd, void *data)
5089: {
5090:
5091:
5092: (void)fd;
5093: (void)dcmd;
5094: (void)data;
5095: return EX_NOTSUP;
5096: }
5097:
5098: 5099: 5100:
5101: LOCAL ER fat_fchdir(FD *fd, UB *utf8nm, W utf8len)
5102: {
5103: FATFS *fs;
5104: #ifndef FAT_CURDIR_CASE_NOCARE
5105: DIRINF dir;
5106: UB *npath, *cpath;
5107: UW len, dcl;
5108: #endif
5109: UB *path, *e_utf8nm;
5110: ER err;
5111:
5112: fs = (FATFS *)fd->fd_fs;
5113:
5114:
5115: path = ((FATNODE *)fd->fd_inode)->fino_c.ino_path;
5116: if (path == NULL) {
5117: err = EX_INVAL;
5118: goto exit0;
5119: }
5120: if (path[0] != '/') {
5121: err = EX_IO;
5122: goto exit0;
5123: }
5124:
5125:
5126: e_utf8nm = utf8nm + utf8len;
5127: *utf8nm++ = '/';
5128: (void)strcpy((B*)utf8nm, fs->ff_c.fs_coninf->connm);
5129: if (path[1] == '\0') goto exit0;
5130:
5131: utf8nm += strlen((B*)utf8nm);
5132:
5133: #ifdef FAT_CURDIR_CASE_NOCARE
5134:
5135: if (utf8nm + strlen(path) >= e_utf8nm) {
5136: err = EX_NAMETOOLONG;
5137: } else {
5138: strcpy((B*)utf8nm, path);
5139: err = E_OK;
5140: }
5141:
5142: #else
5143:
5144:
5145: cpath = &path[1];
5146: for (dcl = fs->ff_rootcl; ; cpath = npath + 1) {
5147:
5148: if ((npath = (UB*)strchr((B*)cpath, '/')) == NULL) {
5149: len = strlen((B*)cpath);
5150: } else {
5151: len = npath - cpath;
5152: }
5153:
5154: err = fatOpenDIR(fs, &dir, dcl, OFSVOID, AC_RDONLY, NULL);
5155: if (err < E_OK) break;
5156:
5157: err = fatSearchDIR_nm(fs, &dir, cpath, len,
5158: AC_RDONLY, fs->ff_nmbf);
5159: if (err >= E_OK) {
5160: if (isFAT_SUBDIR(dir.di_dirent->de_ftype)) {
5161: *utf8nm++ = '/';
5162: len = fatEncUtf16strToUtf8str(
5163: fs->ff_nmbf, fat_strlen16(fs->ff_nmbf),
5164: utf8nm, e_utf8nm - utf8nm);
5165: if ((utf8nm += len) >= e_utf8nm) {
5166: err = EX_NAMETOOLONG;
5167: }
5168:
5169: dcl = dirent_to_fcl(fs, dir.di_dirent);
5170: } else {
5171: dir.di_dirent = NULL;
5172: err = EX_NOTDIR;
5173: }
5174: }
5175:
5176: err = fatCloseDIR(fs, &dir, err);
5177:
5178: CHK_BREAK_AND_SET_ERR(fs, &err);
5179: if (err < E_OK) break;
5180: if (npath == NULL) break;
5181: }
5182: #endif
5183: exit0:
5184: return err;
5185: }
5186:
5187: 5188: 5189:
5190:
5191: 5192: 5193:
5194: LOCAL ER fatfs_open(FS *fs, fimp_t *req)
5195: {
5196: LPINF lp;
5197: FD *fd;
5198: W oflag, fdno;
5199: mode_t mode;
5200: ER err;
5201:
5202:
5203: err = fat_lookup((FATFS*)fs, &lp, req->r_open.path);
5204: if (err < E_OK) goto exit0;
5205:
5206: mode = 0;
5207: oflag = (W)req->r_open.oflags;
5208:
5209:
5210: if (isNOT_RDONLY(oflag) && fs->fs_rdonly != FALSE) {
5211: err = EX_ROFS;
5212: } else if (lp.lp_inode->ino_ino != NOEXS_INO) {
5213:
5214: if (isSET(oflag, O_CREAT) && isSET(oflag, O_EXCL)) {
5215: err = EX_EXIST;
5216: } else if (lp.lp_inode->ino_type == DT_DIR) {
5217: if (isNOT_RDONLY(oflag)) {
5218:
5219: err = EX_ISDIR;
5220: } else if (isSET(oflag, O_TRUNC)) {
5221:
5222: err = EX_ISDIR;
5223: }
5224: } else if (lp.lp_inode->ino_type == DT_REG &&
5225: isSET(oflag, O_DIRECTORY)) {
5226: err = EX_NOTDIR;
5227: }
5228: } else {
5229:
5230: if (! isSET(oflag, O_CREAT)) {
5231: err = EX_NOENT;
5232: } else if (fs->fs_rdonly != FALSE) {
5233:
5234: err = EX_ROFS;
5235: } else {
5236:
5237: mode = req->r_open.mode & ~(fs->fs_uxinfo.uxi_cmask);
5238: }
5239: }
5240: if (err < E_OK) goto exit1;
5241:
5242:
5243: err = fatNewFileDesc(fs, &fd, &fdno);
5244: if (err < E_OK) goto exit1;
5245:
5246:
5247: fd->fd_inode = lp.lp_inode;
5248: err = fat_open(fd, lp.lp_path, oflag, mode);
5249: if (err < E_OK) goto exit2;
5250:
5251: err = fatDCacheSyncFS((FATFS*)fs, 0);
5252: if (err >= E_OK) {
5253:
5254: fatInodeRegister(fs, lp.lp_inode, fd->fd_omode);
5255: *req->r_open.fid = (fid_t)fdno;
5256: }
5257: exit2:
5258: if (err < E_OK) {
5259: fd->fd_inode = NULL;
5260: fatDelFileDesc(fs, fd, fdno);
5261: }
5262: exit1:
5263: if (err < E_OK) {
5264: fatInodeFree(fs, lp.lp_inode);
5265: }
5266: exit0:
5267: return err;
5268: }
5269:
5270: 5271: 5272:
5273: LOCAL ER fatfs_close(FS *fs, fimp_t *req)
5274: {
5275: FD *fd;
5276: ER err;
5277:
5278: err = fatSearchFileDesc(fs, &fd, (W)req->r_close.fid);
5279: if (err >= E_OK) {
5280: if (fd->fd_refcnt <= 1) {
5281: fd->fd_omode = req->r_close.oflags;
5282: err = fat_close(fd);
5283: }
5284: if (err >= E_OK) {
5285: err = fatFDSync(fd);
5286: fatDelFileDesc(fs, fd, (W)req->r_close.fid);
5287: }
5288: }
5289: return err;
5290: }
5291:
5292: 5293: 5294:
5295: LOCAL ER fatfs_read64(FS *fs, fimp_t *req)
5296: {
5297: FD *fd;
5298: ER err;
5299: UW alen;
5300:
5301: err = fatSearchFileDesc(fs, &fd, (W)req->r_read64.fid);
5302: if (err >= E_OK) {
5303: if (fd->fd_inode == NULL) {
5304: err = EX_BADF;
5305: } else if (fd->fd_inode->ino_type != DT_REG) {
5306: err = EX_ISDIR;
5307: } else {
5308: fd->fd_fpos = (D)*(req->r_read64.off);
5309: fd->fd_omode = (W)req->r_read64.oflags;
5310: err = fat_read64(fd, (UB*)req->r_read64.buf,
5311: (UW)*req->r_read64.len, (UW*)&alen,
5312: (D*)req->r_read64.retoff);
5313: if (err >= E_OK) {
5314: *req->r_read64.len = alen;
5315: err = fatFDSync(fd);
5316: }
5317: }
5318: }
5319: return err;
5320: }
5321:
5322: 5323: 5324:
5325: LOCAL ER fatfs_write64(FS *fs, fimp_t *req)
5326: {
5327: FD *fd;
5328: ER err;
5329: UW alen;
5330:
5331: err = fatSearchFileDesc(fs, &fd, (W)req->r_write64.fid);
5332: if (err >= E_OK) {
5333: if (fd->fd_inode == NULL) {
5334: err = EX_BADF;
5335: } else if (fd->fd_inode->ino_type != DT_REG) {
5336: err = EX_ISDIR;
5337: } else {
5338: fd->fd_fpos = (D)*(req->r_write64.off);
5339: fd->fd_omode = (W)req->r_write64.oflags;
5340: err = fat_write64(fd, (const UB*)req->r_write64.buf,
5341: (UW)*req->r_write64.len, (UW*)&alen,
5342: (D*)req->r_write64.retoff);
5343: if (err >= E_OK) {
5344: *req->r_write64.len = alen;
5345: err = fatFDSync(fd);
5346: }
5347: }
5348: }
5349: return err;
5350: }
5351:
5352: 5353: 5354:
5355: LOCAL ER fatfs_ioctl(FS *fs, fimp_t *req)
5356: {
5357: FD *fd;
5358: ER err;
5359:
5360: err = fatSearchFileDesc(fs, &fd, (W)req->r_ioctl.fid);
5361: if (err >= E_OK) {
5362: fd->fd_omode = (W)req->r_ioctl.oflags;
5363: *req->r_ioctl.retval = (INT)
5364: fat_ioctl(fd, (UW)req->r_ioctl.dcmd,req->r_ioctl.arg);
5365: }
5366: return err;
5367: }
5368:
5369: 5370: 5371:
5372: LOCAL ER fatfs_fsync(FS *fs, fimp_t *req)
5373: {
5374: FD *fd;
5375: ER err;
5376:
5377: err = fatSearchFileDesc(fs, &fd, (W)req->r_fsync.fid);
5378: if (err >= E_OK) {
5379: fd->fd_omode = (W)req->r_fsync.oflags;
5380: err = fatDCacheSyncFS((FATFS*)fs, (VW)fd->fd_inode);
5381: }
5382: return err;
5383: }
5384:
5385: 5386: 5387:
5388: LOCAL ER fatfs_truncate64(FS *fs, fimp_t *req)
5389: {
5390: LPINF lp;
5391: ER err;
5392:
5393: err = fat_lookup((FATFS*)fs, &lp, req->r_truncate64.path);
5394: if (err >= E_OK) {
5395: if (fs->fs_rdonly != FALSE) {
5396: err = EX_ROFS;
5397: } else {
5398: err = fat_truncate64((FATFS*)fs, (FATNODE*)lp.lp_inode,
5399: (D)req->r_truncate64.len);
5400: if (err >= E_OK) {
5401: err = fatDCacheSyncFS((FATFS*)fs, 0);
5402: }
5403: }
5404: fatInodeFree(fs, lp.lp_inode);
5405: }
5406: return err;
5407: }
5408:
5409: 5410: 5411:
5412: LOCAL ER fatfs_ftruncate64(FS *fs, fimp_t *req)
5413: {
5414: ER err;
5415: FD *fd;
5416:
5417: err = fatSearchFileDesc(fs, &fd, (W)req->r_ftruncate64.fid);
5418: if (err >= E_OK) {
5419: err = fat_ftruncate64(fd, (D)req->r_ftruncate64.len);
5420: if (err >= E_OK) {
5421: err = fatFDSync(fd);
5422: }
5423: }
5424: return err;
5425: }
5426:
5427: 5428: 5429:
5430: LOCAL ER fatfs_unlink(FS *fs, fimp_t *req)
5431: {
5432: LPINF lp;
5433: ER err;
5434:
5435: err = fat_lookup((FATFS*)fs, &lp, req->r_unlink.path);
5436: if (err >= E_OK) {
5437: if (lp.lp_inode->ino_ino == NOEXS_INO) {
5438: err = EX_NOENT;
5439: } else if (lp.lp_inode->ino_refcnt > 0) {
5440: err = EX_BUSY;
5441: } else if (fs->fs_rdonly != FALSE) {
5442: err = EX_ROFS;
5443: } else {
5444: err = fat_unlink((FATFS*)fs, (FATNODE*)lp.lp_inode);
5445: if (err >= E_OK) {
5446: err = fatDCacheSyncFS((FATFS*)fs, 0);
5447: }
5448: }
5449: fatInodeFree(fs, lp.lp_inode);
5450: }
5451: return err;
5452: }
5453:
5454: 5455: 5456:
5457: LOCAL ER fatfs_rename(FS *fs, fimp_t *req)
5458: {
5459: LPINF olp, nlp;
5460: INODE *from, *to;
5461: ER err;
5462:
5463: err = fat_lookup((FATFS*)fs, &olp, req->r_rename.oldpath);
5464: if (err < E_OK) goto exit0;
5465:
5466: from = olp.lp_inode;
5467: if (from->ino_ino == NOEXS_INO) {
5468: err = EX_NOENT;
5469: goto exit1;
5470: }
5471: if (IsRootINODE(fs, from)) {
5472: err = EX_ACCES;
5473: goto exit1;
5474: }
5475:
5476: err = fat_lookup((FATFS*)fs, &nlp, req->r_rename.newpath);
5477: if (err < E_OK) goto exit1;
5478:
5479: to = nlp.lp_inode;
5480: if (IsRootINODE(fs, to)) {
5481: err = EX_ACCES;
5482: goto exit2;
5483: }
5484:
5485:
5486: if (to->ino_ino != NOEXS_INO) {
5487:
5488: if (fatCheckIsInodeBusy(fs, to) != FALSE) {
5489: err = EX_BUSY;
5490: goto exit2;
5491: }
5492:
5493: if (from->ino_type != to->ino_type) {
5494: err = (to->ino_type == DT_DIR) ? EX_ISDIR : EX_NOTDIR;
5495: goto exit2;
5496: }
5497:
5498: if (from->ino_ino == to->ino_ino) {
5499: goto exit2;
5500: }
5501: }
5502: if (fs->fs_rdonly != FALSE) {
5503: err = EX_ROFS;
5504: goto exit2;
5505: }
5506: err = fat_rename((FATFS*)fs, (FATNODE*)from, (FATNODE*)to, nlp.lp_path);
5507: if (err >= E_OK) {
5508: err = fatDCacheSyncFS((FATFS*)fs, 0);
5509: }
5510: exit2:
5511: fatInodeFree(fs, to);
5512: exit1:
5513: fatInodeFree(fs, from);
5514: exit0:
5515: return err;
5516: }
5517:
5518: 5519: 5520:
5521: LOCAL ER fatfs_chmod(FS *fs, fimp_t *req)
5522: {
5523: LPINF lp;
5524: ER err;
5525:
5526: err = fat_lookup((FATFS*)fs, &lp, req->r_chmod.path);
5527: if (err >= E_OK) {
5528: if (lp.lp_inode->ino_ino == NOEXS_INO) {
5529: err = EX_NOENT;
5530: } else if (fs->fs_rdonly != FALSE) {
5531: err = EX_ROFS;
5532: } else {
5533: err = fat_chmod((FATFS*)fs, (FATNODE*)lp.lp_inode,
5534: req->r_chmod.mode);
5535: if (err >= E_OK) {
5536: err = fatDCacheSyncFS((FATFS*)fs, 0);
5537: }
5538: }
5539: fatInodeFree(fs, lp.lp_inode);
5540: }
5541: return err;
5542: }
5543:
5544: 5545: 5546:
5547: LOCAL ER fatfs_fchmod(FS *fs, fimp_t *req)
5548: {
5549: FD *fd;
5550: ER err;
5551:
5552: err = fatSearchFileDesc(fs, &fd, (W)req->r_fchmod.fid);
5553: if (err >= E_OK) {
5554: if (fs->fs_rdonly != FALSE) {
5555: err = EX_ROFS;
5556: } else {
5557: err = fat_fchmod(fd, req->r_fchmod.mode);
5558: if (err >= E_OK) {
5559: err = fatFDSync(fd);
5560: }
5561: }
5562: }
5563: return err;
5564: }
5565:
5566: 5567: 5568:
5569: LOCAL ER fatfs_mkdir(FS *fs, fimp_t *req)
5570: {
5571: LPINF lp;
5572: ER err;
5573:
5574: err = fat_lookup((FATFS*)fs, &lp, req->r_mkdir.path);
5575: if (err >= E_OK) {
5576: if (lp.lp_inode->ino_ino != NOEXS_INO) {
5577: err = EX_EXIST;
5578: } else if (fs->fs_rdonly != FALSE) {
5579: err = EX_ROFS;
5580: } else {
5581: err = fat_mkdir((FATFS*)fs, (FATNODE*)lp.lp_inode,
5582: lp.lp_path, req->r_mkdir.mode);
5583: if (err >= E_OK) {
5584: err = fatDCacheSyncFS((FATFS*)fs, 0);
5585: }
5586: }
5587: fatInodeFree(fs, lp.lp_inode);
5588: }
5589: return err;
5590: }
5591:
5592: 5593: 5594:
5595: LOCAL ER fatfs_rmdir(FS *fs, fimp_t *req)
5596: {
5597: LPINF lp;
5598: ER err;
5599:
5600: err = fat_lookup((FATFS*)fs, &lp, req->r_rmdir.path);
5601: if (err >= E_OK) {
5602: if (lp.lp_inode->ino_ino == NOEXS_INO) {
5603: err = EX_NOENT;
5604: } else if (IsRootINODE(fs, lp.lp_inode)) {
5605: err = EX_ACCES;
5606: } else if (fatCheckIsInodeBusy(fs, lp.lp_inode) != FALSE) {
5607: err = EX_BUSY;
5608: } else if (fs->fs_rdonly != FALSE) {
5609: err = EX_ROFS;
5610: } else {
5611: err = fat_rmdir((FATFS*)fs, &fs->fs_uxinfo.uxi_curdir,
5612: (FATNODE*)lp.lp_inode);
5613: if (err >= E_OK) {
5614: err = fatDCacheSyncFS((FATFS*)fs, 0);
5615: }
5616: }
5617: fatInodeFree(fs, lp.lp_inode);
5618: }
5619: return err;
5620: }
5621:
5622: 5623: 5624:
5625: LOCAL ER fatfs_chdir(FS *fs, fimp_t *req)
5626: {
5627: (void)fs;
5628: (void)req;
5629:
5630: return E_OK;
5631: }
5632:
5633: 5634: 5635:
5636: LOCAL ER fatfs_fchdir(FS *fs, fimp_t *req)
5637: {
5638: FD *fd;
5639: ER err;
5640:
5641: err = fatSearchFileDesc(fs, &fd, (W)req->r_fchdir.fid);
5642: if (err >= E_OK) {
5643: err = fat_fchdir(fd, (UB*)req->r_fchdir.buf,
5644: (W)req->r_fchdir.len);
5645: if (err >= E_OK) {
5646: err = fatFDSync(fd);
5647: }
5648: }
5649: return err;
5650: }
5651:
5652: 5653: 5654:
5655: LOCAL ER fatfs_getdents(FS *fs, fimp_t *req)
5656: {
5657: FD *fd;
5658: W retofs;
5659: ER err;
5660:
5661: err = fatSearchFileDesc(fs, &fd, (W)req->r_getdents.fid);
5662: if (err >= E_OK) {
5663: fd->fd_fpos = (D)*(req->r_getdents.off);
5664: fd->fd_omode = (W)req->r_getdents.oflags;
5665: err = fat_getdents(fd, req->r_getdents.buf,
5666: (W*)req->r_getdents.len, &retofs);
5667: if (err >= E_OK) {
5668: err = fatFDSync(fd);
5669: if (err >= E_OK) {
5670: *(req->r_getdents.retoff) = (off64_t)retofs;
5671: }
5672: }
5673: }
5674: return err;
5675: }
5676:
5677: 5678: 5679:
5680: LOCAL ER fatfs_fstatvfs(FS *fs, fimp_t *req)
5681: {
5682: return fat_statvfs((FATFS*)fs, req->r_fstatvfs.buf);
5683: }
5684:
5685: 5686: 5687:
5688: LOCAL ER fatfs_statvfs(FS *fs, fimp_t *req)
5689: {
5690: LPINF lp;
5691: ER err;
5692:
5693: err = fat_lookup((FATFS*)fs, &lp, req->r_statvfs.path);
5694: if (err >= E_OK) {
5695: if (lp.lp_inode->ino_ino == NOEXS_INO) {
5696: err = EX_NOENT;
5697: } else {
5698: err = fat_statvfs((FATFS*)fs, req->r_statvfs.buf);
5699:
5700:
5701:
5702: }
5703: fatInodeFree(fs, lp.lp_inode);
5704: }
5705: return err;
5706: }
5707:
5708: 5709: 5710:
5711: LOCAL ER fatfs_sync(FS *fs, fimp_t *req)
5712: {
5713: (void)req;
5714: return fatDCacheSyncFS((FATFS*)fs, 0);
5715: }
5716:
5717: 5718: 5719:
5720: LOCAL ER fatfs_utimes_us(FS *fs, fimp_t *req)
5721: {
5722: LPINF lp;
5723: ER err;
5724:
5725: err = fat_lookup((FATFS*)fs, &lp, req->r_utimes_us.path);
5726: if (err >= E_OK) {
5727: if (lp.lp_inode->ino_ino == NOEXS_INO) {
5728: err = EX_NOENT;
5729: } else if (fs->fs_rdonly != FALSE) {
5730: err = EX_ROFS;
5731: } else {
5732: err = fat_utimes_us((FATFS*)fs, (FATNODE*)lp.lp_inode,
5733: req->r_utimes_us.times_u);
5734: if (err >= E_OK) {
5735: err = fatDCacheSyncFS((FATFS*)fs, 0);
5736: }
5737: }
5738: fatInodeFree(fs, lp.lp_inode);
5739: }
5740: return err;
5741: }
5742:
5743: 5744: 5745:
5746: LOCAL ER fatfs_fcntl64(FS *fs, fimp_t *req)
5747: {
5748: (void)fs;
5749: (void)req;
5750: return EX_NOTSUP;
5751: }
5752:
5753: 5754: 5755:
5756: LOCAL ER fatfs_fstat64_us(FS *fs, fimp_t *req)
5757: {
5758: FD *fd;
5759: ER err;
5760:
5761: err = fatSearchFileDesc(fs, &fd, (W)req->r_fstat64_us.fid);
5762: if (err >= E_OK) {
5763: err = fat_fstat64_us(fd, req->r_fstat64_us.buf);
5764: if (err >= E_OK) {
5765: err = fatFDSync(fd);
5766: }
5767: }
5768: return err;
5769: }
5770:
5771: 5772: 5773:
5774: LOCAL ER fatfs_stat64_us(FS *fs, fimp_t *req)
5775: {
5776: LPINF lp;
5777: ER err;
5778:
5779: err = fat_lookup((FATFS*)fs, &lp, req->r_stat64_us.path);
5780: if (err >= E_OK) {
5781: if (lp.lp_inode->ino_ino == NOEXS_INO) {
5782: err = EX_NOENT;
5783: } else {
5784: err = fat_stat64_us((FATFS*)fs, (FATNODE*)lp.lp_inode,
5785: req->r_stat64_us.buf);
5786:
5787:
5788:
5789: }
5790: fatInodeFree(fs, lp.lp_inode);
5791: }
5792: return err;
5793: }
5794:
5795: 5796: 5797:
5798:
5799: 5800: 5801:
5802: LOCAL ER fatUxinfoInit(FATFS *fs)
5803: {
5804: UXINFO *uxinfo;
5805: FATNODE *rootinode;
5806: UB *buf;
5807: ER err;
5808:
5809: uxinfo = &fs->ff_c.fs_uxinfo;
5810: rootinode = NULL;
5811:
5812:
5813: fatInodeQueInit(&fs->ff_c);
5814: err = fatGetRootINODE(fs, &rootinode);
5815: if (err < E_OK) goto exit0;
5816:
5817:
5818: fatInodeRegister((FS *)fs, (INODE *)rootinode, O_RDONLY);
5819: fatInodeRegister((FS *)fs, (INODE *)rootinode, O_RDONLY);
5820: uxinfo->uxi_curdir.cd_inode = (INODE *)rootinode;
5821:
5822:
5823: uxinfo->uxi_cmask = 0;
5824:
5825:
5826: uxinfo->uxi_relino = NULL;
5827:
5828:
5829: buf = (UB *)fimp_calloc(MaxOpenF, sizeof(FD *));
5830: if (buf == NULL) {
5831: err = EX_NOMEM;
5832: fatInodeRelease((FS *)fs,
5833: uxinfo->uxi_curdir.cd_inode, O_RDONLY);
5834: uxinfo->uxi_curdir.cd_inode = NULL;
5835: goto exit0;
5836: }
5837: uxinfo->uxi_fdtbl = (FD **)buf;
5838: exit0:
5839: return err;
5840: }
5841:
5842: 5843: 5844:
5845: LOCAL void fatUxinfoCleanup(FATFS *fs)
5846: {
5847: UXINFO *uxinfo;
5848: FATNODE *rootinode;
5849: FD *fd;
5850: W i;
5851:
5852: uxinfo = &fs->ff_c.fs_uxinfo;
5853: rootinode = NULL;
5854:
5855:
5856: if (uxinfo->uxi_fdtbl != NULL) {
5857:
5858: for (i = 0; i < MaxOpenF; i++) {
5859: fd = uxinfo->uxi_fdtbl[i];
5860: if (fd != NULL) {
5861: struct fimp_close req;
5862: req.fid = i;
5863: (void)fatfs_close((FS *)fs, (fimp_t *)&req);
5864: }
5865: }
5866:
5867: fimp_free(uxinfo->uxi_fdtbl);
5868: uxinfo->uxi_fdtbl = NULL;
5869: }
5870:
5871:
5872: if (uxinfo->uxi_curdir.cd_inode != NULL) {
5873: fatInodeRelease((FS *)fs,
5874: uxinfo->uxi_curdir.cd_inode, O_RDONLY);
5875: uxinfo->uxi_curdir.cd_inode = NULL;
5876: }
5877:
5878:
5879: (void)fatGetRootINODE(fs, &rootinode);
5880: fatInodeRelease((FS *)fs, (INODE *)rootinode, O_RDONLY);
5881: }
5882:
5883: 5884: 5885:
5886:
5887: 5888: 5889:
5890: LOCAL ER toEXER(ER err)
5891: {
5892: if (err < E_OK && MERCD(err) != EC_ERRNO) {
5893: switch (MERCD(err)) {
5894: case MERCD(E_SYS): err = EX_IO; break;
5895: case MERCD(E_NOCOP): err = EX_IO; break;
5896: case MERCD(E_NOSPT): err = EX_NOTSUP; break;
5897: case MERCD(E_RSFN): err = EX_IO; break;
5898: case MERCD(E_RSATR): err = EX_INVAL; break;
5899: case MERCD(E_PAR): err = EX_INVAL; break;
5900: case MERCD(E_ID): err = EX_INVAL; break;
5901: case MERCD(E_CTX): err = EX_IO; break;
5902: case MERCD(E_MACV): err = EX_FAULT; break;
5903: case MERCD(E_OACV): err = EX_ACCES; break;
5904: case MERCD(E_ILUSE): err = EX_INVAL; break;
5905: case MERCD(E_NOMEM): err = EX_NOMEM; break;
5906: case MERCD(E_LIMIT): err = EX_NOSPC; break;
5907: case MERCD(E_OBJ): err = EX_INVAL; break;
5908: case MERCD(E_NOEXS): err = EX_INVAL; break;
5909: case MERCD(E_QOVR): err = EX_IO; break;
5910: case MERCD(E_RLWAI): err = EX_INVAL; break;
5911: case MERCD(E_TMOUT): err = EX_IO; break;
5912: case MERCD(E_DLT): err = EX_IO; break;
5913: case MERCD(E_DISWAI): err = EX_INTR; break;
5914: case MERCD(E_IO): err = EX_IO; break;
5915: case MERCD(E_NOMDA): err = EX_NODEV; break;
5916: case MERCD(E_BUSY): err = EX_BUSY; break;
5917: case MERCD(E_ABORT): err = EX_INTR; break;
5918: case MERCD(E_RONLY): err = EX_ROFS; break;
5919: default: break;
5920: }
5921: }
5922: return err;
5923: }
5924:
5925: 5926: 5927:
5928: LOCAL void *fatGetReqInf(fimp_t *req, UW *func)
5929: {
5930: static const UW functab[] = {
5931: (UW)((B*)fatfs_open + 0x01),
5932: (UW)((B*)fatfs_close + 0x01),
5933: (UW)fatfs_ioctl,
5934: (UW)fatfs_getdents,
5935: (UW)((B*)fatfs_chdir + 0x01),
5936: (UW)((B*)fatfs_fchdir + 0x01),
5937: (UW)((B*)fatfs_fsync + 0x01),
5938: (UW)fatfs_unlink,
5939: (UW)fatfs_rename,
5940: (UW)fatfs_chmod,
5941: (UW)fatfs_fchmod,
5942: (UW)fatfs_mkdir,
5943: (UW)fatfs_rmdir,
5944: (UW)((B*)fatfs_statvfs + 0x01),
5945: (UW)((B*)fatfs_fstatvfs + 0x01),
5946: (UW)((B*)fatfs_sync + 0x01),
5947: (UW)((B*)fatfs_read64 + 0x01),
5948: (UW)((B*)fatfs_write64 + 0x01),
5949: (UW)((B*)fatfs_truncate64 + 0x01),
5950: (UW)((B*)fatfs_ftruncate64 + 0x01),
5951: (UW)fatfs_fcntl64,
5952: (UW)fatfs_stat64_us,
5953: (UW)fatfs_fstat64_us,
5954: (UW)fatfs_utimes_us,
5955: };
5956: INT i;
5957:
5958: if (req->com.coninf != NULL) {
5959: if ((i = req->com.r_code) >= 0 && i <= FIMP_COMMAND_MAX) {
5960: *func = functab[i];
5961: return req->com.coninf->consd;
5962: }
5963: }
5964: *func = 0;
5965: return NULL;
5966: }
5967:
5968: 5969: 5970:
5971: LOCAL void FileSystemTask(INT stacd)
5972: {
5973: FS *fs;
5974: BOOL fin;
5975: CMDPKT *pkt;
5976: RNO rdvno;
5977: UW func;
5978: ER err;
5979:
5980: fs = (FS *)stacd;
5981: for (fin = FALSE; fin == FALSE; ) {
5982:
5983: if (tk_acp_por(fs->fs_porid, 1, &rdvno,
5984: &pkt, TMO_FEVR) < E_OK) continue;
5985:
5986:
5987: err = SetTaskSpace(pkt->cp_tskid);
5988: if (err < E_OK) goto reply;
5989:
5990: if (pkt->cp_req == NULL) {
5991: fin = TRUE;
5992: err = E_OK;
5993: goto reply;
5994: }
5995:
5996:
5997: if (fatGetReqInf(pkt->cp_req, &func) != fs) {
5998: err = EX_IO;
5999: goto reply;
6000: }
6001:
6002: 6003:
6004: fs->fs_tsksts = &tskStsTab[pkt->cp_tskid];
6005: if (fs->fs_tsksts->c.break_done != 0) {
6006: err = EX_INTR;
6007: goto reply;
6008: }
6009:
6010:
6011: err = ((fatfs_api_t)(func & ~0x01))(fs, pkt->cp_req);
6012:
6013: if (fs->fs_uxinfo.uxi_relino != NULL) {
6014:
6015: fatInodeRelease(fs, fs->fs_uxinfo.uxi_relino, O_RDONLY);
6016: fs->fs_uxinfo.uxi_relino = NULL;
6017: }
6018: reply:
6019:
6020: pkt->cp_err = err;
6021: (void)tk_rpl_rdv(rdvno, &pkt, sizeof(pkt));
6022: }
6023:
6024: tk_exd_tsk();
6025: }
6026:
6027: 6028: 6029:
6030: LOCAL ER CallFileSystemTask(FATFS *fs, CMDPKT *ppkt)
6031: {
6032: ER err;
6033:
6034: ppkt->cp_err = E_OK;
6035: err = tk_cal_por(fs->ff_c.fs_porid, 1, &ppkt,
6036: sizeof(CMDPKT *), TMO_FEVR);
6037: return (err < E_OK) ? err : ppkt->cp_err;
6038: }
6039:
6040: 6041: 6042:
6043: LOCAL ER fatCreateObjects(FATFS *fs)
6044: {
6045: T_CPOR cpor;
6046: T_CTSK ctsk;
6047: ER err;
6048:
6049:
6050: SetOBJNAME(cpor.exinf, "bfat");
6051: cpor.poratr = TA_TPRI;
6052: cpor.maxcmsz = sizeof(CMDPKT *);
6053: cpor.maxrmsz = sizeof(CMDPKT *);
6054: err = tk_cre_por(&cpor);
6055: if (err >= E_OK) {
6056: fs->ff_c.fs_porid = (ID)err;
6057:
6058:
6059: SetOBJNAME(ctsk.exinf, "bfat");
6060: ctsk.tskatr = TA_HLNG | TA_RNG0;
6061: ctsk.task = (void*)FileSystemTask;
6062: ctsk.itskpri = TaskPriority;
6063: ctsk.stksz = TaskStackSize;
6064: err = tk_cre_tsk(&ctsk);
6065: if (err >= E_OK) {
6066: fs->ff_c.fs_tskid = (ID)err;
6067: err = tk_sta_tsk(fs->ff_c.fs_tskid, (INT)fs);
6068: if (err < E_OK) {
6069: (void)tk_del_tsk(fs->ff_c.fs_tskid);
6070: }
6071: }
6072: if (err < E_OK) {
6073: (void)tk_del_por(fs->ff_c.fs_porid);
6074: }
6075: }
6076: return err;
6077: }
6078:
6079: 6080: 6081:
6082: LOCAL void fatDeleteObjects(FATFS *fs)
6083: {
6084: CMDPKT pkt;
6085:
6086:
6087: pkt.cp_tskid = tk_get_tid();
6088: pkt.cp_req = NULL;
6089:
6090: (void)CallFileSystemTask(fs, &pkt);
6091:
6092:
6093: (void)tk_del_por(fs->ff_c.fs_porid);
6094: }
6095:
6096: 6097: 6098:
6099: LOCAL ER fatfs_service(fimp_t *req)
6100: {
6101: FATFS *fs;
6102: UW func;
6103: TaskSts *tsksts;
6104: ER err;
6105: CMDPKT pkt;
6106:
6107:
6108: fs = (FATFS*)fatGetReqInf(req, &func);
6109: if (fs == NULL) {
6110: err = EX_NOTSUP;
6111: } else {
6112: err = E_OK;
6113: pkt.cp_tskid = tk_get_tid();
6114: tsksts = &tskStsTab[pkt.cp_tskid];
6115:
6116:
6117: if ((func & 0x01) != 0) {
6118: tsksts->c.break_enb = 1;
6119: if (tsksts->c.break_done != 0) {
6120: err = EX_INTR;
6121: } else if (tsksts->c.break_req != 0) {
6122: err = EX_INTR;
6123: }
6124: }
6125:
6126:
6127: if (err >= E_OK) {
6128: pkt.cp_req = req;
6129: err = CallFileSystemTask(fs, &pkt);
6130: }
6131:
6132: tsksts->c.break_enb = 0;
6133: if (tsksts->c.break_done != 0) {
6134: tsksts->c.break_done = 0;
6135: }
6136: }
6137: return toEXER(err);
6138: }
6139:
6140: 6141: 6142:
6143: LOCAL void fatGetConfiguration(UB *name, INT *par)
6144: {
6145: INT val;
6146:
6147: if (tk_get_cfn(name, &val, 1) >= 1) *par = val;
6148: }
6149:
6150: 6151: 6152:
6153: LOCAL ER fatfs_registfn(fimpinf_t *fimpinf, void *exinf)
6154: {
6155: FAT_FSInfo *fpi;
6156:
6157: (void)exinf;
6158:
6159:
6160: if ((fpi = fimp_calloc(1, sizeof(FAT_FSInfo))) == NULL) {
6161: return EX_NOMEM;
6162: }
6163:
6164:
6165: tskStsTab = (TaskSts*)fimpinf->fimpsd;
6166:
6167: QueInit(&fpi->fpi_attachque);
6168: fimpinf->fimpsd = (void *)fpi;
6169:
6170:
6171: fatGetConfiguration(SYSCONF_MaxOpenF, &MaxOpenF);
6172: fatGetConfiguration(SYSCONF_TaskStackSize, &TaskStackSize);
6173: fatGetConfiguration(SYSCONF_CacheFATMemorySize, &CacheFATMemorySize);
6174: fatGetConfiguration(SYSCONF_CacheFATRatio, &CacheFATRatio);
6175: fatGetConfiguration(SYSCONF_CacheRootMemorySize, &CacheRootMemorySize);
6176: fatGetConfiguration(SYSCONF_CacheRootRatio, &CacheRootRatio);
6177: fatGetConfiguration(SYSCONF_CacheDataMemorySize, &CacheDataMemorySize);
6178: fatGetConfiguration(SYSCONF_CacheDataRatio, &CacheDataRatio);
6179: fatGetConfiguration(SYSCONF_LastAccess, &LastAccess);
6180:
6181: return E_OK;
6182: }
6183:
6184: 6185: 6186:
6187: LOCAL ER fatfs_unregistfn(fimpinf_t *fimpinf)
6188: {
6189:
6190: fimp_free(fimpinf->fimpsd);
6191: fimpinf->fimpsd = NULL;
6192: return E_OK;
6193: }
6194:
6195: 6196: 6197:
6198: LOCAL ER fatfs_attachfn(coninf_t *coninf, void *exinf)
6199: {
6200: FAT_FSInfo *fpi;
6201: FATFS *fs;
6202: ER err;
6203:
6204: (void)exinf;
6205:
6206: fpi = (FAT_FSInfo *)coninf->fimpinf->fimpsd;
6207:
6208:
6209: if ((fs = fimp_calloc(1, sizeof(FATFS))) == NULL) {
6210: err = EX_NOMEM;
6211: goto exit0;
6212: }
6213:
6214:
6215: err = fatDiskOpen(coninf, fs);
6216: if (err < E_OK) goto exit1;
6217:
6218:
6219: err = fatCheckFileSystem(fs);
6220: if (err < E_OK) goto exit2;
6221:
6222:
6223: err = fatDCacheInit(fs);
6224: if (err < E_OK) goto exit2;
6225:
6226:
6227: err = fatMapFATInit(fs);
6228: if (err < E_OK) goto exit3;
6229:
6230:
6231: err = fatCountFreeCluster(fs, &fs->ff_freecl);
6232: if (err < E_OK) goto exit4;
6233:
6234:
6235: fs->ff_c.fs_rootino = dirINO(fs, fs->ff_rootcl);
6236:
6237:
6238: err = fatGetDeviceNumber(coninf->devnm, &fs->ff_c.fs_devnum);
6239: if (err < E_OK) goto exit4;
6240:
6241:
6242: err = fatUxinfoInit(fs);
6243: if (err < E_OK) goto exit5;
6244:
6245:
6246: err = fatCreateObjects(fs);
6247:
6248: exit5:
6249: if (err < E_OK) {
6250: fatUxinfoCleanup(fs);
6251: }
6252: exit4:
6253: if (err < E_OK) {
6254: fatMapFATCleanup(fs);
6255: }
6256: exit3:
6257: if (err < E_OK) {
6258: fatDCacheCleanup(fs);
6259: }
6260: exit2:
6261: if (err < E_OK) {
6262: fatDiskClose(coninf, fs);
6263: }
6264:
6265: if (err >= E_OK) {
6266:
6267: if (fs->ff_c.fs_diskinfo.protect != 0) {
6268: coninf->dflags |= DEV_FLAG_READONLY;
6269: }
6270: if (fs->ff_c.fs_diskinfo.removable != 0) {
6271: coninf->dflags |= DEV_FLAG_REMOVABLE;
6272: }
6273: coninf->consd = (void *)fs;
6274: fs->ff_c.fs_coninf = coninf;
6275: fs->ff_c.fs_conlen = strlen(coninf->connm) + 1;
6276:
6277:
6278: QueInsert(&fs->ff_c.fs_q, &fpi->fpi_attachque);
6279: }
6280: exit1:
6281: if (err < E_OK) {
6282: fimp_free(fs);
6283: }
6284: exit0:
6285: return toEXER(err);
6286: }
6287:
6288: 6289: 6290:
6291: LOCAL ER fatfs_detachfn(coninf_t *coninf)
6292: {
6293: FATFS *fs;
6294: FATNODE *rootinode;
6295: ER err;
6296:
6297: fs = (FATFS *)coninf->consd;
6298: rootinode = NULL;
6299:
6300: (void)fatGetRootINODE(fs, &rootinode);
6301: fatInodeRegister((FS *)fs, (INODE *)rootinode, O_RDONLY);
6302: fatInodeRelease((FS *)fs, (INODE *)
6303: fs->ff_c.fs_uxinfo.uxi_curdir.cd_inode, O_RDONLY);
6304: fs->ff_c.fs_uxinfo.uxi_curdir.cd_inode = (INODE *)rootinode;
6305:
6306: err = fatInodeCheckEmpty(&fs->ff_c, (INODE *)rootinode);
6307: if (err >= E_OK) {
6308:
6309: QueRemove(&fs->ff_c.fs_q);
6310:
6311:
6312: fatUxinfoCleanup(fs);
6313: fatDeleteObjects(fs);
6314: fatMapFATCleanup(fs);
6315: fatDCacheCleanup(fs);
6316: fatDiskClose(coninf, fs);
6317: fimp_free(fs);
6318: coninf->consd = NULL;
6319: }
6320: return err;
6321: }
6322:
6323: 6324: 6325:
6326: LOCAL ER fatfs_breakfn(coninf_t *coninf, ID tskid, BOOL set)
6327: {
6328: FATFS *fs;
6329: TaskSts *tsksts;
6330:
6331: fs = (FATFS *)coninf->consd;
6332: tsksts = &tskStsTab[tskid];
6333:
6334: 6335:
6336: tk_dis_dsp();
6337: if (set != FALSE) {
6338: if (tsksts->c.break_enb != 0) {
6339:
6340: tsksts->c.break_done = 1;
6341: } else {
6342:
6343: tsksts->c.break_req = 1;
6344: }
6345: } else {
6346:
6347: tsksts->w = 0;
6348: }
6349: tk_ena_dsp();
6350:
6351: return E_OK;
6352: }
6353: