fat.c

Go to the documentation of this file.
00001 #include "sysincludes.h"
00002 #include "msdos.h"
00003 #include "stream.h"
00004 #include "mtools.h"
00005 #include "fsP.h"
00006 
00007 extern Stream_t *default_drive;
00008 
00009 #ifdef HAVE_LONG_LONG
00010 typedef long long fatBitMask;
00011 #else
00012 typedef long fatBitMask;
00013 #endif
00014 
00015 typedef struct FatMap_t {
00016         unsigned char *data;
00017         fatBitMask dirty;
00018         fatBitMask valid;
00019 } FatMap_t;
00020 
00021 #define SECT_PER_ENTRY (sizeof(fatBitMask)*8)
00022 #define ONE ((fatBitMask) 1)
00023 
00024 static inline int readSector(Fs_t *This, char *buf, unsigned int off,
00025                                           size_t size)
00026 {
00027         return READS(This->Next, buf, sectorsToBytes((Stream_t *)This, off), 
00028                                  size << This->sectorShift);
00029 }
00030 
00031 
00032 static inline int forceReadSector(Fs_t *This, char *buf, unsigned int off,
00033                                                                   size_t size)
00034 {
00035         return force_read(This->Next, buf, sectorsToBytes((Stream_t *)This, off), 
00036                                           size << This->sectorShift);
00037 }
00038 
00039 
00040 static inline int writeSector(Fs_t *This, char *buf, unsigned int off,
00041                                                           size_t size)
00042 {
00043         return WRITES(This->Next, buf, sectorsToBytes((Stream_t*)This, off), 
00044                                   size << This->sectorShift);
00045 }
00046 
00047 static inline int forceWriteSector(Fs_t *This, char *buf, unsigned int off,
00048                                           size_t size)
00049 {
00050         return force_write(This->Next, buf, sectorsToBytes((Stream_t*)This, off), 
00051                                            size << This->sectorShift);
00052 }
00053 
00054 
00055 static FatMap_t *GetFatMap(Fs_t *Stream)
00056 {
00057         int nr_entries,i;
00058         FatMap_t *map;
00059 
00060         Stream->fat_error = 0;
00061         nr_entries = (Stream->fat_len + SECT_PER_ENTRY - 1) / SECT_PER_ENTRY;
00062         map = NewArray(nr_entries, FatMap_t);
00063         if(!map)
00064                 return 0;
00065 
00066         for(i=0; i< nr_entries; i++) {
00067                 map[i].data = 0;
00068                 map[i].valid = 0;
00069                 map[i].dirty = 0;
00070         }
00071 
00072         return map;
00073 }
00074 
00075 static inline int locate(Fs_t *Stream, int offset, int *slot, int *bit)
00076 {
00077         if(offset >= Stream->fat_len)
00078                 return -1;
00079         *slot = offset / SECT_PER_ENTRY;
00080         *bit = offset % SECT_PER_ENTRY;
00081         return 0;
00082 }
00083 
00084 static inline int fatReadSector(Fs_t *This, int sector, int slot, 
00085                                 int bit, int dupe)
00086 {
00087         int fat_start, ret;
00088 
00089         dupe = (dupe + This->primaryFat) % This->num_fat;
00090         fat_start = This->fat_start + This->fat_len * dupe;
00091         
00092         /* first, read as much as the buffer can give us */
00093         ret = readSector(This,
00094                                          (char *)(This->FatMap[slot].data+(bit<<This->sectorShift)),
00095                                          fat_start+sector,
00096                                          (SECT_PER_ENTRY - bit%SECT_PER_ENTRY));
00097         if(ret < 0)
00098                 return 0;
00099 
00100         if(ret < This->sector_size) {
00101                 /* if we got less than one sector's worth, insist to get at
00102                  * least one sector */
00103                 ret = forceReadSector(This,
00104                                                           (char *) (This->FatMap[slot].data + 
00105                                                                                 (bit << This->sectorShift)),
00106                                                           fat_start+sector, 1);
00107                 if(ret < This->sector_size)
00108                         return 0;
00109                 return 1;
00110         }
00111 
00112         return ret >> This->sectorShift;
00113 }
00114 
00115 
00116 static int fatWriteSector(Fs_t *This, int sector, int slot, int bit, int dupe)
00117 {
00118         int fat_start;
00119 
00120         dupe = (dupe + This->primaryFat) % This->num_fat;
00121         if(dupe && !This->writeAllFats)
00122                 return This->sector_size;
00123 
00124         fat_start = This->fat_start + This->fat_len * dupe;
00125 
00126         return forceWriteSector(This,
00127                                                         (char *) 
00128                                                         (This->FatMap[slot].data + bit * This->sector_size),
00129                                                         fat_start+sector, 1);
00130 }
00131 
00132 static unsigned char *loadSector(Fs_t *This,
00133                                  unsigned int sector, fatAccessMode_t mode,
00134                                  int recurs)
00135 {
00136         int slot, bit, i, ret;
00137 
00138         if(locate(This,sector, &slot, &bit) < 0)
00139                 return 0;
00140 #if 0
00141         if (((This->fat_len + SECT_PER_ENTRY - 1) / SECT_PER_ENTRY) <= slot) {
00142                 fprintf(stderr,"This should not happen\n");
00143                 fprintf(stderr, "fat_len = %d\n", This->fat_len);
00144                 fprintf(stderr, "SECT_PER_ENTRY=%d\n", (int)SECT_PER_ENTRY);
00145                 fprintf(stderr, "sector = %d slot = %d bit=%d\n", 
00146                         sector, slot, bit);
00147                 fprintf(stderr, "left = %d",(int)
00148                         ((This->fat_len+SECT_PER_ENTRY-1) / SECT_PER_ENTRY));
00149                 return 0;
00150         }
00151 #endif
00152         if(!This->FatMap[slot].data) {
00153                 /* allocate the storage space */
00154                 This->FatMap[slot].data = 
00155                         malloc(This->sector_size * SECT_PER_ENTRY);
00156                 if(!This->FatMap[slot].data)
00157                         return 0;
00158                 memset(This->FatMap[slot].data, 0xee,
00159                        This->sector_size * SECT_PER_ENTRY);
00160         }
00161 
00162         if(! (This->FatMap[slot].valid & (ONE << bit))) {
00163                 ret = -1;
00164                 for(i=0; i< This->num_fat; i++) {
00165                         /* read the sector */
00166                         ret = fatReadSector(This, sector, slot, bit, i);
00167 
00168                         if(ret == 0) {
00169                                 fprintf(stderr,
00170                                         "Error reading fat number %d\n", i);
00171                                 continue;
00172                         }
00173                         break;
00174                 }
00175 
00176                 /* all copies bad.  Return error */
00177                 if(ret == 0)
00178                         return 0;
00179 
00180                 for(i=0; i < ret; i++)
00181                         This->FatMap[slot].valid |= ONE << (bit + i);
00182 
00183                 if(!recurs && ret == 1)
00184                         /* do some prefetching, if we happened to only
00185                          * get one sector */
00186                         loadSector(This, sector+1, mode, 1);
00187                 if(!recurs && batchmode)
00188                         for(i=0; i < 1024; i++)
00189                                 loadSector(This, sector+i, mode, 1);
00190         }
00191 
00192         if(mode == FAT_ACCESS_WRITE) {
00193                 This->FatMap[slot].dirty |= ONE << bit;
00194                 This->fat_dirty = 1;
00195         }
00196         return This->FatMap[slot].data + (bit << This->sectorShift);
00197 }
00198 
00199 
00200 static unsigned char *getAddress(Fs_t *Stream,
00201                                  unsigned int num, fatAccessMode_t mode)
00202 {
00203         unsigned char *ret;
00204         int sector;
00205         int offset;
00206 
00207         sector = num >> Stream->sectorShift;
00208         ret = 0;
00209         if(sector == Stream->lastFatSectorNr &&
00210            Stream->lastFatAccessMode >= mode)
00211                 ret = Stream->lastFatSectorData;
00212         if(!ret) {              
00213                 ret = loadSector(Stream, sector, mode, 0);
00214                 if(!ret)
00215                         return 0;
00216                 Stream->lastFatSectorNr = sector;
00217                 Stream->lastFatSectorData = ret;
00218                 Stream->lastFatAccessMode = mode;
00219         }
00220         offset = num & Stream->sectorMask;
00221         return ret+offset;
00222 }
00223 
00224 
00225 static int readByte(Fs_t *Stream, int start)
00226 {
00227         unsigned char *address;
00228         
00229         address = getAddress(Stream, start, FAT_ACCESS_READ);
00230         if(!address)
00231                 return -1;
00232         return *address;
00233 }
00234 
00235 
00236 /*
00237  * Fat 12 encoding:
00238  *      |    byte n     |   byte n+1    |   byte n+2    |
00239  *      |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
00240  *      | | | | | | | | | | | | | | | | | | | | | | | | |
00241  *      | n+0.0 | n+0.5 | n+1.0 | n+1.5 | n+2.0 | n+2.5 |
00242  *          \_____  \____   \______/________/_____   /
00243  *            ____\______\________/   _____/  ____\_/
00244  *           /     \      \          /       /     \
00245  *      | n+1.5 | n+0.0 | n+0.5 | n+2.0 | n+2.5 | n+1.0 |
00246  *      |      FAT entry k      |    FAT entry k+1      |
00247  */
00248  
00249  /*
00250  * Get and decode a FAT (file allocation table) entry.  Returns the cluster
00251  * number on success or 1 on failure.
00252  */
00253 
00254 static unsigned int fat12_decode(Fs_t *Stream, unsigned int num)
00255 {
00256         unsigned int start = num * 3 / 2;
00257         int byte0 = readByte(Stream, start);
00258         int byte1 = readByte(Stream, start+1);
00259        
00260         if (num < 2 || byte0 < 0 || byte1 < 0 || num > Stream->num_clus+1) {
00261                 fprintf(stderr,"[1] Bad address %d\n", num);
00262                 return 1;
00263         }
00264 
00265         if (num & 1)
00266                 return (byte1 << 4) | ((byte0 & 0xf0)>>4);
00267         else
00268                 return ((byte1 & 0xf) << 8) | byte0;
00269 }
00270 
00271 
00272 /*
00273  * Puts a code into the FAT table.  Is the opposite of fat_decode().  No
00274  * sanity checking is done on the code.  Returns a 1 on error.
00275  */
00276 static void fat12_encode(Fs_t *Stream, unsigned int num, unsigned int code)
00277 {
00278         int start = num * 3 / 2;
00279         unsigned char *address0 = getAddress(Stream, start, FAT_ACCESS_WRITE);
00280         unsigned char *address1 = getAddress(Stream, start+1, FAT_ACCESS_WRITE);
00281 
00282         if (num & 1) {
00283                 /* (odd) not on byte boundary */
00284                 *address0 = (*address0 & 0x0f) | ((code << 4) & 0xf0);
00285                 *address1 = (code >> 4) & 0xff;
00286         } else {
00287                 /* (even) on byte boundary */
00288                 *address0 = code & 0xff;
00289                 *address1 = (*address1 & 0xf0) | ((code >> 8) & 0x0f);
00290         }
00291 }
00292 
00293 
00294 /*
00295  * Fat 16 encoding:
00296  *      |    byte n     |   byte n+1    |
00297  *      |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
00298  *      | | | | | | | | | | | | | | | | |
00299  *      |         FAT entry k           |
00300  */
00301 
00302 static unsigned int fat16_decode(Fs_t *Stream, unsigned int num)
00303 {
00304         unsigned char *address = getAddress(Stream, num << 1, FAT_ACCESS_READ);
00305         return _WORD(address);
00306 }
00307 
00308 static void fat16_encode(Fs_t *Stream, unsigned int num, unsigned int code)
00309 {       
00310         unsigned char *address = getAddress(Stream, num << 1, FAT_ACCESS_WRITE);
00311         set_word(address, code);
00312 }
00313 
00314 
00315 static unsigned int fast_fat16_decode(Fs_t *Stream, unsigned int num)
00316 {
00317         unsigned short *address = 
00318                 (unsigned short *) getAddress(Stream, num << 1, 
00319                                               FAT_ACCESS_READ);
00320         return *address;
00321 }
00322 
00323 static void fast_fat16_encode(Fs_t *Stream, unsigned int num, unsigned int code)
00324 {       
00325         unsigned short *address = 
00326                 (unsigned short *) getAddress(Stream, num << 1, 
00327                                               FAT_ACCESS_WRITE);
00328         *address = code;
00329 }
00330 
00331 
00332 
00333 
00334 /*
00335  * Fat 32 encoding
00336  */
00337 static unsigned int fat32_decode(Fs_t *Stream, unsigned int num)
00338 {
00339         unsigned char *address = getAddress(Stream, num << 2, FAT_ACCESS_READ);
00340         return _DWORD(address);
00341 }
00342 
00343 static void fat32_encode(Fs_t *Stream, unsigned int num, unsigned int code)
00344 {       
00345         unsigned char *address = getAddress(Stream, num << 2, FAT_ACCESS_WRITE);
00346         set_dword(address, code);
00347 }
00348 
00349 
00350 static unsigned int fast_fat32_decode(Fs_t *Stream, unsigned int num)
00351 {
00352         unsigned int *address = 
00353                 (unsigned int *) getAddress(Stream, num << 2, 
00354                                             FAT_ACCESS_READ);
00355         return *address;
00356 }
00357 
00358 static void fast_fat32_encode(Fs_t *Stream, unsigned int num, unsigned int code)
00359 {       
00360         unsigned int *address = 
00361                 (unsigned int *) getAddress(Stream, num << 2, 
00362                                             FAT_ACCESS_WRITE);
00363         *address = code;
00364 }
00365 
00366 
00367 /*
00368  * Write the FAT table to the disk.  Up to now the FAT manipulation has
00369  * been done in memory.  All errors are fatal.  (Might not be too smart
00370  * to wait till the end of the program to write the table.  Oh well...)
00371  */
00372 
00373 void fat_write(Fs_t *This)
00374 {
00375         int i, j, dups, ret, bit, slot;
00376         int fat_start;
00377 
00378         /*fprintf(stderr, "Fat write\n");*/
00379 
00380         if (!This->fat_dirty)
00381                 return;
00382 
00383         dups = This->num_fat;
00384         if (This->fat_error)
00385                 dups = 1;
00386 
00387 
00388         for(i=0; i<dups; i++){
00389                 j = 0;
00390                 fat_start = This->fat_start + i*This->fat_len;
00391                 for(slot=0;j<This->fat_len;slot++) {
00392                         if(!This->FatMap[slot].dirty) {
00393                                 j += SECT_PER_ENTRY;
00394                                 continue;
00395                         }
00396                         for(bit=0; 
00397                             bit < SECT_PER_ENTRY && j<This->fat_len;
00398                             bit++,j++) {
00399                                 if(!(This->FatMap[slot].dirty & (ONE << bit)))
00400                                         continue;
00401                                 ret = fatWriteSector(This,j,slot, bit, i);
00402                                 if (ret < This->sector_size){
00403                                         if (ret < 0 ){
00404                                                 perror("error in fat_write");
00405                                                 exit(1);
00406                                         } else {
00407                                                 fprintf(stderr,
00408                                                         "end of file in fat_write\n");
00409                                                 exit(1);
00410                                         }
00411                                 }
00412                                 /* if last dupe, zero it out */
00413                                 if(i==dups-1)
00414                                         This->FatMap[slot].dirty &= ~(1<<bit);
00415                         }
00416                 }        
00417         }
00418         /* write the info sector, if any */
00419         if(This->infoSectorLoc && This->infoSectorLoc != MAX32) {
00420                 /* initialize info sector */
00421                 InfoSector_t *infoSector;
00422                 infoSector = (InfoSector_t *) safe_malloc(This->sector_size);
00423                 set_dword(infoSector->signature1, INFOSECT_SIGNATURE1);
00424                 memset(infoSector->filler1, sizeof(infoSector->filler1),0);
00425                 memset(infoSector->filler2, sizeof(infoSector->filler2),0);
00426                 set_dword(infoSector->signature2, INFOSECT_SIGNATURE2);
00427                 set_dword(infoSector->pos, This->last);
00428                 set_dword(infoSector->count, This->freeSpace);
00429                 set_dword(infoSector->signature3, 0xaa55);
00430                 if(forceWriteSector(This, (char *)infoSector, This->infoSectorLoc, 1) !=
00431                    This->sector_size)
00432                         fprintf(stderr,"Trouble writing the info sector\n");
00433                 free(infoSector);
00434         }
00435         This->fat_dirty = 0;
00436         This->lastFatAccessMode = FAT_ACCESS_READ;
00437 }
00438 
00439 
00440 
00441 /*
00442  * Zero-Fat
00443  * Used by mformat.
00444  */
00445 int zero_fat(Fs_t *Stream, int media_descriptor)
00446 {
00447         int i, j;
00448         int fat_start;
00449         unsigned char *buf;
00450 
00451         buf = malloc(Stream->sector_size);
00452         if(!buf) {
00453                 perror("alloc fat sector buffer");
00454                 return -1;
00455         }
00456         for(i=0; i< Stream->num_fat; i++) {
00457                 fat_start = Stream->fat_start + i*Stream->fat_len;
00458                 for(j = 0; j < Stream->fat_len; j++) {
00459                         if(j <= 1)
00460                                 memset(buf, 0, Stream->sector_size);
00461                         if(!j) {
00462                                 buf[0] = media_descriptor;
00463                                 buf[2] = buf[1] = 0xff;
00464                                 if(Stream->fat_bits > 12)
00465                                         buf[3] = 0xff;
00466                                 if(Stream->fat_bits > 16) {
00467                                         buf[4] = 0xff;
00468                                         buf[5] = 0xff;
00469                                         buf[6] = 0xff;
00470                                         buf[7] = 0x0f;
00471                                 }
00472                         }
00473 
00474                         if(forceWriteSector(Stream, (char *)buf,
00475                                                                 fat_start + j, 1) !=
00476                            Stream->sector_size) {
00477                                 fprintf(stderr,
00478                                                 "Trouble initializing a FAT sector\n");
00479                                 free(buf);
00480                                 return -1;
00481                         }
00482                 }
00483         }
00484         
00485         free(buf);
00486         Stream->FatMap = GetFatMap(Stream);
00487         if (Stream->FatMap == NULL) {
00488                 perror("alloc fat map");
00489                 return -1;
00490         }
00491         return 0;
00492 }
00493 
00494 
00495 void set_fat12(Fs_t *This)
00496 {
00497         This->fat_bits = 12;
00498         This->end_fat = 0xfff;
00499         This->last_fat = 0xff6;
00500         This->fat_decode = fat12_decode;
00501         This->fat_encode = fat12_encode;
00502 }
00503 
00504 static char word_endian_test[] = { 0x34, 0x12 };
00505 
00506 void set_fat16(Fs_t *This)
00507 {
00508         This->fat_bits = 16;
00509         This->end_fat = 0xffff;
00510         This->last_fat = 0xfff6;
00511 
00512         if(sizeof(unsigned short) == 2 &&  
00513            * (unsigned short *) word_endian_test == 0x1234) {
00514                 This->fat_decode = fast_fat16_decode;
00515                 This->fat_encode = fast_fat16_encode;
00516         } else {
00517                 This->fat_decode = fat16_decode;
00518                 This->fat_encode = fat16_encode;
00519         }
00520 }
00521 
00522 static char dword_endian_test[] = { 0x78, 0x56, 0x34, 0x12 };
00523 
00524 void set_fat32(Fs_t *This)
00525 {
00526         This->fat_bits = 32;
00527         This->end_fat = 0xfffffff;
00528         This->last_fat = 0xffffff6;
00529         
00530         if(sizeof(unsigned int) == 4 &&  
00531            * (unsigned int *) dword_endian_test == 0x12345678) {
00532                 This->fat_decode = fast_fat32_decode;
00533                 This->fat_encode = fast_fat32_encode;
00534         } else {
00535                 This->fat_decode = fat32_decode;
00536                 This->fat_encode = fat32_encode;
00537         }
00538 }
00539 
00540 
00541 static int check_fat(Fs_t *This)
00542 {
00543         /* 
00544          * This is only a sanity check.  For disks with really big FATs,
00545          * there is no point in checking the whole FAT.
00546          */
00547 
00548         int i, f, tocheck;
00549         if(mtools_skip_check)
00550                 return 0;
00551 
00552         /* too few sectors in the FAT */
00553         if(This->fat_len < NEEDED_FAT_SIZE(This))
00554                 return -1;
00555         /* we do not warn about too much sectors in FAT, which may
00556          * happen when a partition has been shrunk using FIPS, or on
00557          * other occurrences */
00558         
00559         tocheck = This->num_clus;
00560         if (tocheck < 0 || tocheck + 1 >= This->last_fat) {
00561                 fprintf(stderr, "Too many clusters in FAT\n");
00562                 return -1;
00563         }
00564 
00565         if(tocheck > 4096)
00566                 tocheck = 4096;
00567 
00568         for ( i= 3 ; i < tocheck; i++){
00569                 f = This->fat_decode(This,i);
00570                 if (f == 1 || (f < This->last_fat && f > This->num_clus)){
00571                         fprintf(stderr,
00572                                 "Cluster # at %d too big(%#x)\n", i,f);
00573                         fprintf(stderr,"Probably non MS-DOS disk\n");
00574                         return -1;
00575                 }
00576         }
00577         return 0;
00578 }
00579 
00580 
00581 /*
00582  * Read the first sector of FAT table into memory.  Crude error detection on
00583  * wrong FAT encoding scheme.
00584  */
00585 static int check_media_type(Fs_t *This, struct bootsector *boot, 
00586                             unsigned int tot_sectors)
00587 {
00588         unsigned char *address;
00589 
00590         This->num_clus = (tot_sectors - This->clus_start) / This->cluster_size;
00591 
00592         This->FatMap = GetFatMap(This);
00593         if (This->FatMap == NULL) {
00594                 perror("alloc fat map");
00595                 return -1;
00596         }
00597 
00598         address = getAddress(This, 0, FAT_ACCESS_READ);
00599         if(!address) {
00600                 fprintf(stderr,
00601                         "Could not read first FAT sector\n");
00602                 return -1;
00603         }
00604 
00605         if(mtools_skip_check)
00606                 return 0;
00607 
00608         if(!address[0] && !address[1] && !address[2])
00609                 /* Some Atari disks have zeroes where Dos has media descriptor
00610                  * and 0xff.  Do not consider this as an error */
00611                 return 0;
00612         
00613         if((address[0] != boot->descr && boot->descr >= 0xf0 &&
00614             ((address[0] != 0xf9 && address[0] != 0xf7) 
00615              || boot->descr != 0xf0)) || address[0] < 0xf0) {
00616                 fprintf(stderr,
00617                         "Bad media types %02x/%02x, probably non-MSDOS disk\n", 
00618                                 address[0],
00619                                 boot->descr);
00620                 return -1;
00621         }
00622 
00623         if(address[1] != 0xff || address[2] != 0xff){
00624                 fprintf(stderr,"Initial byte of fat is not 0xff\n");
00625                 return -1;
00626         }
00627 
00628         return 0;
00629 }
00630 
00631 static int fat_32_read(Fs_t *This, struct bootsector *boot, 
00632                        unsigned int tot_sectors)
00633 {
00634         int size;
00635 
00636         This->fat_len = DWORD(ext.fat32.bigFat);
00637         This->writeAllFats = !(boot->ext.fat32.extFlags[0] & 0x80);
00638         This->primaryFat = boot->ext.fat32.extFlags[0] & 0xf;
00639         This->rootCluster = DWORD(ext.fat32.rootCluster);
00640         This->clus_start = This->fat_start + This->num_fat * This->fat_len;
00641 
00642         /* read the info sector */
00643         size = This->sector_size;
00644         This->infoSectorLoc = WORD(ext.fat32.infoSector);
00645         if(This->sector_size >= 512 &&
00646            This->infoSectorLoc && This->infoSectorLoc != MAX32) {
00647                 InfoSector_t *infoSector;
00648                 infoSector = (InfoSector_t *) safe_malloc(size);
00649                 if(forceReadSector(This, (char *)infoSector,
00650                                                    This->infoSectorLoc, 1) == This->sector_size &&
00651                    _DWORD(infoSector->signature1) == INFOSECT_SIGNATURE1 &&
00652                    _DWORD(infoSector->signature2) == INFOSECT_SIGNATURE2) {
00653                         This->freeSpace = _DWORD(infoSector->count);
00654                         This->last = _DWORD(infoSector->pos);
00655                 }
00656                 free(infoSector);
00657         }
00658         
00659         set_fat32(This);
00660         return(check_media_type(This,boot, tot_sectors) ||
00661                check_fat(This));
00662 }
00663 
00664 
00665 static int old_fat_read(Fs_t *This, struct bootsector *boot, 
00666                                                 int config_fat_bits,
00667                                                 size_t tot_sectors, int nodups)
00668 {
00669         This->writeAllFats = 1;
00670         This->primaryFat = 0;
00671         This->dir_start = This->fat_start + This->num_fat * This->fat_len;
00672         This->clus_start = This->dir_start + This->dir_len;
00673         This->infoSectorLoc = MAX32;
00674 
00675         if(nodups)
00676                 This->num_fat = 1;
00677 
00678         if(check_media_type(This,boot, tot_sectors))
00679                 return -1;
00680 
00681         if(This->num_clus > FAT12) {
00682                 set_fat16(This);
00683                 /* third FAT byte must be 0xff */
00684                 if(!mtools_skip_check && readByte(This, 3) != 0xff)
00685                         return -1;
00686         } else
00687                 set_fat12(This);
00688 
00689         return check_fat(This);
00690 }
00691 
00692 /*
00693  * Read the first sector of the  FAT table into memory and initialize 
00694  * structures.
00695  */
00696 int fat_read(Fs_t *This, struct bootsector *boot, int fat_bits,
00697            size_t tot_sectors, int nodups)
00698 {
00699         This->fat_error = 0;
00700         This->fat_dirty = 0;
00701         This->last = MAX32;
00702         This->freeSpace = MAX32;
00703         This->lastFatSectorNr = 0;
00704         This->lastFatSectorData = 0;
00705 
00706         if(This->fat_len)
00707                 return old_fat_read(This, boot, fat_bits, tot_sectors, nodups);
00708         else
00709                 return fat_32_read(This, boot, tot_sectors);
00710 }
00711 
00712 
00713 unsigned int fatDecode(Fs_t *This, unsigned int pos)
00714 {
00715         int ret;
00716 
00717         ret = This->fat_decode(This, pos);
00718         if(ret && (ret < 2 || ret > This->num_clus+1) && ret < This->last_fat) {
00719                 fprintf(stderr, "Bad FAT entry %d at %d\n", ret, pos);
00720                 This->fat_error++;
00721         }
00722         return ret;
00723 }
00724 
00725 /* append a new cluster */
00726 void fatAppend(Fs_t *This, unsigned int pos, unsigned int newpos)
00727 {
00728         This->fat_encode(This, pos, newpos);
00729         This->fat_encode(This, newpos, This->end_fat);
00730         if(This->freeSpace != MAX32)
00731                 This->freeSpace--;
00732 }
00733 
00734 /* de-allocates the given cluster */
00735 void fatDeallocate(Fs_t *This, unsigned int pos)
00736 {
00737         This->fat_encode(This, pos, 0);
00738         if(This->freeSpace != MAX32)
00739                 This->freeSpace++;
00740 }
00741 
00742 /* allocate a new cluster */
00743 void fatAllocate(Fs_t *This, unsigned int pos, unsigned int value)
00744 {
00745         This->fat_encode(This, pos, value);
00746         if(This->freeSpace != MAX32)
00747                 This->freeSpace--;
00748 }
00749 
00750 void fatEncode(Fs_t *This, unsigned int pos, unsigned int value)
00751 {
00752         unsigned int oldvalue = This->fat_decode(This, pos);
00753         This->fat_encode(This, pos, value);
00754         if(This->freeSpace != MAX32) {
00755                 if(oldvalue)
00756                         This->freeSpace++;
00757                 if(value)
00758                         This->freeSpace--;
00759         }
00760 }
00761 
00762 unsigned int get_next_free_cluster(Fs_t *This, unsigned int last)
00763 {
00764         int i;
00765 
00766         if(This->last != MAX32)
00767                 last = This->last;
00768 
00769         if (last < 2 ||
00770             last >= This->num_clus+1)
00771                 last = 1;
00772 
00773         for (i=last+1; i< This->num_clus+2; i++) {
00774                 if (!fatDecode(This, i)) {
00775                         This->last = i;
00776                         return i;
00777                 }
00778         }
00779 
00780         for(i=2; i < last+1; i++) {
00781                 if (!fatDecode(This, i)) {
00782                         This->last = i;
00783                         return i;
00784                 }
00785         }
00786 
00787 
00788         fprintf(stderr,"No free cluster %d %d\n", This->preallocatedClusters,
00789                 This->last);
00790         return 1;
00791 }
00792 
00793 int fat_error(Stream_t *Dir)
00794 {
00795         Stream_t *Stream = GetFs(Dir);
00796         DeclareThis(Fs_t);
00797 
00798         if(This->fat_error)
00799                 fprintf(stderr,"Fat error detected\n");
00800 
00801         return This->fat_error;
00802 }
00803 
00804 int fat32RootCluster(Stream_t *Dir)
00805 {
00806         Stream_t *Stream = GetFs(Dir);
00807         DeclareThis(Fs_t);
00808         
00809         if(This->fat_bits == 32)
00810                 return This->rootCluster;
00811         else
00812                 return 0;
00813 }
00814 
00815 
00816 /*
00817  * Get the amount of free space on the diskette
00818  */
00819 
00820 mt_size_t getfree(Stream_t *Dir)
00821 {
00822         Stream_t *Stream = GetFs(Dir);
00823         DeclareThis(Fs_t);
00824 
00825         if(This->freeSpace == MAX32 || This->freeSpace == 0) {
00826                 register unsigned int i;
00827                 size_t total;
00828 
00829                 total = 0L;
00830                 for (i = 2; i < This->num_clus + 2; i++)
00831                         if (!fatDecode(This,i))
00832                                 total++;
00833                 This->freeSpace = total;
00834         }
00835         return sectorsToBytes((Stream_t*)This, 
00836                                                   This->freeSpace * This->cluster_size);
00837 }
00838 
00839 
00840 /*
00841  * Ensure that there is a minimum of total sectors free
00842  */
00843 int getfreeMinClusters(Stream_t *Dir, size_t size)
00844 {
00845         Stream_t *Stream = GetFs(Dir);
00846         DeclareThis(Fs_t);
00847         register unsigned int i, last;
00848         size_t total;
00849 
00850         if(batchmode && This->freeSpace == MAX32)
00851                 getfree(Stream);
00852 
00853         if(This->freeSpace != MAX32) {
00854                 if(This->freeSpace >= size)
00855                         return 1;
00856                 else {
00857                         fprintf(stderr, "Disk full\n");
00858                         got_signal = 1;
00859                         return 0;
00860                 }
00861         }
00862 
00863         total = 0L;
00864 
00865         /* we start at the same place where we'll start later to actually
00866          * allocate the sectors.  That way, the same sectors of the FAT, which
00867          * are already loaded during getfreeMin will be able to be reused 
00868          * during get_next_free_cluster */
00869         last = This->last;
00870         
00871         if ( last < 2 || last >= This->num_clus + 2)
00872                 last = 1;
00873         for (i=last+1; i< This->num_clus+2; i++){
00874                 if (!fatDecode(This, i))
00875                         total++;
00876                 if(total >= size)
00877                         return 1;                               
00878         }
00879         for(i=2; i < last+1; i++){
00880                 if (!fatDecode(This, i))
00881                         total++;
00882                 if(total >= size)
00883                         return 1;
00884         }
00885         fprintf(stderr, "Disk full\n");
00886         got_signal = 1;
00887         return 0;
00888 }
00889 
00890 
00891 int getfreeMinBytes(Stream_t *Dir, mt_size_t size)
00892 {
00893         Stream_t *Stream = GetFs(Dir);
00894         DeclareThis(Fs_t);
00895         size_t size2;
00896 
00897         size2 = size  / (This->sector_size * This->cluster_size);
00898         if(size % (This->sector_size * This->cluster_size))
00899                 size2++;
00900         return getfreeMinClusters(Dir, size2);
00901 }
00902 
00903 
00904 unsigned int getStart(Stream_t *Dir, struct directory *dir)
00905 {
00906         Stream_t *Stream = GetFs(Dir);
00907         unsigned int first;
00908 
00909         first = START(dir);
00910         if(fat32RootCluster(Stream))
00911                 first |= STARTHI(dir) << 16;
00912         return first;
00913 }
00914 
00915 int fs_free(Stream_t *Stream)
00916 {
00917         DeclareThis(Fs_t);
00918 
00919         if(This->FatMap) {
00920                 int i, nr_entries;
00921                 nr_entries = (This->fat_len + SECT_PER_ENTRY - 1) / 
00922                         SECT_PER_ENTRY;
00923                 for(i=0; i< nr_entries; i++)
00924                         if(This->FatMap[i].data)
00925                                 free(This->FatMap[i].data);             
00926                 free(This->FatMap);
00927         }
00928         return 0;
00929 }

Generated on Fri Apr 14 22:56:55 2006 for minix by  doxygen 1.4.6