/* * 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); } }
/* * 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 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 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); } } } }
/***********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); }
/************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 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; }