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