19
#include <drivers/block_dev.h>
20
#include <fs/dir_context.h>
22
#include <fs/inode_operation.h>
24
#include <fs/super_block.h>
33
#include <framework/mod/options.h>
35
#define FAT_USE_LONG_NAMES OPTION_GET(BOOLEAN, fat_max_sector_size)
37
#if OPTION_GET(STRING, log_level) >= 4
38
void fat_volinfo_print(struct volinfo *volinfo) {
39
log_debug("volinfo->label(%s)", volinfo->label);
40
log_debug("volinfo->unit(%x)", volinfo->unit);
41
log_debug("volinfo->filesystem(%x)", volinfo->filesystem);
42
log_debug("volinfo->startsector(%d)", volinfo->startsector);
43
log_debug("volinfo->bytepersec(%d)", volinfo->bytepersec);
44
log_debug("volinfo->secperclus(%d)", volinfo->secperclus);
45
log_debug("volinfo->reservedsecs(%d)", volinfo->reservedsecs);
46
log_debug("volinfo->numsecs(%d)", volinfo->numsecs);
47
log_debug("volinfo->secperfat(%d)", volinfo->secperfat);
48
log_debug("volinfo->rootentries(%d)", volinfo->rootentries);
49
log_debug("volinfo->numclusters(%d)", volinfo->numclusters);
50
log_debug("volinfo->fat1(%d)", volinfo->fat1);
51
log_debug("volinfo->rootdir(%d)", volinfo->rootdir);
52
log_debug("volinfo->dataarea(%d)", volinfo->dataarea);
55
#define fat_volinfo_print(volinfo)
58
#define LABEL "EMBOX_DISK "
59
#define SYSTEM12 "FAT12 "
60
#define SYSTEM16 "FAT16 "
61
#define SYSTEM32 "FAT32 "
63
uint8_t fat_sector_buff[FAT_MAX_SECTOR_SIZE] __attribute__((aligned(16)));
65
static const char bootcode[130] =
66
{ 0x0e, 0x1f, 0xbe, 0x5b, 0x7c, 0xac, 0x22, 0xc0, 0x74, 0x0b,
67
0x56, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0x5e, 0xeb,
68
0xf0, 0x32, 0xe4, 0xcd, 0x16, 0xcd, 0x19, 0xeb, 0xfe, 0x54,
69
0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74,
70
0x20, 0x61, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c,
71
0x65, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x2e, 0x20, 0x20, 0x50,
72
0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x65,
73
0x72, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61,
74
0x62, 0x6c, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x70, 0x70, 0x79,
75
0x20, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x70, 0x72, 0x65, 0x73,
76
0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20,
77
0x74, 0x6f, 0x20, 0x74, 0x72, 0x79, 0x20, 0x61, 0x67, 0x61,
78
0x69, 0x6e, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x0d, 0x0a, 0x00 };
80
static uint32_t fat_dir_rewind(struct dirinfo *di, int n);
81
static uint32_t fat_write_de(struct dirinfo *di, struct fat_dirent *de);
82
static uint32_t fat_get_free_entries(struct dirinfo *dir, int n);
83
static uint32_t fat_dir_extend(struct dirinfo *di);
84
int fat_read_sector(struct fat_fs_info *fsi, uint8_t *buffer, uint32_t sector) {
87
int blkpersec = fsi->vi.bytepersec / fsi->bdev->block_size;
89
log_debug("sector(%d), fsi: bytepersec(%d), bdev->block_size(%d)",
90
sector, fsi->vi.bytepersec, fsi->bdev->block_size);
91
blk = sector * blkpersec;
93
ret = block_dev_read(fsi->bdev, (char*) buffer, fsi->vi.bytepersec, blk);
94
if (ret != fsi->vi.bytepersec)
100
int fat_write_sector(struct fat_fs_info *fsi, uint8_t *buffer, uint32_t sector) {
103
int blkpersec = fsi->vi.bytepersec / fsi->bdev->block_size;
105
log_debug("sector(%d), fsi: bytepersec(%d), bdev->block_size(%d)",
106
sector, fsi->vi.bytepersec, fsi->bdev->block_size);
108
blk = sector * blkpersec;
109
ret = block_dev_write(fsi->bdev, (char*) buffer, fsi->vi.bytepersec, blk);
110
if (ret != fsi->vi.bytepersec)
116
uint32_t fat_current_dirsector(struct dirinfo *di) {
117
struct fat_fs_info *fsi = di->fi.fsi;
118
struct volinfo *vi = &fsi->vi;
120
if (di->fi.dirsector == 0 &&
121
(vi->filesystem == FAT12 || vi->filesystem == FAT16)) {
122
return fsi->vi.secperclus * di->currentcluster + di->currentsector;
124
return fat_sec_by_clus(fsi, di->currentcluster) + di->currentsector;
136
int read_dir_buf(struct dirinfo *di) {
137
struct fat_fs_info *fsi = di->fi.fsi;
140
sector = fat_current_dirsector(di);
142
return fat_read_sector(fsi, di->p_scratch, sector);
145
uint32_t fat_direntry_get_clus(struct fat_dirent *de) {
146
return (uint32_t) de->startclus_l_l |
147
((uint32_t) de->startclus_l_h) << 8 |
148
((uint32_t) de->startclus_h_l) << 16 |
149
((uint32_t) de->startclus_h_h) << 24;
152
void fat_direntry_set_clus(struct fat_dirent *de, uint32_t clus) {
153
de->startclus_l_l = clus & 0xff;
154
de->startclus_l_h = (clus & 0xff00) >> 8;
155
de->startclus_h_l = (clus & 0xff0000) >> 16;
156
de->startclus_h_h = (clus & 0xff000000) >> 24;
159
uint32_t fat_direntry_get_size(struct fat_dirent *de) {
160
return (uint32_t) de->filesize_0 |
161
((uint32_t) de->filesize_1) << 8 |
162
((uint32_t) de->filesize_2) << 16 |
163
((uint32_t) de->filesize_3) << 24;
166
void fat_direntry_set_size(struct fat_dirent *de, uint32_t size) {
167
de->filesize_0 = size & 0xff;
168
de->filesize_1 = (size & 0xff00) >> 8;
169
de->filesize_2 = (size & 0xff0000) >> 16;
170
de->filesize_3 = (size & 0xff000000) >> 24;
180
int fat_create_partition(void *dev, int fat_n) {
181
struct block_dev *bdev = dev;
182
uint16_t bytepersec = bdev->block_size;
183
size_t num_sect = block_dev(bdev)->size / bytepersec;
184
assert(bdev->block_size <= FAT_MAX_SECTOR_SIZE);
185
uint32_t secperfat = 1;
186
uint16_t rootentries = 0x0200;
193
struct lbr lbr = (struct lbr) {
194
.jump = {0xeb, 0x3c, 0x90},
195
.oemid = {0x45, 0x45, 0x45, 0x45,
196
0x45, 0x45, 0x45, 0x45},
198
.bytepersec_l = (uint8_t)(bytepersec & 0xFF),
199
.bytepersec_h = (uint8_t)((bytepersec & 0xFF00) >> 8),
204
.rootentries_l = (uint8_t)(0x00FF & rootentries ),
205
.rootentries_h = (uint8_t)(0x00FF & (rootentries >> 8)),
216
if (0xFFFF > num_sect) {
217
lbr.bpb.sectors_s_l = (uint8_t)(0x00000FF & num_sect);
218
lbr.bpb.sectors_s_h = (uint8_t)(0x00000FF & (num_sect >> 8));
220
lbr.bpb.sectors_l_0 = (uint8_t)(0x00000FF & num_sect );
221
lbr.bpb.sectors_l_1 = (uint8_t)(0x00000FF & (num_sect >> 8));
222
lbr.bpb.sectors_l_2 = (uint8_t)(0x00000FF & (num_sect >> 16));
223
lbr.bpb.sectors_l_3 = (uint8_t)(0x00000FF & (num_sect >> 24));
229
lbr.bpb.secperfat_l = (uint8_t)(0x00FF & secperfat),
230
lbr.bpb.secperfat_h = (uint8_t)(0x00FF & (secperfat >> 8)),
231
lbr.ebpb.ebpb = (struct ebpb) {
240
memcpy(lbr.ebpb.ebpb.label, LABEL, sizeof(lbr.ebpb.ebpb.label));
241
memcpy(lbr.ebpb.ebpb.system,
242
fat_n == 12 ? SYSTEM12:SYSTEM16,
243
sizeof(lbr.ebpb.ebpb.system));
245
memcpy(lbr.ebpb.ebpb.code, bootcode, sizeof(bootcode));
248
lbr.ebpb.ebpb32 = (struct ebpb32) {
249
.fatsize_0 = (uint8_t) (0xFF & secperfat),
250
.fatsize_1 = (uint8_t) (0xFF & (secperfat >> 8)),
251
.fatsize_2 = (uint8_t) (0xFF & (secperfat >> 16)),
252
.fatsize_3 = (uint8_t) (0xFF & (secperfat >> 24)),
267
memcpy(lbr.ebpb.ebpb32.label, LABEL, sizeof(lbr.ebpb.ebpb32.label));
268
memcpy(lbr.ebpb.ebpb32.system, SYSTEM32, sizeof(lbr.ebpb.ebpb32.system));
269
memcpy(lbr.ebpb.ebpb32.code, bootcode, sizeof(bootcode));
275
if (0 > (err = block_dev_write(bdev, (void *) &lbr, sizeof(lbr), 0)))
279
memset(fat_sector_buff, 0, sizeof(fat_sector_buff));
280
reserved = (uint16_t) lbr.bpb.reserved_l |
281
(((uint16_t) lbr.bpb.reserved_h) << 8);
282
fat_size = lbr.bpb.numfats * secperfat;
283
blkpersec = bytepersec / bdev->block_size;
285
for (i = reserved; i < reserved + fat_size; i++)
286
if (0 > (err = block_dev_write(bdev, (void*) fat_sector_buff, sizeof(fat_sector_buff), i * blkpersec)))
301
uint32_t fat_get_ptn_start(void *bdev, uint8_t pnum, uint8_t *pactive,
302
uint8_t *pptype, uint32_t *psize) {
304
struct mbr *mbr = (struct mbr*) fat_sector_buff;
311
if (0 > block_dev_read(bdev, (char *) fat_sector_buff, sizeof(struct mbr), 0)) {
315
if ((mbr->bootcode[0] == 0xeb) &&
316
(mbr->bootcode[1] == 0x3c) &&
317
(mbr->bootcode[2] == 0x90)) {
321
result = (uint32_t) mbr->ptable[pnum].start_0 |
322
(((uint32_t) mbr->ptable[pnum].start_1) << 8) |
323
(((uint32_t) mbr->ptable[pnum].start_2) << 16) |
324
(((uint32_t) mbr->ptable[pnum].start_3) << 24);
327
*pactive = mbr->ptable[pnum].active;
331
*pptype = mbr->ptable[pnum].type;
335
*psize = (uint32_t) mbr->ptable[pnum].size_0 |
336
(((uint32_t) mbr->ptable[pnum].size_1) << 8) |
337
(((uint32_t) mbr->ptable[pnum].size_2) << 16) |
338
(((uint32_t) mbr->ptable[pnum].size_3) << 24);
351
uint32_t fat_get_volinfo(void *bdev, struct volinfo * volinfo, uint32_t startsector) {
352
struct lbr *lbr = (struct lbr *) fat_sector_buff;
354
log_debug("startsector %d", startsector);
356
if (0 > block_dev_read(bdev,
357
(char *) fat_sector_buff,
363
volinfo->bytepersec = lbr->bpb.bytepersec_l + (lbr->bpb.bytepersec_h << 8);
364
volinfo->startsector = startsector;
365
volinfo->secperclus = lbr->bpb.secperclus;
366
volinfo->reservedsecs = (uint16_t) lbr->bpb.reserved_l |
367
(((uint16_t) lbr->bpb.reserved_h) << 8);
369
volinfo->numsecs = (uint16_t) lbr->bpb.sectors_s_l |
370
(((uint16_t) lbr->bpb.sectors_s_h) << 8);
372
if (!volinfo->numsecs)
373
volinfo->numsecs = (uint32_t) lbr->bpb.sectors_l_0 |
374
(((uint32_t) lbr->bpb.sectors_l_1) << 8) |
375
(((uint32_t) lbr->bpb.sectors_l_2) << 16) |
376
(((uint32_t) lbr->bpb.sectors_l_3) << 24);
381
volinfo->secperfat = (uint16_t) lbr->bpb.secperfat_l |
382
(((uint16_t) lbr->bpb.secperfat_h) << 8);
384
if (!volinfo->secperfat) {
385
volinfo->secperfat = (uint32_t) lbr->ebpb.ebpb32.fatsize_0 |
386
(((uint32_t) lbr->ebpb.ebpb32.fatsize_1) << 8) |
387
(((uint32_t) lbr->ebpb.ebpb32.fatsize_2) << 16) |
388
(((uint32_t) lbr->ebpb.ebpb32.fatsize_3) << 24);
390
memcpy(volinfo->label, lbr->ebpb.ebpb32.label, MSDOS_NAME);
391
volinfo->label[11] = 0;
393
memcpy(volinfo->label, lbr->ebpb.ebpb.label, MSDOS_NAME);
394
volinfo->label[11] = 0;
398
volinfo->rootentries = (uint16_t) lbr->bpb.rootentries_l |
399
(((uint16_t) lbr->bpb.rootentries_h) << 8);
401
volinfo->fat1 = startsector + volinfo->reservedsecs;
409
if (volinfo->rootentries) {
410
volinfo->rootdir = volinfo->fat1 + (volinfo->secperfat * 2);
411
volinfo->dataarea = volinfo->rootdir
412
+ (((volinfo->rootentries * 32) + (volinfo->bytepersec - 1))
413
/ volinfo->bytepersec);
415
volinfo->dataarea = volinfo->fat1 + (volinfo->secperfat * 2);
416
volinfo->rootdir = (uint32_t) lbr->ebpb.ebpb32.root_0 |
417
(((uint32_t) lbr->ebpb.ebpb32.root_1) << 8) |
418
(((uint32_t) lbr->ebpb.ebpb32.root_2) << 16) |
419
(((uint32_t) lbr->ebpb.ebpb32.root_3) << 24);
422
if (0 == volinfo->secperclus) {
423
volinfo->numclusters = 0;
424
fat_volinfo_print(volinfo);
427
volinfo->numclusters = (volinfo->numsecs - volinfo->dataarea) /
431
if (volinfo->numclusters < 4085) {
432
volinfo->filesystem = FAT12;
433
} else if (volinfo->numclusters < 65525) {
434
volinfo->filesystem = FAT16;
436
volinfo->filesystem = FAT32;
439
fat_volinfo_print(volinfo);
450
uint32_t fat_get_fat(struct fat_fs_info *fsi,
451
uint8_t *p_scratch, uint32_t cluster) {
452
uint32_t offset, sector, result;
453
struct volinfo *volinfo = &fsi->vi;
455
switch (volinfo->filesystem) {
457
offset = cluster + (cluster / 2);
460
offset = cluster * 2;
463
offset = cluster * 4;
469
sector = offset / volinfo->bytepersec + volinfo->fat1;
471
if (fat_read_sector(fsi, p_scratch, sector)) {
482
offset %= volinfo->bytepersec;
483
if (volinfo->filesystem == FAT12) {
488
if (offset == volinfo->bytepersec - 1) {
489
result = (uint32_t) p_scratch[offset];
491
if (fat_read_sector(fsi, p_scratch, sector)) {
494
result |= ((uint32_t) p_scratch[0]) << 8;
496
result = (uint32_t) p_scratch[offset] |
497
((uint32_t) p_scratch[offset+1]) << 8;
500
result = result >> 4;
502
result = result & 0xfff;
503
} else if (volinfo->filesystem == FAT16) {
504
result = (uint32_t) p_scratch[offset] |
505
((uint32_t) p_scratch[offset+1]) << 8;
506
} else if (volinfo->filesystem == FAT32) {
507
result = ((uint32_t) p_scratch[offset] |
508
((uint32_t) p_scratch[offset+1]) << 8 |
509
((uint32_t) p_scratch[offset+2]) << 16 |
510
((uint32_t) p_scratch[offset+3]) << 24) & 0x0fffffff;
512
result = DFS_BAD_CLUS;
517
static uint32_t fat_end_of_chain(struct fat_fs_info *fsi) {
518
switch(fsi->vi.filesystem) {
530
static uint32_t fat_is_end_of_chain(struct fat_fs_info *fsi, uint32_t clus) {
531
switch (fsi->vi.filesystem) {
533
return clus >= 0xff7;
535
return clus >= 0xfff7;
537
return clus >= 0xffffff7;
549
static uint32_t fat_set_fat(struct fat_fs_info *fsi, uint8_t *p_scratch,
550
uint32_t cluster, uint32_t new_contents) {
551
uint32_t offset, sector, result;
552
struct volinfo *volinfo = &fsi->vi;
554
switch (volinfo->filesystem) {
556
offset = cluster + (cluster / 2);
559
offset = cluster * 2;
562
offset = cluster * 4;
568
new_contents &= fat_end_of_chain(fsi);
574
sector = offset / volinfo->bytepersec + volinfo->fat1;
576
if (fat_read_sector(fsi, p_scratch, sector)) {
587
offset %= volinfo->bytepersec;
589
switch (volinfo->filesystem) {
592
new_contents = new_contents << 4;
594
if (offset == volinfo->bytepersec - 1) {
597
p_scratch[offset] = (p_scratch[offset] & 0x0f) |
598
(new_contents & 0xf0);
602
p_scratch[offset] = new_contents & 0xff;
604
result = fat_write_sector(fsi, p_scratch, sector);
606
if (DFS_OK == result) {
607
result = fat_write_sector(fsi, p_scratch,
608
sector + volinfo->secperfat);
615
if (DFS_OK == result) {
616
result = fat_read_sector(fsi, p_scratch, ++sector);
617
if (DFS_OK == result) {
620
p_scratch[0] = new_contents & 0xff00;
624
p_scratch[0] = (p_scratch[0] & 0xf0) |
625
(new_contents & 0x0f);
627
result = fat_write_sector(fsi, p_scratch, sector);
629
if (DFS_OK == result) {
630
result = fat_write_sector(fsi, p_scratch,
631
sector+volinfo->secperfat);
644
p_scratch[offset] = (p_scratch[offset] & 0x0f) |
645
(new_contents & 0xf0);
646
p_scratch[offset + 1] = (new_contents & 0xff00) >> 8;
650
p_scratch[offset] = new_contents & 0xff;
651
p_scratch[offset+1] = (p_scratch[offset+1] & 0xf0) |
652
((new_contents & 0x0f00) >> 8);
654
result = fat_write_sector(fsi, p_scratch, sector);
656
if (DFS_OK == result) {
657
result = fat_write_sector(fsi, p_scratch,
658
sector + volinfo->secperfat);
663
p_scratch[offset + 3] = (p_scratch[offset + 3] & 0xf0) |
664
((new_contents & 0x0f000000) >> 24);
665
p_scratch[offset + 2] = (new_contents & 0xff0000) >> 16;
668
p_scratch[offset + 1] = (new_contents & 0xff00) >> 8;
669
p_scratch[offset] = (new_contents & 0xff);
670
result = fat_write_sector(fsi, p_scratch, sector);
672
if (DFS_OK == result)
673
result = fat_write_sector(
676
sector + volinfo->secperfat
680
result = DFS_ERRMISC;
688
static void fat_append_longname(char *name, struct fat_dirent *di) {
689
struct fat_long_dirent *ld;
690
const int chars_per_long_entry = 13;
698
l = chars_per_long_entry * ((di->name[0] & FAT_LONG_ORDER_NUM_MASK) - 1);
700
name[l++] = (char) ld->name1[0];
701
name[l++] = (char) ld->name1[2];
702
name[l++] = (char) ld->name1[4];
703
name[l++] = (char) ld->name1[6];
704
name[l++] = (char) ld->name1[8];
706
name[l++] = (char) ld->name2[0];
707
name[l++] = (char) ld->name2[2];
708
name[l++] = (char) ld->name2[4];
709
name[l++] = (char) ld->name2[6];
710
name[l++] = (char) ld->name2[8];
711
name[l++] = (char) ld->name2[10];
713
name[l++] = (char) ld->name3[0];
714
name[l++] = (char) ld->name3[2];
716
if (di->name[0] & FAT_LONG_ORDER_LAST) {
728
static uint32_t fat_get_free_fat(struct fat_fs_info *fsi, uint8_t *p_scratch) {
735
for (i = 2; i < fsi->vi.numclusters; i++) {
736
if (!fat_get_fat(fsi, p_scratch, i)) {
743
uint32_t fat_open_rootdir(struct fat_fs_info *fsi, struct dirinfo *dirinfo) {
744
struct volinfo *volinfo;
752
dirinfo->fi.mode = S_IFDIR;
753
dirinfo->currentsector = volinfo->rootdir % volinfo->secperclus;
754
dirinfo->currentcluster = volinfo->rootdir / volinfo->secperclus;
756
log_debug("dirinfo: p_scratch(%p), currentsector(%d), currentcluster(%d)",
757
dirinfo->p_scratch, dirinfo->currentsector, dirinfo->currentcluster);
758
log_debug("volinfo: secperclus %d rootdir %d", volinfo->secperclus, volinfo->rootdir);
760
ret = fat_read_sector(fsi, dirinfo->p_scratch, volinfo->rootdir);
765
static uint32_t fat_fetch_dir(struct dirinfo *dir) {
766
struct fat_fs_info *fsi = dir->fi.fsi;
767
struct volinfo *volinfo = &fsi->vi;
768
int ent_per_sec = volinfo->bytepersec / sizeof(struct fat_dirent);
771
if (dir->currententry >= ent_per_sec) {
773
dir->currententry = 0;
774
dir->currentsector++;
782
if (dir->currentcluster == 0) {
784
next_ent = dir->currentsector * volinfo->bytepersec;
785
next_ent /= sizeof(struct fat_dirent);
786
if (next_ent >= volinfo->rootentries)
790
if (fat_read_sector(fsi, dir->p_scratch, dir->currentsector))
793
if (dir->currentsector >= volinfo->secperclus) {
796
dir->currentsector = 0;
798
tempclus = fat_get_fat(fsi,
800
dir->currentcluster);
802
if (fat_is_end_of_chain(fsi, tempclus)) {
805
dir->currentcluster = tempclus;
809
read_sector = fat_current_dirsector(dir);
811
if (fat_read_sector(fsi, dir->p_scratch, read_sector))
819
static uint32_t fat_get_current(struct dirinfo *dir, struct fat_dirent *dirent) {
820
struct fat_dirent *dirent_src;
824
if (DFS_OK != (tmp = fat_fetch_dir(dir))) {
828
dirent_src = &((struct fat_dirent *) dir->p_scratch)[dir->currententry];
829
memcpy(dirent, dirent_src, sizeof(struct fat_dirent));
831
if (dirent->name[0] == '\0') {
835
if (dirent->name[0] == 0xe5) {
836
dirent->name[0] = '\0';
853
uint32_t fat_get_next(struct dirinfo *dir, struct fat_dirent *dirent) {
854
struct fat_dirent *dirent_src;
857
dirent->name[0] = '\0';
859
log_debug("dir->currententry %d", dir->currententry);
861
if (DFS_OK != (tmp = fat_fetch_dir(dir))) {
862
if (tmp == DFS_ALLOCNEW) {
863
if (DFS_OK != (tmp = fat_dir_extend(dir))) {
871
dirent_src = &((struct fat_dirent *) dir->p_scratch)[dir->currententry];
872
memcpy(dirent, dirent_src, sizeof(struct fat_dirent));
873
log_debug("dir: p_scratch = %p, currententry = %d",dir->p_scratch, dir->currententry);
874
log_debug("dirent->name (%s), dirent->name[0]=0x%x", dirent->name, dirent->name[0]);
876
if (dirent->name[0] == '\0') {
877
if (dir->flags & DFS_DI_BLANKENT) {
885
if (dirent->name[0] == 0xe5) {
886
memset(dirent, 0, sizeof(*dirent));
887
} else if (dirent->name[0] == 0x05)
889
dirent->name[0] = 0xe5;
897
uint32_t fat_get_next_long(struct dirinfo *dir, struct fat_dirent *dirent, char *name_buf) {
903
assert(dir->p_scratch);
908
ret = fat_get_next(dir, dirent);
909
if (ret == DFS_EOF) {
912
} while (dirent->name[0] == '\0');
914
if (dirent->attr != ATTR_LONG_NAME) {
915
if (name_buf != NULL) {
917
for (i = 0; i < 8; i++) {
931
if (dirent->name[8] != ' ') {
933
for (i = 8; i < 11; i++) {
950
while (dirent->attr == ATTR_LONG_NAME) {
951
if (name_buf != NULL) {
952
fat_append_longname(name_buf, dirent);
954
ret = fat_get_next(dir, dirent);
964
static uint32_t fat_clear_clus(struct fat_fs_info *fsi,
965
uint32_t clus, uint8_t *p_scratch) {
971
sec = fat_sec_by_clus(fsi, clus);
973
memset(p_scratch, 0, fsi->vi.bytepersec);
974
for (int i = 0; i < fsi->vi.secperclus; i++) {
975
if (fat_write_sector(fsi, p_scratch, sec + i)) {
983
static uint32_t fat_dir_extend(struct dirinfo *di) {
984
struct fat_fs_info *fsi = di->fi.fsi;
986
clus = fat_get_free_fat(fsi, di->p_scratch);
987
if (clus == DFS_BAD_CLUS) {
991
if (0 != fat_clear_clus(fsi, clus, di->p_scratch)) {
995
fat_set_fat(fsi, di->p_scratch, di->currentcluster, clus);
997
di->currentcluster = clus;
998
di->currentsector = 0;
999
di->currententry = 0;
1001
clus = fat_end_of_chain(fsi);
1003
fat_set_fat(fsi, di->p_scratch, di->currentcluster, clus);
1020
static uint32_t fat_get_free_dir_ent(struct dirinfo *di, struct fat_dirent *de) {
1025
ret = fat_get_current(di, de);
1027
if (ret == DFS_EOF) {
1031
if (ret == DFS_OK) {
1032
if (de->name[0] == '\0') {
1040
ret = fat_fetch_dir(di);
1041
if (ret == DFS_ALLOCNEW) {
1043
if (DFS_OK != (ret = fat_dir_extend(di))) {
1055
static void fat_set_direntry(uint32_t dir_cluster, uint32_t cluster) {
1056
struct fat_dirent *de = (struct fat_dirent *) fat_sector_buff;
1058
de[0] = (struct fat_dirent) {
1060
.attr = ATTR_DIRECTORY,
1062
fat_direntry_set_clus(&de[0], cluster);
1064
de[1] = (struct fat_dirent) {
1065
.name = MSDOS_DOTDOT,
1066
.attr = ATTR_DIRECTORY,
1068
fat_direntry_set_clus(&de[1], dir_cluster);
1070
fat_set_filetime(&de[0]);
1071
fat_set_filetime(&de[1]);
1074
int fat_root_dir_record(void *bdev) {
1076
struct fat_fs_info fsi;
1077
uint32_t pstart, psize;
1078
uint8_t pactive, ptype;
1079
struct fat_dirent de;
1080
int dev_blk_size = block_dev(bdev)->block_size;
1083
assert(dev_blk_size > 0);
1088
pstart = fat_get_ptn_start(bdev, 0, &pactive, &ptype, &psize);
1089
if (pstart == 0xffffffff) {
1093
if (fat_get_volinfo(bdev, &fsi.vi, pstart)) {
1097
cluster = fsi.vi.rootdir / fsi.vi.secperclus;
1099
de = (struct fat_dirent) {
1100
.name = "ROOT DIR ",
1101
.attr = ATTR_DIRECTORY,
1103
fat_direntry_set_clus(&de, cluster);
1105
fat_set_filetime(&de);
1114
memset(fat_sector_buff, 0, sizeof(fat_sector_buff));
1115
memcpy(&(((struct fat_dirent*) fat_sector_buff)[0]), &de, sizeof(struct fat_dirent));
1117
if (0 > block_dev_write( bdev,
1118
(char *) fat_sector_buff,
1120
fsi.vi.rootdir * fsi.vi.bytepersec / dev_blk_size)) {
1124
root_dir_sz = (fsi.vi.rootentries * sizeof(struct fat_dirent) +
1125
fsi.vi.bytepersec - 1) / fsi.vi.bytepersec - 1;
1128
memset(fat_sector_buff, 0, sizeof(struct fat_dirent));
1130
while (root_dir_sz) {
1131
block_dev_write(bdev,
1132
(char *) fat_sector_buff,
1134
(root_dir_sz + fsi.vi.rootdir) * fsi.vi.bytepersec / dev_blk_size);
1138
cluster = fat_end_of_chain(&fsi);
1139
fat_set_fat(&fsi, fat_sector_buff, cluster, cluster);
1151
uint32_t fat_read_file(struct fat_file_info *fi, uint8_t *p_scratch,
1152
uint8_t *buffer, uint32_t *successcount, uint32_t len) {
1157
uint32_t clastersize;
1158
struct fat_fs_info *fsi;
1161
log_debug("len(%d) volinfo: secperclus(%d), bytepersec(%d)",
1162
len, fi->volinfo->secperclus, fi->volinfo->bytepersec );
1167
clastersize = fi->volinfo->secperclus * fi->volinfo->bytepersec;
1169
while (remain && result == DFS_OK) {
1174
sector = fi->volinfo->dataarea +
1175
((fi->cluster - 2) * fi->volinfo->secperclus) +
1176
div(div(fi->pointer, clastersize).rem, fi->volinfo->bytepersec).quot;
1179
if (div(fi->pointer, fi->volinfo->bytepersec).rem) {
1180
uint16_t tempreadsize;
1183
result = fat_read_sector(fsi, p_scratch, sector);
1189
tempreadsize = fi->volinfo->bytepersec -
1190
(div(fi->pointer, fi->volinfo->bytepersec).rem);
1197
if (remain >= tempreadsize) {
1198
memcpy(buffer, p_scratch + (fi->volinfo->bytepersec - tempreadsize),
1200
bytesread = tempreadsize;
1201
buffer += tempreadsize;
1202
fi->pointer += tempreadsize;
1203
remain -= tempreadsize;
1207
memcpy(buffer, p_scratch +
1208
(fi->volinfo->bytepersec - tempreadsize), remain);
1211
fi->pointer += remain;
1228
if (remain >= fi->volinfo->bytepersec) {
1229
result = fat_read_sector(fsi, buffer, sector);
1230
remain -= fi->volinfo->bytepersec;
1231
buffer += fi->volinfo->bytepersec;
1232
fi->pointer += fi->volinfo->bytepersec;
1233
bytesread = fi->volinfo->bytepersec;
1237
result = fat_read_sector(fsi, p_scratch, sector);
1238
memcpy(buffer, p_scratch, remain);
1240
fi->pointer += remain;
1246
*successcount += bytesread;
1248
if (div(fi->pointer - bytesread, clastersize).quot !=
1249
div(fi->pointer, clastersize).quot) {
1250
if (fat_is_end_of_chain(fsi, fi->cluster)) {
1253
fi->cluster = fat_get_fat(fsi, p_scratch, fi->cluster);
1269
uint32_t fat_write_file(struct fat_file_info *fi, uint8_t *p_scratch,
1270
uint8_t *buffer, uint32_t *successcount, uint32_t len, size_t *size) {
1272
uint32_t result = DFS_OK;
1274
uint32_t byteswritten;
1275
uint32_t lastcluster, nextcluster;
1276
uint32_t clastersize;
1277
uint32_t new_clus = 0;
1278
struct fat_fs_info *fsi;
1281
if (!(fi->mode & O_WRONLY) && !(fi->mode & O_APPEND) && !(fi->mode & O_RDWR)) {
1285
log_debug("len(%d) volinfo: secperclus(%d), bytepersec(%d)",
1286
len, fi->volinfo->secperclus, fi->volinfo->bytepersec );
1288
if (fi->firstcluster == 0) {
1289
new_clus = fat_get_free_fat(fsi, fat_sector_buff);
1290
fat_set_fat(fsi, fat_sector_buff, new_clus, fat_end_of_chain(fsi));
1291
fi->firstcluster = fi->cluster = new_clus;
1296
clastersize = fi->volinfo->secperclus * fi->volinfo->bytepersec;
1298
while (remain && result == DFS_OK) {
1305
sector = fi->volinfo->dataarea +
1306
((fi->cluster - 2) * fi->volinfo->secperclus) +
1307
div(div(fi->pointer, clastersize).rem, fi->volinfo->bytepersec).quot;
1310
if (div(fi->pointer, fi->volinfo->bytepersec).rem) {
1314
result = fat_read_sector(fsi, p_scratch, sector);
1320
tempsize = div(fi->pointer, fi->volinfo->bytepersec).rem;
1329
if (remain >= fi->volinfo->bytepersec - tempsize) {
1330
memcpy(p_scratch + tempsize, buffer, fi->volinfo->bytepersec - tempsize);
1332
result = fat_write_sector(fsi, p_scratch, sector);
1335
byteswritten = fi->volinfo->bytepersec - tempsize;
1336
buffer += fi->volinfo->bytepersec - tempsize;
1337
fi->pointer += fi->volinfo->bytepersec - tempsize;
1338
if (*size < fi->pointer) {
1339
*size = fi->pointer;
1341
remain -= fi->volinfo->bytepersec - tempsize;
1345
memcpy(p_scratch + tempsize, buffer, remain);
1347
result = fat_write_sector(fsi, p_scratch, sector);
1351
fi->pointer += remain;
1352
if (*size < fi->pointer) {
1353
*size = fi->pointer;
1355
byteswritten = remain;
1366
if (remain >= fi->volinfo->bytepersec) {
1367
result = fat_write_sector(fsi, buffer, sector);
1368
remain -= fi->volinfo->bytepersec;
1369
buffer += fi->volinfo->bytepersec;
1370
fi->pointer += fi->volinfo->bytepersec;
1371
if (*size < fi->pointer) {
1372
*size = fi->pointer;
1374
byteswritten = fi->volinfo->bytepersec;
1386
if (fi->pointer < *size) {
1387
result = fat_read_sector(fsi, p_scratch, sector);
1389
memcpy(p_scratch, buffer, remain);
1390
result = fat_write_sector(fsi, p_scratch, sector);
1394
memset(p_scratch, 0, fi->volinfo->bytepersec);
1395
memcpy(p_scratch, buffer, remain);
1396
result = fat_write_sector(fsi, p_scratch, sector);
1400
fi->pointer += remain;
1401
if (*size < fi->pointer) {
1402
*size = fi->pointer;
1404
byteswritten = remain;
1409
*successcount += byteswritten;
1412
if (div(fi->pointer - byteswritten, clastersize).quot !=
1413
div(fi->pointer, clastersize).quot) {
1423
lastcluster = fi->cluster;
1424
fi->cluster = fat_get_fat(fsi, p_scratch, fi->cluster);
1427
if (fat_is_end_of_chain(fsi, fi->cluster)) {
1429
tempclus = fat_get_free_fat(fsi, p_scratch);
1430
if (tempclus == DFS_BAD_CLUS)
1433
fat_set_fat(fsi, p_scratch, lastcluster, tempclus);
1434
fi->cluster = tempclus;
1435
tempclus = fat_end_of_chain(fsi);
1436
fat_set_fat(fsi, p_scratch, fi->cluster, tempclus);
1444
if (0 && *size > fi->pointer) {
1445
if (div(*size, clastersize).quot !=
1446
div(fi->pointer, clastersize).quot) {
1448
nextcluster = fat_get_fat(fsi, p_scratch, fi->cluster);
1450
lastcluster = fat_end_of_chain(fsi);
1451
fat_set_fat(fsi, p_scratch, fi->cluster, lastcluster);
1454
while (!fat_is_end_of_chain(fsi, nextcluster)) {
1455
lastcluster = nextcluster;
1456
nextcluster = fat_get_fat(fsi, p_scratch, nextcluster);
1458
fat_set_fat(fsi, p_scratch, lastcluster, 0);
1465
if (fat_read_sector(fsi, p_scratch, fi->dirsector)) {
1469
if (new_clus != 0) {
1470
fat_direntry_set_clus(&((struct fat_dirent*) p_scratch)[fi->diroffset], new_clus);
1473
fat_direntry_set_size(&((struct fat_dirent*) p_scratch)[fi->diroffset], *size);
1475
if (fat_write_sector(fsi, p_scratch, fi->dirsector)) {
1482
static void fat_dir_clean_long(struct dirinfo *di, struct fat_file_info *fi) {
1483
struct fat_dirent de = { };
1484
struct dirinfo saved_di = { };
1485
struct dirinfo last_di = { };
1486
void *p_scratch = di->p_scratch;
1487
struct fat_fs_info *fsi = fi->fsi;
1491
if (read_dir_buf(di)) {
1496
memcpy(&last_di, di, sizeof(last_di));
1498
fat_get_next(di, &de);
1500
if (fi->cluster == fat_direntry_get_clus(&de)) {
1501
if (saved_di.p_scratch == NULL) {
1506
read_dir_buf(&saved_di);
1508
while (saved_di.currententry != di->currententry ||
1509
saved_di.currentcluster != di->currentcluster ||
1510
saved_di.currentsector != di->currentsector) {
1511
((struct fat_dirent*) p_scratch)[saved_di.currententry].name[0] = 0xe5;
1513
if (fat_write_sector(fsi, p_scratch, fat_current_dirsector(&saved_di))) {
1517
fat_get_next(&saved_di, &de);
1523
if (de.attr != ATTR_LONG_NAME) {
1524
memset(&saved_di, 0, sizeof(saved_di));
1525
} else if ((de.name[0] & FAT_LONG_ORDER_NUM_MASK) &&
1526
saved_di.p_scratch == NULL) {
1529
memcpy(&saved_di, &last_di, sizeof(saved_di));
1534
int fat_dir_empty(struct fat_file_info *fi) {
1535
struct dirinfo *di = (void *) fi;
1536
struct fat_dirent de = { };
1541
if (read_dir_buf(di)) {
1545
while (de.name[0] == '\0' && res != DFS_EOF) {
1546
res = fat_get_next(di, &de);
1547
if (!strncmp((void *) de.name, ". ", 3) ||
1548
!strncmp((void *) de.name, ".. ", 3) ||
1549
de.name[0] == 0xe5 ||
1550
ATTR_LONG_NAME == (de.attr & ATTR_LONG_NAME)) {
1555
return DFS_EOF == res;
1562
int fat_unlike_file(struct fat_file_info *fi, uint8_t *p_scratch) {
1564
struct fat_fs_info *fsi;
1565
struct dirinfo *di = fi->fdi;
1570
fat_dir_clean_long(di, fi);
1572
if (fat_read_sector(fsi, p_scratch, fi->dirsector)) {
1575
((struct fat_dirent*) p_scratch)[fi->diroffset].name[0] = 0xe5;
1576
if (fat_write_sector(fsi, p_scratch, fi->dirsector)) {
1581
while (!fat_is_end_of_chain(fsi, fi->firstcluster)) {
1582
tempclus = fi->firstcluster;
1583
fi->firstcluster = fat_get_fat(fsi, p_scratch, fi->firstcluster);
1584
fat_set_fat(fsi, p_scratch, tempclus, 0);
1597
static int fat_dirent_by_file(struct fat_file_info *fi, struct fat_dirent *de) {
1598
struct fat_fs_info *fsi = fi->fsi;
1601
if (fat_read_sector(fsi, fat_sector_buff, fi->dirsector))
1604
de_src = &(((struct fat_dirent *)fat_sector_buff)[fi->diroffset]);
1605
memcpy(de, de_src, sizeof(struct fat_dirent));
1618
int fat_reset_dir(struct dirinfo *di) {
1619
struct fat_dirent de = { };
1622
vi = &di->fi.fsi->vi;
1624
if (di->fi.dirsector == 0) {
1626
di->currentcluster = vi->rootdir / vi->secperclus;
1627
if (vi->filesystem == FAT32) {
1628
di->currentsector = 0;
1629
di->currentcluster = 2;
1631
di->currentsector = (vi->rootdir % vi->secperclus);
1632
di->currentcluster = vi->rootdir / vi->secperclus;
1635
di->currententry = 0;
1637
fat_dirent_by_file(&di->fi, &de);
1639
di->currentcluster = fat_direntry_get_clus(&de);
1640
di->currentsector = 0;
1641
di->currententry = 0;
1653
int fat_create_file(struct fat_file_info *fi, struct dirinfo *di, char *name, int mode) {
1654
uint8_t filename[12];
1655
struct fat_dirent de;
1656
struct volinfo *volinfo;
1658
struct fat_fs_info *fsi;
1670
fi->volinfo = volinfo;
1672
while (*name == '/') {
1675
log_debug("fsi: bytepersec(%d), bdev->block_size(%d)",
1676
fsi->vi.bytepersec, fsi->bdev->block_size);
1677
log_debug("name(%s), mode(%x)", name, mode);
1679
entries = fat_entries_per_name(name);
1683
res = fat_get_free_entries(di, entries);
1688
fat_dir_rewind(di, res);
1691
path_canonical_to_dir((char *) filename, name);
1693
for (int i = entries - 1; i >= 1; i--) {
1694
memset(&de, 0, sizeof(de));
1695
fat_write_longname(name + 13 * (i - 1), &de);
1696
de.attr = ATTR_LONG_NAME;
1697
de.crttimetenth = fat_canonical_name_checksum((char *) filename);
1698
de.name[0] = FAT_LONG_ORDER_NUM_MASK & i;
1699
if (i == entries - 1) {
1700
de.name[0] |= FAT_LONG_ORDER_LAST;
1703
fat_write_de(di, &de);
1705
if (DFS_EOF == fat_fetch_dir(di)) {
1710
memcpy(filename, name, sizeof(filename));
1713
cluster = fat_get_free_fat(fsi, fat_sector_buff);
1714
de = (struct fat_dirent) {
1715
.attr = S_ISDIR(mode) ? ATTR_DIRECTORY : 0,
1717
fat_direntry_set_clus(&de, cluster);
1718
memcpy(de.name, filename, MSDOS_NAME);
1719
fat_set_filetime(&de);
1721
fi->volinfo = volinfo;
1723
fi->dirsector = fat_current_dirsector(di);
1724
fi->diroffset = di->currententry;
1725
fi->cluster = cluster;
1726
fi->firstcluster = cluster;
1728
fat_write_de(di, &de);
1730
cluster = fat_end_of_chain(fsi);
1731
fat_set_fat(fsi, fat_sector_buff, fi->cluster, cluster);
1733
if (S_ISDIR(mode)) {
1735
fat_set_direntry(di->currentcluster, fi->cluster);
1736
cluster = fi->volinfo->dataarea +
1737
((fi->cluster - 2) * fi->volinfo->secperclus);
1738
if (fat_write_sector(fsi, fat_sector_buff, cluster)) {
1746
void fat_write_longname(char *name, struct fat_dirent *di) {
1747
struct fat_long_dirent *ld;
1754
memset(ld->name1, 0xff, sizeof(ld->name1));
1755
memset(ld->name2, 0xff, sizeof(ld->name2));
1756
memset(ld->name3, 0xff, sizeof(ld->name3));
1758
l = strlen(name) + 1;
1760
for (int i = 0; i < sizeof(ld->name1) / 2; i++) {
1765
ld->name1[i * 2] = name[i];
1766
ld->name1[i * 2 + 1] = '\0';
1769
name += sizeof(ld->name1) / 2;
1770
l -= sizeof(ld->name1) / 2;
1772
for (int i = 0; i < sizeof(ld->name2) / 2; i++) {
1777
ld->name2[i * 2] = name[i];
1778
ld->name2[i * 2 + 1] = '\0';
1781
name += sizeof(ld->name2) / 2;
1782
l -= sizeof(ld->name2) / 2;
1784
for (int i = 0; i < sizeof(ld->name3) / 2; i++) {
1789
ld->name3[i * 2] = name[i];
1790
ld->name3[i * 2 + 1] = '\0';
1794
int fat_read_filename(struct fat_file_info *fi, void *p_scratch, char *name) {
1795
struct fat_dirent de;
1796
struct dirinfo *dir;
1802
log_debug("fi->dirsector (%d)", fi->dirsector);
1811
int dirsect =fat_current_dirsector(dir);
1813
if (dirsect == fi->dirsector && dir->currententry == fi->diroffset + 1) {
1817
fat_get_next_long(dir, &de, name);
1820
if (name[0] == '\0') {
1822
fat_get_next_long(dir, &de, name);
1827
offt = strlen(name);
1828
while (name[offt - 1] == ' ' && offt > 0) {
1829
name[--offt] = '\0';
1831
log_debug("name(%s)", name);
1836
static bool fat_old_dirent_symbol(char c) {
1841
if (c >= 'A' && c <= 'Z') {
1845
if (c >= '0' && c <= '9') {
1853
int fat_entries_per_name(const char *name) {
1855
bool old_compat = true;
1861
if (l > MSDOS_NAME) {
1864
for (int i = 0; i < l; i++) {
1865
if (!fat_old_dirent_symbol(name[i])) {
1884
static uint32_t fat_dir_rewind(struct dirinfo *di, int n) {
1888
for (int i = 0; i < n; i++) {
1896
static uint32_t fat_get_free_entries(struct dirinfo *dir, int n) {
1897
struct fat_dirent de;
1911
res = fat_get_free_dir_ent(dir, &de);
1918
if (res == DFS_EOF) {
1923
for (int i = 0; i < n - 1; i++) {
1924
dir->currententry++;
1925
res = fat_fetch_dir(dir);
1926
if (res == DFS_ALLOCNEW) {
1928
if (DFS_OK != (res = fat_dir_extend(dir))) {
1932
res = fat_get_current(dir, &de);
1933
if (res == DFS_OK && de.name[0] != '\0') {
1939
if (res == DFS_EOF) {
1954
static uint32_t fat_write_de(struct dirinfo *di, struct fat_dirent *de) {
1956
struct fat_fs_info *fsi = di->fi.fsi;
1961
sector = fat_current_dirsector(di);
1963
if (fat_read_sector(fsi, di->p_scratch, sector))
1966
memcpy(&(((struct fat_dirent *) di->p_scratch)[di->currententry]),
1967
de, sizeof(struct fat_dirent));
1968
if (fat_write_sector(fsi, di->p_scratch, sector))
1974
uint8_t fat_canonical_name_checksum(const char *name) {
1979
for (int i = 0; i < MSDOS_NAME; i++) {
1980
res = (res / 2) + (res % 2) * 0x80;
1987
int fat_alloc_inode_priv(struct inode *inode, struct fat_dirent *de) {
1988
struct fat_file_info *fi;
1990
fi = inode_priv(inode);
1996
if (de->attr & ATTR_DIRECTORY){
1997
struct dirinfo *new_di;
1999
new_di = fat_dirinfo_alloc();
2000
if (NULL == new_di) {
2004
memset(new_di, 0, sizeof(struct dirinfo));
2005
new_di->p_scratch = fat_sector_buff;
2006
new_di->currentcluster = fat_direntry_get_clus(de);
2010
inode->i_mode |= S_IFDIR;
2012
fi = fat_file_alloc();
2016
memset(fi, 0, sizeof(struct fat_file_info));
2018
inode->i_mode |= S_IFREG;
2021
inode_priv_set(inode, fi);
2034
int fat_fill_inode(struct inode *inode, struct fat_dirent *de, struct dirinfo *di) {
2035
struct fat_file_info *fi;
2036
struct fat_fs_info *fsi;
2038
struct super_block *sb;
2039
int res, tmp_sector, tmp_entry, tmp_cluster;
2054
fi = inode_priv(inode);
2060
tmp_sector = di->currentsector;
2061
tmp_entry = di->currententry;
2062
tmp_cluster = di->currentcluster;
2064
while (de->attr == ATTR_LONG_NAME) {
2065
res = fat_get_next(di, de);
2067
if (res != DFS_OK && res != DFS_ALLOCNEW) {
2072
if (di->fi.dirsector == 0 && (vi->filesystem == FAT12 || vi->filesystem == FAT16)) {
2073
fi->dirsector = tmp_sector + tmp_cluster * vi->secperclus;
2075
fi->dirsector = tmp_sector + fat_sec_by_clus(fsi, tmp_cluster);
2079
fi->diroffset = tmp_entry - 1;
2080
fi->cluster = fat_direntry_get_clus(de);
2081
fi->firstcluster = fi->cluster;
2082
fi->filelen = fat_direntry_get_size(de);
2085
inode_size_set(inode, fi->filelen);
2086
if (de->attr & ATTR_READ_ONLY) {
2087
inode->i_mode |= S_IRALL;
2089
inode->i_mode |= S_IRWXA;
2095
int fat_destroy_inode(struct inode *inode) {
2096
struct fat_file_info *fi;
2099
if (!inode_priv(inode)) {
2103
if (S_ISDIR(inode->i_mode)) {
2104
di = inode_priv(inode);
2105
fat_dirinfo_free(di);
2107
fi = inode_priv(inode);
2111
inode_priv_set(inode, NULL);