/* fat_unformat() * @param struct ph_param *params * @param const struct ph_options *options * @param alloc_data_t *list_search_space * * @returns: * 0: Completed or not possible * 1: Stop by user request * params->offset is set */ int fat_unformat(struct ph_param *params, const struct ph_options *options, alloc_data_t *list_search_space) { unsigned int sectors_per_cluster=0; uint64_t start_data=0; params->blocksize=0; if(pfind_sectors_per_cluster(params->disk, params->partition, options->verbose, §ors_per_cluster, &start_data, list_search_space)==0) { display_message("Can't find FAT cluster size\n"); return 0; } if(start_data <= params->partition->part_offset) { display_message("FAT filesystem was beginning before the actual partition."); return 0; } start_data *= params->disk->sector_size; del_search_space(list_search_space, params->partition->part_offset, start_data - 1); { uint64_t offset=start_data; params->blocksize=sectors_per_cluster * params->disk->sector_size; #ifdef HAVE_NCURSES if(options->expert>0) params->blocksize=menu_choose_blocksize(params->blocksize, params->disk->sector_size, &offset); #endif update_blocksize(params->blocksize, list_search_space, offset); } /* start_data is relative to the disk */ return fat_unformat_aux(params, options, start_data, list_search_space); }
static int fat_unformat_aux(struct ph_param *params, const struct ph_options *options, const uint64_t start_offset, alloc_data_t *list_search_space) { int ind_stop=0; uint64_t offset; uint64_t offset_end; unsigned char *buffer_start; unsigned char *buffer; time_t start_time; time_t previous_time; const unsigned int blocksize=params->blocksize; const unsigned int read_size=(blocksize>65536?blocksize:65536); alloc_data_t *current_search_space; file_recovery_t file_recovery; disk_t *disk=params->disk; const partition_t *partition=params->partition; reset_file_recovery(&file_recovery); file_recovery.blocksize=blocksize; buffer_start=(unsigned char *)MALLOC(READ_SIZE); buffer=buffer_start; start_time=time(NULL); previous_time=start_time; current_search_space=td_list_entry(list_search_space->list.prev, alloc_data_t, list); if(current_search_space==list_search_space) { free(buffer_start); return 0; } offset_end=current_search_space->end; current_search_space=td_list_entry(list_search_space->list.next, alloc_data_t, list); offset=set_search_start(params, ¤t_search_space, list_search_space); if(options->verbose>0) info_list_search_space(list_search_space, current_search_space, disk->sector_size, 0, options->verbose); disk->pread(disk, buffer, READ_SIZE, offset); for(;offset < offset_end; offset+=blocksize) { if(memcmp(buffer, ". ", 8+3)==0 && memcmp(&buffer[0x20], ".. ", 8+3)==0) { file_data_t *dir_list; dir_list=dir_fat_aux(buffer,read_size,0,0); if(dir_list!=NULL) { const file_data_t *current_file; log_info("Sector %llu\n", (long long unsigned)offset/disk->sector_size); dir_aff_log(NULL, dir_list); del_search_space(list_search_space, offset, offset + blocksize -1); current_file=dir_list; while(current_file!=NULL) { if(strcmp(current_file->name,".")==0 && LINUX_S_ISDIR(current_file->stat.st_mode)!=0 && current_file!=dir_list) current_file=NULL; else if(current_file->stat.st_ino>2 && LINUX_S_ISREG(current_file->stat.st_mode)!=0) { const uint64_t file_start=start_offset + (uint64_t)(current_file->stat.st_ino - 2) * blocksize; #ifdef DJGPP const uint64_t file_end=file_start+(current_file->file_size+blocksize-1)/blocksize*blocksize - 1; #else const uint64_t file_end=file_start+(current_file->stat.st_size+blocksize-1)/blocksize*blocksize - 1; #endif if(file_end < partition->part_offset + partition->part_size) { if(fat_copy_file(disk, partition, blocksize, start_offset, params->recup_dir, params->dir_num, current_file)==0) { params->file_nbr++; del_search_space(list_search_space, file_start, file_end); } current_file=current_file->next; } else current_file=NULL; } else current_file=current_file->next; } delete_list_file(dir_list); } } buffer+=blocksize; if(buffer+read_size>buffer_start+READ_SIZE) { buffer=buffer_start; if(options->verbose>1) { log_verbose("Reading sector %10llu/%llu\n", (unsigned long long)((offset-partition->part_offset)/disk->sector_size), (unsigned long long)((partition->part_size-1)/disk->sector_size)); } if(disk->pread(disk, buffer, READ_SIZE, offset) != READ_SIZE) { #ifdef HAVE_NCURSES wmove(stdscr,11,0); wclrtoeol(stdscr); wprintw(stdscr,"Error reading sector %10lu\n", (unsigned long)((offset-partition->part_offset)/disk->sector_size)); #endif } #ifdef HAVE_NCURSES { time_t current_time; current_time=time(NULL); if(current_time>previous_time) { const time_t elapsed_time=current_time - params->real_start_time; previous_time=current_time; wmove(stdscr,9,0); wclrtoeol(stdscr); log_info("Reading sector %10llu/%llu, %u files found\n", (unsigned long long)((offset-partition->part_offset)/disk->sector_size), (unsigned long long)(partition->part_size/disk->sector_size), params->file_nbr); wprintw(stdscr,"Reading sector %10llu/%llu, %u files found\n", (unsigned long long)((offset-partition->part_offset)/disk->sector_size), (unsigned long long)(partition->part_size/disk->sector_size), params->file_nbr); wmove(stdscr,10,0); wclrtoeol(stdscr); wprintw(stdscr,"Elapsed time %uh%02um%02us", (unsigned)(elapsed_time/60/60), (unsigned)(elapsed_time/60%60), (unsigned)(elapsed_time%60)); if(offset-partition->part_offset!=0) { wprintw(stdscr," - Estimated time to completion %uh%02um%02u\n", (unsigned)((partition->part_offset+partition->part_size-1-offset)*elapsed_time/(offset-partition->part_offset)/3600), (unsigned)(((partition->part_offset+partition->part_size-1-offset)*elapsed_time/(offset-partition->part_offset)/60)%60), (unsigned)((partition->part_offset+partition->part_size-1-offset)*elapsed_time/(offset-partition->part_offset))%60); } wrefresh(stdscr); if(check_enter_key_or_s(stdscr)) { log_info("PhotoRec has been stopped\n"); params->offset=offset; offset = offset_end; ind_stop=1; } } } #endif } } free(buffer_start); return ind_stop; }
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); }