A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 3079 lines 90 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2002 by Linus Nielsen Feltzing 11 * Copyright (C) 2014 by Michael Sevakis 12 * 13 * This program is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU General Public License 15 * as published by the Free Software Foundation; either version 2 16 * of the License, or (at your option) any later version. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ****************************************************************************/ 22#include "config.h" 23#include "system.h" 24#include "sys/types.h" 25#include "string-extra.h" 26#include <ctype.h> 27#include <stdlib.h> 28#include <stdio.h> 29#include "fs_attr.h" 30#include "pathfuncs.h" 31#include "disk_cache.h" 32#include "file_internal.h" /* for struct filestr_cache */ 33#include "storage.h" 34#include "timefuncs.h" 35#include "rbunicode.h" 36#include "debug.h" 37#include "panic.h" 38#include "disk.h" 39/*#define LOGF_ENABLE*/ 40#include "logf.h" 41 42#define BYTES2INT32(array, pos) \ 43 (((uint32_t)array[pos+0] << 0) | \ 44 ((uint32_t)array[pos+1] << 8) | \ 45 ((uint32_t)array[pos+2] << 16) | \ 46 ((uint32_t)array[pos+3] << 24)) 47 48#define INT322BYTES(array, pos, val) \ 49 ((array[pos+0] = (uint32_t)(val) >> 0), \ 50 (array[pos+1] = (uint32_t)(val) >> 8), \ 51 (array[pos+2] = (uint32_t)(val) >> 16), \ 52 (array[pos+3] = (uint32_t)(val) >> 24)) 53 54#define BYTES2INT16(array, pos) \ 55 (((uint32_t)array[pos+0] << 0) | \ 56 ((uint32_t)array[pos+1] << 8)) 57 58#define INT162BYTES(array, pos, val) \ 59 ((array[pos+0] = (uint16_t)(val) >> 0), \ 60 (array[pos+1] = (uint16_t)(val) >> 8)) 61 62#define FATTYPE_FAT12 0 63#define FATTYPE_FAT16 1 64#define FATTYPE_FAT32 2 65 66/* BPB offsets; generic */ 67#define BS_JMPBOOT 0 68#define BS_OEMNAME 3 69#define BPB_BYTSPERSEC 11 70#define BPB_SECPERCLUS 13 71#define BPB_RSVDSECCNT 14 72#define BPB_NUMFATS 16 73#define BPB_ROOTENTCNT 17 74#define BPB_TOTSEC16 19 75#define BPB_MEDIA 21 76#define BPB_FATSZ16 22 77#define BPB_SECPERTRK 24 78#define BPB_NUMHEADS 26 79#define BPB_HIDDSEC 28 80#define BPB_TOTSEC32 32 81 82/* fat12/16 */ 83#define BS_DRVNUM 36 84#define BS_RESERVED1 37 85#define BS_BOOTSIG 38 86#define BS_VOLID 39 87#define BS_VOLLAB 43 88#define BS_FILSYSTYPE 54 89 90/* fat32 */ 91#define BPB_FATSZ32 36 92#define BPB_EXTFLAGS 40 93#define BPB_FSVER 42 94#define BPB_ROOTCLUS 44 95#define BPB_FSINFO 48 96#define BPB_BKBOOTSEC 50 97#define BS_32_DRVNUM 64 98#define BS_32_BOOTSIG 66 99#define BS_32_VOLID 67 100#define BS_32_VOLLAB 71 101#define BS_32_FILSYSTYPE 82 102 103#define BPB_LAST_WORD 510 104 105/* Short and long name directory entry template */ 106union raw_dirent 107{ 108 struct /* short entry */ 109 { 110 uint8_t name[8+3]; /* 0 */ 111 uint8_t attr; /* 11 */ 112 uint8_t ntres; /* 12 */ 113 uint8_t crttimetenth; /* 13 */ 114 uint16_t crttime; /* 14 */ 115 uint16_t crtdate; /* 16 */ 116 uint16_t lstaccdate; /* 18 */ 117 uint16_t fstclushi; /* 20 */ 118 uint16_t wrttime; /* 22 */ 119 uint16_t wrtdate; /* 24 */ 120 uint16_t fstcluslo; /* 26 */ 121 uint32_t filesize; /* 28 */ 122 /* 32 */ 123 }; 124 struct /* long entry */ 125 { 126 uint8_t ldir_ord; /* 0 */ 127 uint8_t ldir_name1[10]; /* 1 */ 128 uint8_t ldir_attr; /* 11 */ 129 uint8_t ldir_type; /* 12 */ 130 uint8_t ldir_chksum; /* 13 */ 131 uint8_t ldir_name2[12]; /* 14 */ 132 uint16_t ldir_fstcluslo; /* 26 */ 133 uint8_t ldir_name3[4]; /* 28 */ 134 /* 32 */ 135 }; 136 struct /* raw byte array */ 137 { 138 uint8_t data[32]; /* 0 */ 139 /* 32 */ 140 }; 141}; 142 143 144/* at most 20 LFN entries */ 145#define FATLONG_MAX_ORDER 20 146#define FATLONG_NAME_CHARS 13 147#define FATLONG_ORD_F_LAST 0x40 148 149/* attributes */ 150#define ATTR_LONG_NAME (ATTR_READ_ONLY | ATTR_HIDDEN | \ 151 ATTR_SYSTEM | ATTR_VOLUME_ID) 152#define ATTR_LONG_NAME_MASK (ATTR_READ_ONLY | ATTR_HIDDEN | \ 153 ATTR_SYSTEM | ATTR_VOLUME_ID | \ 154 ATTR_DIRECTORY | ATTR_ARCHIVE ) 155 156#define IS_LDIR_ATTR(attr) \ 157 (((attr) & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME) 158 159#define IS_VOL_ID_ATTR(attr) \ 160 (((attr) & (ATTR_VOLUME_ID | ATTR_DIRECTORY)) == ATTR_VOLUME_ID) 161 162/* NTRES flags */ 163#define FAT_NTRES_LC_NAME 0x08 164#define FAT_NTRES_LC_EXT 0x10 165 166#if defined(MAX_VIRT_SECTOR_SIZE) || defined(MAX_VARIABLE_LOG_SECTOR) 167#define LOG_SECTOR_SIZE(bpb) fat_bpb->sector_size 168#else 169#define LOG_SECTOR_SIZE(bpb) SECTOR_SIZE 170#endif 171 172#define CLUSTERS_PER_FAT_SECTOR (LOG_SECTOR_SIZE(fat_bpb) / 4) 173#define CLUSTERS_PER_FAT16_SECTOR (LOG_SECTOR_SIZE(fat_bpb) / 2) 174#define DIR_ENTRIES_PER_SECTOR (LOG_SECTOR_SIZE(fat_bpb) / DIR_ENTRY_SIZE) 175#define DIR_ENTRY_SIZE 32 176#define FAT_BAD_MARK 0x0ffffff7 177#define FAT_EOF_MARK 0x0ffffff8 178#define FAT16_BAD_MARK 0xfff7 179#define FAT16_EOF_MARK 0xfff8 180 181struct fsinfo 182{ 183 sector_t freecount; /* last known free cluster count */ 184 sector_t nextfree; /* first cluster to start looking for free 185 clusters, or 0xffffffff for no hint */ 186}; 187/* fsinfo offsets */ 188#define FSINFO_SIGNATURE 0 189#define FSINFO_FREECOUNT 488 190#define FSINFO_NEXTFREE 492 191 192#define FSINFO_SIGNATURE_VAL 0x41615252 193 194#ifdef HAVE_FAT16SUPPORT 195#define BPB_FN_SET16(bpb, fn) (bpb)->fn##__ = fn##16 196#define BPB_FN_SET32(bpb, fn) (bpb)->fn##__ = fn##32 197#define BPB_FN_DECL(fn, args...) (*fn##__)(struct bpb *bpb , ##args) 198#define BPB_CALL(fn, bpb, args...) ((bpb)->fn##__(bpb , ##args)) 199 200#define get_next_cluster(bpb, cluster) \ 201 BPB_CALL(get_next_cluster, (bpb), (cluster)) 202#define find_free_cluster(bpb, startcluster) \ 203 BPB_CALL(find_free_cluster, (bpb), (startcluster)) 204#define update_fat_entry(bpb, entry, value) \ 205 BPB_CALL(update_fat_entry, (bpb), (entry), (value)) 206#define fat_recalc_free_internal(bpb) \ 207 BPB_CALL(fat_recalc_free_internal, (bpb)) 208#else /* !HAVE_FAT16SUPPORT */ 209#define get_next_cluster get_next_cluster32 210#define find_free_cluster find_free_cluster32 211#define update_fat_entry update_fat_entry32 212#define fat_recalc_free_internal fat_recalc_free_internal32 213#endif /* HAVE_FAT16SUPPORT */ 214struct bpb; 215static void update_fsinfo32(struct bpb *fat_bpb); 216 217/* Note: This struct doesn't hold the raw values after mounting if 218 * bpb_bytspersec isn't the same as the underlying device's logical 219 sector size. Sector counts are then normalized to that sector 220 size. 221*/ 222static struct bpb 223{ 224 unsigned long bpb_bytspersec; /* Bytes per sector, typically 512 */ 225 unsigned long bpb_secperclus; /* Sectors per cluster */ 226 unsigned long bpb_rsvdseccnt; /* Number of reserved sectors */ 227 unsigned long bpb_totsec16; /* Number of sectors on volume (old 16-bit) */ 228 uint8_t bpb_numfats; /* Number of FAT structures, typically 2 */ 229 uint8_t bpb_media; /* Media type (typically 0xf0 or 0xf8) */ 230 uint16_t bpb_fatsz16; /* Number of used sectors per FAT structure */ 231 unsigned long bpb_totsec32; /* Number of sectors on the volume 232 (new 32-bit) */ 233 uint16_t last_word; /* 0xAA55 */ 234 long bpb_rootclus; 235 236 /**** FAT32 specific *****/ 237 unsigned long bpb_fatsz32; 238 unsigned long bpb_fsinfo; 239 240 /* variables for internal use */ 241 unsigned long fatsize; 242 unsigned long totalsectors; 243 unsigned long rootdirsector; 244 unsigned long firstdatasector; 245 sector_t startsector; 246 unsigned long dataclusters; 247 unsigned long fatrgnstart; 248 unsigned long fatrgnend; 249 struct fsinfo fsinfo; 250#ifdef HAVE_FAT16SUPPORT 251 unsigned int bpb_rootentcnt; /* Number of dir entries in the root */ 252 /* internals for FAT16 support */ 253 sector_t rootdirsectornum; /* sector offset of root dir relative to start 254 * of first pseudo cluster */ 255#endif /* HAVE_FAT16SUPPORT */ 256 257 /** Additional information kept for each volume **/ 258#ifdef HAVE_FAT16SUPPORT 259 uint8_t is_fat16; /* true if we mounted a FAT16 partition, false if FAT32 */ 260#endif 261#ifdef HAVE_MULTIDRIVE 262 uint8_t drive; /* on which physical device is this located */ 263#endif 264#ifdef HAVE_MULTIVOLUME 265 uint8_t volume; /* on which volume is this located (shortcut) */ 266#endif 267 uint8_t mounted; /* true if volume is mounted, false otherwise */ 268#ifdef HAVE_FAT16SUPPORT 269 /* some functions are different for different FAT types */ 270 long BPB_FN_DECL(get_next_cluster, long); 271 long BPB_FN_DECL(find_free_cluster, long); 272 int BPB_FN_DECL(update_fat_entry, unsigned long, unsigned long); 273 void BPB_FN_DECL(fat_recalc_free_internal); 274#endif /* HAVE_FAT16SUPPORT */ 275#if defined(MAX_VIRT_SECTOR_SIZE) || defined(MAX_VARIABLE_LOG_SECTOR) 276 uint16_t sector_size; 277#endif 278} fat_bpbs[NUM_VOLUMES]; /* mounted partition info */ 279 280#ifdef STORAGE_NEEDS_BOUNCE_BUFFER 281#if defined(MAX_VIRT_SECTOR_SIZE) 282#define BOUNCE_SECTOR_SIZE MAX_VIRT_SECTOR_SIZE 283#elif defined(MAX_VARIABLE_LOG_SECTOR) 284#define BOUNCE_SECTOR_SIZE MAX_VARIABLE_LOG_SECTOR 285#elif defined(MAX_PHYS_SECTOR_SIZE) 286#define BOUNCE_SECTOR_SIZE MAX_PHYS_SECTOR_SIZE 287#else 288#define BOUNCE_SECTOR_SIZE SECTOR_SIZE 289#endif 290#ifndef FAT_BOUNCE_SECTORS 291#define FAT_BOUNCE_SECTORS 10 292#endif 293static uint8_t fat_bounce_buffers[NUM_VOLUMES][BOUNCE_SECTOR_SIZE*FAT_BOUNCE_SECTORS] STORAGE_ALIGN_ATTR; 294#define FAT_BOUNCE_BUFFER(bpb) \ 295 (fat_bounce_buffers[IF_MV_VOL((bpb)->volume)]) 296#endif 297 298#define IS_FAT_SECTOR(bpb, sector) \ 299 (!((sector) >= (bpb)->fatrgnend || (sector) < (bpb)->fatrgnstart)) 300 301/* set error code and jump to routine exit */ 302#define FAT_ERROR(_rc) \ 303 ({ __builtin_constant_p(_rc) ? \ 304 ({ if (_rc != RC) rc = (_rc); }) : \ 305 ({ rc = (_rc); }); \ 306 goto fat_error; }) 307 308#define FAT_BPB(volume) \ 309 ({ struct bpb * _bpb = &fat_bpbs[IF_MV_VOL(volume)]; \ 310 if (!_bpb->mounted) \ 311 { \ 312 DEBUGF("%s() - volume %d not mounted\n", \ 313 __func__, IF_MV_VOL(volume)); \ 314 _bpb = NULL; \ 315 } \ 316 _bpb; }) 317 318enum add_dir_entry_flags 319{ 320 DIRENT_RETURN = 0x01, /* return the new short entry */ 321 DIRENT_TEMPL = 0x0e, /* all TEMPL flags */ 322 DIRENT_TEMPL_CRT = 0x02, /* use template crttime */ 323 DIRENT_TEMPL_WRT = 0x04, /* use template wrttime */ 324 DIRENT_TEMPL_ACC = 0x08, /* use template lstacc time */ 325 DIRENT_TEMPL_TIMES = 0x0e, /* keep all time fields */ 326}; 327 328struct fatlong_parse_state 329{ 330 int ord_max; 331 int ord; 332 uint8_t chksum; 333}; 334 335static void cache_commit(struct bpb *fat_bpb) 336{ 337 dc_lock_cache(); 338#ifdef HAVE_FAT16SUPPORT 339 if (!fat_bpb->is_fat16) 340#endif 341 update_fsinfo32(fat_bpb); 342 dc_commit_all(IF_MV(fat_bpb->volume)); 343 dc_unlock_cache(); 344} 345 346static void cache_discard(IF_MV_NONVOID(struct bpb *fat_bpb)) 347{ 348 dc_lock_cache(); 349 dc_discard_all(IF_MV(fat_bpb->volume)); 350 dc_unlock_cache(); 351} 352 353/* caches a FAT or data area sector */ 354static void * cache_sector(struct bpb *fat_bpb, sector_t secnum) 355{ 356 unsigned int flags; 357 void *buf = dc_cache_probe(IF_MV(fat_bpb->volume,) secnum, &flags); 358 359 if (!flags) 360 { 361 int rc = storage_read_sectors(IF_MD(fat_bpb->drive,) 362 secnum + fat_bpb->startsector, 1, buf); 363 if (UNLIKELY(rc < 0)) 364 { 365 DEBUGF("%s() - Could not read sector %llu" 366 " (error %d)\n", __func__, (uint64_t)secnum, rc); 367 dc_discard_buf(buf); 368 return NULL; 369 } 370 } 371 372 return buf; 373} 374 375/* returns a raw buffer for a sector; buffer counts as INUSE but filesystem 376 * contents are NOT loaded before returning - use when completely overwriting 377 * a sector's contents in order to avoid a fill */ 378static void * cache_sector_buffer(IF_MV(struct bpb *fat_bpb,) 379 sector_t secnum) 380{ 381 unsigned int flags; 382 return dc_cache_probe(IF_MV(fat_bpb->volume,) secnum, &flags); 383} 384 385/* flush a cache buffer to storage */ 386void dc_writeback_callback(IF_MV(int volume,) sector_t sector, void *buf) 387{ 388 struct bpb * const fat_bpb = &fat_bpbs[IF_MV_VOL(volume)]; 389 unsigned int copies = !IS_FAT_SECTOR(fat_bpb, sector) ? 390 1 : fat_bpb->bpb_numfats; 391 392 sector += fat_bpb->startsector; 393 394 while (1) 395 { 396 int rc = storage_write_sectors(IF_MD(fat_bpb->drive,) sector, 1, buf); 397 if (rc < 0) 398 { 399 panicf("%s() - Could not write sector %llu" 400 " (error %d)\n", __func__, (uint64_t)sector, rc); 401 } 402 403 if (--copies == 0) 404 break; 405 406 /* Update next FAT */ 407 sector += fat_bpb->fatsize; 408 } 409} 410 411static void raw_dirent_set_fstclus(union raw_dirent *ent, long fstclus) 412{ 413 ent->fstclushi = htole16(fstclus >> 16); 414 ent->fstcluslo = htole16(fstclus & 0xffff); 415} 416 417static int bpb_is_sane(struct bpb *fat_bpb) 418{ 419 if (fat_bpb->bpb_bytspersec % LOG_SECTOR_SIZE(fat_bpb)) 420 { 421 DEBUGF("%s() - Error: sector size is not sane (%lu)\n", 422 __func__, fat_bpb->bpb_bytspersec); 423 return -1; 424 } 425 426 /* The fat_bpb struct does not hold the raw value of bpb_bytspersec, the 427 * value is multiplied in cases where bpb_bytspersec != sector_size. We need 428 * to undo that multiplication before we do the sanity check. */ 429 unsigned long secmult = fat_bpb->bpb_bytspersec / LOG_SECTOR_SIZE(fat_bpb); 430 431 if (fat_bpb->bpb_secperclus * fat_bpb->bpb_bytspersec / secmult > 128*1024ul) 432 { 433 DEBUGF("%s() - Error: cluster size is larger than 128K " 434 "(%lu * %lu = %lu)\n", __func__, 435 fat_bpb->bpb_bytspersec, fat_bpb->bpb_secperclus, 436 fat_bpb->bpb_bytspersec * fat_bpb->bpb_secperclus); 437 return -2; 438 } 439 440 if (fat_bpb->bpb_numfats != 2) 441 { 442 DEBUGF("%s() - Warning: NumFATS is not 2 (%u)\n", 443 __func__, fat_bpb->bpb_numfats); 444 } 445 446 if (fat_bpb->bpb_media != 0xf0 && fat_bpb->bpb_media < 0xf8) 447 { 448 DEBUGF("%s() - Warning: Non-standard media type " 449 "(0x%02x)\n", __func__, fat_bpb->bpb_media); 450 } 451 452 if (fat_bpb->last_word != 0xaa55) 453 { 454 DEBUGF("%s() - Error: Last word is not " 455 "0xaa55 (0x%04x)\n", __func__, fat_bpb->last_word); 456 return -3; 457 } 458 459 if (fat_bpb->fsinfo.freecount > 460 (fat_bpb->totalsectors - fat_bpb->firstdatasector) / 461 fat_bpb->bpb_secperclus) 462 { 463 DEBUGF("%s() - Error: FSInfo.Freecount > disk size " 464 "(0x%04lx)\n", __func__, 465 (unsigned long)fat_bpb->fsinfo.freecount); 466 return -4; 467 } 468 469 return 0; 470} 471 472static uint8_t shortname_checksum(const unsigned char *shortname) 473{ 474 /* calculate shortname checksum */ 475 uint8_t chksum = 0; 476 477 for (unsigned int i = 0; i < 11; i++) 478 chksum = (chksum << 7) + (chksum >> 1) + shortname[i]; 479 480 return chksum; 481} 482 483static void parse_short_direntry(const union raw_dirent *ent, 484 struct fat_direntry *fatent) 485{ 486 fatent->attr = ent->attr; 487 fatent->crttimetenth = ent->crttimetenth; 488 fatent->crttime = letoh16(ent->crttime); 489 fatent->crtdate = letoh16(ent->crtdate); 490 fatent->lstaccdate = letoh16(ent->lstaccdate); 491 fatent->wrttime = letoh16(ent->wrttime); 492 fatent->wrtdate = letoh16(ent->wrtdate); 493 fatent->filesize = letoh32(ent->filesize); 494 fatent->firstcluster = ((uint32_t)letoh16(ent->fstcluslo) ) | 495 ((uint32_t)letoh16(ent->fstclushi) << 16); 496 497 /* fix the name */ 498 bool lowercase = ent->ntres & FAT_NTRES_LC_NAME; 499 unsigned char c = ent->name[0]; 500 501 if (c == 0x05) /* special kanji char */ 502 c = 0xe5; 503 504 int j = 0; 505 506 for (int i = 0; c != ' '; c = ent->name[i]) 507 { 508 fatent->shortname[j++] = lowercase ? tolower(c) : c; 509 510 if (++i >= 8) 511 break; 512 } 513 514 if (ent->name[8] != ' ') 515 { 516 lowercase = ent->ntres & FAT_NTRES_LC_EXT; 517 fatent->shortname[j++] = '.'; 518 519 for (int i = 8; i < 11 && (c = ent->name[i]) != ' '; i++) 520 fatent->shortname[j++] = lowercase ? tolower(c) : c; 521 } 522 523 fatent->shortname[j] = 0; 524} 525 526static unsigned char char2dos(unsigned char c, int *np) 527{ 528 /* FIXME: needs conversion to OEM charset FIRST but there is currently 529 no unicode function for that! */ 530 531 /* smallest tables with one-step lookup that directly map the lists; 532 here we're only concerned with what gets through the longname 533 filter (check_longname will have been called earlier so common 534 illegal chars are neither in these tables nor checked for) */ 535 static const unsigned char remove_chars_tbl[3] = 536 { 0, '.', ' ' }; 537 538 static const unsigned char replace_chars_tbl[11] = 539 { ',', 0, 0, '[', ';', ']', '=', 0, 0, 0, '+' }; 540 541 if (remove_chars_tbl[c % 3] == c) 542 { 543 /* Illegal char, remove */ 544 c = 0; 545 *np = 0; 546 } 547 else if (c >= 0x80 || replace_chars_tbl[c % 11] == c) 548 { 549 /* Illegal char, replace (note: NTFS behavior for extended chars) */ 550 c = '_'; 551 *np = 0; 552 } 553 else 554 { 555 c = toupper(c); 556 } 557 558 return c; 559} 560 561/* convert long name into dos name, possibly recommending randomization */ 562static void create_dos_name(unsigned char *basisname, 563 const unsigned char *name, int *np) 564{ 565 int i; 566 567 /* FIXME: needs conversion to OEM charset FIRST but there is currently 568 no unicode function for that! */ 569 570 /* as per FAT spec, set "lossy conversion" flag if any destructive 571 alterations to the name occur other than case changes */ 572 *np = -1; 573 574 /* find extension part */ 575 unsigned char *ext = strrchr(name, '.'); 576 if (ext && (ext == name || strchr(ext, ' '))) 577 ext = NULL; /* handle .dotnames / extensions cannot have spaces */ 578 579 /* name part */ 580 for (i = 0; *name && (!ext || name < ext) && (i < 8); name++) 581 { 582 unsigned char c = char2dos(*name, np); 583 if (c) 584 basisname[i++] = c; 585 } 586 587 /* pad both name and extension */ 588 while (i < 11) 589 basisname[i++] = ' '; 590 591 if (basisname[0] == 0xe5) /* special kanji character */ 592 basisname[0] = 0x05; 593 594 /* extension part */ 595 if (!ext++) 596 return; /* no extension */ 597 598 for (i = 8; *ext && i < 11; ext++) 599 { 600 unsigned char c = char2dos(*ext, np); 601 if (c) 602 basisname[i++] = c; 603 } 604 605 if (*ext) 606 *np = 0; /* extension too long */ 607} 608 609static void randomize_dos_name(unsigned char *dosname, 610 const unsigned char *basisname, 611 int *np) 612{ 613 int n = *np; 614 615 memcpy(dosname, basisname, 11); 616 617 if (n < 0) 618 { 619 /* first one just copies */ 620 *np = 0; 621 return; 622 } 623 624 /* the "~n" string can range from "~1" to "~999999" 625 of course a directory can have at most 65536 entries which means 626 the numbers will never be required to get that big in order to map 627 to a unique name */ 628 if (++n > 999999) 629 n = 1; 630 631 unsigned char numtail[8]; /* holds "~n" */ 632 unsigned int numtaillen = snprintf(numtail, 8, "~%d", n); 633 634 unsigned int basislen = 0; 635 while (basislen < 8 && basisname[basislen] != ' ') 636 basislen++; 637 638 memcpy(dosname + MIN(8 - numtaillen, basislen), numtail, numtaillen); 639 640 *np = n; 641} 642 643/* check long filename for validity */ 644static int check_longname(const unsigned char *name) 645{ 646 /* smallest table with one-step lookup that directly maps the list */ 647 static const unsigned char invalid_chars_tbl[19] = 648 { 649 0, ':', 0, '<', '*', '>', '?', 0, 0, 650 '/', '|', 0, 0, 0x7f, 0, '"', '\\', 0, 0 651 }; 652 653 if (!name) 654 return -1; 655 656 unsigned int c = *name; 657 658 do 659 { 660 if (c < 0x20 || invalid_chars_tbl[c % 19] == c) 661 return -2; 662 } 663 while ((c = *++name)); 664 665 /* check trailing space(s) and periods */ 666 c = *--name; 667 if (c == ' ' || c == '.') 668 return -3; 669 670 return 0; 671} 672 673/* Get first longname entry name offset */ 674static inline unsigned int longent_char_first(void) 675{ 676 return 1; 677} 678 679/* Get the next longname entry offset or 0 if the end is reached */ 680static inline unsigned int longent_char_next(unsigned int i) 681{ 682 switch (i += 2) 683 { 684 /* flip endian for elements 14 - 27 */ 685 case 26: i -= 1; /* return 28 */ 686 /* Fall-Through */ 687 case 11: i += 3; /* return 14 */ 688 } 689 /* BYTES2INT16() uses [i + 0] and [i + 1] therefore 690 * 30 is the max element available in the raw byte array of size 32 */ 691 return i < 31 ? i : 0; 692} 693 694/* initialize the parse state; call before parsing first long entry */ 695static void NO_INLINE fatlong_parse_start(struct fatlong_parse_state *lnparse) 696{ 697 /* no inline so gcc can't figure out what isn't initialized here; 698 ord_max is king as to the validity of all other fields */ 699 lnparse->ord_max = -1; /* one resync per parse operation */ 700} 701 702/* convert the FAT long name entry to a contiguous segment */ 703static bool fatlong_parse_entry(struct fatlong_parse_state *lnparse, 704 const union raw_dirent *ent, 705 struct fat_direntry *fatent) 706{ 707 int ord = ent->ldir_ord; 708 709 if (ord & FATLONG_ORD_F_LAST) 710 { 711 /* this entry is the first long entry (first in order but 712 containing last part) */ 713 ord &= ~FATLONG_ORD_F_LAST; 714 715 if (ord == 0 || ord > FATLONG_MAX_ORDER) 716 { 717 lnparse->ord_max = 0; 718 return true; 719 } 720 721 lnparse->ord_max = ord; 722 lnparse->ord = ord; 723 lnparse->chksum = ent->ldir_chksum; 724 } 725 else 726 { 727 /* valid ordinals yet? */ 728 if (lnparse->ord_max <= 0) 729 { 730 if (lnparse->ord_max == 0) 731 return true; 732 733 lnparse->ord_max = 0; 734 return false; /* try resync */ 735 } 736 737 /* check ordinal continuity and that the checksum matches the 738 one stored in the last entry */ 739 if (ord == 0 || ord != lnparse->ord - 1 || 740 lnparse->chksum != ent->ldir_chksum) 741 { 742 lnparse->ord_max = 0; 743 return true; 744 } 745 } 746 747 /* so far so good; save entry information */ 748 lnparse->ord = ord; 749 750 /* Treat entries as opaque 16-bit values; 751 utf8decode happens in fatlong_parse_finish() */ 752 uint16_t *ucsp = fatent->ucssegs[ord - 1 + 5]; 753 unsigned int i = longent_char_first(); 754 755 while ((*ucsp++ = BYTES2INT16(ent->data, i))) 756 { 757 if (!(i = longent_char_next(i))) 758 return true; 759 } 760 761 /* segment may end early only in last entry */ 762 if (ord == lnparse->ord_max) 763 { 764 /* the only valid padding, if any, is 0xffff */ 765 do 766 { 767 if (!(i = longent_char_next(i))) 768 return true; 769 } 770 while (BYTES2INT16(ent->data, i) == 0xffff); 771 } 772 773 /* long filename is corrupt */ 774 lnparse->ord_max = 0; 775 return true; 776} 777 778/* finish parsing of the longname entries and do the conversion to 779 UTF-8 if we have all the segments */ 780static bool fatlong_parse_finish(struct fatlong_parse_state *lnparse, 781 const union raw_dirent *ent, 782 struct fat_direntry *fatent) 783{ 784 parse_short_direntry(ent, fatent); 785 786 /* ord_max must not have been set to <= 0 because of any earlier problems 787 and the ordinal immediately before the shortname entry must be 1 */ 788 if (lnparse->ord_max <= 0 || lnparse->ord != 1) 789 return false; 790 791 /* check the longname checksums against the shortname checksum */ 792 if (lnparse->chksum != shortname_checksum(ent->name)) 793 return false; 794 795 /* longname is good so far so convert all the segments to UTF-8 */ 796 unsigned char * const name = fatent->name; 797 unsigned char *p = name; 798 799 /* ensure the last segment is NULL-terminated if it is filled */ 800 fatent->ucssegs[lnparse->ord_max + 5][0] = 0x0000; 801 802 unsigned long ucc; /* Decoded codepoint */ 803 uint16_t *ucsp, ucs; 804 for (ucsp = fatent->ucssegs[5], ucs=*ucsp; ucs; ucs = *++ucsp) 805 { 806 /* end should be hit before ever seeing padding */ 807 if (ucs == 0xffff) 808 return false; 809 810#ifdef UNICODE32 811 /* Check for a surrogate UTF16 pair */ 812 if (ucs >= 0xd800 && ucs < 0xdc00 && 813 *(ucsp+1) >= 0xdc00 && *(ucsp+1) < 0xe000) { 814 ucc = 0x10000 + (((ucs & 0x3ff) << 10) | (*(ucsp+1) & 0x3ff)); 815 ucsp++; 816 } else 817#endif 818 ucc = ucs; 819 820 if ((p = utf8encode(ucc, p)) - name > FAT_DIRENTRY_NAME_MAX) 821 return false; 822 } 823 824 /* longname ok */ 825 *p = '\0'; 826 return true; 827} 828 829static unsigned long cluster2sec(struct bpb *fat_bpb, long cluster) 830{ 831 long zerocluster = 2; 832 833 /* negative clusters (FAT16 root dir) don't get the 2 offset */ 834#ifdef HAVE_FAT16SUPPORT 835 if (fat_bpb->is_fat16 && cluster < 0) 836 { 837 zerocluster = 0; 838 } 839 else 840#endif /* HAVE_FAT16SUPPORT */ 841 if ((unsigned long)cluster > fat_bpb->dataclusters + 1) 842 { 843 DEBUGF( "%s() - Bad cluster number (%ld)\n", __func__, cluster); 844 return 0; 845 } 846 847 return (unsigned long)(cluster - zerocluster)*fat_bpb->bpb_secperclus 848 + fat_bpb->firstdatasector; 849} 850 851#ifdef HAVE_FAT16SUPPORT 852static long get_next_cluster16(struct bpb *fat_bpb, long startcluster) 853{ 854 /* if FAT16 root dir, dont use the FAT */ 855 if (startcluster < 0) 856 return startcluster + 1; 857 858 unsigned long entry = startcluster; 859 unsigned long sector = entry / CLUSTERS_PER_FAT16_SECTOR; 860 unsigned long offset = entry % CLUSTERS_PER_FAT16_SECTOR; 861 862 dc_lock_cache(); 863 864 uint16_t *sec = cache_sector(fat_bpb, sector + fat_bpb->fatrgnstart); 865 if (!sec) 866 { 867 dc_unlock_cache(); 868 DEBUGF("%s: Could not cache sector %lu\n", __func__, sector); 869 return -1; 870 } 871 872 long next = letoh16(sec[offset]); 873 874 /* is this last cluster in chain? */ 875 if (next >= FAT16_EOF_MARK) 876 next = 0; 877 878 dc_unlock_cache(); 879 return next; 880} 881 882static long find_free_cluster16(struct bpb *fat_bpb, long startcluster) 883{ 884 unsigned long entry = startcluster; 885 unsigned long sector = entry / CLUSTERS_PER_FAT16_SECTOR; 886 unsigned long offset = entry % CLUSTERS_PER_FAT16_SECTOR; 887 888 for (unsigned long i = 0; i < fat_bpb->fatsize; i++) 889 { 890 unsigned long nr = (i + sector) % fat_bpb->fatsize; 891 uint16_t *sec = cache_sector(fat_bpb, nr + fat_bpb->fatrgnstart); 892 if (!sec) 893 break; 894 895 for (unsigned long j = 0; j < CLUSTERS_PER_FAT16_SECTOR; j++) 896 { 897 unsigned long k = (j + offset) % CLUSTERS_PER_FAT16_SECTOR; 898 899 if (letoh16(sec[k]) == 0x0000) 900 { 901 unsigned long c = nr * CLUSTERS_PER_FAT16_SECTOR + k; 902 /* Ignore the reserved clusters 0 & 1, and also 903 cluster numbers out of bounds */ 904 if (c < 2 || c > fat_bpb->dataclusters + 1) 905 continue; 906 907 DEBUGF("%s(%lx) == %lx\n", __func__, startcluster, c); 908 909 fat_bpb->fsinfo.nextfree = c; 910 return c; 911 } 912 } 913 914 offset = 0; 915 } 916 917 DEBUGF("%s(%lx) == 0\n", __func__, startcluster); 918 return 0; /* 0 is an illegal cluster number */ 919} 920 921static int update_fat_entry16(struct bpb *fat_bpb, unsigned long entry, 922 unsigned long val) 923{ 924 unsigned long sector = entry / CLUSTERS_PER_FAT16_SECTOR; 925 unsigned long offset = entry % CLUSTERS_PER_FAT16_SECTOR; 926 927 val &= 0xFFFF; 928 929 DEBUGF("%s(entry:%lx,val:%lx)\n", __func__, entry, val); 930 931 if (entry == val) 932 panicf("Creating FAT16 loop: %lx,%lx\n", entry, val); 933 934 if (entry < 2) 935 panicf("Updating reserved FAT16 entry %lu\n", entry); 936 937 dc_lock_cache(); 938 939 int16_t *sec = cache_sector(fat_bpb, sector + fat_bpb->fatrgnstart); 940 if (!sec) 941 { 942 dc_unlock_cache(); 943 DEBUGF("Could not cache sector %lu\n", sector); 944 return -1; 945 } 946 947 uint16_t curval = letoh16(sec[offset]); 948 949 if (val) 950 { 951 /* being allocated */ 952 if (curval == 0x0000 && fat_bpb->fsinfo.freecount > 0) 953 fat_bpb->fsinfo.freecount--; 954 } 955 else 956 { 957 /* being freed */ 958 if (curval != 0x0000) 959 fat_bpb->fsinfo.freecount++; 960 } 961 962 DEBUGF("%lu free clusters\n", (unsigned long)fat_bpb->fsinfo.freecount); 963 964 sec[offset] = htole16(val); 965 dc_dirty_buf(sec); 966 967 dc_unlock_cache(); 968 return 0; 969} 970 971static void fat_recalc_free_internal16(struct bpb *fat_bpb) 972{ 973 unsigned long free = 0; 974 975 for (unsigned long i = 0; i < fat_bpb->fatsize; i++) 976 { 977 uint16_t *sec = cache_sector(fat_bpb, i + fat_bpb->fatrgnstart); 978 if (!sec) 979 break; 980 981 for (unsigned long j = 0; j < CLUSTERS_PER_FAT16_SECTOR; j++) 982 { 983 unsigned long c = i * CLUSTERS_PER_FAT16_SECTOR + j; 984 985 if (c < 2 || c > fat_bpb->dataclusters + 1) /* nr 0 is unused */ 986 continue; 987 988 if (letoh16(sec[j]) != 0x0000) 989 continue; 990 991 free++; 992 if (fat_bpb->fsinfo.nextfree == 0xffffffff) 993 fat_bpb->fsinfo.nextfree = c; 994 } 995 } 996 997 fat_bpb->fsinfo.freecount = free; 998} 999#endif /* HAVE_FAT16SUPPORT */ 1000 1001static void update_fsinfo32(struct bpb *fat_bpb) 1002{ 1003 uint8_t *fsinfo = cache_sector(fat_bpb, fat_bpb->bpb_fsinfo); 1004 if (!fsinfo) 1005 { 1006 DEBUGF("%s() - Couldn't read FSInfo", __func__); 1007 return; 1008 } 1009 1010 INT322BYTES(fsinfo, FSINFO_FREECOUNT, fat_bpb->fsinfo.freecount); 1011 INT322BYTES(fsinfo, FSINFO_NEXTFREE, fat_bpb->fsinfo.nextfree); 1012 dc_dirty_buf(fsinfo); 1013} 1014 1015static long get_next_cluster32(struct bpb *fat_bpb, long startcluster) 1016{ 1017 unsigned long entry = startcluster; 1018 unsigned long sector = entry / CLUSTERS_PER_FAT_SECTOR; 1019 unsigned long offset = entry % CLUSTERS_PER_FAT_SECTOR; 1020 1021 dc_lock_cache(); 1022 1023 uint32_t *sec = cache_sector(fat_bpb, sector + fat_bpb->fatrgnstart); 1024 if (!sec) 1025 { 1026 dc_unlock_cache(); 1027 DEBUGF("%s: Could not cache sector %lu\n", __func__, sector); 1028 return -1; 1029 } 1030 1031 long next = letoh32(sec[offset]) & 0x0fffffff; 1032 1033 /* is this last cluster in chain? */ 1034 if (next >= FAT_EOF_MARK) 1035 next = 0; 1036 1037 dc_unlock_cache(); 1038 return next; 1039} 1040 1041static long find_free_cluster32(struct bpb *fat_bpb, long startcluster) 1042{ 1043 unsigned long entry = startcluster; 1044 unsigned long sector = entry / CLUSTERS_PER_FAT_SECTOR; 1045 unsigned long offset = entry % CLUSTERS_PER_FAT_SECTOR; 1046 1047 for (unsigned long i = 0; i < fat_bpb->fatsize; i++) 1048 { 1049 unsigned long nr = (i + sector) % fat_bpb->fatsize; 1050 uint32_t *sec = cache_sector(fat_bpb, nr + fat_bpb->fatrgnstart); 1051 if (!sec) 1052 break; 1053 1054 for (unsigned long j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) 1055 { 1056 unsigned long k = (j + offset) % CLUSTERS_PER_FAT_SECTOR; 1057 1058 if (!(letoh32(sec[k]) & 0x0fffffff)) 1059 { 1060 unsigned long c = nr * CLUSTERS_PER_FAT_SECTOR + k; 1061 /* Ignore the reserved clusters 0 & 1, and also 1062 cluster numbers out of bounds */ 1063 if (c < 2 || c > fat_bpb->dataclusters + 1) 1064 continue; 1065 1066 DEBUGF("%s(%lx) == %lx\n", __func__, startcluster, c); 1067 1068 fat_bpb->fsinfo.nextfree = c; 1069 return c; 1070 } 1071 } 1072 1073 offset = 0; 1074 } 1075 1076 DEBUGF("%s(%lx) == 0\n", __func__, startcluster); 1077 return 0; /* 0 is an illegal cluster number */ 1078} 1079 1080static int update_fat_entry32(struct bpb *fat_bpb, unsigned long entry, 1081 unsigned long val) 1082{ 1083 unsigned long sector = entry / CLUSTERS_PER_FAT_SECTOR; 1084 unsigned long offset = entry % CLUSTERS_PER_FAT_SECTOR; 1085 1086 DEBUGF("%s(entry:%lx,val:%lx)\n", __func__, entry, val); 1087 1088 if (entry == val) 1089 panicf("Creating FAT32 loop: %lx,%lx\n", entry, val); 1090 1091 if (entry < 2) 1092 panicf("Updating reserved FAT32 entry %lu\n", entry); 1093 1094 dc_lock_cache(); 1095 1096 uint32_t *sec = cache_sector(fat_bpb, sector + fat_bpb->fatrgnstart); 1097 if (!sec) 1098 { 1099 dc_unlock_cache(); 1100 DEBUGF("Could not cache sector %lu\n", sector); 1101 return -1; 1102 } 1103 1104 uint32_t curval = letoh32(sec[offset]); 1105 1106 if (val) 1107 { 1108 /* being allocated */ 1109 if (!(curval & 0x0fffffff) && fat_bpb->fsinfo.freecount > 0) 1110 fat_bpb->fsinfo.freecount--; 1111 } 1112 else 1113 { 1114 /* being freed */ 1115 if (curval & 0x0fffffff) 1116 fat_bpb->fsinfo.freecount++; 1117 } 1118 1119 DEBUGF("%lu free clusters\n", (unsigned long)fat_bpb->fsinfo.freecount); 1120 1121 /* don't change top 4 bits */ 1122 sec[offset] = htole32((curval & 0xf0000000) | (val & 0x0fffffff)); 1123 dc_dirty_buf(sec); 1124 1125 dc_unlock_cache(); 1126 return 0; 1127} 1128 1129static void fat_recalc_free_internal32(struct bpb *fat_bpb) 1130{ 1131 unsigned long free = 0; 1132 1133 for (unsigned long i = 0; i < fat_bpb->fatsize; i++) 1134 { 1135 uint32_t *sec = cache_sector(fat_bpb, i + fat_bpb->fatrgnstart); 1136 if (!sec) 1137 break; 1138 1139 for (unsigned long j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) 1140 { 1141 unsigned long c = i * CLUSTERS_PER_FAT_SECTOR + j; 1142 1143 if (c < 2 || c > fat_bpb->dataclusters + 1) /* nr 0 is unused */ 1144 continue; 1145 1146 if (letoh32(sec[j]) & 0x0fffffff) 1147 continue; 1148 1149 free++; 1150 if (fat_bpb->fsinfo.nextfree == 0xffffffff) 1151 fat_bpb->fsinfo.nextfree = c; 1152 } 1153 } 1154 1155 fat_bpb->fsinfo.freecount = free; 1156 update_fsinfo32(fat_bpb); 1157} 1158 1159static int fat_mount_internal(struct bpb *fat_bpb) 1160{ 1161 int rc; 1162 /* safe to grab buffer: bpb is irrelevant and no sector will be cached 1163 for this volume since it isn't mounted */ 1164 uint8_t * const buf = dc_get_buffer(); 1165 if (!buf) 1166 FAT_ERROR(-1); 1167 1168 /* Read the sector */ 1169 rc = storage_read_sectors(IF_MD(fat_bpb->drive,) fat_bpb->startsector, 1170 1, buf); 1171 if(rc) 1172 { 1173 DEBUGF("%s() - Couldn't read BPB" 1174 " (err %d)\n", __func__, rc); 1175 FAT_ERROR(rc * 10 - 2); 1176 } 1177 1178 fat_bpb->bpb_bytspersec = BYTES2INT16(buf, BPB_BYTSPERSEC); 1179 unsigned long secmult = fat_bpb->bpb_bytspersec / LOG_SECTOR_SIZE(fat_bpb); 1180 /* Sanity check is performed later */ 1181 1182 fat_bpb->bpb_secperclus = secmult * buf[BPB_SECPERCLUS]; 1183 fat_bpb->bpb_rsvdseccnt = secmult * BYTES2INT16(buf, BPB_RSVDSECCNT); 1184 fat_bpb->bpb_numfats = buf[BPB_NUMFATS]; 1185 fat_bpb->bpb_media = buf[BPB_MEDIA]; 1186 fat_bpb->bpb_fatsz16 = secmult * BYTES2INT16(buf, BPB_FATSZ16); 1187 fat_bpb->bpb_fatsz32 = secmult * BYTES2INT32(buf, BPB_FATSZ32); 1188 fat_bpb->bpb_totsec16 = secmult * BYTES2INT16(buf, BPB_TOTSEC16); 1189 fat_bpb->bpb_totsec32 = secmult * BYTES2INT32(buf, BPB_TOTSEC32); 1190 fat_bpb->last_word = BYTES2INT16(buf, BPB_LAST_WORD); 1191 1192 /* calculate a few commonly used values */ 1193 if (fat_bpb->bpb_fatsz16 != 0) 1194 fat_bpb->fatsize = fat_bpb->bpb_fatsz16; 1195 else 1196 fat_bpb->fatsize = fat_bpb->bpb_fatsz32; 1197 1198 fat_bpb->fatrgnstart = fat_bpb->bpb_rsvdseccnt; 1199 fat_bpb->fatrgnend = fat_bpb->bpb_rsvdseccnt + fat_bpb->fatsize; 1200 1201 if (fat_bpb->bpb_totsec16 != 0) 1202 fat_bpb->totalsectors = fat_bpb->bpb_totsec16; 1203 else 1204 fat_bpb->totalsectors = fat_bpb->bpb_totsec32; 1205 1206 unsigned int rootdirsectors = 0; 1207#ifdef HAVE_FAT16SUPPORT 1208 fat_bpb->bpb_rootentcnt = BYTES2INT16(buf, BPB_ROOTENTCNT); 1209 1210 if (!fat_bpb->bpb_bytspersec) 1211 FAT_ERROR(-3); 1212 1213 rootdirsectors = secmult * ((fat_bpb->bpb_rootentcnt * DIR_ENTRY_SIZE 1214 + fat_bpb->bpb_bytspersec - 1) / fat_bpb->bpb_bytspersec); 1215#endif /* HAVE_FAT16SUPPORT */ 1216 1217 fat_bpb->firstdatasector = fat_bpb->bpb_rsvdseccnt 1218 + fat_bpb->bpb_numfats * fat_bpb->fatsize 1219 + rootdirsectors; 1220 1221 /* Determine FAT type */ 1222 unsigned long datasec = fat_bpb->totalsectors - fat_bpb->firstdatasector; 1223 1224 if (!fat_bpb->bpb_secperclus) 1225 FAT_ERROR(-4); 1226 1227 fat_bpb->dataclusters = datasec / fat_bpb->bpb_secperclus; 1228 1229#ifdef TEST_FAT 1230 /* 1231 we are sometimes testing with "illegally small" fat32 images, 1232 so we don't use the proper fat32 test case for test code 1233 */ 1234 if (fat_bpb->bpb_fatsz16) 1235#else /* !TEST_FAT */ 1236 if (fat_bpb->dataclusters < 65525) 1237#endif /* TEST_FAT */ 1238 { /* FAT16 */ 1239#ifdef HAVE_FAT16SUPPORT 1240 fat_bpb->is_fat16 = true; 1241 if (fat_bpb->dataclusters < 4085) 1242 { /* FAT12 */ 1243 DEBUGF("This is FAT12. Go away!\n"); 1244 FAT_ERROR(-5); 1245 } 1246#else /* !HAVE_FAT16SUPPORT */ 1247 DEBUGF("This is not FAT32. Go away!\n"); 1248 FAT_ERROR(-6); 1249#endif /* HAVE_FAT16SUPPORT */ 1250 } 1251 1252#ifdef HAVE_FAT16SUPPORT 1253 if (fat_bpb->is_fat16) 1254 { 1255 /* FAT16 specific part of BPB */ 1256 fat_bpb->rootdirsector = fat_bpb->bpb_rsvdseccnt 1257 + fat_bpb->bpb_numfats * fat_bpb->bpb_fatsz16; 1258 long dirclusters = ((rootdirsectors + fat_bpb->bpb_secperclus - 1) 1259 / fat_bpb->bpb_secperclus); /* rounded up, to full clusters */ 1260 /* I assign negative pseudo cluster numbers for the root directory, 1261 their range is counted upward until -1. */ 1262 fat_bpb->bpb_rootclus = 0 - dirclusters; /* backwards, before the data */ 1263 fat_bpb->rootdirsectornum = dirclusters * fat_bpb->bpb_secperclus 1264 - rootdirsectors; 1265 } 1266 else 1267#endif /* HAVE_FAT16SUPPORT */ 1268 { 1269 /* FAT32 specific part of BPB */ 1270 fat_bpb->bpb_rootclus = BYTES2INT32(buf, BPB_ROOTCLUS); 1271 fat_bpb->bpb_fsinfo = secmult * BYTES2INT16(buf, BPB_FSINFO); 1272 fat_bpb->rootdirsector = cluster2sec(fat_bpb, fat_bpb->bpb_rootclus); 1273 } 1274 1275 rc = bpb_is_sane(fat_bpb); 1276 if (rc < 0) 1277 { 1278 DEBUGF("%s: BPB is insane!\n", __func__); 1279 FAT_ERROR(rc * 10 - 7); 1280 } 1281 1282#ifdef HAVE_FAT16SUPPORT 1283 if (fat_bpb->is_fat16) 1284 { 1285 fat_bpb->fsinfo.freecount = 0xffffffff; /* force recalc later */ 1286 fat_bpb->fsinfo.nextfree = 0xffffffff; 1287 } 1288 else 1289#endif /* HAVE_FAT16SUPPORT */ 1290 { 1291 /* Read the fsinfo sector */ 1292 rc = storage_read_sectors(IF_MD(fat_bpb->drive,) 1293 fat_bpb->startsector + fat_bpb->bpb_fsinfo, 1, buf); 1294 1295 if (rc < 0) 1296 { 1297 DEBUGF("%s() - Couldn't read FSInfo" 1298 " (error code %d)\n", __func__, rc); 1299 FAT_ERROR(rc * 10 - 8); 1300 } 1301 1302 /* Sanity check FS info */ 1303 long info = BYTES2INT32(buf, FSINFO_SIGNATURE); 1304 if (info != FSINFO_SIGNATURE_VAL) { 1305 DEBUGF("%s() FSInfo signature mismatch (%lx)\n", 1306 __func__, info); 1307 FAT_ERROR(-9); 1308 } 1309 1310 fat_bpb->fsinfo.freecount = BYTES2INT32(buf, FSINFO_FREECOUNT); 1311 fat_bpb->fsinfo.nextfree = BYTES2INT32(buf, FSINFO_NEXTFREE); 1312 } 1313 1314#ifdef HAVE_FAT16SUPPORT 1315 /* Fix up calls that change per FAT type */ 1316 if (fat_bpb->is_fat16) 1317 { 1318 BPB_FN_SET16(fat_bpb, get_next_cluster); 1319 BPB_FN_SET16(fat_bpb, find_free_cluster); 1320 BPB_FN_SET16(fat_bpb, update_fat_entry); 1321 BPB_FN_SET16(fat_bpb, fat_recalc_free_internal); 1322 } 1323 else 1324 { 1325 BPB_FN_SET32(fat_bpb, get_next_cluster); 1326 BPB_FN_SET32(fat_bpb, find_free_cluster); 1327 BPB_FN_SET32(fat_bpb, update_fat_entry); 1328 BPB_FN_SET32(fat_bpb, fat_recalc_free_internal); 1329 } 1330#endif /* HAVE_FAT16SUPPORT */ 1331 1332 rc = 0; 1333fat_error: 1334 dc_release_buffer(buf); 1335 return rc; 1336} 1337 1338static union raw_dirent * cache_direntry(struct bpb *fat_bpb, 1339 struct fat_filestr *filestr, 1340 unsigned int entry) 1341{ 1342 filestr->eof = false; 1343 1344 if (entry >= MAX_DIRENTRIES) 1345 { 1346 DEBUGF("%s() - Dir is too large (entry %u)\n", __func__, entry); 1347 return NULL; 1348 } 1349 1350 unsigned long sector = entry / DIR_ENTRIES_PER_SECTOR; 1351 1352 if (fat_query_sectornum(filestr) != sector + 1) 1353 { 1354 int rc = fat_seek(filestr, sector + 1); 1355 if (rc < 0) 1356 { 1357 if (rc == FAT_SEEK_EOF) 1358 { 1359 DEBUGF("%s() - End of dir (entry %u)\n", __func__, entry); 1360 fat_seek(filestr, sector); 1361 filestr->eof = true; 1362 } 1363 1364 return NULL; 1365 } 1366 } 1367 1368 union raw_dirent *ent = cache_sector(fat_bpb, filestr->lastsector); 1369 1370 if (ent) 1371 ent += entry % DIR_ENTRIES_PER_SECTOR; 1372 1373 return ent; 1374} 1375 1376static long next_write_cluster(struct bpb *fat_bpb, long oldcluster) 1377{ 1378 DEBUGF("%s(old:%lx)\n", __func__, oldcluster); 1379 1380 long cluster = 0; 1381 1382 /* cluster already allocated? */ 1383 if (oldcluster) 1384 cluster = get_next_cluster(fat_bpb, oldcluster); 1385 1386 if (!cluster) 1387 { 1388 /* passed end of existing entries and now need to append */ 1389 #ifdef HAVE_FAT16SUPPORT 1390 if (UNLIKELY(oldcluster < 0)) 1391 return 0; /* negative, pseudo-cluster of the root dir */ 1392 /* impossible to append something to the root */ 1393 #endif /* HAVE_FAT16SUPPORT */ 1394 1395 dc_lock_cache(); 1396 1397 long findstart = oldcluster > 0 ? 1398 oldcluster + 1 : (long)fat_bpb->fsinfo.nextfree; 1399 1400 cluster = find_free_cluster(fat_bpb, findstart); 1401 1402 if (cluster) 1403 { 1404 /* create the cluster chain */ 1405 if (oldcluster) 1406 update_fat_entry(fat_bpb, oldcluster, cluster); 1407 1408 update_fat_entry(fat_bpb, cluster, FAT_EOF_MARK); 1409 } 1410 else 1411 { 1412 #ifdef TEST_FAT 1413 if (fat_bpb->fsinfo.freecount > 0) 1414 panicf("There is free space, but find_free_cluster() " 1415 "didn't find it!\n"); 1416 #endif 1417 DEBUGF("Disk full!\n"); 1418 } 1419 1420 dc_unlock_cache(); 1421 } 1422 1423 return cluster; 1424} 1425 1426/* extend dir file by one cluster and clear it; file position should be at the 1427 current last cluster before calling and size of dir checked */ 1428static int fat_extend_dir(struct bpb *fat_bpb, struct fat_filestr *dirstr) 1429{ 1430 DEBUGF("%s()\n", __func__); 1431 1432 int rc; 1433 1434 long cluster = dirstr->lastcluster; 1435 long newcluster = next_write_cluster(fat_bpb, cluster); 1436 1437 if (!newcluster) 1438 { 1439 /* no more room or something went wrong */ 1440 DEBUGF("Out of space\n"); 1441 FAT_ERROR(FAT_RC_ENOSPC); 1442 } 1443 1444 /* we must clear whole clusters */ 1445 unsigned long startsector = cluster2sec(fat_bpb, newcluster); 1446 unsigned long sector = startsector - 1; 1447 1448 if (startsector == 0) 1449 FAT_ERROR(-1); 1450 1451 for (unsigned int i = 0; i < fat_bpb->bpb_secperclus; i++) 1452 { 1453 dc_lock_cache(); 1454 1455 void *sec = cache_sector_buffer(IF_MV(fat_bpb,) ++sector); 1456 if (!sec) 1457 { 1458 dc_unlock_cache(); 1459 DEBUGF("Cannot clear cluster %ld\n", newcluster); 1460 update_fat_entry(fat_bpb, newcluster, 0); 1461 FAT_ERROR(-2); 1462 } 1463 1464 memset(sec, 0, LOG_SECTOR_SIZE(fat_bpb)); 1465 dc_dirty_buf(sec); 1466 dc_unlock_cache(); 1467 } 1468 1469 if (!dirstr->fatfilep->firstcluster) 1470 dirstr->fatfilep->firstcluster = newcluster; 1471 1472 dirstr->lastcluster = newcluster; 1473 dirstr->lastsector = sector; 1474 dirstr->clusternum++; 1475 dirstr->sectornum = sector - startsector; 1476 dirstr->eof = false; 1477 1478 rc = 0; 1479fat_error: 1480 return rc; 1481} 1482 1483static void fat_open_internal(IF_MV(int volume,) long startcluster, 1484 struct fat_file *file) 1485{ 1486#ifdef HAVE_MULTIVOLUME 1487 file->volume = volume; 1488#endif 1489 file->firstcluster = startcluster; 1490 file->dircluster = 0; 1491 file->e.entry = 0; 1492 file->e.entries = 0; 1493} 1494 1495#if CONFIG_RTC 1496static void fat_time(uint16_t *date, uint16_t *time, int16_t *tenth) 1497{ 1498 struct tm *tm = get_time(); 1499 1500 if (date) 1501 { 1502 *date = ((tm->tm_year - 80) << 9) | 1503 ((tm->tm_mon + 1) << 5) | 1504 tm->tm_mday; 1505 } 1506 1507 if (time) 1508 { 1509 *time = (tm->tm_hour << 11) | 1510 (tm->tm_min << 5) | 1511 (tm->tm_sec >> 1); 1512 } 1513 1514 if (tenth) 1515 *tenth = (tm->tm_sec & 1) * 100; 1516} 1517 1518#else /* !CONFIG_RTC */ 1519 1520static void fat_time(uint16_t *date, uint16_t *time, int16_t *tenth) 1521{ 1522 /* non-RTC version returns an increment from the supplied time, or a 1523 * fixed standard time/date if no time given as input */ 1524 1525 /* Macros to convert a 2-digit string to a decimal constant. 1526 (YEAR), MONTH and DAY are set by the date command, which outputs 1527 DAY as 00..31 and MONTH as 01..12. The leading zero would lead to 1528 misinterpretation as an octal constant. */ 1529 #define S100(x) 1 ## x 1530 #define C2DIG2DEC(x) (S100(x)-100) 1531 /* The actual build date, as FAT date constant */ 1532 #define BUILD_DATE_FAT (((YEAR - 1980) << 9) \ 1533 | (C2DIG2DEC(MONTH) << 5) \ 1534 | C2DIG2DEC(DAY)) 1535 1536 bool date_forced = false; 1537 bool next_day = false; 1538 unsigned time2 = 0; /* double time, for CRTTIME with 1s precision */ 1539 1540 if (date && *date < BUILD_DATE_FAT) 1541 { 1542 *date = BUILD_DATE_FAT; 1543 date_forced = true; 1544 } 1545 1546 if (time) 1547 { 1548 time2 = *time << 1; 1549 if (time2 == 0 || date_forced) 1550 { 1551 time2 = (11 < 6) | 11; /* set to 00:11:11 */ 1552 } 1553 else 1554 { 1555 unsigned mins = (time2 >> 6) & 0x3f; 1556 unsigned hours = (time2 >> 12) & 0x1f; 1557 1558 mins = 11 * ((mins / 11) + 1); /* advance to next multiple of 11 */ 1559 if (mins > 59) 1560 { 1561 mins = 11; /* 00 would be a bad marker */ 1562 if (++hours > 23) 1563 { 1564 hours = 0; 1565 next_day = true; 1566 } 1567 } 1568 time2 = (hours << 12) | (mins << 6) | mins; /* secs = mins */ 1569 } 1570 *time = time2 >> 1; 1571 } 1572 1573 if (tenth) 1574 *tenth = (time2 & 1) * 100; 1575 1576 if (date && next_day) 1577 { 1578 static const unsigned char daysinmonth[] = 1579 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 1580 unsigned day = *date & 0x1f; 1581 unsigned month = (*date >> 5) & 0x0f; 1582 unsigned year = (*date >> 9) & 0x7f; 1583 1584 /* simplification: ignore leap years */ 1585 if (++day > daysinmonth[month-1]) 1586 { 1587 day = 1; 1588 if (++month > 12) 1589 { 1590 month = 1; 1591 year++; 1592 } 1593 } 1594 1595 *date = (year << 9) | (month << 5) | day; 1596 } 1597} 1598#endif /* CONFIG_RTC */ 1599 1600static int write_longname(struct bpb *fat_bpb, struct fat_filestr *parentstr, 1601 struct fat_file *file, const unsigned char *name, 1602 unsigned long ucslen, const unsigned char *shortname, 1603 union raw_dirent *srcent, uint8_t attr, 1604 unsigned int flags) 1605{ 1606 DEBUGF("%s(file:0x%lx, first:%d, num:%d, name:%s)\n", __func__, 1607 file->firstcluster, file->e.entry - file->e.entries + 1, 1608 file->e.entries, name); 1609 1610 int rc; 1611 union raw_dirent *ent; 1612 1613 uint16_t date = 0, time = 0, tenth = 0; 1614 fat_time(&date, &time, &tenth); 1615 time = htole16(time); 1616 date = htole16(date); 1617 1618 /* shortname checksum saved in each longname entry */ 1619 uint8_t chksum = shortname_checksum(shortname); 1620 1621 /* we need to convert the name first since the entries are written in 1622 reverse order */ 1623 unsigned long ucspadlen = ALIGN_UP(ucslen, FATLONG_NAME_CHARS); 1624 uint16_t ucsname[ucspadlen]; 1625 1626 for (unsigned long i = 0; i < ucspadlen; i++) 1627 { 1628 if (i < ucslen) { 1629#ifdef UNICODE32 1630 ucschar_t tmp; 1631 name = utf8decode(name, &tmp); 1632 /* For codepoints > U+FFFF we will need to use a UTF16 surrogate 1633 pair. 'ucslen' already takes this into account! */ 1634 if (tmp < 0x10000) { 1635 ucsname[i] = tmp; 1636 } else { 1637 tmp -= 0x10000; 1638 ucsname[i++] = 0xd800 | ((tmp >> 10) & 0x3ff); /* High */ 1639 ucsname[i] = 0xdc00 | (tmp & 0x3ff); /* Low */ 1640 } 1641#else 1642 name = utf8decode(name, &ucsname[i]); 1643#endif 1644 } else if (i == ucslen) { 1645 ucsname[i] = 0x0000; /* name doesn't fill last block */ 1646 } else /* i > ucslen */ { 1647 ucsname[i] = 0xffff; /* pad-out to end */ 1648 } 1649 } 1650 1651 dc_lock_cache(); 1652 1653 const unsigned int longentries = file->e.entries - 1; 1654 const unsigned int firstentry = file->e.entry - longentries; 1655 1656 /* longame entries */ 1657 for (unsigned int i = 0; i < longentries; i++) 1658 { 1659 ent = cache_direntry(fat_bpb, parentstr, firstentry + i); 1660 if (!ent) 1661 FAT_ERROR(-2); 1662 1663 /* verify this entry is free */ 1664 if (ent->name[0] && ent->name[0] != 0xe5) 1665 { 1666 panicf("Dir entry %d in sector %x is not free! " 1667 "%02x %02x %02x %02x", 1668 i + firstentry, (unsigned)parentstr->lastsector, 1669 (unsigned)ent->data[0], (unsigned)ent->data[1], 1670 (unsigned)ent->data[2], (unsigned)ent->data[3]); 1671 } 1672 1673 memset(ent->data, 0, DIR_ENTRY_SIZE); 1674 1675 unsigned int ord = longentries - i; 1676 1677 ent->ldir_ord = ord | (i == 0 ? FATLONG_ORD_F_LAST : 0); 1678 ent->ldir_attr = ATTR_LONG_NAME; 1679 ent->ldir_chksum = chksum; 1680 1681 /* set name */ 1682 uint16_t *ucsptr = &ucsname[(ord - 1) * FATLONG_NAME_CHARS]; 1683 for (unsigned j = longent_char_first(); j; j = longent_char_next(j)) 1684 { 1685 uint16_t ucs = *ucsptr++; 1686 INT162BYTES(ent->data, j, ucs); 1687 } 1688 1689 dc_dirty_buf(ent); 1690 DEBUGF("Longname entry %d\n", ord); 1691 } 1692 1693 /* shortname entry */ 1694 DEBUGF("Shortname '%s'\n", shortname); 1695 1696 ent = cache_direntry(fat_bpb, parentstr, file->e.entry); 1697 if (!ent) 1698 FAT_ERROR(-2); 1699 1700 if (srcent && (flags & DIRENT_TEMPL)) 1701 { 1702 /* srcent points to short entry template */ 1703 *ent = *srcent; 1704 } 1705 else 1706 { 1707 /* make our own short entry */ 1708 memset(ent->data, 0, DIR_ENTRY_SIZE); 1709 ent->attr = attr; 1710 } 1711 1712 /* short name may change even if just moving */ 1713 memcpy(ent->name, shortname, 11); 1714 raw_dirent_set_fstclus(ent, file->firstcluster); 1715 1716 if (!(flags & DIRENT_TEMPL_CRT)) 1717 { 1718 ent->crttimetenth = tenth; 1719 ent->crttime = time; 1720 ent->crtdate = date; 1721 } 1722 1723 if (!(flags & DIRENT_TEMPL_WRT)) 1724 { 1725 ent->wrttime = time; 1726 ent->wrtdate = date; 1727 } 1728 1729 if (!(flags & DIRENT_TEMPL_ACC)) 1730 ent->lstaccdate = date; 1731 1732 if (srcent && (flags & DIRENT_RETURN)) 1733 *srcent = *ent; /* caller wants */ 1734 1735 dc_dirty_buf(ent); 1736 1737 rc = 0; 1738fat_error: 1739 dc_unlock_cache(); 1740 return rc; 1741} 1742 1743static int add_dir_entry(struct bpb *fat_bpb, struct fat_filestr *parentstr, 1744 struct fat_file *file, const char *name, 1745 union raw_dirent *srcent, uint8_t attr, 1746 unsigned int flags) 1747{ 1748 DEBUGF("%s(name:\"%s\",first:%lx)\n", __func__, name, 1749 file->firstcluster); 1750 1751 int rc; 1752 1753 unsigned char basisname[11], shortname[11]; 1754 int entries_needed; 1755 int n = -1; 1756 unsigned long ucslen = 0; 1757 1758 if (is_dotdir_name(name) && (attr & ATTR_DIRECTORY)) 1759 { 1760 /* The "." and ".." directory entries must not be long names */ 1761 int dots = strlcpy(shortname, name, 11); 1762 memset(&shortname[dots], ' ', 11 - dots); 1763 entries_needed = 1; 1764 basisname[0] = '\0'; 1765 } 1766 else 1767 { 1768 rc = check_longname(name); 1769 if (rc < 0) 1770 FAT_ERROR(rc * 10 - 1); /* filename is invalid */ 1771 1772 create_dos_name(basisname, name, &n); 1773 randomize_dos_name(shortname, basisname, &n); 1774 1775 /* one dir entry needed for every 13 utf16 "code units" 1776 of filename, plus one entry for the short name. 1777 Keep in mind that a unicode character can take up to 1778 two code units! 1779 */ 1780 ucslen = utf16len_utf8(name); 1781 if (ucslen > 255) 1782 FAT_ERROR(-2); /* name is too long */ 1783 1784 entries_needed = (ucslen + FATLONG_NAME_CHARS - 1) 1785 / FATLONG_NAME_CHARS + 1; 1786 } 1787 1788 int entry = 0, entries_found = 0, firstentry = -1; 1789 const int entperclus = DIR_ENTRIES_PER_SECTOR*fat_bpb->bpb_secperclus; 1790 1791 /* step 1: search for a sufficiently-long run of free entries and check 1792 for duplicate shortname */ 1793 dc_lock_cache(); 1794 1795 for (bool done = false; !done;) 1796 { 1797 union raw_dirent *ent = cache_direntry(fat_bpb, parentstr, entry); 1798 1799 if (!ent) 1800 { 1801 if (parentstr->eof) 1802 { 1803 DEBUGF("End of dir (entry %d)\n", entry); 1804 break; 1805 } 1806 1807 DEBUGF("Couldn't read dir (entry %d)\n", entry); 1808 dc_unlock_cache(); 1809 FAT_ERROR(-3); 1810 } 1811 1812 switch (ent->name[0]) 1813 { 1814 case 0: /* all remaining entries in cluster are free */ 1815 DEBUGF("Found end of dir %d\n", entry); 1816 int found = entperclus - (entry % entperclus); 1817 entries_found += found; 1818 entry += found; /* move entry passed end of cluster */ 1819 done = true; 1820 break; 1821 1822 case 0xe5: /* individual free entry */ 1823 entries_found++; 1824 entry++; 1825 DEBUGF("Found free entry %d (%d/%d)\n", 1826 entry, entries_found, entries_needed); 1827 break; 1828 1829 default: /* occupied */ 1830 entries_found = 0; 1831 entry++; 1832 1833 if ((ent->ldir_attr & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME) 1834 break; /* ignore long name entry */ 1835 1836 /* check that our intended shortname doesn't already exist */ 1837 if (!strncmp(shortname, ent->name, 11)) 1838 { 1839 /* shortname exists already, make a new one */ 1840 DEBUGF("Duplicate shortname '%.11s'", shortname); 1841 randomize_dos_name(shortname, basisname, &n); 1842 DEBUGF(", changing to '%.11s'\n", shortname); 1843 1844 /* name has changed, we need to restart search */ 1845 entry = 0; 1846 firstentry = -1; 1847 } 1848 break; 1849 } 1850 1851 if (firstentry < 0 && entries_found >= entries_needed) 1852 { 1853 /* found adequate space; point to initial free entry */ 1854 firstentry = entry - entries_found; 1855 } 1856 } 1857 1858 dc_unlock_cache(); 1859 1860 /* step 2: extend the dir if necessary */ 1861 if (firstentry < 0) 1862 { 1863 DEBUGF("Adding new cluster(s) to dir\n"); 1864 1865 if (entry + entries_needed - entries_found > MAX_DIRENTRIES) 1866 { 1867 /* FAT specification allows no more than 65536 entries (2MB) 1868 per directory */ 1869 DEBUGF("Directory would be too large.\n"); 1870 FAT_ERROR(-4); 1871 } 1872 1873 while (entries_found < entries_needed) 1874 { 1875 rc = fat_extend_dir(fat_bpb, parentstr); 1876 if (rc == FAT_RC_ENOSPC) 1877 FAT_ERROR(RC); 1878 else if (rc < 0) 1879 FAT_ERROR(rc * 10 - 5); 1880 1881 entries_found += entperclus; 1882 entry += entperclus; 1883 } 1884 1885 firstentry = entry - entries_found; 1886 } 1887 1888 /* remember the parent directory entry information */ 1889#ifdef HAVE_MULTIVOLUME 1890 file->volume = parentstr->fatfilep->volume; 1891#endif 1892 file->dircluster = parentstr->fatfilep->firstcluster; 1893 file->e.entry = firstentry + entries_needed - 1; 1894 file->e.entries = entries_needed; 1895 1896 /* step 3: add entry */ 1897 DEBUGF("Adding longname to entry %d\n", firstentry); 1898 rc = write_longname(fat_bpb, parentstr, file, name, ucslen, 1899 shortname, srcent, attr, flags); 1900 if (rc < 0) 1901 FAT_ERROR(rc * 10 - 6); 1902 1903 DEBUGF("Added new dir entry %u; using %u entries\n", 1904 file->e.entry, file->e.entries); 1905 1906 rc = 0; 1907fat_error: 1908 return rc; 1909} 1910 1911static int update_short_entry(struct bpb *fat_bpb, struct fat_file *file, 1912 uint32_t size, struct fat_direntry *fatent) 1913{ 1914 DEBUGF("%s(cluster:%lx entry:%d size:%ld)\n", 1915 __func__, file->firstcluster, file->e.entry, size); 1916 1917 int rc; 1918 1919#if CONFIG_RTC 1920 uint16_t time = 0; 1921 uint16_t date = 0; 1922#else 1923 /* get old time to increment from */ 1924 uint16_t time = letoh16(fatent->wrttime); 1925 uint16_t date = letoh16(fatent->wrtdate); 1926#endif 1927 fat_time(&date, &time, NULL); 1928 date = htole16(date); 1929 time = htole16(time); 1930 1931 /* open the parent directory */ 1932 struct fat_file parent; 1933 fat_open_internal(IF_MV(file->volume,) file->dircluster, &parent); 1934 1935 struct fat_filestr parentstr; 1936 fat_filestr_init(&parentstr, &parent); 1937 1938 dc_lock_cache(); 1939 1940 union raw_dirent *ent = cache_direntry(fat_bpb, &parentstr, file->e.entry); 1941 if (!ent) 1942 FAT_ERROR(-1); 1943 1944 if (!ent->name[0] || ent->name[0] == 0xe5) 1945 panicf("Updating size on empty dir entry %d\n", file->e.entry); 1946 1947 /* basic file data */ 1948 raw_dirent_set_fstclus(ent, file->firstcluster); 1949 ent->filesize = htole32(size); 1950 1951 /* time and date info */ 1952 ent->wrttime = time; 1953 ent->wrtdate = date; 1954 ent->lstaccdate = date; 1955 1956 if (fatent) 1957 { 1958 fatent->name[0] = '\0'; /* not gonna bother here */ 1959 parse_short_direntry(ent, fatent); 1960 } 1961 1962 dc_dirty_buf(ent); 1963 1964 rc = 0; 1965fat_error: 1966 dc_unlock_cache(); 1967 return rc; 1968} 1969 1970static int free_direntries(struct bpb *fat_bpb, struct fat_file *file) 1971{ 1972 /* open the parent directory */ 1973 struct fat_file parent; 1974 fat_open_internal(IF_MV(file->volume,) file->dircluster, &parent); 1975 1976 struct fat_filestr parentstr; 1977 fat_filestr_init(&parentstr, &parent); 1978 1979 for (unsigned int entries = file->e.entries, 1980 entry = file->e.entry - entries + 1; 1981 entries; entries--, entry++) 1982 { 1983 DEBUGF("Clearing dir entry %d (%d/%d)\n", 1984 entry, entries - file->e.entries + 1, file->e.entries); 1985 1986 1987 dc_lock_cache(); 1988 1989 union raw_dirent *ent = cache_direntry(fat_bpb, &parentstr, entry); 1990 if (!ent) 1991 { 1992 dc_unlock_cache(); 1993 1994 if (entries == file->e.entries) 1995 return -1; /* nothing at all freed */ 1996 1997 /* longname already destroyed; revert to shortname */ 1998 file->e.entries = 1; 1999 return 0; 2000 } 2001 2002 ent->data[0] = 0xe5; 2003 2004 dc_dirty_buf(ent); 2005 dc_unlock_cache(); 2006 } 2007 2008 /* directory entry info is now gone */ 2009 file->dircluster = 0; 2010 file->e.entry = FAT_DIRSCAN_RW_VAL; 2011 file->e.entries = 0; 2012 2013 return 1; 2014} 2015 2016static int free_cluster_chain(struct bpb *fat_bpb, long startcluster) 2017{ 2018 for (long last = startcluster, next; last; last = next) 2019 { 2020 next = get_next_cluster(fat_bpb, last); 2021 int rc = update_fat_entry(fat_bpb, last, 0); 2022 if (LIKELY(rc >= 0 && !startcluster)) 2023 continue; 2024 2025 if (rc < 0) 2026 return startcluster ? -1 : 0; 2027 2028 startcluster = 0; 2029 } 2030 2031 return 1; 2032} 2033 2034 2035/** File entity functions **/ 2036 2037#if defined(MAX_VARIABLE_LOG_SECTOR) 2038int fat_file_sector_size(IF_MV_NONVOID(const struct fat_file *file)) 2039{ 2040 const struct bpb *fat_bpb = FAT_BPB(file->volume); 2041 2042 return LOG_SECTOR_SIZE(fat_bpb); 2043} 2044#endif 2045 2046int fat_create_file(struct fat_file *parent, const char *name, 2047 uint8_t attr, struct fat_file *file, 2048 struct fat_direntry *fatent) 2049{ 2050 DEBUGF("%s(\"%s\",%lx,%lx)\n", __func__, name, (long)file, (long)parent); 2051 struct bpb * const fat_bpb = FAT_BPB(parent->volume); 2052 if (!fat_bpb) 2053 return -1; 2054 2055 int rc; 2056 2057 fat_open_internal(IF_MV(parent->volume,) 0, file); 2058 2059 struct fat_filestr parentstr; 2060 fat_filestr_init(&parentstr, parent); 2061 2062 const bool isdir = attr & ATTR_DIRECTORY; 2063 unsigned int addflags = fatent ? DIRENT_RETURN : 0; 2064 union raw_dirent *newentp = (isdir || fatent) ? 2065 alloca(sizeof (union raw_dirent)) : NULL; 2066 2067 if (isdir) 2068 { 2069 struct fat_filestr dirstr; 2070 fat_filestr_init(&dirstr, file); 2071 2072 /* create the first cluster */ 2073 rc = fat_extend_dir(fat_bpb, &dirstr); 2074 if (rc == FAT_RC_ENOSPC) 2075 FAT_ERROR(RC); 2076 else if (rc < 0) 2077 FAT_ERROR(rc * 10 - 2); 2078 2079 struct fat_file dummyfile; 2080 2081 /* add the "." entry */ 2082 fat_open_internal(IF_MV(0,) file->firstcluster, &dummyfile); 2083 2084 /* this returns the short entry template for the remaining entries */ 2085 rc = add_dir_entry(fat_bpb, &dirstr, &dummyfile, ".", newentp, 2086 attr, DIRENT_RETURN); 2087 if (rc < 0) 2088 FAT_ERROR(rc * 10 - 3); 2089 2090 /* and the ".." entry */ 2091 /* the root cluster is cluster 0 in the ".." entry */ 2092 fat_open_internal(IF_MV(0,) 2093 parent->firstcluster == fat_bpb->bpb_rootclus ? 2094 0 : parent->firstcluster, &dummyfile); 2095 2096 rc = add_dir_entry(fat_bpb, &dirstr, &dummyfile, "..", newentp, 2097 attr, DIRENT_TEMPL_TIMES); 2098 if (rc < 0) 2099 FAT_ERROR(rc * 10 - 4); 2100 2101 addflags |= DIRENT_TEMPL_TIMES; 2102 } 2103 2104 /* lastly, add the entry in the parent directory */ 2105 rc = add_dir_entry(fat_bpb, &parentstr, file, name, newentp, 2106 attr, addflags); 2107 if (rc == FAT_RC_ENOSPC) 2108 FAT_ERROR(RC); 2109 else if (rc < 0) 2110 FAT_ERROR(rc * 10 - 5); 2111 2112 if (fatent) 2113 { 2114 strcpy(fatent->name, name); 2115 parse_short_direntry(newentp, fatent); 2116 } 2117 2118 rc = 0; 2119fat_error: 2120 if (rc < 0) 2121 free_cluster_chain(fat_bpb, file->firstcluster); 2122 2123 cache_commit(fat_bpb); 2124 return rc; 2125} 2126 2127bool fat_dir_is_parent(const struct fat_file *dir, const struct fat_file *file) 2128{ 2129 /* if the directory file's first cluster is the same as the file's 2130 directory cluster and they're on the same volume, 'dir' is its parent 2131 directory; the file must also have a dircluster (ie. not removed) */ 2132 long dircluster = file->dircluster; 2133 return dircluster && dircluster == dir->firstcluster 2134 IF_MV( && dir->volume == file->volume ); 2135} 2136 2137bool fat_file_is_same(const struct fat_file *file1, 2138 const struct fat_file *file2) 2139{ 2140 /* first, triviality */ 2141 if (file1 == file2) 2142 return true; 2143 2144 /* if the directory info matches and the volumes are the same, file1 and 2145 file2 refer to the same file/directory */ 2146 return file1->dircluster == file2->dircluster 2147 && file1->e.entry == file2->e.entry 2148 IF_MV( && file1->volume == file2->volume ); 2149} 2150 2151int fat_open(const struct fat_file *parent, long startcluster, 2152 struct fat_file *file) 2153{ 2154 if (!parent) 2155 return -2; /* this does _not_ open any root */ 2156 2157 struct bpb * const fat_bpb = FAT_BPB(parent->volume); 2158 if (!fat_bpb) 2159 return -1; 2160 2161 /* inherit basic parent information; dirscan info is expected to have been 2162 initialized beforehand (usually via scanning for the entry ;) */ 2163#ifdef HAVE_MULTIVOLUME 2164 file->volume = parent->volume; 2165#endif 2166 file->firstcluster = startcluster; 2167 file->dircluster = parent->firstcluster; 2168 2169 return 0; 2170} 2171 2172int fat_open_rootdir(IF_MV(int volume,) struct fat_file *dir) 2173{ 2174 struct bpb * const fat_bpb = FAT_BPB(volume); 2175 if (!fat_bpb) 2176 return -1; 2177 2178 fat_open_internal(IF_MV(volume,) fat_bpb->bpb_rootclus, dir); 2179 return 0; 2180} 2181 2182int fat_remove(struct fat_file *file, enum fat_remove_op what) 2183{ 2184 struct bpb * const fat_bpb = FAT_BPB(file->volume); 2185 if (!fat_bpb) 2186 return -1; 2187 2188 int rc; 2189 2190 if (file->firstcluster == fat_bpb->bpb_rootclus) 2191 { 2192 DEBUGF("Trying to remove root of volume %d\n", 2193 IF_MV_VOL(file->volume)); 2194 FAT_ERROR(-2); 2195 } 2196 2197 if (file->dircluster && (what & FAT_RM_DIRENTRIES)) 2198 { 2199 /* free everything in the parent directory */ 2200 DEBUGF("Removing dir entries: %lX\n", file->dircluster); 2201 rc = free_direntries(fat_bpb, file); 2202 if (rc <= 0) 2203 FAT_ERROR(rc * 10 - 3); 2204 } 2205 2206 if (file->firstcluster && (what & FAT_RM_DATA)) 2207 { 2208 /* mark all clusters in the chain as free */ 2209 DEBUGF("Removing cluster chain: %lX\n", file->firstcluster); 2210 rc = free_cluster_chain(fat_bpb, file->firstcluster); 2211 if (rc < 0) 2212 FAT_ERROR(rc * 10 - 4); 2213 2214 /* at least the first cluster was freed */ 2215 file->firstcluster = 0; 2216 2217 if (rc == 0) 2218 FAT_ERROR(-5); 2219 } 2220 2221 rc = 0; 2222fat_error: 2223 cache_commit(fat_bpb); 2224 return rc; 2225} 2226 2227int fat_rename(struct fat_file *parent, struct fat_file *file, 2228 const unsigned char *newname) 2229{ 2230 struct bpb * const fat_bpb = FAT_BPB(parent->volume); 2231 if (!fat_bpb) 2232 return -1; 2233 2234 int rc; 2235 /* save old file; don't change it unless everything succeeds */ 2236 struct fat_file newfile = *file; 2237 2238#ifdef HAVE_MULTIVOLUME 2239 /* rename only works on the same volume */ 2240 if (file->volume != parent->volume) 2241 { 2242 DEBUGF("No rename across volumes!\n"); 2243 FAT_ERROR(-2); 2244 } 2245#endif 2246 2247 /* root directories can't be renamed */ 2248 if (file->firstcluster == fat_bpb->bpb_rootclus) 2249 { 2250 DEBUGF("Trying to rename root of volume %d\n", 2251 IF_MV_VOL(file->volume)); 2252 FAT_ERROR(-3); 2253 } 2254 2255 if (!file->dircluster) 2256 { 2257 /* file was removed but is still open */ 2258 DEBUGF("File has no dir cluster!\n"); 2259 FAT_ERROR(-4); 2260 } 2261 2262 struct fat_file dir; 2263 struct fat_filestr dirstr; 2264 2265 /* open old parent */ 2266 fat_open_internal(IF_MV(file->volume,) file->dircluster, &dir); 2267 fat_filestr_init(&dirstr, &dir); 2268 2269 /* fetch a copy of the existing short entry */ 2270 dc_lock_cache(); 2271 2272 union raw_dirent *ent = cache_direntry(fat_bpb, &dirstr, file->e.entry); 2273 if (!ent) 2274 { 2275 dc_unlock_cache(); 2276 FAT_ERROR(-5); 2277 } 2278 2279 union raw_dirent rawent = *ent; 2280 2281 dc_unlock_cache(); 2282 2283 /* create new name in new parent directory */ 2284 fat_filestr_init(&dirstr, parent); 2285 rc = add_dir_entry(fat_bpb, &dirstr, &newfile, newname, &rawent, 2286 0, DIRENT_TEMPL_CRT | DIRENT_TEMPL_WRT); 2287 if (rc == FAT_RC_ENOSPC) 2288 FAT_ERROR(RC); 2289 else if (rc < 0) 2290 FAT_ERROR(rc * 10 - 6); 2291 2292 /* if renaming a directory and it was a move, update the '..' entry to 2293 keep it pointing to its parent directory */ 2294 if ((rawent.attr & ATTR_DIRECTORY) && newfile.dircluster != file->dircluster) 2295 { 2296 /* open the dir that was renamed */ 2297 fat_open_internal(IF_MV(newfile.volume,) newfile.firstcluster, &dir); 2298 fat_filestr_init(&dirstr, &dir); 2299 2300 /* obtain dot-dot directory entry */ 2301 dc_lock_cache(); 2302 ent = cache_direntry(fat_bpb, &dirstr, 1); 2303 if (!ent) 2304 { 2305 dc_unlock_cache(); 2306 FAT_ERROR(-7); 2307 } 2308 2309 if (strncmp(".. ", ent->name, 11)) 2310 { 2311 /* .. entry must be second entry according to FAT spec (p.29) */ 2312 DEBUGF("Second dir entry is not double-dot!\n"); 2313 dc_unlock_cache(); 2314 FAT_ERROR(-8); 2315 } 2316 2317 /* parent cluster is 0 if parent dir is the root - FAT spec (p.29) */ 2318 long parentcluster = 0; 2319 if (parent->firstcluster != fat_bpb->bpb_rootclus) 2320 parentcluster = parent->firstcluster; 2321 2322 raw_dirent_set_fstclus(ent, parentcluster); 2323 2324 dc_dirty_buf(ent); 2325 dc_unlock_cache(); 2326 } 2327 2328 /* remove old name */ 2329 rc = free_direntries(fat_bpb, file); 2330 if (rc <= 0) 2331 FAT_ERROR(rc * 10 - 9); 2332 2333 /* finally, update old file with new directory entry info */ 2334 *file = newfile; 2335 2336 rc = 0; 2337fat_error: 2338 if (rc < 0 && !fat_file_is_same(&newfile, file)) 2339 free_direntries(fat_bpb, &newfile); 2340 2341 cache_commit(fat_bpb); 2342 return rc; 2343} 2344 2345int fat_modtime(struct fat_file *parent, struct fat_file *file, 2346 time_t modtime) 2347{ 2348 struct bpb * const fat_bpb = FAT_BPB(parent->volume); 2349 2350 if (!fat_bpb) 2351 return -1; 2352 2353 int rc; 2354 2355 struct fat_filestr parentstr; 2356 fat_filestr_init(&parentstr, parent); 2357 2358 dc_lock_cache(); 2359 2360 union raw_dirent *ent = cache_direntry(fat_bpb, &parentstr, file->e.entry); 2361 if (!ent) 2362 FAT_ERROR(-2); 2363 2364 uint16_t date; 2365 uint16_t time; 2366 dostime_localtime(modtime, &date, &time); 2367 2368 ent->wrttime = htole16(time); 2369 ent->wrtdate = htole16(date); 2370 ent->lstaccdate = htole16(date); 2371 2372 dc_dirty_buf(ent); 2373 2374 rc = 0; 2375fat_error: 2376 dc_unlock_cache(); 2377 cache_commit(fat_bpb); 2378 return rc; 2379} 2380 2381/** File stream functions **/ 2382 2383int fat_closewrite(struct fat_filestr *filestr, uint32_t size, 2384 struct fat_direntry *fatentp) 2385{ 2386 DEBUGF("%s(size=%ld)\n", __func__, size); 2387 struct fat_file * const file = filestr->fatfilep; 2388 struct bpb * const fat_bpb = FAT_BPB(file->volume); 2389 if (!fat_bpb) 2390 return -1; 2391 2392 int rc; 2393 2394 if (!size && file->firstcluster) 2395 { 2396 /* empty file */ 2397 rc = update_fat_entry(fat_bpb, file->firstcluster, 0); 2398 if (rc < 0) 2399 FAT_ERROR(rc * 10 - 2); 2400 2401 file->firstcluster = 0; 2402 fat_rewind(filestr); 2403 } 2404 2405 if (file->dircluster) 2406 { 2407 rc = update_short_entry(fat_bpb, file, size, fatentp); 2408 if (rc < 0) 2409 FAT_ERROR(rc * 10 - 3); 2410 } 2411 else if (fatentp) 2412 { 2413 fat_empty_fat_direntry(fatentp); 2414 } 2415 2416#ifdef TEST_FAT 2417 if (file->firstcluster) 2418 { 2419 unsigned long count = 0; 2420 for (long next = file->firstcluster; next; 2421 next = get_next_cluster(fat_bpb, next)) 2422 { 2423 DEBUGF("cluster %ld: %lx\n", count, next); 2424 count++; 2425 } 2426 2427 uint32_t len = count * fat_bpb->bpb_secperclus * LOG_SECTOR_SIZE(fat_bpb); 2428 DEBUGF("File is %lu clusters (chainlen=%lu, size=%lu)\n", 2429 count, len, size ); 2430 2431 if (len > size + fat_bpb->bpb_secperclus * LOG_SECTOR_SIZE(fat_bpb)) 2432 panicf("Cluster chain is too long\n"); 2433 2434 if (len < size) 2435 panicf("Cluster chain is too short\n"); 2436 } 2437#endif /* TEST_FAT */ 2438 2439 rc = 0; 2440fat_error: 2441 cache_commit(fat_bpb); 2442 return rc; 2443} 2444 2445void fat_filestr_init(struct fat_filestr *fatstr, struct fat_file *file) 2446{ 2447 fatstr->fatfilep = file; 2448 fat_rewind(fatstr); 2449} 2450 2451sector_t fat_query_sectornum(const struct fat_filestr *filestr) 2452{ 2453 /* return next sector number to be transferred */ 2454 struct bpb * const fat_bpb = FAT_BPB(filestr->fatfilep->volume); 2455 if (!fat_bpb) 2456 return INVALID_SECNUM; 2457 2458 return fat_bpb->bpb_secperclus*filestr->clusternum + filestr->sectornum + 1; 2459} 2460 2461/* helper for fat_readwrite */ 2462static long transfer(struct bpb *fat_bpb, sector_t start, long count, 2463 char *buf, bool write) 2464{ 2465 long rc = 0; 2466 2467 DEBUGF("%s(s=%llx, c=%lx, wr=%u)\n", __func__, 2468 start + fat_bpb->startsector, count, write ? 1 : 0); 2469 2470 if (write) 2471 { 2472 unsigned long firstallowed; 2473#ifdef HAVE_FAT16SUPPORT 2474 if (fat_bpb->is_fat16) 2475 firstallowed = fat_bpb->rootdirsector; 2476 else 2477#endif /* HAVE_FAT16SUPPORT */ 2478 firstallowed = fat_bpb->firstdatasector; 2479 2480 if (start < firstallowed) 2481 panicf("Write %llu before data\n", (uint64_t)(firstallowed - start)); 2482 2483 if (start + count > fat_bpb->totalsectors) 2484 { 2485 panicf("Write %llu after data\n", 2486 (uint64_t)(start + count - fat_bpb->totalsectors)); 2487 } 2488 } 2489 2490#ifdef STORAGE_NEEDS_BOUNCE_BUFFER 2491 if(UNLIKELY(STORAGE_OVERLAP((uintptr_t)buf))) { 2492 void* xfer_buf = FAT_BOUNCE_BUFFER(fat_bpb); 2493 while(count > 0) { 2494 int xfer_count = MIN(count*LOG_SECTOR_SIZE(fat_bpb), (FAT_BOUNCE_SECTORS * BOUNCE_SECTOR_SIZE)) / LOG_SECTOR_SIZE(fat_bpb); 2495 2496 if(write) { 2497 memcpy(xfer_buf, buf, xfer_count * LOG_SECTOR_SIZE(fat_bpb)); 2498 rc = storage_write_sectors(IF_MD(fat_bpb->drive,) 2499 start + fat_bpb->startsector, xfer_count, xfer_buf); 2500 } else { 2501 rc = storage_read_sectors(IF_MD(fat_bpb->drive,) 2502 start + fat_bpb->startsector, xfer_count, xfer_buf); 2503 memcpy(buf, xfer_buf, xfer_count * LOG_SECTOR_SIZE(fat_bpb)); 2504 } 2505 2506 if(rc < 0) 2507 break; 2508 2509 buf += xfer_count * LOG_SECTOR_SIZE(fat_bpb); 2510 start += xfer_count; 2511 count -= xfer_count; 2512 } 2513 } else { 2514#endif 2515 if(write) { 2516 rc = storage_write_sectors(IF_MD(fat_bpb->drive,) 2517 start + fat_bpb->startsector, count, buf); 2518 } else { 2519 rc = storage_read_sectors(IF_MD(fat_bpb->drive,) 2520 start + fat_bpb->startsector, count, buf); 2521 } 2522#ifdef STORAGE_NEEDS_BOUNCE_BUFFER 2523 } 2524#endif 2525 2526 if (rc < 0) 2527 { 2528 DEBUGF("Couldn't %s sector %llx (err %ld)\n", 2529 write ? "write":"read", (uint64_t)start, rc); 2530 return rc; 2531 } 2532 2533 return 0; 2534} 2535 2536long fat_readwrite(struct fat_filestr *filestr, unsigned long sectorcount, 2537 void *buf, bool write) 2538{ 2539 struct fat_file * const file = filestr->fatfilep; 2540 struct bpb * const fat_bpb = FAT_BPB(file->volume); 2541 if (!fat_bpb) 2542 return -1; 2543 2544 bool eof = filestr->eof; 2545 2546 if ((eof && !write) || !sectorcount) 2547 return 0; 2548 2549 long rc; 2550 2551 long cluster = filestr->lastcluster; 2552 sector_t sector = filestr->lastsector; 2553 long clusternum = filestr->clusternum; 2554 unsigned long sectornum = filestr->sectornum; 2555 2556 DEBUGF("%s(file:0x%lx,count:0x%lx,buf:%lx,%s)\n", __func__, 2557 file->firstcluster, sectorcount, (long)buf, 2558 write ? "write":"read"); 2559 DEBUGF("%s: sec:%llx numsec:%ld eof:%d\n", __func__, 2560 sector, (long)sectornum, eof ? 1 : 0); 2561 2562 eof = false; 2563 2564 if (!sector) 2565 { 2566 /* look up first sector of file */ 2567 long newcluster = file->firstcluster; 2568 2569 if (write && !newcluster) 2570 { 2571 /* file is empty; try to allocate its first cluster */ 2572 newcluster = next_write_cluster(fat_bpb, 0); 2573 file->firstcluster = newcluster; 2574 } 2575 2576 if (newcluster) 2577 { 2578 cluster = newcluster; 2579 sector = cluster2sec(fat_bpb, cluster) - 1; 2580 2581 #ifdef HAVE_FAT16SUPPORT 2582 if (fat_bpb->is_fat16 && file->firstcluster < 0) 2583 { 2584 sector += fat_bpb->rootdirsectornum; 2585 sectornum = fat_bpb->rootdirsectornum; 2586 } 2587 #endif /* HAVE_FAT16SUPPORT */ 2588 } 2589 } 2590 2591 if (!sector) 2592 { 2593 sectorcount = 0; 2594 eof = true; 2595 } 2596 2597 unsigned long transferred = 0; 2598 unsigned long count = 0; 2599 sector_t last = sector; 2600 2601 while (transferred + count < sectorcount) 2602 { 2603 if (++sectornum >= fat_bpb->bpb_secperclus) 2604 { 2605 /* out of sectors in this cluster; get the next cluster */ 2606 long newcluster = write ? next_write_cluster(fat_bpb, cluster) : 2607 get_next_cluster(fat_bpb, cluster); 2608 if (newcluster) 2609 { 2610 cluster = newcluster; 2611 sector = cluster2sec(fat_bpb, cluster) - 1; 2612 clusternum++; 2613 sectornum = 0; 2614 2615 /* jumped clusters right at start? */ 2616 if (!count) 2617 last = sector; 2618 } 2619 else 2620 { 2621 sectornum--; /* remain in previous position */ 2622 eof = true; 2623 break; 2624 } 2625 } 2626 2627 /* find sequential sectors and transfer them all at once */ 2628 if (sector != last || count >= FAT_MAX_TRANSFER_SIZE) 2629 { 2630 /* not sequential/over limit */ 2631 rc = transfer(fat_bpb, last - count + 1, count, buf, write); 2632 if (rc < 0) 2633 FAT_ERROR(rc * 10 - 2); 2634 2635 transferred += count; 2636 buf += count * LOG_SECTOR_SIZE(fat_bpb); 2637 count = 0; 2638 } 2639 2640 count++; 2641 last = ++sector; 2642 } 2643 2644 if (count) 2645 { 2646 /* transfer any remainder */ 2647 rc = transfer(fat_bpb, last - count + 1, count, buf, write); 2648 if (rc < 0) 2649 FAT_ERROR(rc * 10 - 3); 2650 2651 transferred += count; 2652 } 2653 2654 rc = (eof && write) ? FAT_RC_ENOSPC : (long)transferred; 2655fat_error: 2656 filestr->lastcluster = cluster; 2657 filestr->lastsector = sector; 2658 filestr->clusternum = clusternum; 2659 filestr->sectornum = sectornum; 2660 filestr->eof = eof; 2661 2662 if (rc >= 0) 2663 DEBUGF("Sectors transferred: %ld\n", rc); 2664 2665 return rc; 2666} 2667 2668void fat_rewind(struct fat_filestr *filestr) 2669{ 2670 /* rewind the file position */ 2671 filestr->lastcluster = filestr->fatfilep->firstcluster; 2672 filestr->lastsector = 0; 2673 filestr->clusternum = 0; 2674 filestr->sectornum = FAT_FILE_RW_VAL; 2675 filestr->eof = false; 2676} 2677 2678void fat_seek_to_stream(struct fat_filestr *filestr, 2679 const struct fat_filestr *filestr_seek_to) 2680{ 2681 filestr->lastcluster = filestr_seek_to->lastcluster; 2682 filestr->lastsector = filestr_seek_to->lastsector; 2683 filestr->clusternum = filestr_seek_to->clusternum; 2684 filestr->sectornum = filestr_seek_to->sectornum; 2685 filestr->eof = filestr_seek_to->eof; 2686} 2687 2688int fat_seek(struct fat_filestr *filestr, unsigned long seeksector) 2689{ 2690 const struct fat_file * const file = filestr->fatfilep; 2691 struct bpb * const fat_bpb = FAT_BPB(file->volume); 2692 if (!fat_bpb) 2693 return -1; 2694 2695 int rc; 2696 long cluster = file->firstcluster; 2697 unsigned long sector = 0; 2698 long clusternum = 0; 2699 unsigned long sectornum = FAT_FILE_RW_VAL; 2700 2701#ifdef HAVE_FAT16SUPPORT 2702 if (fat_bpb->is_fat16 && cluster < 0) /* FAT16 root dir */ 2703 seeksector += fat_bpb->rootdirsectornum; 2704#endif /* HAVE_FAT16SUPPORT */ 2705 2706 filestr->eof = false; 2707 if (seeksector) 2708 { 2709 if (cluster == 0) 2710 { 2711 DEBUGF("Seeking beyond the end of empty file! " 2712 "(sector %lu, cluster %ld)\n", seeksector, 2713 seeksector / fat_bpb->bpb_secperclus); 2714 FAT_ERROR(FAT_SEEK_EOF); 2715 } 2716 2717 /* we need to find the sector BEFORE the requested, since 2718 the file struct stores the last accessed sector */ 2719 seeksector--; 2720 clusternum = seeksector / fat_bpb->bpb_secperclus; 2721 sectornum = seeksector % fat_bpb->bpb_secperclus; 2722 2723 long numclusters = clusternum; 2724 2725 if (filestr->clusternum && clusternum >= filestr->clusternum) 2726 { 2727 /* seek forward from current position */ 2728 cluster = filestr->lastcluster; 2729 numclusters -= filestr->clusternum; 2730 } 2731 2732 for (long i = 0; i < numclusters; i++) 2733 { 2734 cluster = get_next_cluster(fat_bpb, cluster); 2735 2736 if (!cluster) 2737 { 2738 DEBUGF("Seeking beyond the end of the file! " 2739 "(sector %lu, cluster %ld)\n", seeksector, i); 2740 FAT_ERROR(FAT_SEEK_EOF); 2741 } 2742 } 2743 2744 sector = cluster2sec(fat_bpb, cluster) + sectornum; 2745 } 2746 2747 DEBUGF("%s(%lx, %lx) == %lx, %lx, %lx\n", __func__, 2748 file->firstcluster, seeksector, cluster, sector, sectornum); 2749 2750 filestr->lastcluster = cluster; 2751 filestr->lastsector = sector; 2752 filestr->clusternum = clusternum; 2753 filestr->sectornum = sectornum; 2754 2755 rc = 0; 2756fat_error: 2757 return rc; 2758} 2759 2760int fat_truncate(const struct fat_filestr *filestr) 2761{ 2762 DEBUGF("%s(): %lX\n", __func__, filestr->lastcluster); 2763 2764 struct bpb * const fat_bpb = FAT_BPB(filestr->fatfilep->volume); 2765 if (!fat_bpb) 2766 return -1; 2767 2768 int rc = 1; 2769 2770 long last = filestr->lastcluster; 2771 long next = 0; 2772 2773 /* truncate trailing clusters after the current position */ 2774 if (last) 2775 { 2776 next = get_next_cluster(fat_bpb, last); 2777 int rc2 = update_fat_entry(fat_bpb, last, FAT_EOF_MARK); 2778 if (rc2 < 0) 2779 FAT_ERROR(rc2 * 10 - 2); 2780 } 2781 2782 int rc2 = free_cluster_chain(fat_bpb, next); 2783 if (rc2 <= 0) 2784 { 2785 DEBUGF("Failed freeing cluster chain\n"); 2786 rc = 0; /* still partial success */ 2787 } 2788 2789fat_error: 2790 return rc; 2791} 2792 2793 2794/** Directory stream functions **/ 2795 2796int fat_readdir(struct fat_filestr *dirstr, struct fat_dirscan_info *scan, 2797 struct filestr_cache *cachep, struct fat_direntry *entry) 2798{ 2799 int rc = 0; 2800 2801 /* long file names are stored in special entries; each entry holds up to 2802 13 UTF-16 characters' thus, UTF-8 converted names can be max 255 chars 2803 (1020 bytes) long, not including the trailing '\0'. */ 2804 struct fatlong_parse_state lnparse; 2805 fatlong_parse_start(&lnparse); 2806 2807 scan->entries = 0; 2808 2809#if defined(MAX_VIRT_SECTOR_SIZE) || defined(MAX_VARIABLE_LOG_SECTOR) 2810 struct bpb *fat_bpb = FAT_BPB(dirstr->fatfilep->volume); 2811#endif 2812 2813 while (1) 2814 { 2815 unsigned int direntry = ++scan->entry; 2816 if (direntry >= MAX_DIRENTRIES) 2817 { 2818 DEBUGF("%s() - Dir is too large (entry %u)\n", __func__, 2819 direntry); 2820 FAT_ERROR(-1); 2821 } 2822 2823 unsigned long sector = direntry / DIR_ENTRIES_PER_SECTOR; 2824 if (cachep->sector != sector) 2825 { 2826 if (cachep->sector + 1 != sector) 2827 { 2828 /* Nothing cached or sector isn't contiguous */ 2829 int rc2 = fat_seek(dirstr, sector); 2830 if (rc2 < 0) 2831 FAT_ERROR(rc2 * 10 - 2); 2832 } 2833 2834 int rc2 = fat_readwrite(dirstr, 1, cachep->buffer, false); 2835 if (rc2 <= 0) 2836 { 2837 if (rc2 == 0) 2838 break; /* eof */ 2839 2840 DEBUGF("%s() - Couldn't read dir (err %d)\n", __func__, rc); 2841 FAT_ERROR(rc2 * 10 - 3); 2842 } 2843 2844 cachep->sector = sector; 2845 } 2846 2847 unsigned int index = direntry % DIR_ENTRIES_PER_SECTOR; 2848 union raw_dirent *ent = &((union raw_dirent *)cachep->buffer)[index]; 2849 2850 if (ent->name[0] == 0) 2851 break; /* last entry */ 2852 2853 if (ent->name[0] == 0xe5) 2854 { 2855 scan->entries = 0; 2856 continue; /* free entry */ 2857 } 2858 2859 ++scan->entries; 2860 2861 if (IS_LDIR_ATTR(ent->ldir_attr)) 2862 { 2863 /* LFN entry */ 2864 if (UNLIKELY(!fatlong_parse_entry(&lnparse, ent, entry))) 2865 { 2866 /* resync so we don't return just the short name if what we 2867 landed in the middle of is valid (directory changes 2868 between calls likely created the situation; ignoring this 2869 case can be harmful elsewhere and is destructive to the 2870 entry series itself) */ 2871 struct bpb *fat_bpb = FAT_BPB(dirstr->fatfilep->volume); 2872 if (!fat_bpb) 2873 FAT_ERROR(-4); 2874 2875 dc_lock_cache(); 2876 2877 while (--scan->entry != FAT_DIRSCAN_RW_VAL) /* at beginning? */ 2878 { 2879 ent = cache_direntry(fat_bpb, dirstr, scan->entry); 2880 2881 /* name[0] == 0 shouldn't happen here but... */ 2882 if (!ent || ent->name[0] == 0 || ent->name[0] == 0xe5 || 2883 !IS_LDIR_ATTR(ent->ldir_attr)) 2884 break; 2885 } 2886 2887 dc_unlock_cache(); 2888 2889 /* retry it once from the new position */ 2890 scan->entries = 0; 2891 continue; 2892 } 2893 } 2894 else if (!IS_VOL_ID_ATTR(ent->attr)) /* ignore volume id entry */ 2895 { 2896 rc = 1; 2897 2898 if (!fatlong_parse_finish(&lnparse, ent, entry)) 2899 { 2900 /* the long entries failed to pass all checks or there is 2901 just a short entry. */ 2902 DEBUGF("SN-DOS:'%s'", entry->shortname); 2903 strcpy(entry->name, entry->shortname); 2904 scan->entries = 1; 2905 rc = 2; /* name is OEM */ 2906 } 2907 2908 DEBUGF("LN:\"%s\"", entry->name); 2909 break; 2910 } 2911 } /* end while */ 2912 2913fat_error: 2914 if (rc <= 0) 2915 { 2916 /* error or eod; stay on last good position */ 2917 fat_empty_fat_direntry(entry); 2918 scan->entry--; 2919 scan->entries = 0; 2920 } 2921 2922 return rc; 2923} 2924 2925void fat_rewinddir(struct fat_dirscan_info *scan) 2926{ 2927 /* rewind the directory scan counter to the beginning */ 2928 scan->entry = FAT_DIRSCAN_RW_VAL; 2929 scan->entries = 0; 2930} 2931 2932/** Mounting and unmounting functions **/ 2933 2934bool fat_ismounted(IF_MV_NONVOID(int volume)) 2935{ 2936 return !!FAT_BPB(volume); 2937} 2938 2939int fat_mount(IF_MV(int volume,) IF_MD(int drive,) unsigned long startsector) 2940{ 2941 int rc; 2942 2943 struct bpb * const fat_bpb = &fat_bpbs[IF_MV_VOL(volume)]; 2944 if (fat_bpb->mounted) 2945 FAT_ERROR(-1); /* double mount */ 2946 2947 /* fill-in basic info first */ 2948 fat_bpb->startsector = startsector; 2949#ifdef HAVE_MULTIVOLUME 2950 fat_bpb->volume = volume; 2951#endif 2952#ifdef HAVE_MULTIDRIVE 2953 fat_bpb->drive = drive; 2954#endif 2955#if defined(MAX_VIRT_SECTOR_SIZE) || defined(MAX_VARIABLE_LOG_SECTOR) 2956 fat_bpb->sector_size = disk_get_log_sector_size(IF_MD(drive)); 2957#endif 2958 2959 rc = fat_mount_internal(fat_bpb); 2960 if (rc < 0) 2961 FAT_ERROR(rc * 10 - 2); 2962 2963 /* it worked */ 2964 fat_bpb->mounted = true; 2965 2966 /* calculate freecount if unset */ 2967 if (fat_bpb->fsinfo.freecount == 0xffffffff) 2968 fat_recalc_free(IF_MV(fat_bpb->volume)); 2969 2970 DEBUGF("Freecount: %ld\n", (unsigned long)fat_bpb->fsinfo.freecount); 2971 DEBUGF("Nextfree: 0x%lx\n", (unsigned long)fat_bpb->fsinfo.nextfree); 2972 DEBUGF("Cluster count: 0x%lx\n", fat_bpb->dataclusters); 2973 DEBUGF("Sectors per cluster: %lu\n", fat_bpb->bpb_secperclus); 2974 DEBUGF("FAT sectors: 0x%lx\n", fat_bpb->fatsize); 2975 2976 rc = 0; 2977fat_error: 2978 return rc; 2979} 2980 2981int fat_unmount(IF_MV_NONVOID(int volume)) 2982{ 2983 struct bpb * const fat_bpb = FAT_BPB(volume); 2984 if (!fat_bpb) 2985 return -1; /* not mounted */ 2986 2987 /* free the entries for this volume */ 2988 cache_discard(IF_MV(fat_bpb)); 2989 fat_bpb->mounted = false; 2990 2991 return 0; 2992} 2993 2994 2995/** Debug screen stuff **/ 2996 2997#if defined(MAX_VIRT_SECTOR_SIZE) || defined(MAX_VARIABLE_LOG_SECTOR) 2998/* This isn't necessarily the same as storage's logical sector size; 2999 we can have situations where the filesystem (and partition table) 3000 uses a larger "virtual sector" than the underlying storage device */ 3001int fat_get_bytes_per_sector(IF_MV_NONVOID(int volume)) 3002{ 3003 int bytes = 0; 3004 3005 struct bpb * const fat_bpb = FAT_BPB(volume); 3006 if (fat_bpb) 3007 bytes = fat_bpb->bpb_bytspersec; 3008 3009 return bytes; 3010} 3011#endif /* MAX_VIRT_SECTOR_SIZE || MAX_VARIAGLE_LOG_SECTOR */ 3012 3013unsigned int fat_get_cluster_size(IF_MV_NONVOID(int volume)) 3014{ 3015 unsigned int size = 0; 3016 3017 struct bpb * const fat_bpb = FAT_BPB(volume); 3018 if (fat_bpb) 3019 size = fat_bpb->bpb_secperclus * LOG_SECTOR_SIZE(fat_bpb); 3020 3021 return size; 3022} 3023 3024void fat_recalc_free(IF_MV_NONVOID(int volume)) 3025{ 3026 struct bpb * const fat_bpb = FAT_BPB(volume); 3027 if (!fat_bpb) 3028 return; 3029 3030 dc_lock_cache(); 3031 fat_recalc_free_internal(fat_bpb); 3032 dc_unlock_cache(); 3033} 3034 3035bool fat_size(IF_MV(int volume,) sector_t *size, sector_t *free) 3036{ 3037 struct bpb * const fat_bpb = FAT_BPB(volume); 3038 if (!fat_bpb) 3039 return false; 3040 3041 unsigned long factor = fat_bpb->bpb_secperclus * LOG_SECTOR_SIZE(fat_bpb) / 1024; 3042 3043 if (size) *size = fat_bpb->dataclusters * factor; 3044 if (free) *free = fat_bpb->fsinfo.freecount * factor; 3045 3046 return true; 3047} 3048 3049 3050/** Misc. **/ 3051 3052void fat_empty_fat_direntry(struct fat_direntry *entry) 3053{ 3054 entry->name[0] = 0; 3055 entry->shortname[0] = 0; 3056 entry->attr = 0; 3057 entry->crttimetenth = 0; 3058 entry->crttime = 0; 3059 entry->crtdate = 0; 3060 entry->lstaccdate = 0; 3061 entry->wrttime = 0; 3062 entry->wrtdate = 0; 3063 entry->filesize = 0; 3064 entry->firstcluster = 0; 3065} 3066 3067void fat_init(void) 3068{ 3069 dc_lock_cache(); 3070 3071 /* mark the possible volumes as not mounted */ 3072 for (unsigned int i = 0; i < NUM_VOLUMES; i++) 3073 { 3074 dc_discard_all(IF_MV(i)); 3075 fat_bpbs[i].mounted = false; 3076 } 3077 3078 dc_unlock_cache(); 3079}