📄 fat.c
字号:
year++; } } *date = (year << 9) | (month << 5) | day; } } } if (tenth) *tenth = 0;#endif /* HAVE_RTC */}static int write_long_name(struct fat_file* file, unsigned int firstentry, unsigned int numentries, unsigned char* name, unsigned char* shortname, bool is_directory){ unsigned char buf[SECTOR_SIZE]; unsigned char* entry; unsigned int idx = firstentry % DIR_ENTRIES_PER_SECTOR; unsigned int sector = firstentry / DIR_ENTRIES_PER_SECTOR; unsigned int i, j=0; unsigned char chksum = 0; int nameidx=0, namelen = strlen(name); int rc; LDEBUGF("write_long_name(file:%x, first:%d, num:%d, name:%s)\n", file->firstcluster, firstentry, numentries, name); rc = fat_seek(file, sector); if (rc<0) return rc * 10 - 1; rc = fat_readwrite(file, 1, buf, false); if (rc<1) return rc * 10 - 2; /* calculate shortname checksum */ for (i=11; i>0; i--) chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++]; /* calc position of last name segment */ if ( namelen > NAME_BYTES_PER_ENTRY ) for (nameidx=0; nameidx < (namelen - NAME_BYTES_PER_ENTRY); nameidx += NAME_BYTES_PER_ENTRY); for (i=0; i < numentries; i++) { /* new sector? */ if ( idx >= DIR_ENTRIES_PER_SECTOR ) { /* update current sector */ rc = fat_seek(file, sector); if (rc<0) return rc * 10 - 3; rc = fat_readwrite(file, 1, buf, true); if (rc<1) return rc * 10 - 4; /* read next sector */ rc = fat_readwrite(file, 1, buf, false); if (rc<0) { LDEBUGF("Failed writing new sector: %d\n",rc); return rc * 10 - 5; } if (rc==0) /* end of dir */ memset(buf, 0, sizeof buf); sector++; idx = 0; } entry = buf + idx * DIR_ENTRY_SIZE; /* verify this entry is free */ if (entry[0] && entry[0] != 0xe5 ) panicf("Dir entry %d in sector %x is not free! " "%02x %02x %02x %02x", idx, sector, entry[0], entry[1], entry[2], entry[3]); memset(entry, 0, DIR_ENTRY_SIZE); if ( i+1 < numentries ) { /* longname entry */ int k, l = nameidx; entry[FATLONG_ORDER] = numentries-i-1; if (i==0) { /* mark this as last long entry */ entry[FATLONG_ORDER] |= 0x40; /* pad name with 0xffff */ for (k=1; k<12; k++) entry[k] = 0xff; for (k=14; k<26; k++) entry[k] = 0xff; for (k=28; k<32; k++) entry[k] = 0xff; }; /* set name */ for (k=0; k<5 && l <= namelen; k++) { entry[k*2 + 1] = name[l++]; entry[k*2 + 2] = 0; } for (k=0; k<6 && l <= namelen; k++) { entry[k*2 + 14] = name[l++]; entry[k*2 + 15] = 0; } for (k=0; k<2 && l <= namelen; k++) { entry[k*2 + 28] = name[l++]; entry[k*2 + 29] = 0; } entry[FATDIR_ATTR] = FAT_ATTR_LONG_NAME; entry[FATDIR_FSTCLUSLO] = 0; entry[FATLONG_TYPE] = 0; entry[FATLONG_CHKSUM] = chksum; LDEBUGF("Longname entry %d: %.13s\n", idx, name+nameidx); } else { /* shortname entry */ unsigned short date=0, time=0, tenth=0; LDEBUGF("Shortname entry: %.13s\n", shortname); strncpy(entry + FATDIR_NAME, shortname, 11); entry[FATDIR_ATTR] = is_directory?FAT_ATTR_DIRECTORY:0; entry[FATDIR_NTRES] = 0; fat_time(&date, &time, &tenth); entry[FATDIR_CRTTIMETENTH] = tenth; *(unsigned short*)(entry + FATDIR_CRTTIME) = SWAB16(time); *(unsigned short*)(entry + FATDIR_WRTTIME) = SWAB16(time); *(unsigned short*)(entry + FATDIR_CRTDATE) = SWAB16(date); *(unsigned short*)(entry + FATDIR_WRTDATE) = SWAB16(date); *(unsigned short*)(entry + FATDIR_LSTACCDATE) = SWAB16(date); } idx++; nameidx -= NAME_BYTES_PER_ENTRY; } /* update last sector */ rc = fat_seek(file, sector); if (rc<0) return rc * 10 - 6; rc = fat_readwrite(file, 1, buf, true); if (rc<1) return rc * 10 - 7; return 0;}static int add_dir_entry(struct fat_dir* dir, struct fat_file* file, char* name, bool is_directory, bool dotdir){ unsigned char buf[SECTOR_SIZE]; unsigned char shortname[16]; int rc; unsigned int sector; bool done = false; bool eof = false; bool last = false; int entries_needed, entries_found = 0; int namelen = strlen(name); int firstentry; LDEBUGF( "add_dir_entry(%s,%x)\n", name, file->firstcluster); /* The "." and ".." directory entries must not be long names */ if(dotdir) { int i; strncpy(shortname, name, 16); for(i = strlen(shortname);i < 12;i++) shortname[i] = ' '; entries_needed = 1; } else { /* create dos name */ rc = create_dos_name(name, shortname); if (rc < 0) return rc * 10 - 0; /* one dir entry needed for every 13 bytes of filename, plus one entry for the short name */ entries_needed = namelen / NAME_BYTES_PER_ENTRY + 1; if (namelen % NAME_BYTES_PER_ENTRY) entries_needed++; } restart: firstentry = 0; rc = fat_seek(&dir->file, 0); if (rc < 0) return rc * 10 - 1; for (sector=0; !done; sector++) { unsigned int i; rc = 0; if (!eof) { rc = fat_readwrite(&dir->file, 1, buf, false); } if (rc == 0) { /* eof: add new sector */ eof = true; memset(buf, 0, sizeof buf); LDEBUGF("Adding new sector to dir\n"); rc = fat_seek(&dir->file, sector); if (rc < 0) return rc * 10 - 2; /* add sectors (we must clear the whole cluster) */ do { rc = fat_readwrite(&dir->file, 1, buf, true); if (rc < 1) return rc * 10 - 3; } while (dir->file.sectornum < (int)fat_bpb.bpb_secperclus); } if (rc < 0) { DEBUGF( "add_dir_entry() - Couldn't read dir" " (error code %d)\n", rc); return rc * 10 - 4; } /* look for free slots */ for (i=0; i < DIR_ENTRIES_PER_SECTOR && !done; i++) { unsigned char firstbyte = buf[i * DIR_ENTRY_SIZE]; switch (firstbyte) { case 0: /* end of dir */ entries_found = entries_needed; LDEBUGF("Found last entry %d\n", sector * DIR_ENTRIES_PER_SECTOR + i); done = true; break; case 0xe5: /* free entry */ entries_found++; LDEBUGF("Found free entry %d (%d/%d)\n", sector * DIR_ENTRIES_PER_SECTOR + i, entries_found, entries_needed); break; default: entries_found = 0; /* check that our intended shortname doesn't already exist */ if (!strncmp(shortname, buf + i * DIR_ENTRY_SIZE, 12)) { /* filename exists already. make a new one */ snprintf(shortname+8, 4, "%03X", (unsigned)rand() & 0xfff); LDEBUGF("Duplicate shortname, changing to %s\n", shortname); /* name has changed, we need to restart search */ goto restart; } break; } if (!firstentry && (entries_found == entries_needed)) { firstentry = sector * DIR_ENTRIES_PER_SECTOR + i; /* if we're not extending the dir, we must go back to first free entry */ if (done) last = true; else firstentry -= (entries_needed - 1); } } } sector = firstentry / DIR_ENTRIES_PER_SECTOR; LDEBUGF("Adding longname to entry %d in sector %d\n", firstentry, sector); rc = write_long_name(&dir->file, firstentry, entries_needed, name, shortname, is_directory); if (rc < 0) return rc * 10 - 5; /* remember where the shortname dir entry is located */ file->direntry = firstentry + entries_needed - 1; file->direntries = entries_needed; file->dircluster = dir->file.firstcluster; LDEBUGF("Added new dir entry %d, using %d slots.\n", file->direntry, file->direntries); /* advance the end-of-dir marker? */ if (last) { unsigned int lastentry = firstentry + entries_needed; LDEBUGF("Updating end-of-dir entry %d\n",lastentry); if (lastentry % DIR_ENTRIES_PER_SECTOR) { int idx = (lastentry % DIR_ENTRIES_PER_SECTOR) * DIR_ENTRY_SIZE; rc = fat_seek(&dir->file, lastentry / DIR_ENTRIES_PER_SECTOR); if (rc < 0) return rc * 10 - 6; rc = fat_readwrite(&dir->file, 1, buf, false); if (rc < 1) return rc * 10 - 7; /* clear last entry */ buf[idx] = 0; rc = fat_seek(&dir->file, lastentry / DIR_ENTRIES_PER_SECTOR); if (rc < 0) return rc * 10 - 8; /* we must clear entire last cluster */ do { rc = fat_readwrite(&dir->file, 1, buf, true); if (rc < 1) return rc * 10 - 9; memset(buf, 0, sizeof buf); } while (dir->file.sectornum < (int)fat_bpb.bpb_secperclus); } else { /* add a new sector/cluster for last entry */ memset(buf, 0, sizeof buf); do { rc = fat_readwrite(&dir->file, 1, buf, true); if (rc < 1) return rc * 10 - 9; /* Same error code as above, can't be more than -9 */ } while (dir->file.sectornum < (int)fat_bpb.bpb_secperclus); } } return 0;}unsigned char char2dos(unsigned char c){ switch(c) { case 0xe5: /* Special kanji character */ c = 0x05; break; case 0x20: case 0x22: case 0x2a: case 0x2b: case 0x2c: case 0x2e: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: case 0x5b: case 0x5c: case 0x5d: case 0x7c: /* Illegal name */ c = 0; break; default: if(c < 0x20) { /* Illegal name */ c = 0; } break; } return c;}static int create_dos_name(unsigned char *name, unsigned char *newname){ int i,j; /* Name part */ for (i=0, j=0; name[i] && (j < 8); i++) { unsigned char c = char2dos(name[i]); if (c) newname[j++] = toupper(c); } while (j < 8) newname[j++] = ' '; /* Extension part */ snprintf(newname+8, 4, "%03X", (unsigned)rand() & 0xfff);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -