1/* Copyright 1996-2006,2008,2009 Alain Knaff. 2 * This file is part of mtools. 3 * 4 * Mtools is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * Mtools is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with Mtools. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18#include "sysincludes.h" 19#include "msdos.h" 20#include "stream.h" 21#include "mtools.h" 22#include "fsP.h" 23#include "file_name.h" 24 25#ifdef HAVE_LONG_LONG 26typedef long long fatBitMask; 27#else 28typedef long fatBitMask; 29#endif 30 31typedef struct FatMap_t { 32 unsigned char *data; 33 fatBitMask dirty; 34 fatBitMask valid; 35} FatMap_t; 36 37#define SECT_PER_ENTRY (sizeof(fatBitMask)*8) 38#define ONE ((fatBitMask) 1) 39 40static __inline__ int readSector(Fs_t *This, char *buf, unsigned int off, 41 size_t size) 42{ 43 return READS(This->Next, buf, sectorsToBytes((Stream_t *)This, off), 44 size << This->sectorShift); 45} 46 47 48static __inline__ int forceReadSector(Fs_t *This, char *buf, unsigned int off, 49 size_t size) 50{ 51 return force_read(This->Next, buf, sectorsToBytes((Stream_t *)This, off), 52 size << This->sectorShift); 53} 54 55 56static __inline__ int writeSector(Fs_t *This, char *buf, unsigned int off, 57 size_t size) 58{ 59 return WRITES(This->Next, buf, sectorsToBytes((Stream_t*)This, off), 60 size << This->sectorShift); 61} 62 63static __inline__ int forceWriteSector(Fs_t *This, char *buf, unsigned int off, 64 size_t size) 65{ 66 return force_write(This->Next, buf, sectorsToBytes((Stream_t*)This, off), 67 size << This->sectorShift); 68} 69 70 71static FatMap_t *GetFatMap(Fs_t *Stream) 72{ 73 int nr_entries,i; 74 FatMap_t *map; 75 76 Stream->fat_error = 0; 77 nr_entries = (Stream->fat_len + SECT_PER_ENTRY - 1) / SECT_PER_ENTRY; 78 map = NewArray(nr_entries, FatMap_t); 79 if(!map) 80 return 0; 81 82 for(i=0; i< nr_entries; i++) { 83 map[i].data = 0; 84 map[i].valid = 0; 85 map[i].dirty = 0; 86 } 87 88 return map; 89} 90 91static __inline__ int locate(Fs_t *Stream, size_t offset, int *slot, int *bit) 92{ 93 if(offset >= Stream->fat_len) 94 return -1; 95 *slot = offset / SECT_PER_ENTRY; 96 *bit = offset % SECT_PER_ENTRY; 97 return 0; 98} 99 100static __inline__ int fatReadSector(Fs_t *This, int sector, int slot, 101 int bit, int dupe, fatBitMask bitmap) 102{ 103 int fat_start, ret; 104 int nr_sectors; 105 106 dupe = (dupe + This->primaryFat) % This->num_fat; 107 fat_start = This->fat_start + This->fat_len * dupe; 108 109 if(bitmap == 0) { 110 nr_sectors = SECT_PER_ENTRY - bit%SECT_PER_ENTRY; 111 } else { 112 nr_sectors = 1; 113 } 114 115 /* first, read as much as the buffer can give us */ 116 ret = readSector(This, 117 (char *)(This->FatMap[slot].data+(bit<<This->sectorShift)), 118 fat_start+sector, 119 nr_sectors); 120 if(ret < 0) 121 return 0; 122 123 if((unsigned int) ret < This->sector_size) { 124 /* if we got less than one sector's worth, insist to get at 125 * least one sector */ 126 ret = forceReadSector(This, 127 (char *) (This->FatMap[slot].data + 128 (bit << This->sectorShift)), 129 fat_start+sector, 1); 130 if(ret < (int) This->sector_size) 131 return 0; 132 return 1; 133 } 134 135 return ret >> This->sectorShift; 136} 137 138 139static int fatWriteSector(Fs_t *This, int sector, int slot, int bit, int dupe) 140{ 141 int fat_start; 142 143 dupe = (dupe + This->primaryFat) % This->num_fat; 144 if(dupe && !This->writeAllFats) 145 return This->sector_size; 146 147 fat_start = This->fat_start + This->fat_len * dupe; 148 149 return forceWriteSector(This, 150 (char *) 151 (This->FatMap[slot].data + bit * This->sector_size), 152 fat_start+sector, 1); 153} 154 155static unsigned char *loadSector(Fs_t *This, 156 unsigned int sector, fatAccessMode_t mode, 157 int recurs) 158{ 159 int slot, bit, ret; 160 161 if(locate(This,sector, &slot, &bit) < 0) 162 return 0; 163#if 0 164 if (((This->fat_len + SECT_PER_ENTRY - 1) / SECT_PER_ENTRY) <= slot) { 165 fprintf(stderr,"This should not happen\n"); 166 fprintf(stderr, "fat_len = %d\n", This->fat_len); 167 fprintf(stderr, "SECT_PER_ENTRY=%d\n", (int)SECT_PER_ENTRY); 168 fprintf(stderr, "sector = %d slot = %d bit=%d\n", 169 sector, slot, bit); 170 fprintf(stderr, "left = %d",(int) 171 ((This->fat_len+SECT_PER_ENTRY-1) / SECT_PER_ENTRY)); 172 return 0; 173 } 174#endif 175 if(!This->FatMap[slot].data) { 176 /* allocate the storage space */ 177 This->FatMap[slot].data = 178 malloc(This->sector_size * SECT_PER_ENTRY); 179 if(!This->FatMap[slot].data) 180 return 0; 181 memset(This->FatMap[slot].data, 0xee, 182 This->sector_size * SECT_PER_ENTRY); 183 } 184 185 if(! (This->FatMap[slot].valid & (ONE << bit))) { 186 unsigned int i; 187 ret = -1; 188 for(i=0; i< This->num_fat; i++) { 189 /* read the sector */ 190 ret = fatReadSector(This, sector, slot, bit, i, 191 This->FatMap[slot].valid); 192 193 if(ret == 0) { 194 fprintf(stderr, 195 "Error reading fat number %d\n", i); 196 continue; 197 } 198 if(This->FatMap[slot].valid) 199 /* Set recurs if there have already been 200 * sectors loaded in this bitmap long 201 */ 202 recurs = 1; 203 break; 204 } 205 206 /* all copies bad. Return error */ 207 if(ret == 0) 208 return 0; 209 210 for(i=0; (int) i < ret; i++) 211 This->FatMap[slot].valid |= ONE << (bit + i); 212 213 if(!recurs && ret == 1) 214 /* do some prefetching, if we happened to only 215 * get one sector */ 216 loadSector(This, sector+1, mode, 1); 217 if(!recurs && batchmode) 218 for(i=0; i < 1024; i++) 219 loadSector(This, sector+i, mode, 1); 220 } 221 222 if(mode == FAT_ACCESS_WRITE) { 223 This->FatMap[slot].dirty |= ONE << bit; 224 This->fat_dirty = 1; 225 } 226 return This->FatMap[slot].data + (bit << This->sectorShift); 227} 228 229 230static unsigned char *getAddress(Fs_t *Stream, 231 unsigned int num, fatAccessMode_t mode) 232{ 233 unsigned char *ret; 234 int sector; 235 int offset; 236 237 sector = num >> Stream->sectorShift; 238 ret = 0; 239 if(sector == Stream->lastFatSectorNr && 240 Stream->lastFatAccessMode >= mode) 241 ret = Stream->lastFatSectorData; 242 if(!ret) { 243 ret = loadSector(Stream, sector, mode, 0); 244 if(!ret) 245 return 0; 246 Stream->lastFatSectorNr = sector; 247 Stream->lastFatSectorData = ret; 248 Stream->lastFatAccessMode = mode; 249 } 250 offset = num & Stream->sectorMask; 251 return ret+offset; 252} 253 254 255static int readByte(Fs_t *Stream, int start) 256{ 257 unsigned char *address; 258 259 address = getAddress(Stream, start, FAT_ACCESS_READ); 260 if(!address) 261 return -1; 262 return *address; 263} 264 265 266/* 267 * Fat 12 encoding: 268 * | byte n | byte n+1 | byte n+2 | 269 * |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0| 270 * | | | | | | | | | | | | | | | | | | | | | | | | | 271 * | n+0.0 | n+0.5 | n+1.0 | n+1.5 | n+2.0 | n+2.5 | 272 * \_____ \____ \______/________/_____ / 273 * ____\______\________/ _____/ ____\_/ 274 * / \ \ / / \ 275 * | n+1.5 | n+0.0 | n+0.5 | n+2.0 | n+2.5 | n+1.0 | 276 * | FAT entry k | FAT entry k+1 | 277 */ 278 279 /* 280 * Get and decode a FAT (file allocation table) entry. Returns the cluster 281 * number on success or 1 on failure. 282 */ 283 284static unsigned int fat12_decode(Fs_t *Stream, unsigned int num) 285{ 286 unsigned int start = num * 3 / 2; 287 int byte0 = readByte(Stream, start); 288 int byte1 = readByte(Stream, start+1); 289 290 if (num < 2 || byte0 < 0 || byte1 < 0 || num > Stream->num_clus+1) { 291 fprintf(stderr,"[1] Bad address %d\n", num); 292 return 1; 293 } 294 295 if (num & 1) 296 return (byte1 << 4) | ((byte0 & 0xf0)>>4); 297 else 298 return ((byte1 & 0xf) << 8) | byte0; 299} 300 301 302/* 303 * Puts a code into the FAT table. Is the opposite of fat_decode(). No 304 * sanity checking is done on the code. Returns a 1 on error. 305 */ 306static void fat12_encode(Fs_t *Stream, unsigned int num, unsigned int code) 307{ 308 int start = num * 3 / 2; 309 unsigned char *address0 = getAddress(Stream, start, FAT_ACCESS_WRITE); 310 unsigned char *address1 = getAddress(Stream, start+1, FAT_ACCESS_WRITE); 311 312 if (num & 1) { 313 /* (odd) not on byte boundary */ 314 *address0 = (*address0 & 0x0f) | ((code << 4) & 0xf0); 315 *address1 = (code >> 4) & 0xff; 316 } else { 317 /* (even) on byte boundary */ 318 *address0 = code & 0xff; 319 *address1 = (*address1 & 0xf0) | ((code >> 8) & 0x0f); 320 } 321} 322 323 324/* 325 * Fat 16 encoding: 326 * | byte n | byte n+1 | 327 * |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0| 328 * | | | | | | | | | | | | | | | | | 329 * | FAT entry k | 330 */ 331 332static unsigned int fat16_decode(Fs_t *Stream, unsigned int num) 333{ 334 unsigned char *address = getAddress(Stream, num << 1, FAT_ACCESS_READ); 335 if(!address) 336 return 1; 337 return _WORD(address); 338} 339 340static void fat16_encode(Fs_t *Stream, unsigned int num, unsigned int code) 341{ 342 unsigned char *address = getAddress(Stream, num << 1, FAT_ACCESS_WRITE); 343 set_word(address, code); 344} 345 346 347static unsigned int fast_fat16_decode(Fs_t *Stream, unsigned int num) 348{ 349 unsigned short *address = 350 (unsigned short *) getAddress(Stream, num << 1, 351 FAT_ACCESS_READ); 352 if(!address) 353 return 1; 354 return *address; 355} 356 357static void fast_fat16_encode(Fs_t *Stream, unsigned int num, unsigned int code) 358{ 359 unsigned short *address = 360 (unsigned short *) getAddress(Stream, num << 1, 361 FAT_ACCESS_WRITE); 362 *address = code; 363} 364 365 366 367 368/* 369 * Fat 32 encoding 370 */ 371#define FAT32_HIGH 0xf0000000 372#define FAT32_ADDR 0x0fffffff 373 374static unsigned int fat32_decode(Fs_t *Stream, unsigned int num) 375{ 376 unsigned char *address = getAddress(Stream, num << 2, FAT_ACCESS_READ); 377 if(!address) 378 return 1; 379 return _DWORD(address) & FAT32_ADDR; 380} 381 382static void fat32_encode(Fs_t *Stream, unsigned int num, unsigned int code) 383{ 384 unsigned char *address = getAddress(Stream, num << 2, FAT_ACCESS_WRITE); 385 set_dword(address,(code&FAT32_ADDR) | (_DWORD(address)&FAT32_HIGH)); 386} 387 388 389static unsigned int fast_fat32_decode(Fs_t *Stream, unsigned int num) 390{ 391 unsigned int *address = 392 (unsigned int *) getAddress(Stream, num << 2, 393 FAT_ACCESS_READ); 394 if(!address) 395 return 1; 396 return (*address) & FAT32_ADDR; 397} 398 399static void fast_fat32_encode(Fs_t *Stream, unsigned int num, unsigned int code) 400{ 401 unsigned int *address = 402 (unsigned int *) getAddress(Stream, num << 2, 403 FAT_ACCESS_WRITE); 404 *address = (*address & FAT32_HIGH) | (code & FAT32_ADDR); 405} 406 407 408/* 409 * Write the FAT table to the disk. Up to now the FAT manipulation has 410 * been done in memory. All errors are fatal. (Might not be too smart 411 * to wait till the end of the program to write the table. Oh well...) 412 */ 413 414void fat_write(Fs_t *This) 415{ 416 unsigned int i, j, dups, bit, slot; 417 int ret; 418 int fat_start; 419 420 /*fprintf(stderr, "Fat write\n");*/ 421 422 if (!This->fat_dirty) 423 return; 424 425 dups = This->num_fat; 426 if (This->fat_error) 427 dups = 1; 428 429 430 for(i=0; i<dups; i++){ 431 j = 0; 432 fat_start = This->fat_start + i*This->fat_len; 433 for(slot=0;j<This->fat_len;slot++) { 434 if(!This->FatMap[slot].dirty) { 435 j += SECT_PER_ENTRY; 436 continue; 437 } 438 for(bit=0; 439 bit < SECT_PER_ENTRY && j<This->fat_len; 440 bit++,j++) { 441 if(!(This->FatMap[slot].dirty & (ONE << bit))) 442 continue; 443 ret = fatWriteSector(This,j,slot, bit, i); 444 if (ret < (int) This->sector_size){ 445 if (ret < 0 ){ 446 perror("error in fat_write"); 447 exit(1); 448 } else { 449 fprintf(stderr, 450 "end of file in fat_write\n"); 451 exit(1); 452 } 453 } 454 /* if last dupe, zero it out */ 455 if(i==dups-1) 456 This->FatMap[slot].dirty &= ~(ONE<<bit); 457 } 458 } 459 } 460 /* write the info sector, if any */ 461 if(This->infoSectorLoc && This->infoSectorLoc != MAX32) { 462 /* initialize info sector */ 463 InfoSector_t *infoSector; 464 infoSector = (InfoSector_t *) safe_malloc(This->sector_size); 465 set_dword(infoSector->signature1, INFOSECT_SIGNATURE1); 466 memset(infoSector->filler1, 0, sizeof(infoSector->filler1)); 467 memset(infoSector->filler2, 0, sizeof(infoSector->filler2)); 468 set_dword(infoSector->signature2, INFOSECT_SIGNATURE2); 469 set_dword(infoSector->pos, This->last); 470 set_dword(infoSector->count, This->freeSpace); 471 set_dword(infoSector->signature3, 0xaa55); 472 if(forceWriteSector(This, (char *)infoSector, This->infoSectorLoc, 1) != 473 (signed int) This->sector_size) 474 fprintf(stderr,"Trouble writing the info sector\n"); 475 free(infoSector); 476 } 477 This->fat_dirty = 0; 478 This->lastFatAccessMode = FAT_ACCESS_READ; 479} 480 481 482 483/* 484 * Zero-Fat 485 * Used by mformat. 486 */ 487int zero_fat(Fs_t *Stream, int media_descriptor) 488{ 489 unsigned int i, j; 490 unsigned int fat_start; 491 unsigned char *buf; 492 493 buf = malloc(Stream->sector_size); 494 if(!buf) { 495 perror("alloc fat sector buffer"); 496 return -1; 497 } 498 for(i=0; i< Stream->num_fat; i++) { 499 fat_start = Stream->fat_start + i*Stream->fat_len; 500 for(j = 0; j < Stream->fat_len; j++) { 501 if(j <= 1) 502 memset(buf, 0, Stream->sector_size); 503 if(!j) { 504 buf[0] = media_descriptor; 505 buf[2] = buf[1] = 0xff; 506 if(Stream->fat_bits > 12) 507 buf[3] = 0xff; 508 if(Stream->fat_bits > 16) { 509 buf[4] = 0xff; 510 buf[5] = 0xff; 511 buf[6] = 0xff; 512 buf[7] = 0x0f; 513 } 514 } 515 516 if(forceWriteSector(Stream, (char *)buf, 517 fat_start + j, 1) != 518 (signed int) Stream->sector_size) { 519 fprintf(stderr, 520 "Trouble initializing a FAT sector\n"); 521 free(buf); 522 return -1; 523 } 524 } 525 } 526 527 free(buf); 528 Stream->FatMap = GetFatMap(Stream); 529 if (Stream->FatMap == NULL) { 530 perror("alloc fat map"); 531 return -1; 532 } 533 return 0; 534} 535 536 537void set_fat12(Fs_t *This) 538{ 539 This->fat_bits = 12; 540 This->end_fat = 0xfff; 541 This->last_fat = 0xff6; 542 This->fat_decode = fat12_decode; 543 This->fat_encode = fat12_encode; 544} 545 546static char word_endian_test[] = { 0x34, 0x12 }; 547 548void set_fat16(Fs_t *This) 549{ 550 This->fat_bits = 16; 551 This->end_fat = 0xffff; 552 This->last_fat = 0xfff6; 553 554 if(sizeof(unsigned short) == 2 && 555 * (unsigned short *) word_endian_test == 0x1234) { 556 This->fat_decode = fast_fat16_decode; 557 This->fat_encode = fast_fat16_encode; 558 } else { 559 This->fat_decode = fat16_decode; 560 This->fat_encode = fat16_encode; 561 } 562} 563 564static char dword_endian_test[] = { 0x78, 0x56, 0x34, 0x12 }; 565 566void set_fat32(Fs_t *This) 567{ 568 This->fat_bits = 32; 569 This->end_fat = 0xfffffff; 570 This->last_fat = 0xffffff6; 571 572 if(sizeof(unsigned int) == 4 && 573 * (unsigned int *) dword_endian_test == 0x12345678) { 574 This->fat_decode = fast_fat32_decode; 575 This->fat_encode = fast_fat32_encode; 576 } else { 577 This->fat_decode = fat32_decode; 578 This->fat_encode = fat32_encode; 579 } 580} 581 582 583static int check_fat(Fs_t *This) 584{ 585 /* 586 * This is only a sanity check. For disks with really big FATs, 587 * there is no point in checking the whole FAT. 588 */ 589 590 unsigned int i, f; 591 unsigned int tocheck; 592 if(mtools_skip_check) 593 return 0; 594 595 /* too few sectors in the FAT */ 596 if(This->fat_len < NEEDED_FAT_SIZE(This)) 597 return -1; 598 /* we do not warn about too much sectors in FAT, which may 599 * happen when a partition has been shrunk using FIPS, or on 600 * other occurrences */ 601 602 tocheck = This->num_clus; 603 if (tocheck + 1 >= This->last_fat) { 604 fprintf(stderr, "Too many clusters in FAT\n"); 605 return -1; 606 } 607 608 if(tocheck > 4096) 609 tocheck = 4096; 610 611 for ( i= 3 ; i < tocheck; i++){ 612 f = This->fat_decode(This,i); 613 if (f == 1 || (f < This->last_fat && f > This->num_clus)){ 614 fprintf(stderr, 615 "Cluster # at %d too big(%#x)\n", i,f); 616 fprintf(stderr,"Probably non MS-DOS disk\n"); 617 return -1; 618 } 619 } 620 return 0; 621} 622 623 624/* 625 * Read the first sector of FAT table into memory. Crude error detection on 626 * wrong FAT encoding scheme. 627 */ 628static int check_media_type(Fs_t *This, struct bootsector *boot, 629 unsigned int tot_sectors) 630{ 631 unsigned char *address; 632 633 This->num_clus = (tot_sectors - This->clus_start) / This->cluster_size; 634 635 This->FatMap = GetFatMap(This); 636 if (This->FatMap == NULL) { 637 perror("alloc fat map"); 638 return -1; 639 } 640 641 address = getAddress(This, 0, FAT_ACCESS_READ); 642 if(!address) { 643 fprintf(stderr, 644 "Could not read first FAT sector\n"); 645 return -1; 646 } 647 648 if(mtools_skip_check) 649 return 0; 650 651 if(!address[0] && !address[1] && !address[2]) 652 /* Some Atari disks have zeroes where Dos has media descriptor 653 * and 0xff. Do not consider this as an error */ 654 return 0; 655 656 if((address[0] != boot->descr && boot->descr >= 0xf0 && 657 ((address[0] != 0xf9 && address[0] != 0xf7) 658 || boot->descr != 0xf0)) || address[0] < 0xf0) { 659 fprintf(stderr, 660 "Bad media types %02x/%02x, probably non-MSDOS disk\n", 661 address[0], 662 boot->descr); 663 return -1; 664 } 665 666 if(address[1] != 0xff || address[2] != 0xff){ 667 fprintf(stderr,"Initial byte of fat is not 0xff\n"); 668 return -1; 669 } 670 671 return 0; 672} 673 674static int fat_32_read(Fs_t *This, struct bootsector *boot, 675 unsigned int tot_sectors) 676{ 677 int size; 678 679 This->fat_len = DWORD(ext.fat32.bigFat); 680 This->writeAllFats = !(boot->ext.fat32.extFlags[0] & 0x80); 681 This->primaryFat = boot->ext.fat32.extFlags[0] & 0xf; 682 This->rootCluster = DWORD(ext.fat32.rootCluster); 683 This->clus_start = This->fat_start + This->num_fat * This->fat_len; 684 685 /* read the info sector */ 686 size = This->sector_size; 687 This->infoSectorLoc = WORD(ext.fat32.infoSector); 688 if(This->sector_size >= 512 && 689 This->infoSectorLoc && This->infoSectorLoc != MAX32) { 690 InfoSector_t *infoSector; 691 infoSector = (InfoSector_t *) safe_malloc(size); 692 if(forceReadSector(This, (char *)infoSector, 693 This->infoSectorLoc, 1) == 694 (signed int) This->sector_size && 695 _DWORD(infoSector->signature1) == INFOSECT_SIGNATURE1 && 696 _DWORD(infoSector->signature2) == INFOSECT_SIGNATURE2) { 697 This->freeSpace = _DWORD(infoSector->count); 698 This->last = _DWORD(infoSector->pos); 699 } 700 free(infoSector); 701 } 702 703 set_fat32(This); 704 return(check_media_type(This,boot, tot_sectors) || 705 check_fat(This)); 706} 707 708 709static int old_fat_read(Fs_t *This, struct bootsector *boot, 710 int config_fat_bits, 711 size_t tot_sectors, int nodups) 712{ 713 This->writeAllFats = 1; 714 This->primaryFat = 0; 715 This->dir_start = This->fat_start + This->num_fat * This->fat_len; 716 This->clus_start = This->dir_start + This->dir_len; 717 This->infoSectorLoc = MAX32; 718 719 if(nodups) 720 This->num_fat = 1; 721 722 if(check_media_type(This,boot, tot_sectors)) 723 return -1; 724 725 if(This->num_clus >= FAT12) { 726 set_fat16(This); 727 /* third FAT byte must be 0xff */ 728 if(!mtools_skip_check && readByte(This, 3) != 0xff) 729 return -1; 730 } else 731 set_fat12(This); 732 733 return check_fat(This); 734} 735 736/* 737 * Read the first sector of the FAT table into memory and initialize 738 * structures. 739 */ 740int fat_read(Fs_t *This, struct bootsector *boot, int fat_bits, 741 size_t tot_sectors, int nodups) 742{ 743 This->fat_error = 0; 744 This->fat_dirty = 0; 745 This->last = MAX32; 746 This->freeSpace = MAX32; 747 This->lastFatSectorNr = 0; 748 This->lastFatSectorData = 0; 749 750 if(This->fat_len) 751 return old_fat_read(This, boot, fat_bits, tot_sectors, nodups); 752 else 753 return fat_32_read(This, boot, tot_sectors); 754} 755 756 757unsigned int fatDecode(Fs_t *This, unsigned int pos) 758{ 759 unsigned int ret; 760 761 ret = This->fat_decode(This, pos); 762 if(ret && (ret < 2 || ret > This->num_clus+1) && ret < This->last_fat) { 763 fprintf(stderr, "Bad FAT entry %d at %d\n", ret, pos); 764 This->fat_error++; 765 } 766 return ret; 767} 768 769/* append a new cluster */ 770void fatAppend(Fs_t *This, unsigned int pos, unsigned int newpos) 771{ 772 This->fat_encode(This, pos, newpos); 773 This->fat_encode(This, newpos, This->end_fat); 774 if(This->freeSpace != MAX32) 775 This->freeSpace--; 776} 777 778/* de-allocates the given cluster */ 779void fatDeallocate(Fs_t *This, unsigned int pos) 780{ 781 This->fat_encode(This, pos, 0); 782 if(This->freeSpace != MAX32) 783 This->freeSpace++; 784} 785 786/* allocate a new cluster */ 787void fatAllocate(Fs_t *This, unsigned int pos, unsigned int value) 788{ 789 This->fat_encode(This, pos, value); 790 if(This->freeSpace != MAX32) 791 This->freeSpace--; 792} 793 794void fatEncode(Fs_t *This, unsigned int pos, unsigned int value) 795{ 796 unsigned int oldvalue = This->fat_decode(This, pos); 797 This->fat_encode(This, pos, value); 798 if(This->freeSpace != MAX32) { 799 if(oldvalue) 800 This->freeSpace++; 801 if(value) 802 This->freeSpace--; 803 } 804} 805 806unsigned int get_next_free_cluster(Fs_t *This, unsigned int last) 807{ 808 unsigned int i; 809 810 if(This->last != MAX32) 811 last = This->last; 812 813 if (last < 2 || 814 last >= This->num_clus+1) 815 last = 1; 816 817 for (i=last+1; i< This->num_clus+2; i++) { 818 unsigned int r = fatDecode(This, i); 819 if(r == 1) 820 goto exit_0; 821 if (!r) { 822 This->last = i; 823 return i; 824 } 825 } 826 827 for(i=2; i < last+1; i++) { 828 unsigned int r = fatDecode(This, i); 829 if(r == 1) 830 goto exit_0; 831 if (!r) { 832 This->last = i; 833 return i; 834 } 835 } 836 837 838 fprintf(stderr,"No free cluster %d %d\n", This->preallocatedClusters, 839 This->last); 840 return 1; 841 exit_0: 842 fprintf(stderr, "FAT error\n"); 843 return 1; 844} 845 846int fat_error(Stream_t *Dir) 847{ 848 Stream_t *Stream = GetFs(Dir); 849 DeclareThis(Fs_t); 850 851 if(This->fat_error) 852 fprintf(stderr,"Fat error detected\n"); 853 854 return This->fat_error; 855} 856 857int fat32RootCluster(Stream_t *Dir) 858{ 859 Stream_t *Stream = GetFs(Dir); 860 DeclareThis(Fs_t); 861 862 if(This->fat_bits == 32) 863 return This->rootCluster; 864 else 865 return 0; 866} 867 868 869/* 870 * Get the amount of free space on the diskette 871 */ 872 873mt_size_t getfree(Stream_t *Dir) 874{ 875 Stream_t *Stream = GetFs(Dir); 876 DeclareThis(Fs_t); 877 878 if(This->freeSpace == MAX32 || This->freeSpace == 0) { 879 register unsigned int i; 880 size_t total; 881 882 total = 0L; 883 for (i = 2; i < This->num_clus + 2; i++) { 884 unsigned int r = fatDecode(This,i); 885 if(r == 1) { 886 return -1; 887 } 888 if (!r) 889 total++; 890 } 891 This->freeSpace = total; 892 } 893 return sectorsToBytes((Stream_t*)This, 894 This->freeSpace * This->cluster_size); 895} 896 897 898/* 899 * Ensure that there is a minimum of total sectors free 900 */ 901int getfreeMinClusters(Stream_t *Dir, size_t size) 902{ 903 Stream_t *Stream = GetFs(Dir); 904 DeclareThis(Fs_t); 905 register unsigned int i, last; 906 size_t total; 907 908 if(batchmode && This->freeSpace == MAX32) 909 getfree(Stream); 910 911 if(This->freeSpace != MAX32) { 912 if(This->freeSpace >= size) 913 return 1; 914 else { 915 fprintf(stderr, "Disk full\n"); 916 got_signal = 1; 917 return 0; 918 } 919 } 920 921 total = 0L; 922 923 /* we start at the same place where we'll start later to actually 924 * allocate the sectors. That way, the same sectors of the FAT, which 925 * are already loaded during getfreeMin will be able to be reused 926 * during get_next_free_cluster */ 927 last = This->last; 928 929 if ( last < 2 || last >= This->num_clus + 2) 930 last = 1; 931 for (i=last+1; i< This->num_clus+2; i++){ 932 unsigned int r = fatDecode(This, i); 933 if(r == 1) { 934 goto exit_0; 935 } 936 if (!r) 937 total++; 938 if(total >= size) 939 return 1; 940 } 941 for(i=2; i < last+1; i++){ 942 unsigned int r = fatDecode(This, i); 943 if(r == 1) { 944 goto exit_0; 945 } 946 if (!r) 947 total++; 948 if(total >= size) 949 return 1; 950 } 951 fprintf(stderr, "Disk full\n"); 952 got_signal = 1; 953 return 0; 954 exit_0: 955 fprintf(stderr, "FAT error\n"); 956 return 0; 957} 958 959 960int getfreeMinBytes(Stream_t *Dir, mt_size_t size) 961{ 962 Stream_t *Stream = GetFs(Dir); 963 DeclareThis(Fs_t); 964 size_t size2; 965 966 size2 = size / (This->sector_size * This->cluster_size); 967 if(size % (This->sector_size * This->cluster_size)) 968 size2++; 969 return getfreeMinClusters(Dir, size2); 970} 971 972 973unsigned int getStart(Stream_t *Dir, struct directory *dir) 974{ 975 Stream_t *Stream = GetFs(Dir); 976 unsigned int first; 977 978 first = START(dir); 979 if(fat32RootCluster(Stream)) 980 first |= STARTHI(dir) << 16; 981 return first; 982} 983 984int fs_free(Stream_t *Stream) 985{ 986 DeclareThis(Fs_t); 987 988 if(This->FatMap) { 989 int i, nr_entries; 990 nr_entries = (This->fat_len + SECT_PER_ENTRY - 1) / 991 SECT_PER_ENTRY; 992 for(i=0; i< nr_entries; i++) 993 if(This->FatMap[i].data) 994 free(This->FatMap[i].data); 995 free(This->FatMap); 996 } 997 if(This->cp) 998 cp_close(This->cp); 999 return 0; 1000} 1001