void print_cluster(FILE *f, struct BPB_t *bpb, struct dir_t *dir) { const uint32_t cluster_size = bpb->BytsPerSec * bpb->SecPerClus; for(uint16_t c = dir->FstClusLO; c < 0xFFF8; c = get_next_cluster(f, bpb, c)) { char buf[cluster_size]; //FAT16 spec says that you have to subtract 2 from the cluster number to get the actual data //so weird. but whatevs.... read_bytes(f, BPB_Data_addr(bpb) + (c - 2) * cluster_size, buf, sizeof(buf)); printf("%.*s", (int)(sizeof(buf)), buf); } }
shared_ptr<FileBuffer> Fat::get_file_buff(string filename) { if (m_filemap.find(filename) == m_filemap.end()) { string err; err = "Can't find file "; err += filename; set_last_err_string(err); return NULL; } shared_ptr<FileBuffer> pbuff = get_file_buffer(m_filename); shared_ptr<FileBuffer> p(new FileBuffer); size_t filesize = m_filemap[filename].file_size; p->resize(filesize); int cur = m_filemap[filename].start_cluster; size_t off; for (off = 0; off < filesize; off += m_cluster) { size_t sz; sz = filesize - off; if (sz > m_cluster) sz = m_cluster; if (cur == 0xFFFF) { set_last_err_string("Early finished at fat"); return NULL; } void *pcluster = get_data_buff(pbuff, cur); memcpy(p->data() + off, pcluster, sz); cur = get_next_cluster(pbuff, cur); } return p; }
unsigned int exfat_remove_used_space(disk_t *disk, const partition_t *partition, alloc_data_t *list_search_space) { struct exfat_super_block *exfat_header; unsigned int cluster_shift; /* Load boot sector */ exfat_header=(struct exfat_super_block *)MALLOC(0x200); if(disk->pread(disk, exfat_header, 0x200, partition->part_offset) != 0x200) { log_error("Can't read exFAT boot sector.\n"); free(exfat_header); return 0; } cluster_shift=exfat_header->block_per_clus_bits + exfat_header->blocksize_bits; /* Load bitmap information */ { const struct exfat_alloc_bitmap_entry *bitmap; const uint64_t start=partition->part_offset + exfat_cluster_to_offset(exfat_header, le32(exfat_header->rootdir_clusnr)); unsigned char *buffer_rootdir=(unsigned char *)MALLOC(1<<cluster_shift); unsigned char *buffer; unsigned int i; unsigned int cluster_bitmap; const uint64_t start_exfat1=(uint64_t)le32(exfat_header->fat_blocknr) << exfat_header->blocksize_bits; uint64_t start_free=0; uint64_t end_free=0; if(disk->pread(disk, buffer_rootdir, 1 << cluster_shift, start) != (1<<cluster_shift)) { log_error("exFAT: Can't root directory cluster.\n"); free(buffer_rootdir); free(exfat_header); return 0; } bitmap=exfat_get_bitmap(buffer_rootdir, 1<<cluster_shift); if(bitmap==NULL) { log_error("exFAT: Can't find bitmap.\n"); free(buffer_rootdir); free(exfat_header); return 0; } cluster_bitmap=le32(bitmap->first_cluster); log_trace("exfat_remove_used_space\n"); buffer=(unsigned char *)MALLOC(1<<cluster_shift); for(i=2; i<le32(exfat_header->total_clusters)+2; i++) { const unsigned int offset_o=(i-2)%(8<<cluster_shift); if(offset_o==0) { exfat_read_cluster(disk, partition, exfat_header, buffer, cluster_bitmap); cluster_bitmap=get_next_cluster(disk, partition, UP_FAT32, start_exfat1, cluster_bitmap); } if(((buffer[offset_o/8]>>(offset_o%8))&1) != 0) { /* Not free */ if(end_free+1==partition->part_offset + exfat_cluster_to_offset(exfat_header, i)) end_free+=(1<<cluster_shift); else { if(start_free != end_free) del_search_space(list_search_space, start_free, end_free); start_free=partition->part_offset + exfat_cluster_to_offset(exfat_header, i); end_free=start_free + (1<<cluster_shift) - 1; } } } free(buffer); if(start_free != end_free) del_search_space(list_search_space, start_free, end_free); free(buffer_rootdir); free(exfat_header); } return (1<<cluster_shift); }
int fat_readdir(struct dirent *d) { int retVal=0; do { // Advance to next entry dir_sector_offset+=32; if (dir_sector_offset==512) { dir_sector_offset=0; dir_sector++; dir_sector_in_cluster++; if (dir_sector_in_cluster==sectors_per_cluster) { // Follow to next cluster int next_cluster=get_next_cluster(dir_cluster); if (next_cluster<0xFFFFFF0) { dir_cluster=next_cluster; dir_sector_in_cluster=0; dir_sector=first_cluster_sector+(next_cluster-first_cluster)*sectors_per_cluster; } else { // End of directory reached dir_sector=-1; retVal=-1; break; } } if (dir_sector!=-1) retVal=read_sector(partition_start+dir_sector,dir_sector_buffer,0); if (retVal) dir_sector=-1; } if (dir_sector==-1) { retVal=-1; break; } if (!d) { retVal=-1; break; } // printf("Found dirent %d %d %d\n",dir_sector,dir_sector_offset,dir_sector_in_cluster); // XXX - Support FAT32 long names! // Put cluster number in d_ino d->d_ino= (dir_sector_buffer[dir_sector_offset+0x1A]<<0)| (dir_sector_buffer[dir_sector_offset+0x1B]<<8)| (dir_sector_buffer[dir_sector_offset+0x14]<<16)| (dir_sector_buffer[dir_sector_offset+0x15]<<24); int namelen=0; if (dir_sector_buffer[dir_sector_offset]) { for(int i=0;i<8;i++) if (dir_sector_buffer[dir_sector_offset+i]) d->d_name[namelen++]=dir_sector_buffer[dir_sector_offset+i]; while(namelen&&d->d_name[namelen-1]==' ') namelen--; } if (dir_sector_buffer[dir_sector_offset+8]&&dir_sector_buffer[dir_sector_offset+8]!=' ') { d->d_name[namelen++]='.'; for(int i=0;i<3;i++) if (dir_sector_buffer[dir_sector_offset+8+i]) d->d_name[namelen++]=dir_sector_buffer[dir_sector_offset+8+i]; while(namelen&&d->d_name[namelen-1]==' ') namelen--; } d->d_name[namelen]=0; // if (d->d_name[0]) dump_bytes(0,"dirent raw",&dir_sector_buffer[dir_sector_offset],32); d->d_off= // XXX As a hack we put the size here (dir_sector_buffer[dir_sector_offset+0x1C]<<0)| (dir_sector_buffer[dir_sector_offset+0x1D]<<8)| (dir_sector_buffer[dir_sector_offset+0x1E]<<16)| (dir_sector_buffer[dir_sector_offset+0x1F]<<24); d->d_reclen=dir_sector_buffer[dir_sector_offset+0xb]; // XXX as a hack, we put DOS file attributes here if (d->d_off&0xC8) d->d_type=DT_UNKNOWN; else if (d->d_off&0x10) d->d_type=DT_DIR; else d->d_type=DT_REG; } while(0); return retVal; }