blob: e4419c3dfd26909e84e0c27d3d00dc7f9cd42698 [file] [log] [blame]
Alistair Delvabeaee832021-02-24 11:27:23 -08001/* 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 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
64static 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
85static __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
94static __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
133static 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
149static 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
224static 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
249static 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
278static 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 */
300static 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
326static 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
334static 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
341static 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
351static 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
368static 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
376static 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
383static 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
393static 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
408void 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 */
484int 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
534void 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
543static char word_endian_test[] = { 0x34, 0x12 };
544
545void 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
561static char dword_endian_test[] = { 0x78, 0x56, 0x34, 0x12 };
562
563void 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
580static 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 */
625static 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
671static 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
706static 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 */
736int 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
753unsigned 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 */
766void 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 */
775void 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 */
783void 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
790void 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
802unsigned 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
842int 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
853int 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
869mt_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 */
897int 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
956int 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
969unsigned 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
980int 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}