/* * repair an inconsistent file */ void repair(struct direntry *dirent, uint8_t *image_buf, struct bpb33 *bpb, int actual_size) { uint16_t cluster = getushort(dirent->deStartCluster); uint16_t cluster_size = bpb->bpbBytesPerSec * bpb->bpbSecPerClust; uint16_t prev_cluster = cluster; uint16_t num_bytes = 0; // accumulate all the related clusters in the FAT while (num_bytes < actual_size) { num_bytes += cluster_size; prev_cluster = cluster; cluster = get_fat_entry(cluster, image_buf, bpb); } if (num_bytes != 0) { set_fat_entry(prev_cluster, eof_cluster, image_buf, bpb); } // update all other clusters attached and mark them as free while (!is_end_of_file(cluster)) { uint16_t old_cluster = cluster; cluster = get_fat_entry(cluster, image_buf, bpb); set_fat_entry(old_cluster, free_cluster, image_buf, bpb); } }
uint32_t get_file_length(uint16_t cluster, uint8_t *image_buf, struct bpb33* bpb) { uint32_t length = 1; cluster = get_fat_entry(cluster, image_buf, bpb); while (!is_end_of_file(cluster)) { cluster = get_fat_entry(cluster, image_buf, bpb); length++; } return length; }
/***********SAVE_ORPHANS***************/ void orphan_search(uint8_t *image_buf, struct bpb33* bpb, int * refcount, int FATsz) { int count = 0; //count orphans int i = 2; for(; i < FATsz; i++) { uint16_t cluster = get_fat_entry(i, image_buf, bpb); if(cluster != (FAT12_MASK & CLUST_FREE) && cluster != (FAT12_MASK & CLUST_BAD) && refcount[i] == 0) { printf("FOUND AN ORPHAN, CLUSTER # = %d\n", i); count++; int orphan_size = 1; refcount[i] = 1; uint16_t orphan_cluster = cluster; while(is_valid_cluster(orphan_cluster, bpb)) { if (refcount[orphan_cluster] == 1) { set_fat_entry(orphan_cluster, (FAT12_MASK & CLUST_EOFS), image_buf, bpb); } else if(refcount[orphan_cluster] > 1) { struct direntry *dirent = (struct direntry*)cluster_to_addr(cluster, image_buf, bpb); dirent->deName[0] = SLOT_DELETED; refcount[orphan_cluster]--; printf("DELETED\n"); } else if(refcount[orphan_cluster] < 1) { refcount[orphan_cluster]++; } orphan_cluster = get_fat_entry(orphan_cluster, image_buf, bpb); orphan_size++; } //got to concatanate stuff struct direntry *dirent = (struct direntry*)root_dir_addr(image_buf, bpb); char name[5]; sprintf(name, "%d", count); char str[1024] = ""; strcat(str, "located"); strcat(str, name); strcat(str, ".dat\0"); char * file_name = str; create_dirent(dirent, file_name, i, orphan_size * 512, image_buf, bpb); printf("added %s to directory \n", str); printf("orphan cluster chain size = %d \n", orphan_size); } } printf("orphans saved: %d\n", count); }
/************FOLLOW_DIR***************/ void follow_dir(uint16_t cluster, int indent, uint8_t *image_buf, struct bpb33* bpb, int* refcount) { while (is_valid_cluster(cluster, bpb)) { struct direntry *dirent = (struct direntry*)cluster_to_addr(cluster, image_buf, bpb); int numDirEntries = (bpb->bpbBytesPerSec * bpb->bpbSecPerClust) / sizeof(struct direntry); //can't we just use int numDirEntries = bpb->RootDirEnts?? int i = 0; for ( ; i < numDirEntries; i++) { // char buffer[MAXFILENAME]; // uint16_t followclust = get_dirent(dirent, buffer); uint16_t followclust = print_dirent(dirent, indent, image_buf, bpb, refcount); //changed to print as follow_dir is called if (followclust) { refcount[followclust]++; follow_dir(followclust, indent+1, image_buf, bpb, refcount); } dirent++; } cluster = get_fat_entry(cluster, image_buf, bpb); } }
/* * follow dir recursively scans through the file hierarchy * we check for consistency for every directory entry * taken from dos with some modifications. */ void follow_dir(uint16_t cluster, int indent, uint8_t *image_buf, struct bpb33* bpb) { while (is_valid_cluster(cluster, bpb)) { append_clusters(cluster); struct direntry *dirent = (struct direntry*) cluster_to_addr(cluster, image_buf, bpb); int numDirEntries = (bpb->bpbBytesPerSec * bpb->bpbSecPerClust) / sizeof(struct direntry); char buffer[MAXFILENAME]; int i = 0; for ( ; i < numDirEntries; i++) { append_clusters(cluster); uint16_t followclust = get_dirent(dirent, buffer); chkerr(dirent, buffer, image_buf, bpb); if (followclust) { follow_dir(followclust, indent+1, image_buf, bpb); } dirent++; } cluster = get_fat_entry(cluster, image_buf, bpb); } }
/* * given a directory entry the function counts the number of * clusters referred to by the entry. */ int count_clusters(struct direntry *dirent, uint8_t *image_buf, struct bpb33 *bpb) { uint16_t cluster = getushort(dirent->deStartCluster); uint16_t cluster_size = bpb->bpbBytesPerSec * bpb->bpbSecPerClust; int num_bytes = 0; uint16_t prev_cluster = cluster; append_clusters(cluster); if (is_end_of_file(cluster)) num_bytes = 512; while (!is_end_of_file(cluster) && cluster < usable_clusters) { if (cluster == bad_cluster) { printf("Bad cluster: cluster number %d \n\n", cluster); set_fat_entry(prev_cluster, eof_cluster, image_buf, bpb); break; } if (cluster == free_cluster) { set_fat_entry(prev_cluster, eof_cluster, image_buf, bpb); break; } num_bytes += cluster_size; prev_cluster = cluster; cluster = get_fat_entry(cluster, image_buf, bpb); if (prev_cluster == cluster) { printf("Self referential cluster. \n\n"); set_fat_entry(prev_cluster, eof_cluster, image_buf, bpb); break; } append_clusters(cluster); } return num_bytes; }
void follow_dir(char* filename, uint16_t cluster, int indent, uint8_t *image_buf, struct bpb33* bpb) { while (is_valid_cluster(cluster, bpb)) { struct direntry *dirent = (struct direntry*)cluster_to_addr(cluster, image_buf, bpb); int numDirEntries = (bpb->bpbBytesPerSec * bpb->bpbSecPerClust) / sizeof(struct direntry); for ( int i=0; i < numDirEntries; i++) { uint16_t followclust = print_dirent(filename, dirent, indent); int count = -1; if (followclust!= 0) { count=compare(filename, followclust,dirent,image_buf,bpb); } else { } //printf("count: %i\n", count); if (followclust !=0) follow_dir(filename, followclust, indent+1, image_buf, bpb); dirent++; } cluster = get_fat_entry(cluster, image_buf, bpb); } }
void find_orphans(uint8_t *image_buf, struct bpb33* bpb) {//looks through the array we made and looks for clusters we didnt touch for(int i=0; i<4096, i++) { if (desperation[i]==0){ if(get_fat_entry(i,image_buf,pbp)!=FAT12_MASK&CLUST_FREE) { //if finds one we didnt touch and it is not currently set free this will free it set_fat_entry(i, FAT12_MASK&CLUST_FREE, image_buf, bpb); } } } }
/* * function that runs through the cluster list and stores orphans * in persistent memory */ void foster_orphans(uint8_t *image_buf, struct bpb33* bpb) { int orphan_count = 0; uint16_t curr_cluster = start_cluster; for ( ; curr_cluster < usable_clusters; curr_cluster++) { if ((get_fat_entry(curr_cluster, image_buf, bpb) != CLUST_FREE) && !in_cluster_list(curr_cluster)) { orphan_count = foster_single_orphan(orphan_count, curr_cluster, image_buf, bpb); } } }
void mark_file_clusters_used(int usedClusters[], uint16_t cluster, uint32_t bytes_remaining, uint8_t *image_buf, struct bpb33* bpb) { usedClusters[cluster] = 1; int clust_size = bpb->bpbSecPerClust * bpb->bpbBytesPerSec; int total_clusters = bpb->bpbSectors / bpb->bpbSecPerClust; if (cluster == 0) { fprintf(stderr, "Bad file termination\n"); return; } else if (cluster > total_clusters) { abort(); /* this shouldn't be able to happen */ } uint16_t next_cluster = get_fat_entry(cluster, image_buf, bpb); if (is_end_of_file(next_cluster)) { return; } else { mark_file_clusters_used(usedClusters, get_fat_entry(cluster, image_buf, bpb), bytes_remaining - clust_size, image_buf, bpb); } }
/* * calculate the size of a cluster chain */ uint32_t size_of_cluster(uint16_t cluster, uint8_t *image_buf, struct bpb33 *bpb) { uint16_t cluster_size = bpb->bpbBytesPerSec * bpb->bpbSecPerClust; uint32_t num_bytes = 0; append_clusters(cluster); while (!is_end_of_file(cluster)) { if (cluster == bad_cluster) { printf("Bad cluster: cluster number %d \n\n", cluster); } num_bytes += cluster_size; cluster = get_fat_entry(cluster, image_buf, bpb); append_clusters(cluster); } return num_bytes; }
void free_clusters(uint16_t cluster_begin, uint16_t cluster_end, uint8_t *image_buf, struct bpb33* bpb) { uint16_t current_cluster = cluster_begin; while(1) { uint16_t next_cluster = get_fat_entry(current_cluster, image_buf, bpb); set_fat_entry(current_cluster, FAT12_MASK&CLUST_FREE, image_buf, bpb); if (current_cluster == cluster_end || is_end_of_file(next_cluster)) { break; } current_cluster = next_cluster; } set_fat_entry(cluster_begin, FAT12_MASK&CLUST_EOFS, image_buf, bpb); }
void follow_dir(uint16_t cluster, int indent, uint8_t *image_buf, struct bpb33* bpb) { while (is_valid_cluster(cluster, bpb)) { struct direntry *dirent = (struct direntry*)cluster_to_addr(cluster, image_buf, bpb); int numDirEntries = (bpb->bpbBytesPerSec * bpb->bpbSecPerClust) / sizeof(struct direntry); int i = 0; for ( ; i < numDirEntries; i++) { uint16_t followclust = print_dirent(dirent, indent); if (followclust) follow_dir(followclust, indent+1, image_buf, bpb); dirent++; } cluster = get_fat_entry(cluster, image_buf, bpb); } }
int* lookupSectors(int FLC, int * length, ubyte* image){ int* sectors = (int*)malloc(10 * sizeof(int)); int currEntry = FLC; int end = 0; *length = 1; sectors[0] = currEntry + 31; while (!end && *length <= 10) { currEntry = get_fat_entry(currEntry, (byte*)image); if(currEntry < 0xFF8){ sectors[*length] = currEntry + 31; (*length)++; } else{ end = 1; } } return sectors; }
/************PRINT_DIRENT***************/ uint16_t print_dirent(struct direntry *dirent, int indent, uint8_t *image_buf, struct bpb33* bpb, int *refcount ) { uint16_t followclust = 0; int i; char name[9]; char extension[4]; uint32_t size; uint16_t file_cluster; name[8] = ' '; extension[3] = ' '; memcpy(name, &(dirent->deName[0]), 8); memcpy(extension, dirent->deExtension, 3); if (name[0] == SLOT_EMPTY) { return followclust; } /* skip over deleted entries */ if (((uint8_t)name[0]) == SLOT_DELETED) { return followclust; } if (((uint8_t)name[0]) == 0x2E) { // dot entry ("." or "..") // skip it return followclust; } /* names are space padded - remove the spaces */ for (i = 8; i > 0; i--) { if (name[i] == ' ') name[i] = '\0'; else break; } /* remove the spaces from extensions */ for (i = 3; i > 0; i--) { if (extension[i] == ' ') extension[i] = '\0'; else break; } if ((dirent->deAttributes & ATTR_WIN95LFN) == ATTR_WIN95LFN) { // ignore any long file name extension entries // // printf("Win95 long-filename entry seq 0x%0x\n", dirent->deName[0]); } else if ((dirent->deAttributes & ATTR_VOLUME) != 0) { printf("Volume: %s\n", name); } else if ((dirent->deAttributes & ATTR_DIRECTORY) != 0) { // don't deal with hidden directories; MacOS makes these // for trash directories and such; just ignore them. if ((dirent->deAttributes & ATTR_HIDDEN) != ATTR_HIDDEN) { print_indent(indent); printf("%s/ (directory)\n", name); file_cluster = getushort(dirent->deStartCluster); followclust = file_cluster; } } else { /* * a "regular" file entry * print attributes, size, starting cluster, etc. */ int ro = (dirent->deAttributes & ATTR_READONLY) == ATTR_READONLY; int hidden = (dirent->deAttributes & ATTR_HIDDEN) == ATTR_HIDDEN; int sys = (dirent->deAttributes & ATTR_SYSTEM) == ATTR_SYSTEM; int arch = (dirent->deAttributes & ATTR_ARCHIVE) == ATTR_ARCHIVE; size = getulong(dirent->deFileSize); print_indent(indent); printf("%s.%s (%u bytes) (starting cluster %d) %c%c%c%c\n", name, extension, size, getushort(dirent->deStartCluster), ro?'r':' ', hidden?'h':' ', sys?'s':' ', arch?'a':' '); int cluster_count = 0; uint16_t curr_cluster = getushort(dirent->deStartCluster); uint16_t original_cluster = curr_cluster; uint16_t previous; while(is_valid_cluster(curr_cluster,bpb)) { refcount[curr_cluster]++; if(refcount[curr_cluster] > 1) //problem { printf("ERROR REFCOUNT > 1 FOR: %d, refcount = %d\n", curr_cluster, refcount[curr_cluster]); dirent->deName[0] = SLOT_DELETED; refcount[curr_cluster]--; } previous = curr_cluster; curr_cluster = get_fat_entry(curr_cluster, image_buf, bpb); if(previous == curr_cluster) //points to itself { printf("ERROR POINTS TO SELF\n"); set_fat_entry(curr_cluster, FAT12_MASK & CLUST_EOFS, image_buf, bpb); cluster_count++; break; } if(curr_cluster == (FAT12_MASK & CLUST_BAD)) { printf("BAD CLUSTER\n"); set_fat_entry(curr_cluster, FAT12_MASK & CLUST_FREE, image_buf, bpb); set_fat_entry(previous, FAT12_MASK & CLUST_EOFS, image_buf, bpb); break; } cluster_count++; } int clusters = 0; if(size%512 == 0) { clusters = size/512; } else { clusters = (size/512)+1; } if(clusters < cluster_count) { printf("ERROR: FILE SIZE TOO SMALL FOR NUM CLUSTERS\n"); curr_cluster = get_fat_entry(original_cluster+clusters - 1, image_buf, bpb); printf("FIXED \n"); while(is_valid_cluster(curr_cluster, bpb)) { previous = curr_cluster; set_fat_entry(previous, FAT12_MASK & CLUST_FREE, image_buf, bpb); curr_cluster = get_fat_entry(curr_cluster, image_buf, bpb); } set_fat_entry(original_cluster +clusters -1, FAT12_MASK &CLUST_EOFS, image_buf, bpb); } else if(clusters > cluster_count) { printf("ERROR: FILE SIZE TOO LARGE FOR NUM CLUSTERS\n"); uint32_t correct_size = cluster_count * bpb->bpbBytesPerSec; putulong(dirent->deFileSize, correct_size); printf("FIXED \n"); } } return followclust; }
int main(int argc, char** argv) { uint8_t *image_buf; int fd; struct bpb33* bpb; if (argc != 2) { usage(); } image_buf = mmap_file(argv[1], &fd); bpb = check_bootsector(image_buf); int total_clusters = bpb->bpbSectors / bpb->bpbSecPerClust; int clust_size = bpb->bpbSecPerClust * bpb->bpbBytesPerSec; int used_clusters[total_clusters]; check_lost_files(used_clusters, 0, image_buf, bpb); int i; int shownPrefix = 0; for (i = 2; i < total_clusters; i++) { if (used_clusters[i] == 0 && get_fat_entry(i, image_buf, bpb) != CLUST_FREE) { if (!shownPrefix) { printf("Unreferenced:"); shownPrefix = 1; } printf(" %i", i); } if (i == total_clusters - 1 && shownPrefix) { printf("\n"); } } int foundCount = 1; shownPrefix = 0; for (i = 2; i < total_clusters; i++) { if (used_clusters[i] == 0 && get_fat_entry(i, image_buf, bpb) != CLUST_FREE) { if (!shownPrefix) { printf("Lost File: "); } uint16_t size = get_file_length(i, image_buf, bpb); printf("%i %i\n", i, size); struct direntry *dirent = (struct direntry*) cluster_to_addr(0, image_buf, bpb); uint32_t size_bytes = size * clust_size; const char base[] = "found"; const char extension[] = ".dat"; char filename [13]; sprintf(filename, "%s%i%s", base, foundCount++, extension); create_dirent(dirent, filename, i, size_bytes, image_buf, bpb); check_lost_files(used_clusters, 0, image_buf, bpb); } if (i == total_clusters - 1 && shownPrefix) { printf("\n"); } } check_file_length(0, image_buf, bpb); close(fd); exit(0); }
void check_lost_files(int usedClusters[], uint16_t cluster, uint8_t *image_buf, struct bpb33* bpb) { // A value of 1 means that the cluster is used somewhere. usedClusters[cluster] = 1; struct direntry *dirent; int d, i; dirent = (struct direntry*) cluster_to_addr(cluster, image_buf, bpb); int clust_size = bpb->bpbBytesPerSec * bpb->bpbSecPerClust; while (1) { for (d = 0; d < clust_size; d += sizeof(struct direntry)) { char name[9]; char extension[4]; uint32_t size; uint16_t file_cluster; name[8] = ' '; extension[3] = ' '; memcpy(name, &(dirent->deName[0]), 8); memcpy(extension, dirent->deExtension, 3); if (name[0] == SLOT_EMPTY) return; /* skip over deleted entries */ if (((uint8_t)name[0]) == SLOT_DELETED) continue; /* names are space padded - remove the spaces */ for (i = 8; i > 0; i--) { if (name[i] == ' ') name[i] = '\0'; else break; } /* remove the spaces from extensions */ for (i = 3; i > 0; i--) { if (extension[i] == ' ') extension[i] = '\0'; else break; } /* don't print "." or ".." directories */ if (strcmp(name, ".") == 0) { dirent++; continue; } if (strcmp(name, "..") == 0) { dirent++; continue; } if ((dirent->deAttributes & ATTR_VOLUME) != 0) { } else if ((dirent->deAttributes & ATTR_DIRECTORY) != 0) { file_cluster = getushort(dirent->deStartCluster); check_lost_files(usedClusters, file_cluster, image_buf, bpb); } else { /* We have a file. We should follow the file and remove all the used clusters from our collection! */ size = getulong(dirent->deFileSize); uint16_t file_cluster_begin = getushort(dirent->deStartCluster); //uint16_t cluster, uint32_t bytes_remaining, uint8_t *image_buf, struct bpb33* bpb mark_file_clusters_used(usedClusters, file_cluster_begin, size, image_buf, bpb); } dirent++; } /* We've reached the end of the cluster for this directory. Where's the next cluster? */ if (cluster == 0) { // root dir is special dirent++; } else { cluster = get_fat_entry(cluster, image_buf, bpb); dirent = (struct direntry*) cluster_to_addr(cluster, image_buf, bpb); } } }
int compare(char *filename, uint16_t followclust, struct direntry *dirent, uint8_t *image_buf, struct bpb33* bpb){ //will loop through fat until eof marking the good/bad/free clusters and freeing them uint32_t realsize = getulong(dirent->deFileSize); uint32_t clustersize = bpb->bpbSecPerClust*bpb->bpbBytesPerSec; int expected_num_clust = (realsize+511)/clustersize; // finds num clusters according to the meta data //find actual num clusters in fat uint16_t fatent = get_fat_entry(followclust, image_buf, bpb); uint16_t prev_fatent = fatent; int count = 1; while(!is_end_of_file(fatent)) { //loops through checking if eof uint16_t temp =get_fat_entry(fatent, image_buf, bpb); if (fatent == (FAT12_MASK & CLUST_BAD)){ //if the fatent is bad it will mark it in the array printf("Bad cluster"); desperation[followclust+count]=-1; printf("File is inconsistant: name is: %s\n",filename); } if(count>=expected_num_clust) //if we have more clusters than expected { if (count==expected_num_clust) { //will only happen once printf("count is greater\n"); //will set the previous entry to be eof and fee the current cluster //will also set desperation =2 at the eof and 3 at the free cluster // this is becasue we want a record in desperation of free normal or not looked at clusters set_fat_entry(prev_fatent,FAT12_MASK&CLUST_EOFS, image_buf, bpb); desperation[followclust+count-1]=2; set_fat_entry(fatent, FAT12_MASK&CLUST_FREE, image_buf, bpb); desperation[followclust+count]=3; printf("file is inconsistant!!! name is: %s\n",filename); } else { // if we are over the size just free current cluster set_fat_entry(fatent, FAT12_MASK&CLUST_FREE, image_buf, bpb); } //when count is over expected we will put 3 in every cluster over size eof desperation[followclust+count]=3; fatent=temp; count++; } else { //if we are still running through the clusters then if we find a free set it as 3 or if it is just normal then set it as 1 if (fatent == (FAT12_MASK&CLUST_FREE)) { printf("FREE CLUSTER BEFORE EOF WEEWOOWEEWOO"); desperation[followclust+count]=3; } else { desperation[followclust+count]=1; } prev_fatent=fatent; fatent=get_fat_entry(fatent,image_buf, bpb); count++; } } desperation[followclust+count]=2;//set this block as an eof in desperation if (expected_num_clust>count){ //if at the end cluster is greater than expected change the size in the meta data to be what the fat size is uint32_t clustersize = bpb->bpbSecPerClust*bpb->bpbBytesPerSec; putulong(dirent->deFileSize, (count*clustersize)); printf("File is inconsistant!!! name is: %s \n", filename); } //loop through the current files clusters on desperation and until you hit the eof int i= followclust; int countgucci=0; while (desperation[i]!=2) { if (desperation[i]==1) { countgucci++; } } //put the newsize into the metadata putulong(dirent->deFileSize, (countgucci*clustersize)); return count; }
WORD read_from_file(WORD pos, WORD size, char *buf, FileInfo *info) { int to_read; int sector, /* no of sector to read */ first_clus, /* 1st cluster to read */ num, /* no of cluster */ begin, /* pos of 1st byte in 1st cluster */ i, nb_clus, /* no total of cluster to read */ reste, e; Wait( &Var_access ); #ifdef debug IOdebug("msdosfs : read_from_file(%s), %dbytes",info->Name,size); #endif if( size == 0 ) { Signal( &Var_access ); return 0; } first_clus = pos / Cluster_byte; begin = pos % Cluster_byte; num = info->Cluster; /* get cluster in chain */ for(i = 0; i < first_clus; i++) { num = get_fat_entry(num); if(num < 0) goto error; if( num >= 0xff8 ) { #ifdef debugE IOdebug("msdosfs ERROR : read_from_file : eof unexpected"); #endif goto error; } } /* read up to boundary of next cluster */ to_read = (size > (Cluster_byte - begin)) ? Cluster_byte - begin : size; sector = (num - 2)*Cluster_size + Dir_start + Dir_size; e = flop_read(sector, Cluster_byte, buf); for(i = 0 ; i < to_read ; i++) buf[i] = buf[begin + i]; if( e < to_read ) goto error; buf += to_read; /* read full clusters */ nb_clus = (size-to_read)/Cluster_byte; for(i=0; i<nb_clus; i++) { num = get_fat_entry(num); if( num<0 || num>=0xff8 ) goto error; sector = (num - 2)*Cluster_size + Dir_start + Dir_size; if(flop_read(sector, Cluster_byte, buf) < Cluster_byte ) { Signal( &Var_access ); return (i*Cluster_byte + to_read); } buf += Cluster_byte; } /* read last cluster */ reste = size - to_read - nb_clus*Cluster_byte; if(reste>0) { char *freeloc; char *tbuff=Malloc(Cluster_byte); if(tbuff == NULL) goto error; freeloc = tbuff; num = get_fat_entry(num); if( num<0 || num>=0xff8 ) { Free(freeloc); goto error; } sector = (num - 2)*Cluster_size + Dir_start + Dir_size; e = flop_read(sector, Cluster_byte, tbuff); for(i = 0 ; i < reste ; i++) *buf++ = *tbuff++; Free(freeloc); if( e < reste ) { Signal( &Var_access ); return (nb_clus*Cluster_byte + to_read); } } Signal( &Var_access ); return(size); error : Signal( &Var_access ); return(0); }
void check_file_length(uint16_t cluster, uint8_t *image_buf, struct bpb33* bpb) { struct direntry *dirent; int d, i; dirent = (struct direntry*) cluster_to_addr(cluster, image_buf, bpb); int clust_size = bpb->bpbBytesPerSec * bpb->bpbSecPerClust; while (1) { for (d = 0; d < clust_size; d += sizeof(struct direntry)) { char name[9]; char extension[4]; uint32_t size; uint16_t file_cluster; name[8] = ' '; extension[3] = ' '; memcpy(name, &(dirent->deName[0]), 8); memcpy(extension, dirent->deExtension, 3); if (name[0] == SLOT_EMPTY) return; /* skip over deleted entries */ if (((uint8_t)name[0]) == SLOT_DELETED) continue; /* names are space padded - remove the spaces */ for (i = 8; i > 0; i--) { if (name[i] == ' ') name[i] = '\0'; else break; } /* remove the spaces from extensions */ for (i = 3; i > 0; i--) { if (extension[i] == ' ') extension[i] = '\0'; else break; } /* don't print "." or ".." directories */ if (strcmp(name, ".") == 0) { dirent++; continue; } if (strcmp(name, "..") == 0) { dirent++; continue; } if ((dirent->deAttributes & ATTR_VOLUME) != 0) { continue; } else if ((dirent->deAttributes & ATTR_DIRECTORY) != 0) { file_cluster = getushort(dirent->deStartCluster); check_file_length(file_cluster, image_buf, bpb); } else { size = getulong(dirent->deFileSize); file_cluster = getushort(dirent->deStartCluster); uint16_t fat_size_clusters = get_file_length(file_cluster, image_buf, bpb); uint32_t size_clusters = (size + (clust_size - 1)) / clust_size; uint32_t fat_size = fat_size_clusters * clust_size; if (size_clusters != fat_size_clusters) { printf("%s.%s %u %u\n", name, extension, size, fat_size); uint16_t begin_cluster = file_cluster + size_clusters - 1; uint16_t end_cluster = file_cluster + fat_size_clusters; free_clusters(begin_cluster, end_cluster, image_buf, bpb); } } dirent++; } /* We've reached the end of the cluster for this directory. Where's the next cluster? */ if (cluster == 0) { // root dir is special dirent++; } else { cluster = get_fat_entry(cluster, image_buf, bpb); dirent = (struct direntry*) cluster_to_addr(cluster, image_buf, bpb); } } }