static int del_entry(direntry_t *entry, MainParam_t *mp) { Arg_t *arg=(Arg_t *) mp->arg; if(got_signal) return ERROR_ONE; if(entry->entry == -3) { fprintf(stderr, "Cannot remove root directory\n"); return ERROR_ONE; } if (arg->verbose) { fprintf(stderr,"Removing "); fprintPwd(stderr, entry,0); fputc('\n', stderr); } if (entry->dir.attr & (ATTR_READONLY | ATTR_SYSTEM)) { char tmp[4*MAX_VNAMELEN+1]; wchar_to_native(entry->name,tmp,MAX_VNAMELEN); if (ask_confirmation("%s: \"%s\" is read only, erase anyway (y/n) ? ", progname, tmp)) return ERROR_ONE; } if (fatFreeWithDirentry(entry)) return ERROR_ONE; wipeEntry(entry); return GOT_ONE; }
void *operatore(){ while(1){ //generatore di numeri random usato da wait_client() e ask_confirmation() srand(time(NULL)); //attende un cliente wait_client(); //proteggo l'accesso dell'operatore al db pthread_mutex_lock(&op_lock); active_op++; if (active_op==1){ pthread_mutex_lock(&db_lock); } pthread_mutex_unlock(&op_lock); //controllo disponibilita' if (check_availability()){ pthread_mutex_lock(&op_lock); active_op--; if (active_op==0){ pthread_mutex_unlock(&db_lock); } pthread_mutex_unlock(&op_lock); //se il posto e' disponibile chiedo conferma della prenotazione if (ask_confirmation()){ pthread_mutex_lock(&db_lock); //avuta la conferma dal cliente, ricontrollo se il posto sia ancora libero if (check_availability()){ //ricevuta la conferma, prenoto il posto e rilascio il lock sul db book_seat(); pthread_mutex_unlock(&db_lock); //confermo al cliente l'avvenuta prenotazione confirm_booking(); } else { pthread_mutex_unlock(&db_lock); printf("Ci dispiace, qualcuno ha prenotato il posto prima di lei\n"); } } else { //prenotazione non confermata, rilascio il lock sul db pthread_mutex_lock(&op_lock); active_op--; if (active_op==0){ pthread_mutex_unlock(&db_lock); } pthread_mutex_unlock(&op_lock); printf("Ci dispiace che abbia cambiato idea, speriamo di rivederla al piu' presto!\n"); } } else { pthread_mutex_lock(&op_lock); active_op--; if (active_op==0){ pthread_mutex_unlock(&db_lock); } pthread_mutex_unlock(&op_lock); printf("Ci dispiace, il viaggio che le interessa e' gia' al completo! Speriamo di rivederla presto.\n"); break; } } }
int do_curses_photorec(struct ph_param *params, struct ph_options *options, const list_disk_t *list_disk) { static alloc_data_t list_search_space={ .list = TD_LIST_HEAD_INIT(list_search_space.list) }; if(params->cmd_device==NULL) { char *saved_device=NULL; char *saved_cmd=NULL; session_load(&saved_device, &saved_cmd,&list_search_space); if(saved_device!=NULL && saved_cmd!=NULL && !td_list_empty(&list_search_space.list) #ifdef HAVE_NCURSES && ask_confirmation("Continue previous session ? (Y/N)")!=0 #endif ) { /* yes */ params->cmd_run=saved_cmd; params->cmd_device=saved_device; } else { free(saved_device); free(saved_cmd); free_list_search_space(&list_search_space); } } if(params->cmd_device!=NULL && params->cmd_run!=NULL) { params->disk=photorec_disk_selection_cli(params->cmd_device, list_disk, &list_search_space); #ifdef HAVE_NCURSES if(params->disk==NULL) { log_critical("No disk found\n"); return intrf_no_disk_ncurses("PhotoRec"); } if(change_arch_type_cli(params->disk, options->verbose, ¶ms->cmd_run)==0 || change_arch_type_ncurses(params->disk, options->verbose)==0) { menu_photorec(params, options, &list_search_space); } return 0; #else if(params->disk==NULL) { log_critical("No disk found\n"); return 0; } change_arch_type_cli(params->disk, options->verbose, ¶ms->cmd_run); menu_photorec(params, options, &list_search_space); return 0; #endif } #ifdef HAVE_NCURSES return photorec_disk_selection_ncurses(params, options, list_disk, &list_search_space); #else return 0; #endif }
int exFAT_boot_sector(disk_t *disk, partition_t *partition, char **current_cmd) { unsigned char *buffer_bs; unsigned char *buffer_backup_bs; int rescan=1; const int size_bs=12 * disk->sector_size; const char *options; #ifdef HAVE_NCURSES const struct MenuItem menu_exFAT[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'Q', "Quit","Return to Advanced menu"}, { 'O', "Org. BS","Copy superblock over backup sector"}, { 'B', "Backup BS","Copy backup superblock over superblock"}, { 'D', "Dump","Dump superblock and backup superblock"}, { 0, NULL, NULL } }; #endif buffer_bs=(unsigned char*)MALLOC(size_bs); buffer_backup_bs=(unsigned char*)MALLOC(size_bs); while(1) { int command; screen_buffer_reset(); if(rescan==1) { options=exFAT_boot_sector_rescan(disk, partition, buffer_bs, buffer_backup_bs); rescan=0; } screen_buffer_to_log(); if(*current_cmd!=NULL) { command=exFAT_boot_sector_command(current_cmd, options); } else { #ifdef HAVE_NCURSES unsigned int menu=0; #endif log_flush(); #ifdef HAVE_NCURSES command=screen_buffer_display_ext(stdscr, options, menu_exFAT, &menu); #else command=0; #endif } switch(command) { case 0: free(buffer_bs); free(buffer_backup_bs); return 0; case 'O': /* O : copy original superblock over backup boot */ #ifdef HAVE_NCURSES if(ask_confirmation("Copy original exFAT boot record over backup, confirm ? (Y/N)")!=0) #endif { log_info("copy original superblock over backup boot\n"); if(disk->pwrite(disk, buffer_bs, size_bs, partition->part_offset + size_bs) != size_bs) { display_message("Write error: Can't overwrite exFAT backup boot record\n"); } disk->sync(disk); rescan=1; } break; case 'B': /* B : copy backup superblock over main superblock */ #ifdef HAVE_NCURSES if(ask_confirmation("Copy backup exFAT boot record over main boot record, confirm ? (Y/N)")!=0) #endif { log_info("copy backup superblock over main superblock\n"); /* Reset information about backup boot record */ partition->sb_offset=0; if(disk->pwrite(disk, buffer_backup_bs, size_bs, partition->part_offset) != size_bs) { display_message("Write error: Can't overwrite exFAT main boot record\n"); } disk->sync(disk); rescan=1; } break; case 'D': exFAT_dump(disk, partition, buffer_bs, buffer_backup_bs, current_cmd); break; } } }
int repair_MFT(disk_t *disk_car, partition_t *partition, const int verbose, const unsigned int expert, char **current_cmd) { struct ntfs_boot_sector *ntfs_header; unsigned char *buffer_mft; unsigned char *buffer_mftmirr; unsigned int cluster_size; unsigned int mft_record_size; unsigned int mftmirr_size_bytes; unsigned int use_MFT=0; /* 0: do nothing * 1: fix MFT mirror using MFT * 2: fix MFT using MFT mirror */ uint64_t mft_pos; uint64_t mftmirr_pos; log_trace("repair_MFT\n"); if(check_NTFS(disk_car, partition, verbose, 0)!=0) { display_message("Boot sector not valid, can't repair MFT.\n"); return -1; } ntfs_header=(struct ntfs_boot_sector *)MALLOC(DEFAULT_SECTOR_SIZE); if(disk_car->pread(disk_car, ntfs_header, DEFAULT_SECTOR_SIZE, partition->part_offset) != DEFAULT_SECTOR_SIZE) { free(ntfs_header); display_message("Can't read NTFS boot sector.\n"); return -1; } mft_pos=partition->part_offset+(uint64_t)(le16(ntfs_header->reserved)+le64(ntfs_header->mft_lcn)*ntfs_header->sectors_per_cluster)*ntfs_sector_size(ntfs_header); mftmirr_pos=partition->part_offset+(uint64_t)(le16(ntfs_header->reserved)+le64(ntfs_header->mftmirr_lcn)*ntfs_header->sectors_per_cluster)*ntfs_sector_size(ntfs_header); if(ntfs_header->clusters_per_mft_record>0) mft_record_size=ntfs_header->sectors_per_cluster*ntfs_header->clusters_per_mft_record; else mft_record_size=1<<(-ntfs_header->clusters_per_mft_record); cluster_size=ntfs_header->sectors_per_cluster; mftmirr_size_bytes = (cluster_size <= 4 * mft_record_size ? 4 * mft_record_size : cluster_size) * ntfs_sector_size(ntfs_header); #ifdef DEBUG_REPAIR_MFT log_debug("mft_pos %lu\n",(unsigned long)(mft_pos/disk_car->sector_size)); log_debug("mftmirr_pos %lu\n",(unsigned long)(mftmirr_pos/disk_car->sector_size)); log_debug("cluster_size %u\n", cluster_size); log_debug("mft_record_size %u\n", mft_record_size); log_debug("ntfs_sector_size %u\n", ntfs_sector_size(ntfs_header)); log_debug("mftmirr_size_bytes %u\n", mftmirr_size_bytes); #endif if(mftmirr_size_bytes==0) { display_message("Invalid NTFS MFT size.\n"); log_error("Invalid NTFS MFT size.\n"); free(ntfs_header); return -1; } /* Check if MFT mirror is identical to the beginning of MFT */ buffer_mft=(unsigned char *)MALLOC(mftmirr_size_bytes); if((unsigned)disk_car->pread(disk_car, buffer_mft, mftmirr_size_bytes, mft_pos) != mftmirr_size_bytes) { display_message("Can't read NTFS MFT.\n"); log_error("Can't read NTFS MFT.\n"); free(buffer_mft); free(ntfs_header); return -1; } buffer_mftmirr=(unsigned char *)MALLOC(mftmirr_size_bytes); if((unsigned)disk_car->pread(disk_car, buffer_mftmirr, mftmirr_size_bytes, mftmirr_pos) != mftmirr_size_bytes) { display_message("Can't read NTFS MFT mirror.\n"); log_error("Can't read NTFS MFT mirror.\n"); free(buffer_mftmirr); free(buffer_mft); free(ntfs_header); return -1; } if(memcmp(buffer_mft, buffer_mftmirr, mftmirr_size_bytes)==0) { log_info("MFT and MFT mirror match perfectly.\n"); if(*current_cmd==NULL) display_message("MFT and MFT mirror match perfectly.\n"); free(buffer_mftmirr); free(buffer_mft); free(ntfs_header); return 0; } if(partition->sb_offset!=0) { log_info("Please quit TestDisk and reboot your computer before trying to fix the MFT.\n"); display_message("Please quit TestDisk and reboot your computer before trying to fix the MFT.\n"); free(buffer_mftmirr); free(buffer_mft); free(ntfs_header); return -1; } /* log_debug("MFT\n"); dump_log(buffer_mft, mftmirr_size_bytes); log_debug("MFT mirror\n"); dump_log(buffer_mftmirr, mftmirr_size_bytes); */ /* The idea is to use the internal IO redirector built-in TestDisk to redirect read access to the MFT to the MFT backup instead (or vice-versa) when listing the NTFS files. If TestDisk can get a file listing, it also knows which MFT to use. */ { int res1,res2; dir_data_t dir_data; /* Use MFT */ io_redir_add_redir(disk_car, mftmirr_pos, mftmirr_size_bytes, 0, buffer_mft); res1=dir_partition_ntfs_init(disk_car,partition,&dir_data,verbose); if(res1==DIR_PART_ENOSYS) { display_message("Can't determine which MFT is correct, ntfslib is missing.\n"); log_error("Can't determine which MFT is correct, ntfslib is missing.\n"); free(buffer_mftmirr); free(buffer_mft); free(ntfs_header); io_redir_del_redir(disk_car,mftmirr_pos); return 0; } if(res1==DIR_PART_OK) { file_info_t dir_list; TD_INIT_LIST_HEAD(&dir_list.list); dir_data.get_dir(disk_car,partition,&dir_data,dir_data.current_inode, &dir_list); if(!td_list_empty(&dir_list.list)) { log_info("NTFS listing using MFT:\n"); dir_aff_log(&dir_data, &dir_list); if(delete_list_file(&dir_list)>2) res1++; } dir_data.close(&dir_data); } io_redir_del_redir(disk_car,mftmirr_pos); /* Use MFT mirror */ io_redir_add_redir(disk_car, mft_pos, mftmirr_size_bytes, 0, buffer_mftmirr); res2=dir_partition_ntfs_init(disk_car,partition,&dir_data,verbose); if(res2==DIR_PART_OK) { file_info_t dir_list; TD_INIT_LIST_HEAD(&dir_list.list); dir_data.get_dir(disk_car,partition,&dir_data,dir_data.current_inode, &dir_list); if(!td_list_empty(&dir_list.list)) { log_info("NTFS listing using MFT mirror:\n"); dir_aff_log(&dir_data, &dir_list); if(delete_list_file(&dir_list)>2) res2++; } dir_data.close(&dir_data); } io_redir_del_redir(disk_car,mft_pos); /* */ if(res1>res2 && res1>DIR_PART_OK) { /* Use MFT */ #ifdef HAVE_NCURSES if(ask_confirmation("Fix MFT mirror using MFT ? (Y/N)")!=0) use_MFT=1; else #endif log_info("Don't fix MFT mirror.\n"); } else if(res1<res2 && res2>DIR_PART_OK) { /* Use MFT mirror */ #ifdef HAVE_NCURSES if(ask_confirmation("Fix MFT using its mirror ? (Y/N) - DANGEROUS NON REVERSIBLE OPERATION\nUse it ONLY IF Windows failed to access this filesystem.")!=0) use_MFT=2; else #endif log_info("Don't fix MFT.\n"); } else { /* res1==res2 */ if(res1>DIR_PART_OK && res2>DIR_PART_OK) log_error("Both MFT seems ok but they don't match, use chkdsk.\n"); else log_error("MFT and MFT mirror are bad. Failed to repair them.\n"); if(expert==0) { if(res1>DIR_PART_OK && res2>DIR_PART_OK) display_message("Both MFT seems ok but they don't match, use chkdsk.\n"); else display_message("MFT and MFT mirror are bad. Failed to repair them.\n"); } else { #ifdef HAVE_NCURSES unsigned int menu=2; int real_key; int command; static const struct MenuItem menuMFT[]= { {'B',"MFT", "Fix MFT using MFT mirror"}, {'M',"MFT Mirror", "Fix MFT mirror using MFT"}, {'Q',"Quit","Return to NTFS functions"}, {0,NULL,NULL} }; aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); mvwaddstr(stdscr,5,0,msg_PART_HEADER_LONG); wmove(stdscr,6,0); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition); wmove(stdscr,8,0); if(res1>0 && res2>0) wprintw(stdscr, "Both MFT seem ok but they don't match.\n"); else wprintw(stdscr, "MFT and MFT mirror are bad.\n"); command=wmenuSelect_ext(stdscr, 23, INTER_MFT_Y, INTER_MFT_X, menuMFT, 10, "MBQ", MENU_VERT | MENU_VERT_WARN | MENU_BUTTON, &menu, &real_key); switch(command) { case 'b': case 'B': use_MFT=2; break; case 'm': case 'M': use_MFT=1; break; default: use_MFT=0; break; } #endif } } } if(use_MFT==2) { if((unsigned)disk_car->pwrite(disk_car, buffer_mftmirr, mftmirr_size_bytes, mft_pos) != mftmirr_size_bytes) { display_message("Failed to fix MFT: write error.\n"); } else { disk_car->sync(disk_car); display_message("MFT fixed.\n"); } } else if(use_MFT==1) { if((unsigned)disk_car->pwrite(disk_car, buffer_mft, mftmirr_size_bytes, mftmirr_pos) != mftmirr_size_bytes) { display_message("Failed to fix MFT mirror: write error.\n"); } else { disk_car->sync(disk_car); display_message("MFT mirror fixed.\n"); } } free(buffer_mftmirr); free(buffer_mft); free(ntfs_header); return 0; }
static __inline__ clash_action get_slots(Stream_t *Dir, dos_name_t *dosname, char *longname, struct scan_state *ssp, ClashHandling_t *ch) { int error; clash_action ret; int match_pos=0; direntry_t entry; int isprimary; int no_overwrite; int reason; int pessimisticShortRename; doscp_t *cp = GET_DOSCONVERT(Dir); pessimisticShortRename = (ch->action[0] == NAMEMATCH_AUTORENAME); entry.Dir = Dir; no_overwrite = 1; if((is_reserved(longname,1)) || longname[strspn(longname,". ")] == '\0'){ reason = RESERVED; isprimary = 1; } else if(contains_illegals(longname,long_illegals,1024)) { reason = ILLEGALS; isprimary = 1; } else if(is_reserved(dosname->base,0)) { reason = RESERVED; ch->use_longname = 1; isprimary = 0; } else if(contains_illegals(dosname->base,short_illegals,11)) { reason = ILLEGALS; ch->use_longname = 1; isprimary = 0; } else { reason = EXISTS; switch (lookupForInsert(Dir, &entry, dosname, longname, ssp, ch->ignore_entry, ch->source_entry, pessimisticShortRename && ch->use_longname, ch->use_longname)) { case -1: return NAMEMATCH_ERROR; case 0: return NAMEMATCH_SKIP; /* Single-file error error or skip request */ case 5: return NAMEMATCH_GREW; /* Grew directory, try again */ case 6: return NAMEMATCH_SUCCESS; /* Success */ } match_pos = -2; if (ssp->longmatch > -1) { /* Primary Long Name Match */ #ifdef debug fprintf(stderr, "Got longmatch=%d for name %s.\n", longmatch, longname); #endif match_pos = ssp->longmatch; isprimary = 1; } else if ((ch->use_longname & 1) && (ssp->shortmatch != -1)) { /* Secondary Short Name Match */ #ifdef debug fprintf(stderr, "Got secondary short name match for name %s.\n", longname); #endif match_pos = ssp->shortmatch; isprimary = 0; } else if (ssp->shortmatch >= 0) { /* Primary Short Name Match */ #ifdef debug fprintf(stderr, "Got primary short name match for name %s.\n", longname); #endif match_pos = ssp->shortmatch; isprimary = 1; } else return NAMEMATCH_RENAME; if(match_pos > -1) { entry.entry = match_pos; dir_read(&entry, &error); if (error) return NAMEMATCH_ERROR; /* if we can't overwrite, don't propose it */ no_overwrite = (match_pos == ch->source || IS_DIR(&entry)); } } ret = process_namematch(cp, dosname, longname, isprimary, ch, no_overwrite, reason); if (ret == NAMEMATCH_OVERWRITE && match_pos > -1){ if((entry.dir.attr & 0x5) && (ask_confirmation("file is read only, overwrite anyway (y/n) ? "))) return NAMEMATCH_RENAME; /* Free up the file to be overwritten */ if(fatFreeWithDirentry(&entry)) return NAMEMATCH_ERROR; #if 0 if(isprimary && match_pos - ssp->match_free + 1 >= ssp->size_needed){ /* reuse old entry and old short name for overwrite */ ssp->free_start = match_pos - ssp->size_needed + 1; ssp->free_size = ssp->size_needed; ssp->slot = match_pos; ssp->got_slots = 1; strncpy(dosname, dir.name, 3); strncpy(dosname + 8, dir.ext, 3); return ret; } else #endif { wipeEntry(&entry); return NAMEMATCH_RENAME; } } return ret; }
void mlabel(int argc, char **argv, int type) { char *newLabel; int verbose, clear, interactive, show; direntry_t entry; int result=0; char longname[VBUFSIZE]; char shortname[45]; ClashHandling_t ch; struct MainParam_t mp; Stream_t *RootDir; int c; int mangled; enum { SER_NONE, SER_RANDOM, SER_SET } set_serial = SER_NONE; long serial = 0; int need_write_boot = 0; int have_boot = 0; char *eptr; union bootsector boot; Stream_t *Fs=0; int r; struct label_blk_t *labelBlock; int isRo=0; int *isRop=NULL; init_clash_handling(&ch); ch.name_converter = label_name; ch.ignore_entry = -2; verbose = 0; clear = 0; show = 0; if(helpFlag(argc, argv)) usage(0); while ((c = getopt(argc, argv, "i:vcsnN:h")) != EOF) { switch (c) { case 'i': set_cmd_line_image(optarg, 0); break; case 'v': verbose = 1; break; case 'c': clear = 1; break; case 's': show = 1; break; case 'n': set_serial = SER_RANDOM; srandom((long)time (0)); serial=random(); break; case 'N': set_serial = SER_SET; serial = strtol(optarg, &eptr, 16); if(*eptr) { fprintf(stderr, "%s not a valid serial number\n", optarg); exit(1); } break; case 'h': usage(0); default: usage(1); } } if (argc - optind != 1 || !argv[optind][0] || argv[optind][1] != ':') usage(1); init_mp(&mp); newLabel = argv[optind]+2; if(strlen(newLabel) > VBUFSIZE) { fprintf(stderr, "Label too long\n"); FREE(&RootDir); exit(1); } interactive = !show && !clear &&!newLabel[0] && (set_serial == SER_NONE); if(!clear && !newLabel[0]) { isRop = &isRo; } RootDir = open_root_dir(argv[optind][0], isRop ? 0 : O_RDWR, isRop); if(isRo) { show = 1; interactive = 0; } if(!RootDir) { fprintf(stderr, "%s: Cannot initialize drive\n", argv[0]); exit(1); } initializeDirentry(&entry, RootDir); r=vfat_lookup(&entry, 0, 0, ACCEPT_LABEL | MATCH_ANY, shortname, longname); if (r == -2) { FREE(&RootDir); exit(1); } if(show || interactive){ if(isNotFound(&entry)) printf(" Volume has no label\n"); else if (*longname) printf(" Volume label is %s (abbr=%s)\n", longname, shortname); else printf(" Volume label is %s\n", shortname); } /* ask for new label */ if(interactive){ newLabel = longname; fprintf(stderr,"Enter the new volume label : "); if(fgets(newLabel, VBUFSIZE, stdin) == NULL) { newLabel[0] = '\0'; fprintf(stderr, "\n"); } if(newLabel[0]) newLabel[strlen(newLabel)-1] = '\0'; } if((!show || newLabel[0]) && !isNotFound(&entry)){ /* if we have a label, wipe it out before putting new one */ if(interactive && newLabel[0] == '\0') if(ask_confirmation("Delete volume label (y/n): ")){ FREE(&RootDir); exit(0); } entry.dir.attr = 0; /* for old mlabel */ wipeEntry(&entry); } if (newLabel[0] != '\0') { ch.ignore_entry = 1; result = mwrite_one(RootDir,newLabel,0,labelit,NULL,&ch) ? 0 : 1; } have_boot = 0; if( (!show || newLabel[0]) || set_serial != SER_NONE) { Fs = GetFs(RootDir); have_boot = (force_read(Fs,boot.characters,0,sizeof(boot)) == sizeof(boot)); } if(WORD_S(fatlen)) { labelBlock = &boot.boot.ext.old.labelBlock; } else { labelBlock = &boot.boot.ext.fat32.labelBlock; } if(!show || newLabel[0]){ dos_name_t dosname; const char *shrtLabel; doscp_t *cp; if(!newLabel[0]) shrtLabel = "NO NAME "; else shrtLabel = newLabel; cp = GET_DOSCONVERT(Fs); label_name(cp, shrtLabel, verbose, &mangled, &dosname); if(have_boot && boot.boot.descr >= 0xf0 && labelBlock->dos4 == 0x29) { strncpy(labelBlock->label, dosname.base, 11); need_write_boot = 1; } } if((set_serial != SER_NONE) & have_boot) { if(have_boot && boot.boot.descr >= 0xf0 && labelBlock->dos4 == 0x29) { set_dword(labelBlock->serial, serial); need_write_boot = 1; } } if(need_write_boot) { force_write(Fs, (char *)&boot, 0, sizeof(boot)); } FREE(&RootDir); exit(result); }
int copy_file(const char *source, const char *dest, int flags) { struct stat source_stat; struct stat dest_stat; int dest_exists = 0; int status = 0; if ((!(flags & FILEUTILS_PRESERVE_SYMLINKS) && lstat(source, &source_stat) < 0) || ((flags & FILEUTILS_PRESERVE_SYMLINKS) && stat(source, &source_stat) < 0)) { perror_msg("%s", source); return -1; } if (lstat(dest, &dest_stat) < 0) { if (errno != ENOENT) { perror_msg("unable to stat `%s'", dest); return -1; } } else { if (source_stat.st_dev == dest_stat.st_dev && source_stat.st_ino == dest_stat.st_ino) { error_msg("`%s' and `%s' are the same file", source, dest); return -1; } dest_exists = 1; } if (S_ISDIR(source_stat.st_mode)) { DIR *dp; struct dirent *d; mode_t saved_umask = 0; if (!(flags & FILEUTILS_RECUR)) { error_msg("%s: omitting directory", source); return -1; } /* Create DEST. */ if (dest_exists) { if (!S_ISDIR(dest_stat.st_mode)) { error_msg("`%s' is not a directory", dest); return -1; } } else { mode_t mode; saved_umask = umask(0); mode = source_stat.st_mode; if (!(flags & FILEUTILS_PRESERVE_STATUS)) mode = source_stat.st_mode & ~saved_umask; mode |= S_IRWXU; if (mkdir(dest, mode) < 0) { umask(saved_umask); perror_msg("cannot create directory `%s'", dest); return -1; } umask(saved_umask); } /* Recursively copy files in SOURCE. */ if ((dp = opendir(source)) == NULL) { perror_msg("unable to open directory `%s'", source); status = -1; goto end; } while ((d = readdir(dp)) != NULL) { char *new_source, *new_dest; if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) continue; new_source = concat_path_file(source, d->d_name); new_dest = concat_path_file(dest, d->d_name); if (copy_file(new_source, new_dest, flags) < 0) status = -1; free(new_source); free(new_dest); } /* closedir have only EBADF error, but "dp" not changes */ closedir(dp); if (!dest_exists && chmod(dest, source_stat.st_mode & ~saved_umask) < 0) { perror_msg("unable to change permissions of `%s'", dest); status = -1; } } else if (S_ISREG(source_stat.st_mode)) { FILE *sfp, *dfp=NULL; #ifdef CONFIG_FEATURE_PRESERVE_HARDLINKS char *link_name; if (!(flags & FILEUTILS_PRESERVE_SYMLINKS) && is_in_ino_dev_hashtable(&source_stat, &link_name)) { if (link(link_name, dest) < 0) { perror_msg("unable to link `%s'", dest); return -1; } return 0; } #endif if ((sfp = wfopen(source, "r")) == NULL) { return -1; } if (dest_exists) { if (flags & FILEUTILS_INTERACTIVE) { fprintf(stderr, "%s: overwrite `%s'? ", applet_name, dest); if (!ask_confirmation()) { fclose (sfp); return 0; } } if ((dfp = fopen(dest, "w")) == NULL) { if (!(flags & FILEUTILS_FORCE)) { perror_msg("unable to open `%s'", dest); fclose (sfp); return -1; } if (unlink(dest) < 0) { perror_msg("unable to remove `%s'", dest); fclose (sfp); return -1; } dest_exists = 0; } } if (!dest_exists) { int fd; if ((fd = open(dest, O_WRONLY|O_CREAT, source_stat.st_mode)) < 0 || (dfp = fdopen(fd, "w")) == NULL) { if (fd >= 0) close(fd); perror_msg("unable to open `%s'", dest); fclose (sfp); return -1; } } if (copy_file_chunk(sfp, dfp, -1) < 0) status = -1; if (fclose(dfp) < 0) { perror_msg("unable to close `%s'", dest); status = -1; } if (fclose(sfp) < 0) { perror_msg("unable to close `%s'", source); status = -1; } } else if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode) || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode) || S_ISLNK(source_stat.st_mode)) { if (dest_exists && ((flags & FILEUTILS_FORCE) == 0 || unlink(dest) < 0)) { perror_msg("unable to remove `%s'", dest); return -1; } } else { error_msg("internal error: unrecognized file type"); return -1; } if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode) || S_ISSOCK(source_stat.st_mode)) { if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) { perror_msg("unable to create `%s'", dest); return -1; } } else if (S_ISFIFO(source_stat.st_mode)) { if (mkfifo(dest, source_stat.st_mode) < 0) { perror_msg("cannot create fifo `%s'", dest); return -1; } } else if (S_ISLNK(source_stat.st_mode)) { char *lpath; lpath = xreadlink(source); if (symlink(lpath, dest) < 0) { perror_msg("cannot create symlink `%s'", dest); return -1; } free(lpath); #if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) if (flags & FILEUTILS_PRESERVE_STATUS) if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0) perror_msg("unable to preserve ownership of `%s'", dest); #endif #ifdef CONFIG_FEATURE_PRESERVE_HARDLINKS add_to_ino_dev_hashtable(&source_stat, dest); #endif return 0; } #ifdef CONFIG_FEATURE_PRESERVE_HARDLINKS add_to_ino_dev_hashtable(&source_stat, dest); #endif end: if (flags & FILEUTILS_PRESERVE_STATUS) { struct utimbuf times; times.actime = source_stat.st_atime; times.modtime = source_stat.st_mtime; if (utime(dest, ×) < 0) perror_msg("unable to preserve times of `%s'", dest); if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) { source_stat.st_mode &= ~(S_ISUID | S_ISGID); perror_msg("unable to preserve ownership of `%s'", dest); } if (chmod(dest, source_stat.st_mode) < 0) perror_msg("unable to preserve permissions of `%s'", dest); } return status; }
int disk_image(disk_t *disk, const partition_t *partition, const char *image_dd) { int ind_stop=0; uint64_t nbr_read_error=0; uint64_t src_offset=partition->part_offset; uint64_t src_offset_old; uint64_t dst_offset=0; const uint64_t src_offset_end=partition->part_offset+partition->part_size; const uint64_t offset_inc=(src_offset_end-src_offset)/10000; uint64_t src_offset_next=src_offset; struct stat stat_buf; unsigned char *buffer=(unsigned char *)MALLOC(READ_SIZE); unsigned int readsize=READ_SIZE; int disk_dst; #ifdef HAVE_NCURSES WINDOW *window; #endif if((disk_dst=open(image_dd, O_CREAT|O_LARGEFILE|O_RDWR|O_BINARY, 0644)) < 0) { log_error("Can't create file %s.\n",image_dd); display_message("Can't create file!\n"); free(buffer); return -1; } if(fstat(disk_dst, &stat_buf)==0) { int res=1; #ifdef HAVE_NCURSES if(stat_buf.st_size > 0) res=ask_confirmation("Append to existing file ? (Y/N)"); #endif if(res>0) { dst_offset=stat_buf.st_size; src_offset+=dst_offset; } } src_offset_old=src_offset; #ifdef HAVE_NCURSES window=newwin(LINES, COLS, 0, 0); /* full screen */ aff_copy(window); wmove(window,5,0); wprintw(window,"%s\n",disk->description_short(disk)); wmove(window,6,0); aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk,partition); wmove(window,10,0); waddstr(window, "Disk images are mainly used "); wmove(window,11,0); waddstr(window, "- for forensics purpose"); wmove(window,12,0); waddstr(window, "- or to deal with media with bad sectors"); #ifdef WIN32 wmove(window,14,0); waddstr(window, "To use TestDisk or PhotoRec with this disk image, go in command line and run"); wmove(window,15,0); waddstr(window, " testdisk_win.exe image.dd"); wmove(window,16,0); waddstr(window, "or photorec_win.exe image.dd"); #else wmove(window,14,0); waddstr(window, "To use TestDisk or PhotoRec with this disk image, start a Terminal and run"); wmove(window,15,0); waddstr(window, " testdisk image.dd"); wmove(window,16,0); waddstr(window, "or photorec image.dd"); #endif wmove(window,22,0); wattrset(window, A_REVERSE); waddstr(window," Stop "); wattroff(window, A_REVERSE); #endif while(ind_stop==0 && src_offset < src_offset_end) { ssize_t pread_res; int update=0; if(src_offset_end-src_offset < readsize) readsize=src_offset_end-src_offset; pread_res=disk->pread(disk, buffer, readsize, src_offset); if(pread_res > 0) { #if defined(HAVE_PWRITE) if(pwrite(disk_dst, buffer, pread_res, dst_offset)<0) { ind_stop=2; } #else if(lseek(disk_dst, dst_offset, SEEK_SET)<0) { ind_stop=2; } if(write(disk_dst, buffer, pread_res) != pread_res) { ind_stop=2; } #endif if(src_offset_old + SKIP_SIZE==src_offset) { disk_image_backward(disk_dst, disk, src_offset_old, src_offset, dst_offset); } } src_offset_old=src_offset; if((unsigned)pread_res == readsize) { src_offset+=readsize; dst_offset+=readsize; readsize=READ_SIZE; } else { update=1; nbr_read_error++; readsize=disk->sector_size; src_offset+=SKIP_SIZE; dst_offset+=SKIP_SIZE; } if(src_offset>src_offset_next) { update=1; src_offset_next=src_offset+offset_inc; } if(update) { #ifdef HAVE_NCURSES unsigned int i; const float percent=(src_offset-partition->part_offset)*100.00/partition->part_size; wmove(window,7,0); wprintw(window,"%3.2f %% ", percent); for(i=0;i<percent*3/5;i++) wprintw(window,"="); wprintw(window,">"); wrefresh(window); ind_stop=check_enter_key_or_s(window); #endif } } close(disk_dst); #ifdef HAVE_NCURSES delwin(window); (void) clearok(stdscr, TRUE); #ifdef HAVE_TOUCHWIN touchwin(stdscr); #endif #endif if(ind_stop==2) { display_message("No space left for the file image.\n"); free(buffer); return -2; } if(ind_stop) { if(nbr_read_error==0) display_message("Incomplete image created.\n"); else display_message("Incomplete image created: read errors have occured.\n"); free(buffer); return 0; } if(nbr_read_error==0) display_message("Image created successfully.\n"); else display_message("Image created successfully but read errors have occured.\n"); free(buffer); return 0; }
/* Write the Unix file */ static int unix_write(direntry_t *entry, MainParam_t *mp, int needfilter) { Arg_t *arg=(Arg_t *) mp->arg; time_t mtime; Stream_t *File=mp->File; Stream_t *Target, *Source; struct stat stbuf; int ret; char errmsg[80]; char *unixFile; File->Class->get_data(File, &mtime, 0, 0, 0); if (!arg->preserveTime) mtime = 0L; if(arg->type) unixFile = "-"; else unixFile = mpBuildUnixFilename(mp); if(!unixFile) { printOom(); return ERROR_ONE; } /* if we are creating a file, check whether it already exists */ if(!arg->type) { if (!arg->nowarn && &arg->type && !access(unixFile, 0)){ if( ask_confirmation("File \"%s\" exists, overwrite (y/n) ? ", unixFile,0)) { free(unixFile); return ERROR_ONE; } /* sanity checking */ if (!stat(unixFile, &stbuf) && !S_ISREG(stbuf.st_mode)) { fprintf(stderr,"\"%s\" is not a regular file\n", unixFile); free(unixFile); return ERROR_ONE; } } } if(!arg->type && arg->verbose) { fprintf(stderr,"Copying "); mpPrintFilename(stderr,mp); fprintf(stderr,"\n"); } if(got_signal) { free(unixFile); return ERROR_ONE; } if ((Target = SimpleFileOpen(0, 0, unixFile, O_WRONLY | O_CREAT | O_TRUNC, errmsg, 0, 0, 0))) { ret = 0; if(needfilter && arg->textmode){ Source = open_filter(COPY(File)); if (!Source) ret = -1; } else Source = COPY(File); if (ret == 0 ) ret = copyfile(Source, Target); FREE(&Source); FREE(&Target); if(ret <= -1){ if(!arg->type) { unlink(unixFile); free(unixFile); } return ERROR_ONE; } if(!arg->type) { set_mtime(unixFile, mtime); free(unixFile); } return GOT_ONE; } else { fprintf(stderr,"%s\n", errmsg); if(!arg->type) free(unixFile); return ERROR_ONE; } }
int interface_recovery(disk_t *disk_car, const list_part_t * list_part_org, const int verbose, const int dump_ind, const int align, const int ask_part_order, const unsigned int expert, char **current_cmd) { int res_interface_write; int fast_mode=0; do { list_part_t *list_part; const list_part_t *element; unsigned int menu=0; if(fast_mode==0) menu=3; /* Search! */ #ifdef HAVE_NCURSES aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); wmove(stdscr,5,0); #endif res_interface_write=0; list_part=search_part(disk_car, list_part_org, verbose, dump_ind, fast_mode, current_cmd); if(list_part!=NULL && (disk_car->arch==&arch_i386 || disk_car->arch==&arch_sun)) { /* Correct disk geometry is necessary for successfull Intel and Sun partition recovery */ const unsigned int heads_per_cylinder=get_geometry_from_list_part(disk_car, list_part, verbose); if(disk_car->geom.heads_per_cylinder!=heads_per_cylinder) { log_warning("Warning: the current number of heads per cylinder is %u but the correct value may be %u.\n", disk_car->geom.heads_per_cylinder, heads_per_cylinder); #ifdef HAVE_NCURSES if(*current_cmd==NULL) { warning_geometry_ncurses(disk_car, heads_per_cylinder); } #endif } } align_structure(list_part, disk_car, align); disk_car->arch->init_structure(disk_car,list_part,verbose); if(verbose>0) { #ifdef TARGET_LINUX unsigned int i=0; #endif /* Write found partitions in the log file */ log_info("\nResults\n"); for(element=list_part;element!=NULL;element=element->next) log_partition(disk_car,element->part); #ifdef TARGET_LINUX if(list_part!=NULL) log_info("\nHint for advanced users: dmsetup may be used if you prefer to avoid rewriting the partition table for the moment:\n"); for(element=list_part;element!=NULL;element=element->next) { const partition_t *partition=element->part; log_info("echo \"0 %llu linear %s %llu\" | dmsetup create test%u\n", (long long unsigned)(partition->part_size/512), disk_car->device, (long long unsigned)(partition->part_offset/512), i++); } #endif } do { list_part=ask_structure(disk_car,list_part,verbose,current_cmd); } while(fast_mode!=0 && list_part!=NULL && is_structure_empty(list_part) #ifdef HAVE_NCURSES && ask_confirmation("Discard the results, confirm ? (Y/N)")==0 #endif ); if(disk_car->arch->test_structure(list_part)==0) { int do_again=0; int max_ext=0; int can_ask_minmax_ext=0; int no_confirm=0; list_part=reduce_structure(list_part); /* sort list_part */ list_part=sort_partition_list(list_part); /* Create PC/Intel Extended partition */ /* if(disk_car->arch==&arch_i386) */ { list_part_t *parts; uint64_t partext_offset=0; uint64_t partext_size=0; list_part=add_ext_part_i386(disk_car, list_part, !max_ext, verbose); for(parts=list_part;parts!=NULL;parts=parts->next) if(parts->part->status==STATUS_EXT) { partext_offset=parts->part->part_offset; partext_size=parts->part->part_size; } if(partext_offset>0) { list_part=add_ext_part_i386(disk_car, list_part, max_ext, verbose); for(parts=list_part;parts!=NULL;parts=parts->next) if(parts->part->status==STATUS_EXT) { if(partext_offset!=parts->part->part_offset || partext_size!=parts->part->part_size) can_ask_minmax_ext=1; } } } list_part=disk_car->arch->init_part_order(disk_car,list_part); if(ask_part_order!=0) { /* Demande l'ordre des entrees dans le MBR */ #ifdef HAVE_NCURSES ask_mbr_order_i386(disk_car,list_part); #endif /* Demande l'ordre des partitions etendues */ } do { do_again=0; res_interface_write=interface_write(disk_car,list_part,(fast_mode<1),can_ask_minmax_ext, &no_confirm, current_cmd,&menu); switch(res_interface_write) { case 'W': if(disk_car->arch == &arch_mac) { #ifdef HAVE_NCURSES write_part_mac_warning_ncurses(); #endif } else if(disk_car->arch == &arch_sun) { #ifdef HAVE_NCURSES not_implemented("write_part_sun"); #endif } else if(disk_car->arch == &arch_xbox) { #ifdef HAVE_NCURSES not_implemented("write_part_xbox"); #endif } else if(disk_car->arch->write_part!=NULL) { if(no_confirm!=0 #ifdef HAVE_NCURSES || ask_confirmation("Write partition table, confirm ? (Y/N)")!=0 #endif ) { log_info("write!\n"); if(disk_car->arch->write_part(disk_car, list_part, RW, verbose)) { display_message(msg_PART_WR_ERR); } else { use_backup(disk_car,list_part,verbose,dump_ind,expert,current_cmd); if(no_confirm==0) display_message("You will have to reboot for the change to take effect.\n"); } } else log_info("Don't write, no confirmation\n"); } break; case 0: if(disk_car->arch->write_part!=NULL) { log_info("simulate write!\n"); disk_car->arch->write_part(disk_car, list_part, RO, verbose); } break; case 'S': if(fast_mode<2) fast_mode++; break; case 'E': max_ext=!max_ext; list_part=add_ext_part_i386(disk_car, list_part, max_ext, verbose); do_again=1; break; } } while(do_again==1); } else { display_message("Invalid partition structure.\n"); } part_free_list(list_part); } while(res_interface_write=='S'); return 0; }
extern int remove_file(const char *path, int flags) { struct stat path_stat; int path_exists = 1; if (lstat(path, &path_stat) < 0) { if (errno != ENOENT) { perror_msg("unable to stat `%s'", path); return -1; } path_exists = 0; } if (!path_exists) { if (!(flags & FILEUTILS_FORCE)) { perror_msg("cannot remove `%s'", path); return -1; } return 0; } if (S_ISDIR(path_stat.st_mode)) { DIR *dp; struct dirent *d; int status = 0; if (!(flags & FILEUTILS_RECUR)) { error_msg("%s: is a directory", path); return -1; } if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0 && isatty(0)) || (flags & FILEUTILS_INTERACTIVE)) { fprintf(stderr, "%s: descend into directory `%s'? ", applet_name, path); if (!ask_confirmation()) return 0; } if ((dp = opendir(path)) == NULL) { perror_msg("unable to open `%s'", path); return -1; } while ((d = readdir(dp)) != NULL) { char *new_path; if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) continue; new_path = concat_path_file(path, d->d_name); if (remove_file(new_path, flags) < 0) status = -1; free(new_path); } if (closedir(dp) < 0) { perror_msg("unable to close `%s'", path); return -1; } if (flags & FILEUTILS_INTERACTIVE) { fprintf(stderr, "%s: remove directory `%s'? ", applet_name, path); if (!ask_confirmation()) return status; } if (rmdir(path) < 0) { perror_msg("unable to remove `%s'", path); return -1; } return status; } else { if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0 && !S_ISLNK(path_stat.st_mode) && isatty(0)) || (flags & FILEUTILS_INTERACTIVE)) { fprintf(stderr, "%s: remove `%s'? ", applet_name, path); if (!ask_confirmation()) return 0; } if (unlink(path) < 0) { perror_msg("unable to remove `%s'", path); return -1; } return 0; } }
int exFAT_boot_sector(disk_t *disk, partition_t *partition, const int verbose, char **current_cmd) { unsigned char *buffer_bs; unsigned char *buffer_backup_bs; const char *options=""; int rescan=1; #ifdef HAVE_NCURSES struct MenuItem menu_exFAT[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'Q', "Quit","Return to Advanced menu"}, { 'O', "Org. BS","Copy superblock over backup sector"}, { 'B', "Backup BS","Copy backup superblock over superblock"}, { 'D', "Dump","Dump superblock and backup superblock"}, { 0, NULL, NULL } }; #endif buffer_bs=(unsigned char*)MALLOC(12 * disk->sector_size); buffer_backup_bs=(unsigned char*)MALLOC(12 * disk->sector_size); while(1) { #ifdef HAVE_NCURSES unsigned int menu=0; #endif int command; screen_buffer_reset(); if(rescan==1) { int opt_over=0; int opt_B=0; int opt_O=0; options="D"; #ifdef HAVE_NCURSES aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk->description(disk)); mvwaddstr(stdscr,5,0,msg_PART_HEADER_LONG); wmove(stdscr,6,0); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk,partition); #endif log_info("\nexFAT_boot_sector\n"); log_partition(disk,partition); screen_buffer_add("Boot sector\n"); if(disk->pread(disk, buffer_bs, 12 * disk->sector_size, partition->part_offset) != 12 * disk->sector_size) { screen_buffer_add("Bad: can't read exFAT boot record.\n"); memset(buffer_bs,0,12 * disk->sector_size); } else if(test_EXFAT((const struct exfat_super_block*)buffer_bs, partition)==0) { screen_buffer_add("exFAT OK\n"); opt_O=1; opt_over=1; } else screen_buffer_add("Bad\n"); screen_buffer_add("\nBackup boot record\n"); if(disk->pread(disk, buffer_backup_bs, 12 * disk->sector_size, partition->part_offset + 12 * disk->sector_size) != 12 * disk->sector_size) { screen_buffer_add("Bad: can't read exFAT backup boot record.\n"); memset(buffer_backup_bs,0,12 * disk->sector_size); } else if(test_EXFAT((const struct exfat_super_block*)buffer_backup_bs, partition)==0) { screen_buffer_add("exFAT OK\n"); opt_B=1; opt_over=1; } else screen_buffer_add("Bad\n"); screen_buffer_add("\n"); if(memcmp(buffer_bs,buffer_backup_bs,12 * disk->sector_size)==0) { screen_buffer_add("Sectors are identical.\n"); opt_over=0; } else { screen_buffer_add("Sectors are not identical.\n"); } if(opt_over!=0) { if(opt_B!=0 && opt_O!=0) options="DOB"; else if(opt_B!=0) options="DB"; else if(opt_O!=0) options="DO"; } rescan=0; } screen_buffer_to_log(); if(*current_cmd!=NULL) { command=0; while(*current_cmd[0]==',') (*current_cmd)++; if(strncmp(*current_cmd,"dump",4)==0) { (*current_cmd)+=4; command='D'; } else if(strncmp(*current_cmd,"originalexFAT",11)==0) { (*current_cmd)+=11; if(strchr(options,'O')!=NULL) command='O'; } else if(strncmp(*current_cmd,"backupexFAT",9)==0) { (*current_cmd)+=9; if(strchr(options,'B')!=NULL) command='B'; } } else { log_flush(); #ifdef HAVE_NCURSES command=screen_buffer_display_ext(stdscr, options, menu_exFAT, &menu); #else command=0; #endif } switch(command) { case 0: free(buffer_bs); free(buffer_backup_bs); return 0; case 'O': /* O : copy original superblock over backup boot */ #ifdef HAVE_NCURSES if(ask_confirmation("Copy original exFAT boot record over backup, confirm ? (Y/N)")!=0) { log_info("copy original superblock over backup boot\n"); if(disk->pwrite(disk, buffer_bs, 12 * disk->sector_size, partition->part_offset + 12 * disk->sector_size) != 12 * disk->sector_size) { display_message("Write error: Can't overwrite exFAT backup boot record\n"); } disk->sync(disk); rescan=1; } #endif break; case 'B': /* B : copy backup superblock over main superblock */ #ifdef HAVE_NCURSES if(ask_confirmation("Copy backup exFAT boot record over main boot record, confirm ? (Y/N)")!=0) { log_info("copy backup superblock over main superblock\n"); /* Reset information about backup boot record */ partition->sb_offset=0; if(disk->pwrite(disk, buffer_backup_bs, 12 * disk->sector_size, partition->part_offset) != 12 * disk->sector_size) { display_message("Write error: Can't overwrite exFAT main boot record\n"); } disk->sync(disk); rescan=1; } #endif break; case 'D': exFAT_dump(disk, partition, buffer_bs, buffer_backup_bs, current_cmd); break; } } }
int ntfs_boot_sector(disk_t *disk_car, partition_t *partition, const int verbose, const unsigned int expert, char **current_cmd) { unsigned char *buffer_bs; unsigned char *buffer_backup_bs; const char *options=""; #ifdef HAVE_NCURSES struct MenuItem menu_ntfs[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'Q', "Quit","Return to Advanced menu"}, { 'L', "List", "List directories and files, copy data from NTFS" }, { 'O', "Org. BS","Copy boot sector over backup sector"}, { 'B', "Backup BS","Copy backup boot sector over boot sector"}, { 'R', "Rebuild BS","Rebuild boot sector"}, { 'M', "Repair MFT","Check MFT"}, { 'D', "Dump","Dump boot sector and backup boot sector"}, { 0, NULL, NULL } }; #endif buffer_bs=(unsigned char*)MALLOC(NTFS_BOOT_SECTOR_SIZE); buffer_backup_bs=(unsigned char*)MALLOC(NTFS_BOOT_SECTOR_SIZE); while(1) { unsigned int menu=0; int command; screen_buffer_reset(); { int identical_sectors=0; int opt_B=0; int opt_O=0; #ifdef HAVE_NCURSES aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); mvwaddstr(stdscr,5,0,msg_PART_HEADER_LONG); wmove(stdscr,6,0); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition); #endif log_info("\nntfs_boot_sector\n"); log_partition(disk_car,partition); screen_buffer_add("Boot sector\n"); if(disk_car->pread(disk_car, buffer_bs, NTFS_BOOT_SECTOR_SIZE, partition->part_offset) != NTFS_BOOT_SECTOR_SIZE) { screen_buffer_add("ntfs_boot_sector: Can't read boot sector.\n"); memset(buffer_bs,0,NTFS_BOOT_SECTOR_SIZE); } if(test_NTFS(disk_car,(struct ntfs_boot_sector*)buffer_bs,partition,verbose,0)==0) { screen_buffer_add("Status: OK\n"); opt_O=1; } else { screen_buffer_add("Status: Bad\n"); } screen_buffer_add("\nBackup boot sector\n"); if(disk_car->pread(disk_car, buffer_backup_bs, NTFS_BOOT_SECTOR_SIZE, partition->part_offset + partition->part_size - disk_car->sector_size) != NTFS_BOOT_SECTOR_SIZE) { screen_buffer_add("ntfs_boot_sector: Can't read backup boot sector.\n"); memset(buffer_backup_bs,0,NTFS_BOOT_SECTOR_SIZE); } if(test_NTFS(disk_car,(struct ntfs_boot_sector*)buffer_backup_bs,partition,verbose,0)==0) { screen_buffer_add("Status: OK\n"); opt_B=1; } else { screen_buffer_add("Status: Bad\n"); } screen_buffer_add("\n"); if(memcmp(buffer_bs,buffer_backup_bs,NTFS_BOOT_SECTOR_SIZE)==0) { log_ntfs_info((const struct ntfs_boot_sector *)buffer_bs); screen_buffer_add("Sectors are identical.\n"); identical_sectors=1; } else { log_ntfs2_info((const struct ntfs_boot_sector *)buffer_bs, (const struct ntfs_boot_sector *)buffer_backup_bs); screen_buffer_add("Sectors are not identical.\n"); identical_sectors=0; } screen_buffer_add("\n"); screen_buffer_add("A valid NTFS Boot sector must be present in order to access\n"); screen_buffer_add("any data; even if the partition is not bootable.\n"); if(opt_B!=0 && opt_O!=0) { if(identical_sectors==0) options="DOBRL"; else options="DRML"; } else if(opt_B!=0) { menu=5; if(expert>0) options="DBRML"; else options="DBRL"; } else if(opt_O!=0) { menu=4; options="DORL"; } else options="DR"; } screen_buffer_to_log(); if(*current_cmd!=NULL) { command=0; while(*current_cmd[0]==',') (*current_cmd)++; if(strncmp(*current_cmd,"rebuildbs",9)==0) { (*current_cmd)+=9; command='R'; } else if(strncmp(*current_cmd,"dump",4)==0) { (*current_cmd)+=4; command='D'; } else if(strncmp(*current_cmd,"list",4)==0) { (*current_cmd)+=4; command='L'; } else if(strncmp(*current_cmd,"originalntfs",11)==0) { (*current_cmd)+=11; if(strchr(options,'O')!=NULL) command='O'; } else if(strncmp(*current_cmd,"backupntfs",9)==0) { (*current_cmd)+=9; if(strchr(options,'B')!=NULL) command='B'; } else if(strncmp(*current_cmd,"repairmft",9)==0) { (*current_cmd)+=9; if(strchr(options,'M')!=NULL) command='M'; } } else { log_flush(); #ifdef HAVE_NCURSES command=screen_buffer_display_ext(stdscr, options, menu_ntfs, &menu); #else command=0; #endif } switch(command) { case 0: free(buffer_bs); free(buffer_backup_bs); return 0; case 'O': /* O : copy original boot sector over backup boot */ #ifdef HAVE_NCURSES if(ask_confirmation("Copy original NTFS boot sector over backup boot, confirm ? (Y/N)")!=0) { log_info("copy original boot sector over backup boot\n"); if(disk_car->pwrite(disk_car, buffer_bs, NTFS_BOOT_SECTOR_SIZE, partition->part_offset + partition->part_size - disk_car->sector_size) != NTFS_BOOT_SECTOR_SIZE) { display_message("Write error: Can't overwrite NTFS backup boot sector\n"); } disk_car->sync(disk_car); } #endif break; case 'B': /* B : copy backup boot sector over boot sector */ #ifdef HAVE_NCURSES if(ask_confirmation("Copy backup NTFS boot sector over boot sector, confirm ? (Y/N)")!=0) { log_info("copy backup boot sector over boot sector\n"); /* Reset information about backup boot sector */ partition->sb_offset=0; if(disk_car->pwrite(disk_car, buffer_backup_bs, NTFS_BOOT_SECTOR_SIZE, partition->part_offset) != NTFS_BOOT_SECTOR_SIZE) { display_message("Write error: Can't overwrite NTFS boot sector\n"); } disk_car->sync(disk_car); } #endif break; case 'L': if(strchr(options,'O')==NULL && strchr(options,'B')!=NULL) { io_redir_add_redir(disk_car,partition->part_offset,NTFS_BOOT_SECTOR_SIZE,0,buffer_backup_bs); dir_partition(disk_car, partition, 0,current_cmd); io_redir_del_redir(disk_car,partition->part_offset); } else dir_partition(disk_car, partition, 0,current_cmd); break; case 'M': repair_MFT(disk_car, partition, verbose, expert, current_cmd); break; case 'R': /* R : rebuild boot sector */ rebuild_NTFS_BS(disk_car, partition, verbose, 1, expert, current_cmd); break; case 'D': dump_NTFS(disk_car, partition, buffer_bs, buffer_backup_bs); break; } } }