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