/* * If we have an FSInfo block, update it. */ static int msdosfs_fsiflush(struct msdosfsmount *pmp, int waitfor) { struct fsinfo *fp; struct buf *bp; int error; MSDOSFS_LOCK_MP(pmp); if (pmp->pm_fsinfo == 0 || (pmp->pm_flags & MSDOSFS_FSIMOD) == 0) { error = 0; goto unlock; } error = bread(pmp->pm_devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec, NOCRED, &bp); if (error != 0) { brelse(bp); goto unlock; } fp = (struct fsinfo *)bp->b_data; putulong(fp->fsinfree, pmp->pm_freeclustercount); putulong(fp->fsinxtfree, pmp->pm_nxtfree); pmp->pm_flags &= ~MSDOSFS_FSIMOD; if (waitfor == MNT_WAIT) error = bwrite(bp); else bawrite(bp); unlock: MSDOSFS_UNLOCK_MP(pmp); return (error); }
/* write the values into a directory entry */ void write_dirent(struct direntry *dirent, char *filename, uint16_t start_cluster, uint32_t size) { char *p, *p2; char *uppername; int len, i; /* clean out anything old that used to be here */ memset(dirent, 0, sizeof(struct direntry)); /* extract just the filename part */ uppername = strdup(filename); p2 = uppername; for (i = 0; i < strlen(filename); i++) { if (p2[i] == '/' || p2[i] == '\\') { uppername = p2+i+1; } } /* convert filename to upper case */ for (i = 0; i < strlen(uppername); i++) { uppername[i] = toupper(uppername[i]); } /* set the file name and extension */ memset(dirent->deName, ' ', 8); p = strchr(uppername, '.'); memcpy(dirent->deExtension, "___", 3); if (p == NULL) { fprintf(stderr, "No filename extension given - defaulting to .___\n"); } else { *p = '\0'; p++; len = strlen(p); if (len > 3) len = 3; memcpy(dirent->deExtension, p, len); } if (strlen(uppername)>8) { uppername[8]='\0'; } memcpy(dirent->deName, uppername, strlen(uppername)); free(p2); /* set the attributes and file size */ dirent->deAttributes = ATTR_NORMAL; putushort(dirent->deStartCluster, start_cluster); putulong(dirent->deFileSize, size); /* could also set time and date here if we really cared... */ }
/* * worker function that checks and repairs incosistency errors */ void chkerr(struct direntry* dirent, char* filename, uint8_t *image_buf, struct bpb33* bpb) { int num_clusters = count_clusters(dirent, image_buf, bpb); uint32_t entry_size = getulong(dirent->deFileSize); // remove empty files if (entry_size == 0) { if (dirent->deAttributes == ATTR_NORMAL && dirent->deName[0] != SLOT_EMPTY && dirent->deName[0] != SLOT_DELETED) { printf("Empty file found... removing. \n\n"); dirent->deName[0] = SLOT_DELETED; } } // fix size inconsistencies if (num_clusters != 0 && entry_size < num_clusters - 512 ) { // take entry to be right printf("OUT OF BOUNDS: \n\tFilename: %s \n\t\tsize in directory entry: %d, size in FAT chain: %d.) \n\n", filename, entry_size, num_clusters); repair(dirent, image_buf, bpb, entry_size); } else if (entry_size > num_clusters) { // take FAT to be right printf("OUT OF BOUNDS: \n\tFilename: %s \n\t\tsize in directory entry: %d, size in FAT chain: %d \n\n", filename, entry_size, num_clusters); putulong(dirent->deFileSize, num_clusters); } }
static void vprint(printer *p, const char *format, va_list ap) { const char *s = format; char c; INT ival; while ((c = *s++)) { switch (c) { case '%': switch ((c = *s++)) { case 'M': { /* md5 value */ md5uint x = va_arg(ap, md5uint); putulong(p, (unsigned long)(0xffffffffUL & x), 16, 8); break; } case 'c': { int x = va_arg(ap, int); p->putchr(p, x); break; } case 's': { char *x = va_arg(ap, char *); if (x) myputs(p, x); else goto putnull; break; } case 'd': { int x = va_arg(ap, int); ival = (INT)x; goto putival; } case 'D': { ival = va_arg(ap, INT); goto putival; } case 'v': { /* print optional vector length */ ival = va_arg(ap, INT); if (ival > 1) { myputs(p, "-x"); goto putival; } break; } case 'o': { /* integer option. Usage: %oNAME= */ ival = va_arg(ap, INT); if (ival) p->putchr(p, '/'); while ((c = *s++) != '=') if (ival) p->putchr(p, c); if (ival) { p->putchr(p, '='); goto putival; } break; } case 'u': { unsigned x = va_arg(ap, unsigned); putulong(p, (unsigned long)x, 10, 0); break; } case 'x': { unsigned x = va_arg(ap, unsigned); putulong(p, (unsigned long)x, 16, 0); break; } case '(': { /* newline, augment indent level */ p->indent += p->indent_incr; newline(p); break; } case ')': { /* decrement indent level */ p->indent -= p->indent_incr; break; } case 'p': { /* note difference from C's %p */ /* print plan */ plan *x = va_arg(ap, plan *); if (x) x->adt->print(x, p); else goto putnull; break; } case 'P': { /* print problem */ problem *x = va_arg(ap, problem *); if (x) x->adt->print(x, p); else goto putnull; break; } case 'T': { /* print tensor */ tensor *x = va_arg(ap, tensor *); if (x) X(tensor_print)(x, p); else goto putnull; break; } default: A(0 /* unknown format */); break; putnull: myputs(p, "(null)"); break; putival: putint(p, ival); break; } break; default: p->putchr(p, c); break; } } }
/************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; }