Imported Upstream version 4.0.18
[platform/upstream/mtools.git] / fat.c
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
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
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
56 static __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
63 static __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
71 static 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
91 static __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
100 static __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
139 static 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
155 static 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
230 static 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
255 static 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
284 static 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  */
306 static 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
332 static 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
340 static 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
347 static 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
357 static 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
374 static 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
382 static 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
389 static 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
399 static 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
414 void fat_write(Fs_t *This)
415 {
416         unsigned int i, j, dups, bit, slot;
417         int ret;
418
419         /*fprintf(stderr, "Fat write\n");*/
420
421         if (!This->fat_dirty)
422                 return;
423
424         dups = This->num_fat;
425         if (This->fat_error)
426                 dups = 1;
427
428
429         for(i=0; i<dups; i++){
430                 j = 0;
431                 for(slot=0;j<This->fat_len;slot++) {
432                         if(!This->FatMap[slot].dirty) {
433                                 j += SECT_PER_ENTRY;
434                                 continue;
435                         }
436                         for(bit=0; 
437                             bit < SECT_PER_ENTRY && j<This->fat_len;
438                             bit++,j++) {
439                                 if(!(This->FatMap[slot].dirty & (ONE << bit)))
440                                         continue;
441                                 ret = fatWriteSector(This,j,slot, bit, i);
442                                 if (ret < (int) This->sector_size){
443                                         if (ret < 0 ){
444                                                 perror("error in fat_write");
445                                                 exit(1);
446                                         } else {
447                                                 fprintf(stderr,
448                                                         "end of file in fat_write\n");
449                                                 exit(1);
450                                         }
451                                 }
452                                 /* if last dupe, zero it out */
453                                 if(i==dups-1)
454                                         This->FatMap[slot].dirty &= ~(ONE<<bit);
455                         }
456                 }
457         }
458         /* write the info sector, if any */
459         if(This->infoSectorLoc && This->infoSectorLoc != MAX32) {
460                 /* initialize info sector */
461                 InfoSector_t *infoSector;
462                 infoSector = (InfoSector_t *) safe_malloc(This->sector_size);
463                 set_dword(infoSector->signature1, INFOSECT_SIGNATURE1);
464                 memset(infoSector->filler1, 0, sizeof(infoSector->filler1));
465                 memset(infoSector->filler2, 0, sizeof(infoSector->filler2));
466                 set_dword(infoSector->signature2, INFOSECT_SIGNATURE2);
467                 set_dword(infoSector->pos, This->last);
468                 set_dword(infoSector->count, This->freeSpace);
469                 set_word(infoSector->signature3, 0xaa55);
470                 if(forceWriteSector(This, (char *)infoSector, This->infoSectorLoc, 1) !=
471                    (signed int) This->sector_size)
472                         fprintf(stderr,"Trouble writing the info sector\n");
473                 free(infoSector);
474         }
475         This->fat_dirty = 0;
476         This->lastFatAccessMode = FAT_ACCESS_READ;
477 }
478
479
480
481 /*
482  * Zero-Fat
483  * Used by mformat.
484  */
485 int zero_fat(Fs_t *Stream, int media_descriptor)
486 {
487         unsigned int i, j;
488         unsigned int fat_start;
489         unsigned char *buf;
490
491         buf = malloc(Stream->sector_size);
492         if(!buf) {
493                 perror("alloc fat sector buffer");
494                 return -1;
495         }
496         for(i=0; i< Stream->num_fat; i++) {
497                 fat_start = Stream->fat_start + i*Stream->fat_len;
498                 for(j = 0; j < Stream->fat_len; j++) {
499                         if(j <= 1)
500                                 memset(buf, 0, Stream->sector_size);
501                         if(!j) {
502                                 buf[0] = media_descriptor;
503                                 buf[2] = buf[1] = 0xff;
504                                 if(Stream->fat_bits > 12)
505                                         buf[3] = 0xff;
506                                 if(Stream->fat_bits > 16) {
507                                         buf[4] = 0xff;
508                                         buf[5] = 0xff;
509                                         buf[6] = 0xff;
510                                         buf[7] = 0x0f;
511                                 }
512                         }
513
514                         if(forceWriteSector(Stream, (char *)buf,
515                                             fat_start + j, 1) !=
516                            (signed int) Stream->sector_size) {
517                                 fprintf(stderr,
518                                         "Trouble initializing a FAT sector\n");
519                                 free(buf);
520                                 return -1;
521                         }
522                 }
523         }
524         
525         free(buf);
526         Stream->FatMap = GetFatMap(Stream);
527         if (Stream->FatMap == NULL) {
528                 perror("alloc fat map");
529                 return -1;
530         }
531         return 0;
532 }
533
534
535 void set_fat12(Fs_t *This)
536 {
537         This->fat_bits = 12;
538         This->end_fat = 0xfff;
539         This->last_fat = 0xff6;
540         This->fat_decode = fat12_decode;
541         This->fat_encode = fat12_encode;
542 }
543
544 static char word_endian_test[] = { 0x34, 0x12 };
545
546 void set_fat16(Fs_t *This)
547 {
548         This->fat_bits = 16;
549         This->end_fat = 0xffff;
550         This->last_fat = 0xfff6;
551
552         if(sizeof(unsigned short) == 2 &&  
553            * (unsigned short *) word_endian_test == 0x1234) {
554                 This->fat_decode = fast_fat16_decode;
555                 This->fat_encode = fast_fat16_encode;
556         } else {
557                 This->fat_decode = fat16_decode;
558                 This->fat_encode = fat16_encode;
559         }
560 }
561
562 static char dword_endian_test[] = { 0x78, 0x56, 0x34, 0x12 };
563
564 void set_fat32(Fs_t *This)
565 {
566         This->fat_bits = 32;
567         This->end_fat = 0xfffffff;
568         This->last_fat = 0xffffff6;
569         
570         if(sizeof(unsigned int) == 4 &&  
571            * (unsigned int *) dword_endian_test == 0x12345678) {
572                 This->fat_decode = fast_fat32_decode;
573                 This->fat_encode = fast_fat32_encode;
574         } else {
575                 This->fat_decode = fat32_decode;
576                 This->fat_encode = fat32_encode;
577         }
578 }
579
580
581 static int check_fat(Fs_t *This)
582 {
583         /* 
584          * This is only a sanity check.  For disks with really big FATs,
585          * there is no point in checking the whole FAT.
586          */
587
588         unsigned int i, f;
589         unsigned int tocheck;
590         if(mtools_skip_check)
591                 return 0;
592
593         /* too few sectors in the FAT */
594         if(This->fat_len < NEEDED_FAT_SIZE(This))
595                 return -1;
596         /* we do not warn about too much sectors in FAT, which may
597          * happen when a partition has been shrunk using FIPS, or on
598          * other occurrences */
599         
600         tocheck = This->num_clus;
601         if (tocheck + 1 >= This->last_fat) {
602                 fprintf(stderr, "Too many clusters in FAT\n");
603                 return -1;
604         }
605
606         if(tocheck > 4096)
607                 tocheck = 4096;
608
609         for ( i= 3 ; i < tocheck; i++){
610                 f = This->fat_decode(This,i);
611                 if (f == 1 || (f < This->last_fat && f > This->num_clus)){
612                         fprintf(stderr,
613                                 "Cluster # at %d too big(%#x)\n", i,f);
614                         fprintf(stderr,"Probably non MS-DOS disk\n");
615                         return -1;
616                 }
617         }
618         return 0;
619 }
620
621
622 /*
623  * Read the first sector of FAT table into memory.  Crude error detection on
624  * wrong FAT encoding scheme.
625  */
626 static int check_media_type(Fs_t *This, union bootsector *boot, 
627                             unsigned int tot_sectors)
628 {
629         unsigned char *address;
630
631         This->num_clus = (tot_sectors - This->clus_start) / This->cluster_size;
632
633         This->FatMap = GetFatMap(This);
634         if (This->FatMap == NULL) {
635                 perror("alloc fat map");
636                 return -1;
637         }
638
639         address = getAddress(This, 0, FAT_ACCESS_READ);
640         if(!address) {
641                 fprintf(stderr,
642                         "Could not read first FAT sector\n");
643                 return -1;
644         }
645
646         if(mtools_skip_check)
647                 return 0;
648
649         if(!address[0] && !address[1] && !address[2])
650                 /* Some Atari disks have zeroes where Dos has media descriptor
651                  * and 0xff.  Do not consider this as an error */
652                 return 0;
653         
654         if((address[0] != boot->boot.descr && boot->boot.descr >= 0xf0 &&
655             ((address[0] != 0xf9 && address[0] != 0xf7) 
656              || boot->boot.descr != 0xf0)) || address[0] < 0xf0) {
657                 fprintf(stderr,
658                         "Bad media types %02x/%02x, probably non-MSDOS disk\n", 
659                                 address[0],
660                                 boot->boot.descr);
661                 return -1;
662         }
663
664         if(address[1] != 0xff || address[2] != 0xff){
665                 fprintf(stderr,"Initial byte of fat is not 0xff\n");
666                 return -1;
667         }
668
669         return 0;
670 }
671
672 static int fat_32_read(Fs_t *This, union bootsector *boot, 
673                        unsigned int tot_sectors)
674 {
675         int size;
676
677         This->fat_len = DWORD(ext.fat32.bigFat);
678         This->writeAllFats = !(boot->boot.ext.fat32.extFlags[0] & 0x80);
679         This->primaryFat = boot->boot.ext.fat32.extFlags[0] & 0xf;
680         This->rootCluster = DWORD(ext.fat32.rootCluster);
681         This->clus_start = This->fat_start + This->num_fat * This->fat_len;
682
683         /* read the info sector */
684         size = This->sector_size;
685         This->infoSectorLoc = WORD(ext.fat32.infoSector);
686         if(This->sector_size >= 512 &&
687            This->infoSectorLoc && This->infoSectorLoc != MAX32) {
688                 InfoSector_t *infoSector;
689                 infoSector = (InfoSector_t *) safe_malloc(size);
690                 if(forceReadSector(This, (char *)infoSector,
691                                    This->infoSectorLoc, 1) == 
692                    (signed int) This->sector_size &&
693                    _DWORD(infoSector->signature1) == INFOSECT_SIGNATURE1 &&
694                    _DWORD(infoSector->signature2) == INFOSECT_SIGNATURE2) {
695                         This->freeSpace = _DWORD(infoSector->count);
696                         This->last = _DWORD(infoSector->pos);
697                 }
698                 free(infoSector);
699         }
700         
701         set_fat32(This);
702         return(check_media_type(This, boot, tot_sectors) ||
703                check_fat(This));
704 }
705
706
707 static int old_fat_read(Fs_t *This, union bootsector *boot, 
708                         size_t tot_sectors, int nodups)
709 {
710         This->writeAllFats = 1;
711         This->primaryFat = 0;
712         This->dir_start = This->fat_start + This->num_fat * This->fat_len;
713         This->clus_start = This->dir_start + This->dir_len;
714         This->infoSectorLoc = MAX32;
715
716         if(nodups)
717                 This->num_fat = 1;
718
719         if(check_media_type(This,boot, tot_sectors))
720                 return -1;
721
722         if(This->num_clus >= FAT12) {
723                 set_fat16(This);
724                 /* third FAT byte must be 0xff */
725                 if(!mtools_skip_check && readByte(This, 3) != 0xff)
726                         return -1;
727         } else
728                 set_fat12(This);
729
730         return check_fat(This);
731 }
732
733 /*
734  * Read the first sector of the  FAT table into memory and initialize 
735  * structures.
736  */
737 int fat_read(Fs_t *This, union bootsector *boot,
738            size_t tot_sectors, int nodups)
739 {
740         This->fat_error = 0;
741         This->fat_dirty = 0;
742         This->last = MAX32;
743         This->freeSpace = MAX32;
744         This->lastFatSectorNr = 0;
745         This->lastFatSectorData = 0;
746
747         if(This->fat_len)
748                 return old_fat_read(This, boot, tot_sectors, nodups);
749         else
750                 return fat_32_read(This, boot, tot_sectors);
751 }
752
753
754 unsigned int fatDecode(Fs_t *This, unsigned int pos)
755 {
756         unsigned int ret;
757
758         ret = This->fat_decode(This, pos);
759         if(ret && (ret < 2 || ret > This->num_clus+1) && ret < This->last_fat) {
760                 fprintf(stderr, "Bad FAT entry %d at %d\n", ret, pos);
761                 This->fat_error++;
762         }
763         return ret;
764 }
765
766 /* append a new cluster */
767 void fatAppend(Fs_t *This, unsigned int pos, unsigned int newpos)
768 {
769         This->fat_encode(This, pos, newpos);
770         This->fat_encode(This, newpos, This->end_fat);
771         if(This->freeSpace != MAX32)
772                 This->freeSpace--;
773 }
774
775 /* de-allocates the given cluster */
776 void fatDeallocate(Fs_t *This, unsigned int pos)
777 {
778         This->fat_encode(This, pos, 0);
779         if(This->freeSpace != MAX32)
780                 This->freeSpace++;
781 }
782
783 /* allocate a new cluster */
784 void fatAllocate(Fs_t *This, unsigned int pos, unsigned int value)
785 {
786         This->fat_encode(This, pos, value);
787         if(This->freeSpace != MAX32)
788                 This->freeSpace--;
789 }
790
791 void fatEncode(Fs_t *This, unsigned int pos, unsigned int value)
792 {
793         unsigned int oldvalue = This->fat_decode(This, pos);
794         This->fat_encode(This, pos, value);
795         if(This->freeSpace != MAX32) {
796                 if(oldvalue)
797                         This->freeSpace++;
798                 if(value)
799                         This->freeSpace--;
800         }
801 }
802
803 unsigned int get_next_free_cluster(Fs_t *This, unsigned int last)
804 {
805         unsigned int i;
806
807         if(This->last != MAX32)
808                 last = This->last;
809
810         if (last < 2 ||
811             last >= This->num_clus+1)
812                 last = 1;
813
814         for (i=last+1; i< This->num_clus+2; i++) {
815                 unsigned int r = fatDecode(This, i);
816                 if(r == 1)
817                         goto exit_0;
818                 if (!r) {
819                         This->last = i;
820                         return i;
821                 }
822         }
823
824         for(i=2; i < last+1; i++) {
825                 unsigned int r = fatDecode(This, i);
826                 if(r == 1)
827                         goto exit_0;
828                 if (!r) {
829                         This->last = i;
830                         return i;
831                 }
832         }
833
834
835         fprintf(stderr,"No free cluster %d %d\n", This->preallocatedClusters,
836                 This->last);
837         return 1;
838  exit_0:
839         fprintf(stderr, "FAT error\n");
840         return 1;
841 }
842
843 int fat_error(Stream_t *Dir)
844 {
845         Stream_t *Stream = GetFs(Dir);
846         DeclareThis(Fs_t);
847
848         if(This->fat_error)
849                 fprintf(stderr,"Fat error detected\n");
850
851         return This->fat_error;
852 }
853
854 int fat32RootCluster(Stream_t *Dir)
855 {
856         Stream_t *Stream = GetFs(Dir);
857         DeclareThis(Fs_t);
858         
859         if(This->fat_bits == 32)
860                 return This->rootCluster;
861         else
862                 return 0;
863 }
864
865
866 /*
867  * Get the amount of free space on the diskette
868  */
869
870 mt_size_t getfree(Stream_t *Dir)
871 {
872         Stream_t *Stream = GetFs(Dir);
873         DeclareThis(Fs_t);
874
875         if(This->freeSpace == MAX32 || This->freeSpace == 0) {
876                 register unsigned int i;
877                 size_t total;
878
879                 total = 0L;
880                 for (i = 2; i < This->num_clus + 2; i++) {
881                         unsigned int r = fatDecode(This,i);
882                         if(r == 1) {
883                                 return -1;
884                         }
885                         if (!r)
886                                 total++;
887                 }
888                 This->freeSpace = total;
889         }
890         return sectorsToBytes((Stream_t*)This, 
891                                                   This->freeSpace * This->cluster_size);
892 }
893
894
895 /*
896  * Ensure that there is a minimum of total sectors free
897  */
898 int getfreeMinClusters(Stream_t *Dir, size_t size)
899 {
900         Stream_t *Stream = GetFs(Dir);
901         DeclareThis(Fs_t);
902         register unsigned int i, last;
903         size_t total;
904
905         if(batchmode && This->freeSpace == MAX32)
906                 getfree(Stream);
907
908         if(This->freeSpace != MAX32) {
909                 if(This->freeSpace >= size)
910                         return 1;
911                 else {
912                         fprintf(stderr, "Disk full\n");
913                         got_signal = 1;
914                         return 0;
915                 }
916         }
917
918         total = 0L;
919
920         /* we start at the same place where we'll start later to actually
921          * allocate the sectors.  That way, the same sectors of the FAT, which
922          * are already loaded during getfreeMin will be able to be reused 
923          * during get_next_free_cluster */
924         last = This->last;
925         
926         if ( last < 2 || last >= This->num_clus + 2)
927                 last = 1;
928         for (i=last+1; i< This->num_clus+2; i++){
929                 unsigned int r = fatDecode(This, i);
930                 if(r == 1) {
931                         goto exit_0;
932                 }
933                 if (!r)
934                         total++;
935                 if(total >= size)
936                         return 1;                               
937         }
938         for(i=2; i < last+1; i++){
939                 unsigned int r = fatDecode(This, i);            
940                 if(r == 1) {
941                         goto exit_0;
942                 }
943                 if (!r)
944                         total++;
945                 if(total >= size)
946                         return 1;
947         }
948         fprintf(stderr, "Disk full\n");
949         got_signal = 1;
950         return 0;
951  exit_0:
952         fprintf(stderr, "FAT error\n");
953         return 0;
954 }
955
956
957 int getfreeMinBytes(Stream_t *Dir, mt_size_t size)
958 {
959         Stream_t *Stream = GetFs(Dir);
960         DeclareThis(Fs_t);
961         size_t size2;
962
963         size2 = size  / (This->sector_size * This->cluster_size);
964         if(size % (This->sector_size * This->cluster_size))
965                 size2++;
966         return getfreeMinClusters(Dir, size2);
967 }
968
969
970 unsigned int getStart(Stream_t *Dir, struct directory *dir)
971 {
972         Stream_t *Stream = GetFs(Dir);
973         unsigned int first;
974
975         first = START(dir);
976         if(fat32RootCluster(Stream))
977                 first |= STARTHI(dir) << 16;
978         return first;
979 }
980
981 int fs_free(Stream_t *Stream)
982 {
983         DeclareThis(Fs_t);
984
985         if(This->FatMap) {
986                 int i, nr_entries;
987                 nr_entries = (This->fat_len + SECT_PER_ENTRY - 1) / 
988                         SECT_PER_ENTRY;
989                 for(i=0; i< nr_entries; i++)
990                         if(This->FatMap[i].data)
991                                 free(This->FatMap[i].data);             
992                 free(This->FatMap);
993         }
994         if(This->cp)
995                 cp_close(This->cp);
996         return 0;
997 }