From 9a58a494f354766e1bda5ca0f72e0af60f5124de Mon Sep 17 00:00:00 2001 From: Christophe Grenier Date: Sun, 24 Aug 2008 13:36:34 +0200 Subject: [PATCH] Split the interface in several files Initial work to handle 24 lines and more than 25 --- src/Makefile.am | 2 +- src/adv.c | 251 +++++----- src/chgtype.c | 34 +- src/dir.c | 12 +- src/diskacc.c | 142 ++++++ src/diskacc.h | 23 + src/diskcapa.c | 119 +++++ src/diskcapa.h | 1 + src/diskcp.c | 254 ++++++++++ src/ext2_sb.c | 92 ++++ src/ext2_sb.h | 22 + src/fat_adv.c | 16 +- src/godmode.c | 17 +- src/intrf.c | 63 ++- src/intrf.h | 5 - src/intrface.c | 1241 +---------------------------------------------- src/intrface.h | 6 - src/ntfs_udl.c | 12 +- src/phrecn.c | 76 ++- src/tanalyse.c | 115 +++++ src/tanalyse.h | 23 + src/tdelete.c | 82 ++++ src/tdelete.h | 22 + src/tdiskop.c | 257 ++++++++++ src/tdiskop.h | 23 + src/tdisksel.c | 236 +++++++++ src/tdisksel.h | 24 + src/testdisk.c | 2 + src/tload.c | 254 ++++++++++ src/tload.h | 24 + src/tlog.c | 101 ++++ src/tlog.h | 22 + src/tmbrcode.c | 84 ++++ src/tmbrcode.h | 2 + src/toptions.c | 127 +++++ src/toptions.h | 22 + src/tpartwr.c | 150 ++++++ src/tpartwr.h | 22 + 38 files changed, 2488 insertions(+), 1492 deletions(-) create mode 100644 src/diskacc.c create mode 100644 src/diskacc.h create mode 100644 src/diskcapa.c create mode 100644 src/diskcapa.h create mode 100644 src/diskcp.c create mode 100644 src/ext2_sb.c create mode 100644 src/ext2_sb.h create mode 100644 src/tanalyse.c create mode 100644 src/tanalyse.h create mode 100644 src/tdelete.c create mode 100644 src/tdelete.h create mode 100644 src/tdiskop.c create mode 100644 src/tdiskop.h create mode 100644 src/tdisksel.c create mode 100644 src/tdisksel.h create mode 100644 src/tload.c create mode 100644 src/tload.h create mode 100644 src/tlog.c create mode 100644 src/tlog.h create mode 100644 src/tmbrcode.c create mode 100644 src/tmbrcode.h create mode 100644 src/toptions.c create mode 100644 src/toptions.h create mode 100644 src/tpartwr.c create mode 100644 src/tpartwr.h diff --git a/src/Makefile.am b/src/Makefile.am index 2175249f..9128f75e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -16,7 +16,7 @@ base_H = alignio.h common.h crc.h ewf.h fnctdsk.h hdaccess.h hdwin32.h guid_cm fs_C = analyse.c bfs.c bsd.c cramfs.c fat.c fatx.c ext2.c jfs.c hfs.c hfsp.c luks.c lvm.c md.c netware.c ntfs.c rfs.c savehdr.c sun.c swap.c sysv.c ufs.c xfs.c fs_H = analyse.h bfs.h bsd.h cramfs.h fat.h fatx.h ext2.h jfs_superblock.h jfs.h hfs.h hfsp.h luks.h lvm.h md.h netware.h ntfs.h rfs.h savehdr.h sun.h swap.h sysv.h ufs.h xfs.h -testdisk_SOURCES = testdisk.c $(base_C) $(base_H) $(fs_C) $(fs_H) testdisk.h adv.c adv.h dir.c dir.h dirpart.c dirpart.h edit.c edit.h ext2_dir.c ext2_dir.h ext2_inc.h fat_adv.c fat_adv.h fat_dir.c fat_dir.h geometry.c godmode.c godmode.h intrface.c intrface.h ntfs_adv.c ntfs_dir.c ntfs_dir.h ntfs_fix.c ntfs_inc.h rfs_dir.c rfs_dir.h $(ICON_TESTDISK) next.c next.h dimage.c dimage.h ntfs_udl.c ntfs_udl.h +testdisk_SOURCES = testdisk.c $(base_C) $(base_H) $(fs_C) $(fs_H) testdisk.h adv.c adv.h dir.c dir.h dirpart.c dirpart.h diskacc.c diskacc.h edit.c edit.h ext2_dir.c ext2_dir.h ext2_inc.h ext2_sb.c ext2_sb.h fat_adv.c fat_adv.h fat_dir.c fat_dir.h geometry.c godmode.c godmode.h intrface.c diskcapa.c diskcapa.h intrface.h ntfs_adv.c ntfs_dir.c ntfs_dir.h ntfs_fix.c ntfs_inc.h rfs_dir.c rfs_dir.h $(ICON_TESTDISK) next.c next.h dimage.c dimage.h ntfs_udl.c ntfs_udl.h tanalyse.c tanalyse.h tdelete.c tdelete.h tdisksel.c tdisksel.h tdiskop.c tdiskop.h tload.c tload.h tlog.c tlog.h tmbrcode.c tmbrcode.h toptions.c toptions.h tpartwr.c tpartwr.h photorec_SOURCES = photorec.c photorec.h phcfg.c phcfg.h phrecn.c phrecn.h dir.c dir.h ext2grp.c ext2grp.h ext2p.c ext2p.h ext2_dir.c ext2_dir.h ext2_inc.h fat_dir.c fat_dir.h fatp.c fatp.h filegen.c filegen.h file_7z.c file_a.c file_ab.c file_ace.c file_ahn.c file_aif.c file_all.c file_als.c file_amd.c file_amr.c file_arj.c file_asf.c file_asm.c file_au.c file_bkf.c file_bld.c file_bmp.c file_bz2.c file_cab.c file_cam.c file_chm.c file_cm.c file_compress.c file_crw.c file_ctg.c file_cwk.c file_dat.c file_dbf.c file_dim.c file_dir.c file_djv.c file_doc.c file_dpx.c file_drw.c file_ds2.c file_dsc.c file_dss.c file_dta.c file_dump.c file_dv.c file_dwg.c file_elf.c file_emf.c file_evt.c file_exe.c pe.h file_ext.c file_fcp.c file_fcs.c file_fbk.c file_fdb.c file_fh10.c file_fh5.c file_fits.c file_flac.c file_flv.c file_fob.c file_frm.c file_fs.c file_gho.c file_gif.c file_gpg.c file_gz.c file_ifo.c file_imb.c file_indd.c file_iso.c file_itu.c file_jpg.c file_jpg.h file_kdb.c file_lnk.c file_m2ts.c file_max.c file_mb.c file_mcd.c file_mdb.c file_mdf.c file_mfg.c file_mid.c file_mkv.c file_mov.c file_mp3.c file_mpg.c file_mrw.c file_mus.c file_mysql.c file_njx.c file_ogg.c file_one.c file_orf.c file_paf.c file_pap.c file_pcap.c file_pct.c file_pcx.c file_pdf.c file_pfx.c file_png.c file_prc.c file_prt.c file_ps.c file_psd.c file_psp.c file_pst.c file_ptb.c file_qbb.c file_qdf.c file_qxd.c file_ra.c file_raf.c file_rar.c file_raw.c file_rdc.c file_reg.c file_res.c file_riff.c file_rm.c file_rns.c file_rpm.c file_sib.c file_sit.c file_skp.c file_spe.c file_spss.c file_sql.c file_stl.c file_stu.c file_swf.c file_tar.c file_tar.h file_tib.c file_tiff.c file_tph.c file_txt.c file_veg.c file_vmdk.c file_wks.c file_wmf.c file_wnk.c file_wpd.c file_x3f.c file_xcf.c file_xm.c file_xsv.c file_zip.c memmem.h geometry.c list.c list.h ole.h ntfs_dir.c ntfs_dir.h ntfsp.c ntfsp.h ntfs_inc.h sessionp.c sessionp.h $(base_C) $(base_H) $(fs_C) $(fs_H) $(ICON_PHOTOREC) diff --git a/src/adv.c b/src/adv.c index 64a8876b..0f9dcaad 100644 --- a/src/adv.c +++ b/src/adv.c @@ -46,13 +46,13 @@ #include "hfsp.h" #include "adv.h" #include "analyse.h" -#include "intrface.h" #include "io_redir.h" #include "log.h" #include "guid_cmp.h" #include "dimage.h" #include "fat_adv.h" #include "ntfs_udl.h" +#include "ext2_sb.h" extern const arch_fnct_t arch_gpt; extern const arch_fnct_t arch_i386; @@ -357,32 +357,6 @@ void interface_adv(disk_t *disk_car, const int verbose,const int dump_ind, const } switch(command) { -#ifdef HAVE_NCURSES - case KEY_UP: - if(current_element!=NULL) - { - if(current_element->prev!=NULL) - { - current_element=current_element->prev; - current_element_num--; - } - if(current_element_numnext!=NULL) - { - current_element=current_element->next; - current_element_num++; - } - if(current_element_num>=offset+INTER_ADV) - offset++; - } - break; -#endif case 'q': case 'Q': quit=1; @@ -396,104 +370,141 @@ void interface_adv(disk_t *disk_car, const int verbose,const int dump_ind, const rewrite=1; } break; - case 'b': - case 'B': - if(current_element!=NULL) - { - partition_t *partition=current_element->part; - if(is_part_fat32(partition)) + } + if(current_element!=NULL) + { + switch(command) + { +#ifdef HAVE_NCURSES + case 'p': + case 'P': + case KEY_UP: + if(current_element->prev!=NULL) { - fat32_boot_sector(disk_car, partition, verbose, dump_ind, expert,current_cmd); + current_element=current_element->prev; + current_element_num--; + } + break; + case 'n': + case 'N': + case KEY_DOWN: + if(current_element->next!=NULL) + { + current_element=current_element->next; + current_element_num++; + } + break; + case KEY_PPAGE: + for(i=0;iprev!=NULL;i++) + { + current_element=current_element->prev; + current_element_num--; + } + break; + case KEY_NPAGE: + for(i=0;inext!=NULL;i++) + { + current_element=current_element->next; + current_element_num++; + } + break; +#endif + case 'b': + case 'B': + { + partition_t *partition=current_element->part; + if(is_part_fat32(partition)) + { + fat32_boot_sector(disk_car, partition, verbose, dump_ind, expert,current_cmd); + rewrite=1; + } + else if(is_part_fat12(partition) || is_part_fat16(partition)) + { + fat1x_boot_sector(disk_car, partition, verbose, dump_ind,expert,current_cmd); + rewrite=1; + } + else if(is_part_ntfs(partition)) + { + ntfs_boot_sector(disk_car, partition, verbose, dump_ind, expert, current_cmd); + rewrite=1; + } + else if(partition->upart_type==UP_FAT32) + { + fat32_boot_sector(disk_car, partition, verbose, dump_ind, expert,current_cmd); + rewrite=1; + } + else if(partition->upart_type==UP_FAT12 || partition->upart_type==UP_FAT16) + { + fat1x_boot_sector(disk_car, partition, verbose, dump_ind,expert,current_cmd); + rewrite=1; + } + else if(partition->upart_type==UP_NTFS) + { + ntfs_boot_sector(disk_car, partition, verbose, dump_ind, expert, current_cmd); + rewrite=1; + } + } + break; + case 'c': + case 'C': + { + char *image_dd; + menu=0; + image_dd=ask_location("Do you want to save disk file image.dd in %s%s ? [Y/N]",""); + if(image_dd!=NULL) + { + char *new_recup_dir=(char *)MALLOC(strlen(image_dd)+1+strlen(DEFAULT_IMAGE_NAME)+1); + strcpy(new_recup_dir,image_dd); + strcat(new_recup_dir,"/"); + strcat(new_recup_dir,DEFAULT_IMAGE_NAME); + free(image_dd); + image_dd=new_recup_dir; + } + if(image_dd!=NULL) + { + disk_image(disk_car, current_element->part, image_dd); + free(image_dd); + } + } + break; + case 'u': + case 'U': + case 'l': + case 'L': + { + partition_t *partition=current_element->part; + if(partition->upart_type==UP_NTFS) + ntfs_undelete_part(disk_car, partition, verbose, current_cmd); + else + dir_partition(disk_car, partition, 0, current_cmd); + } + break; + case 's': + case 'S': + { + if(is_linux(current_element->part)) + { + list_part_t *list_sb=search_superblock(disk_car,current_element->part,verbose,dump_ind,1); + interface_superblock(disk_car,list_sb,current_cmd); + part_free_list(list_sb); + } + if(is_hfs(current_element->part) || is_hfsp(current_element->part)) + { + HFS_HFSP_boot_sector(disk_car, current_element->part, verbose, dump_ind, expert, current_cmd); + } rewrite=1; } - else if(is_part_fat12(partition) || is_part_fat16(partition)) - { - fat1x_boot_sector(disk_car, partition, verbose, dump_ind,expert,current_cmd); - rewrite=1; - } - else if(is_part_ntfs(partition)) - { - ntfs_boot_sector(disk_car, partition, verbose, dump_ind, expert, current_cmd); - rewrite=1; - } - else if(partition->upart_type==UP_FAT32) - { - fat32_boot_sector(disk_car, partition, verbose, dump_ind, expert,current_cmd); - rewrite=1; - } - else if(partition->upart_type==UP_FAT12 || partition->upart_type==UP_FAT16) - { - fat1x_boot_sector(disk_car, partition, verbose, dump_ind,expert,current_cmd); - rewrite=1; - } - else if(partition->upart_type==UP_NTFS) - { - ntfs_boot_sector(disk_car, partition, verbose, dump_ind, expert, current_cmd); - rewrite=1; - } - } - break; - case 'c': - case 'C': - if(current_element!=NULL) - { - char *image_dd; - menu=0; - image_dd=ask_location("Do you want to save disk file image.dd in %s%s ? [Y/N]",""); - if(image_dd!=NULL) - { - char *new_recup_dir=(char *)MALLOC(strlen(image_dd)+1+strlen(DEFAULT_IMAGE_NAME)+1); - strcpy(new_recup_dir,image_dd); - strcat(new_recup_dir,"/"); - strcat(new_recup_dir,DEFAULT_IMAGE_NAME); - free(image_dd); - image_dd=new_recup_dir; - } - if(image_dd!=NULL) - { - disk_image(disk_car, current_element->part, image_dd); - free(image_dd); - } - } - break; - case 'u': - case 'U': - case 'l': - case 'L': - if(current_element!=NULL) - { - partition_t *partition=current_element->part; - if(partition->upart_type==UP_NTFS) - ntfs_undelete_part(disk_car, partition, verbose, current_cmd); - else - dir_partition(disk_car, partition, 0, current_cmd); - } - break; - case 's': - case 'S': - if(current_element!=NULL) - { - if(is_linux(current_element->part)) - { - list_part_t *list_sb=search_superblock(disk_car,current_element->part,verbose,dump_ind,1); - interface_superblock(disk_car,list_sb,current_cmd); - part_free_list(list_sb); - } - if(is_hfs(current_element->part) || is_hfsp(current_element->part)) - { - HFS_HFSP_boot_sector(disk_car, current_element->part, verbose, dump_ind, expert, current_cmd); - } - rewrite=1; - } - break; - case 't': - case 'T': - if(current_element!=NULL) - { + break; + case 't': + case 'T': change_part_type(disk_car,current_element->part, current_cmd); rewrite=1; - } - break; + break; + } + if(current_element_num=offset+INTER_ADV) + offset=current_element_num-INTER_ADV+1; } } while(quit==0); part_free_list(list_part); diff --git a/src/chgtype.c b/src/chgtype.c index a1e8658b..4e6346e5 100644 --- a/src/chgtype.c +++ b/src/chgtype.c @@ -120,7 +120,7 @@ static void change_part_type_ncurses(const disk_t *disk_car,partition_t *partiti wmove(stdscr,4,0); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition); screen_buffer_display(stdscr,"",menuType); - wmove(stdscr,23,0); + wmove(stdscr,LINES-2,0); wprintw(stdscr,"New partition type [current %02x] ? ",partition->arch->get_part_type(partition)); if (get_string(response, sizeof(response), NULL) > 0) { int tmp_val = strtol(response, NULL, 16); @@ -208,48 +208,36 @@ static void change_part_type_ncurses2(const disk_t *disk_car, partition_t *parti case KEY_UP: if(current_element_num>0) current_element_num--; - if(current_element_num= offset+3*INTER_CHGTYPE) - offset++; break; case KEY_LEFT: if(current_element_num > INTER_CHGTYPE) current_element_num-=INTER_CHGTYPE; else current_element_num=0; - if(current_element_num < offset) - offset=current_element_num; break; case KEY_PPAGE: if(current_element_num > 3*INTER_CHGTYPE-1) current_element_num-=3*INTER_CHGTYPE-1; else current_element_num=0; - if(current_element_num < offset) - offset=current_element_num; break; case KEY_RIGHT: if(current_element_num+INTER_CHGTYPE < intr_nbr_line-1) current_element_num+=INTER_CHGTYPE; else current_element_num=intr_nbr_line-1; - if(current_element_num >= offset+3*INTER_CHGTYPE) - offset=current_element_num-3*INTER_CHGTYPE+1; break; case KEY_NPAGE: if(current_element_num+3*INTER_CHGTYPE-1 < intr_nbr_line-1) current_element_num+=3*INTER_CHGTYPE-1; else current_element_num=intr_nbr_line-1; - if(current_element_num >= offset+3*INTER_CHGTYPE) - offset=current_element_num-3*INTER_CHGTYPE+1; break; case 'Q': case 'q': @@ -260,6 +248,10 @@ static void change_part_type_ncurses2(const disk_t *disk_car, partition_t *parti partition->arch->set_part_type(partition, part_name[current_element_num].index); return; } + if(current_element_num < offset) + offset=current_element_num; + if(current_element_num >= offset+3*INTER_CHGTYPE) + offset=current_element_num-3*INTER_CHGTYPE+1; } } @@ -329,40 +321,30 @@ static void gpt_change_part_type(const disk_t *disk_car, partition_t *partition) case KEY_UP: if(current_element_num>0) current_element_num--; - if(current_element_num= offset+3*INTER_CHGTYPE) - offset++; break; case KEY_LEFT: if(current_element_num > INTER_CHGTYPE) current_element_num-=INTER_CHGTYPE; else current_element_num=0; - if(current_element_num < offset) - offset=current_element_num; break; case KEY_PPAGE: if(current_element_num > 3*INTER_CHGTYPE-1) current_element_num-=3*INTER_CHGTYPE-1; else current_element_num=0; - if(current_element_num < offset) - offset=current_element_num; break; case KEY_RIGHT: for(j=0;j= offset+3*INTER_CHGTYPE) - offset++; } break; case KEY_NPAGE: @@ -370,8 +352,6 @@ static void gpt_change_part_type(const disk_t *disk_car, partition_t *partition) { if(gpt_sys_types[current_element_num].name!=NULL && gpt_sys_types[current_element_num+1].name!=NULL) current_element_num++; - if(current_element_num >= offset+3*INTER_CHGTYPE) - offset++; } break; case 'Q': @@ -383,6 +363,10 @@ static void gpt_change_part_type(const disk_t *disk_car, partition_t *partition) guid_cpy(&partition->part_type_gpt, &gpt_sys_types[current_element_num].part_type); return; } + if(current_element_num= offset+3*INTER_CHGTYPE) + offset=current_element_num-3*INTER_CHGTYPE+1; } } #endif diff --git a/src/dir.c b/src/dir.c index ae939730..00f5911d 100644 --- a/src/dir.c +++ b/src/dir.c @@ -413,8 +413,6 @@ static long int dir_aff_ncurses(disk_t *disk_car, const partition_t *partition, pos=pos->prev; pos_num--; } - if(pos_numnext; pos_num++; } - if(pos_num>=offset+INTER_DIR) - offset++; break; case 'p': case 'P': @@ -460,8 +456,6 @@ static long int dir_aff_ncurses(disk_t *disk_car, const partition_t *partition, { pos=pos->prev; pos_num--; - if(pos_numnext; pos_num++; - if(pos_num>=offset+INTER_DIR) - offset++; } break; case 'c': @@ -538,6 +530,10 @@ static long int dir_aff_ncurses(disk_t *disk_car, const partition_t *partition, } break; } + if(pos_num=offset+INTER_DIR) + offset=pos_num-INTER_DIR+1; } } while(quit==0 && old_LINES==LINES); } while(quit==0); diff --git a/src/diskacc.c b/src/diskacc.c new file mode 100644 index 00000000..90b70881 --- /dev/null +++ b/src/diskacc.c @@ -0,0 +1,142 @@ +/* + + File: diskacc.c + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#include "types.h" +#include "common.h" +#include "lang.h" +#include "intrf.h" +#ifdef HAVE_NCURSES +#include "intrfn.h" +#else +#include +#endif +#include "intrface.h" +#include "godmode.h" +#include "fnctdsk.h" +#include "testdisk.h" +#include "adv.h" +#include "analyse.h" +#include "chgtype.h" +#include "edit.h" +#include "savehdr.h" +#include "dirpart.h" +#include "fat.h" +#include "partauto.h" +#include "log.h" +#include "guid_cmp.h" +#include "hdaccess.h" +#include "io_redir.h" +#include "diskacc.h" + +#ifdef HAVE_NCURSES +static int interface_check_disk_access_ncurses(disk_t *disk_car) +{ + static const struct MenuItem menuDiskAccess[]= + { + { 'C', "Continue", "Continue even if write access isn't available"}, + { 'Q', "Quit", "Return to disk selection"}, + { 0,NULL,NULL} + }; + unsigned int menu=0; + int car; + int line=9; + aff_copy(stdscr); + wmove(stdscr,4,0); + wprintw(stdscr,"%s\n",disk_car->description_short(disk_car)); + wmove(stdscr,6,0); + wprintw(stdscr,"Write access for this media is not available."); + wmove(stdscr,7,0); + wprintw(stdscr,"TestDisk won't be able to modify it."); +#ifdef DJGPP +#elif defined(__CYGWIN__) || defined(__MINGW32__) + wmove(stdscr,line++,0); + wprintw(stdscr,"- You may need to be administrator to have write access.\n"); + wmove(stdscr,line++,0); + wprintw(stdscr,"Under Vista, select TestDisk, right-click and choose \"Run as administrator\".\n"); +#elif defined HAVE_GETEUID + if(geteuid()!=0) + { + wmove(stdscr,line++,0); + wprintw(stdscr,"- You may need to be root to have write access.\n"); +#if defined(__APPLE__) + wmove(stdscr,line++,0); + wprintw(stdscr,"Use the sudo command to launch TestDisk.\n"); +#endif + wmove(stdscr,line++,0); + wprintw(stdscr,"- Check the OS permission for this file or device.\n"); + } +#endif +#if defined(__APPLE__) + wmove(stdscr,line++,0); + wprintw(stdscr,"- No partition from this disk must be mounted:\n"); + wmove(stdscr,line++,0); + wprintw(stdscr,"Open the Disk Utility (In Finder -> Application -> Utility folder)\n"); + wmove(stdscr,line++,0); + wprintw(stdscr,"and press Umount button for each volume from this disk\n"); +#endif + wmove(stdscr,line++,0); + wprintw(stdscr,"- This media may be physically write-protected, check the jumpers.\n"); + car= wmenuSelect_ext(stdscr, 24, INTER_MAIN_Y, INTER_MAIN_X, menuDiskAccess, 10, + "CQ", MENU_VERT | MENU_VERT_WARN | MENU_BUTTON, &menu,NULL); + if(car=='c' || car=='C') + return 0; + return 1; +} +#endif + +int interface_check_disk_access(disk_t *disk_car, char **current_cmd) +{ + if((disk_car->access_mode&TESTDISK_O_RDWR)==TESTDISK_O_RDWR) + return 0; + if(*current_cmd!=NULL) + return 0; + log_warning("Media is opened in read-only.\n"); + log_flush(); +#ifdef HAVE_NCURSES + return interface_check_disk_access_ncurses(disk_car); +#else + return 0; +#endif +} diff --git a/src/diskacc.h b/src/diskacc.h new file mode 100644 index 00000000..94bd5ff6 --- /dev/null +++ b/src/diskacc.h @@ -0,0 +1,23 @@ +/* + + File: diskacc.h + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ + +int interface_check_disk_access(disk_t *disk_car, char **current_cmd); diff --git a/src/diskcapa.c b/src/diskcapa.c new file mode 100644 index 00000000..7d020481 --- /dev/null +++ b/src/diskcapa.c @@ -0,0 +1,119 @@ +/* + + File: diskcapa.c + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#include "types.h" +#include "common.h" +#include "lang.h" +#include "intrf.h" +#ifdef HAVE_NCURSES +#include "intrfn.h" +#else +#include +#endif +#include "intrface.h" +#include "godmode.h" +#include "fnctdsk.h" +#include "testdisk.h" +#include "adv.h" +#include "analyse.h" +#include "chgtype.h" +#include "edit.h" +#include "savehdr.h" +#include "dirpart.h" +#include "fat.h" +#include "partauto.h" +#include "log.h" +#include "guid_cmp.h" +#include "hdaccess.h" +#include "io_redir.h" + +#include "diskcapa.h" + +#ifdef HAVE_NCURSES +static int interface_check_disk_capacity_ncurses(disk_t *disk_car) +{ + static const struct MenuItem menuMain[]= + { + { 'C', "Continue","The HD is really 137 GB only."}, + { 'Q',"Quit","The HD is bigger, it's safer to enable LBA48 support first."}, + { 0,NULL,NULL} + }; + unsigned int menu=1; + int car; + aff_copy(stdscr); + wmove(stdscr,4,0); + wprintw(stdscr,"%s\n",disk_car->description(disk_car)); + wmove(stdscr,6,0); + wprintw(stdscr,"The Harddisk size seems to be 137GB."); + wmove(stdscr,7,0); + wprintw(stdscr,"Support for 48-bit Logical Block Addressing (LBA) is needed to access"); + wmove(stdscr,8,0); + wprintw(stdscr,"hard disks larger than 137 GB."); + wmove(stdscr,9,0); +#if defined(__CYGWIN__) || defined(__MINGW32__) + wprintw(stdscr,"Update Windows to support LBA48 (minimum: W2K SP4 or XP SP1)"); +#endif + car= wmenuSelect_ext(stdscr, 24, INTER_MAIN_Y, INTER_MAIN_X, menuMain, 10, + "CQ", MENU_VERT | MENU_VERT_WARN | MENU_BUTTON, &menu,NULL); + if(car=='c' || car=='C') + return 0; + return 1; +} +#endif + +int interface_check_disk_capacity(disk_t *disk_car) +{ + /* Test for LBA28 limitation */ + if(disk_car->geom.sectors_per_head>0 && + disk_car->geom.cylinders == (((1<<28)-1) / disk_car->geom.heads_per_cylinder / disk_car->geom.sectors_per_head)) + { + log_warning("LBA28 limitation\n"); + log_flush(); +#ifdef HAVE_NCURSES + return interface_check_disk_capacity_ncurses(disk_car); +#endif + } + return 0; +} diff --git a/src/diskcapa.h b/src/diskcapa.h new file mode 100644 index 00000000..2c51749d --- /dev/null +++ b/src/diskcapa.h @@ -0,0 +1 @@ +int interface_check_disk_capacity(disk_t *disk_car); diff --git a/src/diskcp.c b/src/diskcp.c new file mode 100644 index 00000000..fcae555f --- /dev/null +++ b/src/diskcp.c @@ -0,0 +1,254 @@ +/* + + File: diskcp.c + + Copyright (C) 2007 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include /* BLKFLSBUF */ +#endif +#ifdef HAVE_SYS_DISK_H +#include +#endif +#include "types.h" +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +enum { STATUS_NON_TRIED = '?', STATUS_NON_SPLIT = '/', STATUS_BAD_BLOCK = '-', STATUS_DONE = '+' }; + +const char *size_to_unit(uint64_t disk_size, char *buffer) +{ + if(disk_size<(uint64_t)10*1024) + sprintf(buffer,"%u B", (unsigned)disk_size); + else if(disk_size<(uint64_t)10*1024*1024) + sprintf(buffer,"%u KB / %u KiB", (unsigned)(disk_size/1000), (unsigned)(disk_size/1024)); + else if(disk_size<(uint64_t)10*1024*1024*1024) + sprintf(buffer,"%u MB / %u MiB", (unsigned)(disk_size/1000/1000), (unsigned)(disk_size/1024/1024)); + else if(disk_size<(uint64_t)10*1024*1024*1024*1024) + sprintf(buffer,"%u GB / %u GiB", (unsigned)(disk_size/1000/1000/1000), (unsigned)(disk_size/1024/1024/1024)); + else + sprintf(buffer,"%u TB / %u TiB", (unsigned)(disk_size/1000/1000/1000/1000), (unsigned)(disk_size/1024/1024/1024/1024)); + return buffer; +} + +int main(int argc, char **argv) +{ + int i; + int readsize; + int readsize_min; + int readsize_max; + int first_disk_readsize; + uint64_t readok=0; + uint64_t location; + uint64_t old_status_location=0; + int old_status=STATUS_DONE; + int sector_size=512; + int current_disk=0; + int first_disk; + int nbr_disk=0; + int disk_src[1]; + int disk_dst; + FILE *log; + char *buffer; + uint64_t disk_size=0; + int gap=-1; + if(argc<=2) + { + printf("disk_cp src dst\n"); + return 1; + } + /* O_DIRECT ? */ + if((disk_src[nbr_disk++]=open(argv[1],O_LARGEFILE|O_RDONLY|O_BINARY))<0) + { + printf("Can't open file %s\n",argv[1]); + return 1; + } + if((disk_dst=open(argv[2],O_LARGEFILE|O_RDWR|O_BINARY|O_CREAT,0644))<0) + { + printf("Can't open file %s\n",argv[2]); + return 1; + } + { + void *res; + uint64_t longsectors64=0; + if (ioctl(disk_src[0], BLKGETSIZE64, &longsectors64)>=0) + { + disk_size=longsectors64; + } + readsize_min=sector_size; + /* 1,2,4,8,16,32 */ + readsize_max=16*sector_size; + readsize=readsize_min; + first_disk=current_disk; + first_disk_readsize=readsize; + if(posix_memalign(&res,4096,readsize_max)!=0) + { + printf("posix_memalign failed\n"); + return 1; + } + buffer=res; + } + if(1==2) + { + if((log=fopen("diskcp.log","w"))==NULL) + { + printf("Can't create diskcp.log file\n"); + return 1; + } + /* It may be possible to improve the speed by using readv, a ttl (or a timestamp) may be used for bad disks */ + for(location=0;location=start[nbr];location-=readsize_min) + { + + } + } + } + } + fclose(log); + fclose(oldlog); + } + + /* Pass 3: read */ + for(i=0;i + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif +#include "types.h" +#include "common.h" +#include "lang.h" +#include "intrf.h" +#ifdef HAVE_NCURSES +#include "intrfn.h" +#else +#include +#endif +#include "log.h" +#include "guid_cmp.h" +#include "ext2_sb.h" + +int interface_superblock(disk_t *disk_car,list_part_t *list_part, char**current_cmd) +{ + const list_part_t *parts; + const partition_t *old_part=NULL; +#ifdef HAVE_NCURSES + struct MenuItem menuSuperblock[]= + { + { 'P', "Previous",""}, + { 'N', "Next","" }, + { 'Q',"Quit","Return to Advanced menu"}, + { 0, NULL, NULL } + }; +#endif + screen_buffer_reset(); +#ifdef HAVE_NCURSES + aff_copy(stdscr); + wmove(stdscr,4,0); + wprintw(stdscr,"%s",disk_car->description(disk_car)); + wmove(stdscr,5,0); + mvwaddstr(stdscr,6,0,msg_PART_HEADER_LONG); +#endif + for(parts=list_part;parts!=NULL;parts=parts->next) + { + const partition_t *partition=parts->part; + if(old_part==NULL || + old_part->part_offset!=partition->part_offset || + old_part->part_size!=partition->part_size || + guid_cmp(old_part->part_type_gpt, partition->part_type_gpt)!=0 || + old_part->part_type_i386!=partition->part_type_i386 || + old_part->part_type_sun!=partition->part_type_sun || + old_part->part_type_mac!=partition->part_type_mac || + old_part->upart_type!=partition->upart_type) + { + aff_part_buffer(AFF_PART_BASE, disk_car, partition); + old_part=partition; + } + if(partition->blocksize!=0) + screen_buffer_add("superblock %lu, blocksize=%u\n", + (long unsigned)(partition->sb_offset/partition->blocksize), + partition->blocksize); + } + screen_buffer_to_log(); + if(*current_cmd==NULL) + { + log_flush(); +#ifdef HAVE_NCURSES + screen_buffer_display(stdscr,"",menuSuperblock); +#endif + } + return 0; +} diff --git a/src/ext2_sb.h b/src/ext2_sb.h new file mode 100644 index 00000000..0c84a67c --- /dev/null +++ b/src/ext2_sb.h @@ -0,0 +1,22 @@ +/* + + File: ext2_sb.h + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +int interface_superblock(disk_t *disk_car,list_part_t *list_part,char**current_cmd); diff --git a/src/fat_adv.c b/src/fat_adv.c index 2b22732d..6135feac 100644 --- a/src/fat_adv.c +++ b/src/fat_adv.c @@ -274,8 +274,6 @@ static int ask_root_directory(disk_t *disk_car, const partition_t *partition, co pos=pos->prev; pos_num--; } - if(pos_numnext!=NULL) @@ -283,28 +281,26 @@ static int ask_root_directory(disk_t *disk_car, const partition_t *partition, co pos=pos->next; pos_num++; } - if(pos_num>=offset+INTER_DIR) - offset++; break; case KEY_PPAGE: - for(i=0;(iprev!=NULL);i++) + for(i=0; iprev!=NULL; i++) { pos=pos->prev; pos_num--; - if(pos_numnext!=NULL);i++) + for(i=0; inext!=NULL; i++) { pos=pos->next; pos_num++; - if(pos_num>=offset+INTER_DIR) - offset++; } break; } + if(pos_num=offset+INTER_DIR) + offset=pos_num-INTER_DIR+1; } } while(quit==0); curs_set(0); diff --git a/src/godmode.c b/src/godmode.c index cf79897e..74960d4a 100644 --- a/src/godmode.c +++ b/src/godmode.c @@ -46,6 +46,7 @@ #include "adv.h" #include "ntfs.h" #include "next.h" +#include "tpartwr.h" #include "log.h" #define RO 1 @@ -209,8 +210,6 @@ static int interface_part_bad_ncurses(disk_t *disk_car, list_part_t *list_part) pos=pos->prev; pos_num--; } - if(pos_numnext; pos_num++; } - if(pos_num>=offset+INTER_BAD_PART) - offset++; } break; case KEY_PPAGE: if(list_part!=NULL) { - for(i=0;(iprev!=NULL);i++) + for(i=0; iprev!=NULL; i++) { pos=pos->prev; pos_num--; - if(pos_numnext!=NULL);i++) + for(i=0; inext!=NULL; i++) { pos=pos->next; pos_num++; - if(pos_num>=offset+INTER_BAD_PART) - offset++; } } break; default: break; } + if(pos_num=offset+INTER_BAD_PART) + offset=pos_num-INTER_BAD_PART+1; } while(quit==0); return 0; } diff --git a/src/intrf.c b/src/intrf.c index 720e5145..25fb1c28 100644 --- a/src/intrf.c +++ b/src/intrf.c @@ -965,6 +965,11 @@ int screen_buffer_display(WINDOW *window, const char *options_org, const struct return screen_buffer_display_ext(window,options_org,menuItems,&menu); } +#define INTER_ANALYSE_X 0 +#define INTER_ANALYSE_Y 8 +#define INTER_ANALYSE_MENU_X 0 +#define INTER_ANALYSE_MENU_Y (LINES-2) +#define INTER_MAX_LINES (INTER_ANALYSE_MENU_Y-INTER_ANALYSE_Y-2) int screen_buffer_display_ext(WINDOW *window, const char *options_org, const struct MenuItem *menuItems, unsigned int *menu) { int i; @@ -993,22 +998,36 @@ int screen_buffer_display_ext(WINDOW *window, const char *options_org, const str wclrtoeol(window); if(first_line_to_display>0) wprintw(window, "Previous"); - for (i=first_line_to_display; (iINTER_MAX_LINES && has_colors()) { - wmove(window,INTER_ANALYSE_Y+i-first_line_to_display,INTER_ANALYSE_X); - wclrtoeol(window); - if(i==current_line && intr_nbr_line>INTER_MAX_LINES && has_colors()) - wattrset(window, A_REVERSE); - wprintw(window,"%s",intr_buffer_screen[i]); - if(i==current_line && intr_nbr_line>INTER_MAX_LINES && has_colors()) - wattroff(window, A_REVERSE); + for (i=first_line_to_display; i0) current_line--; - if(current_line=first_line_to_display+INTER_MAX_LINES) - first_line_to_display=current_line-INTER_MAX_LINES+1; break; case KEY_PPAGE: if(current_line>INTER_MAX_LINES-1) current_line-=INTER_MAX_LINES-1; else current_line=0; - if(current_line=first_line_to_display+INTER_MAX_LINES) - first_line_to_display=current_line-INTER_MAX_LINES+1; break; default: if(strchr(options,toupper(key))!=NULL) return toupper(key); break; } + if(current_line=first_line_to_display+INTER_MAX_LINES) + first_line_to_display=current_line-INTER_MAX_LINES+1; } while(done!=TRUE); return 0; } @@ -1722,8 +1737,6 @@ char *ask_location(const char*msg, const char *src_dir) { current_file=current_file->prev; pos_num--; - if(pos_numnext; pos_num++; - if(pos_num>=offset+INTER_DIR) - offset++; quit=ASK_LOCATION_UPDATE; } break; @@ -1745,8 +1756,6 @@ char *ask_location(const char*msg, const char *src_dir) { current_file=current_file->prev; pos_num--; - if(pos_numnext; pos_num++; - if(pos_num>=offset+INTER_DIR) - offset++; quit=ASK_LOCATION_UPDATE; } } @@ -1808,6 +1815,10 @@ char *ask_location(const char*msg, const char *src_dir) break; } + if(pos_num=offset+INTER_DIR) + offset=pos_num-INTER_DIR+1; } while(quit==ASK_LOCATION_WAITKEY && old_LINES==LINES); } while(quit==ASK_LOCATION_UPDATE || old_LINES!=LINES); delete_list_file_info(&dir_list.list); diff --git a/src/intrf.h b/src/intrf.h index a5c090dc..1a5a7a5a 100644 --- a/src/intrf.h +++ b/src/intrf.h @@ -38,11 +38,6 @@ struct MenuItem #define DUMP_MAX_LINES 14 #define INTER_DUMP_X DUMP_X #define INTER_DUMP_Y DUMP_Y+DUMP_MAX_LINES+1 -#define INTER_ANALYSE_X 0 -#define INTER_ANALYSE_Y 8 -#define INTER_MAX_LINES 13 -#define INTER_ANALYSE_MENU_X 0 -#define INTER_ANALYSE_MENU_Y 23 #define INTER_OPTION_X 0 #define INTER_OPTION_Y 10 #define INTER_PARTITION_X 0 diff --git a/src/intrface.c b/src/intrface.c index 458e9907..0867860e 100644 --- a/src/intrface.c +++ b/src/intrface.c @@ -2,7 +2,7 @@ File: intrface.c - Copyright (C) 1998-2007 Christophe GRENIER + Copyright (C) 1998-2008 Christophe GRENIER This software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,26 +23,9 @@ #include #endif -#include -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif #ifdef HAVE_STRING_H #include #endif -#include -#ifdef HAVE_TIME_H -#include -#endif -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif #include "types.h" #include "common.h" #include "lang.h" @@ -52,38 +35,18 @@ #else #include #endif -#include "intrface.h" #include "godmode.h" #include "fnctdsk.h" -#include "testdisk.h" -#include "adv.h" -#include "analyse.h" #include "chgtype.h" -#include "edit.h" #include "savehdr.h" #include "dirpart.h" -#include "fat.h" -#include "partauto.h" #include "log.h" -#include "guid_cmp.h" -#include "hdaccess.h" #include "io_redir.h" +#include "tload.h" +#include "intrface.h" #define INTER_DISK_X 0 #define INTER_DISK_Y 7 -extern const arch_fnct_t arch_i386; - -static void interface_options(int *dump_ind, int *align, int *allow_partial_last_cylinder, unsigned int *expert, char**current_cmd); -#ifdef HAVE_NCURSES -static list_part_t *interface_load(disk_t *disk_car,list_part_t *list_part, const int verbose); -static list_part_t *merge_partition_list(list_part_t *list_part,list_part_t *backup_part, const int verbose); -#endif -static int write_MBR_code(disk_t *disk_car); -static int write_clean_table(disk_t *disk_car); -static int interface_check_disk_capacity(disk_t *disk_car); -static int interface_check_disk_access(disk_t *disk_car, char **current_cmd); -static list_part_t *interface_analyse(disk_t *disk_car, const int verbose, const int saveheader, char**current_cmd); -static int menu_disk(disk_t *disk_car, const int verbose,int dump_ind, const int saveheader, char **current_cmd); void interface_list(disk_t *disk_car, const int verbose, const int saveheader, const int backup, char **current_cmd) { @@ -101,877 +64,6 @@ void interface_list(disk_t *disk_car, const int verbose, const int saveheader, c part_free_list(list_part); } -#ifdef HAVE_NCURSES -static int write_MBR_code(disk_t *disk_car) -{ - aff_copy(stdscr); - wmove(stdscr,5,0); - wprintw(stdscr,"%s\n",disk_car->description(disk_car)); - wmove(stdscr,INTER_DISK_Y,INTER_DISK_X); - if(disk_car->arch->write_MBR_code==NULL) - { - display_message("Function to write a new MBR code not implemented for this partition type.\n"); - return 1; - } - wprintw(stdscr,msg_WRITE_MBR_CODE); - if(ask_YN(stdscr)!=0 && ask_confirmation("Write a new copy of MBR code, confirm ? (Y/N)")!=0) - { - if(disk_car->arch->write_MBR_code(disk_car)) - { - display_message("Write error: Can't write new MBR code.\n"); - return 2; - } - else - display_message("A new copy of MBR code has been written.\nYou have to reboot for the change to take effect.\n"); - } - return 0; -} - -static int write_clean_table(disk_t *disk_car) -{ - aff_copy(stdscr); - wmove(stdscr,5,0); - wprintw(stdscr,"%s\n",disk_car->description(disk_car)); - wmove(stdscr,INTER_DISK_Y,INTER_DISK_X); - if(disk_car->arch->erase_list_part==NULL) - { - display_message("Clear partition table not implemented for this partition type.\n"); - return 1; - } - wprintw(stdscr,msg_WRITE_CLEAN_TABLE); - if(ask_YN(stdscr)!=0 && ask_confirmation("Clear partition table, confirm ? (Y/N)")!=0) - { - if(disk_car->arch->erase_list_part(disk_car)) - { - display_message("Write error: Can't clear partition table.\n"); - return 2; - } - else - display_message("Partition table has been cleared.\nYou have to reboot for the change to take effect.\n"); - } - return 0; -} -#else -static int write_MBR_code(disk_t *disk_car) -{ - if(disk_car->arch->write_MBR_code==NULL) - { - log_error("Function to write a new MBR code not implemented for this partition type.\n"); - return 1; - } - if(disk_car->arch->write_MBR_code(disk_car)) - { - log_error("Write error: Can't write new MBR code.\n"); - return 2; - } - else - log_info("A new copy of MBR code has been written.\nYou have to reboot for the change to take effect.\n"); - return 0; -} - -static int write_clean_table(disk_t *disk_car) -{ - if(disk_car->arch->erase_list_part==NULL) - { - log_error("Clear partition table not implemented for this partition type.\n"); - return 1; - } - if(disk_car->arch->erase_list_part(disk_car)) - { - log_error("Write error: Can't clear partition table.\n"); - return 2; - } - else - log_info("Partition table has been cleared.\nYou have to reboot for the change to take effect.\n"); - return 0; -} -#endif - -static int menu_disk_cli(disk_t *disk_car, const int verbose,int dump_ind, const int saveheader, char **current_cmd) -{ - int align=2; - int allow_partial_last_cylinder=0; - int ask_part_order=0; - unsigned int expert=0; - char options[16]; - strcpy(options, "AGOPTQ"); - while(1) - { - while(*current_cmd[0]==',') - (*current_cmd)++; - if(strncmp(*current_cmd,"analyze",7)==0 || strncmp(*current_cmd,"analyse",7)==0) - { - (*current_cmd)+=7; - { - int search_vista_part=0; - list_part_t *list_part; - list_part=interface_analyse(disk_car, verbose, saveheader, current_cmd); - if(disk_car->arch==&arch_i386) - { - const int old_allow_partial_last_cylinder=allow_partial_last_cylinder; - const list_part_t *element; - for(element=list_part;element!=NULL;element=element->next) - { - if(element->part->part_offset%(2048*512)==0 && element->part->part_size%(2048*512)==0) - search_vista_part=1; - } - while(*current_cmd[0]==',') - (*current_cmd)++; - if(strncmp(*current_cmd,"mode_vista",10)==0) - { - (*current_cmd)+=10; - search_vista_part=1; - } - if(search_vista_part==1) - allow_partial_last_cylinder=1; - if(old_allow_partial_last_cylinder!=allow_partial_last_cylinder) - hd_update_geometry(disk_car,allow_partial_last_cylinder,verbose); - log_info("Allow partial last cylinder : %s\n", allow_partial_last_cylinder>0?"Yes":"No"); - log_info("search_vista_part: %d\n", search_vista_part); - } - interface_recovery(disk_car, list_part, verbose, dump_ind, align, ask_part_order, expert, search_vista_part, current_cmd); - part_free_list(list_part); - } - } - else if(strncmp(*current_cmd,"geometry,",9)==0) - { - (*current_cmd)+=9; - change_geometry(disk_car, current_cmd); - } - else if(strncmp(*current_cmd,"advanced",8)==0) - { - (*current_cmd)+=8; - interface_adv(disk_car, verbose, dump_ind, expert,current_cmd); - } - else if(strncmp(*current_cmd,"options,",8)==0) - { - const int old_allow_partial_last_cylinder=allow_partial_last_cylinder; - (*current_cmd)+=8; - interface_options(&dump_ind, &align,&allow_partial_last_cylinder,&expert,current_cmd); - if(old_allow_partial_last_cylinder!=allow_partial_last_cylinder) - hd_update_geometry(disk_car,allow_partial_last_cylinder,verbose); - } - else if(strncmp(*current_cmd,"delete",6)==0) - { - (*current_cmd)+=6; - write_clean_table(disk_car); - } - else if(strncmp(*current_cmd,"mbr_code",8)==0) - { - (*current_cmd)+=8; - write_MBR_code(disk_car); - } - else - { - return 0; - } - } -} - -#ifdef HAVE_NCURSES -static int menu_disk_ncurses(disk_t *disk_car, const int verbose,int dump_ind, const int saveheader, char **current_cmd) -{ - int align=2; - int allow_partial_last_cylinder=0; - int ask_part_order=0; - int command; - unsigned int menu=0; - int real_key; - unsigned int expert=0; - char options[16]; - static struct MenuItem menuMain[]= - { - {'A',"Analyse","Analyse current partition structure and search for lost partitions"}, - {'T',"Advanced","Filesystem Utils"}, - {'G',"Geometry", "Change disk geometry" }, - {'O',"Options","Modify options"}, - {'C',"MBR Code","Write TestDisk MBR code to first sector"}, - {'D',"Delete","Delete all data in the partition table"}, - {'Q',"Quit","Return to disk selection"}, - {'E',"Editor","Basic disk editor"}, - {0,NULL,NULL} - }; - strcpy(options, "AGOPTQ"); - if(disk_car->arch->write_MBR_code!=NULL) - strcat(options,"C"); - if(disk_car->arch->erase_list_part!=NULL) - strcat(options,"D"); - while(1) - { - aff_copy(stdscr); - wmove(stdscr,5,0); - wprintw(stdscr,"%s\n",disk_car->description(disk_car)); - wmove(stdscr,20,0); - wprintw(stdscr,"Note: Correct disk geometry is required for a successful recovery. 'Analyse'"); - wmove(stdscr,21,0); - wprintw(stdscr,"process may give some warnings if it thinks the logical geometry is mismatched."); - command = wmenuSelect_ext(stdscr, 24, INTER_DISK_Y, INTER_DISK_X, menuMain, 10, - options, MENU_VERT | MENU_VERT_WARN | MENU_BUTTON | MENU_ACCEPT_OTHERS, &menu,&real_key); - /* e for editor will be added when the editor will be better */ - switch(command) - { - case 'a': - case 'A': - { - int search_vista_part=0; - list_part_t *list_part; - list_part=interface_analyse(disk_car, verbose, saveheader, current_cmd); - if(disk_car->arch==&arch_i386) - { - const int old_allow_partial_last_cylinder=allow_partial_last_cylinder; - const list_part_t *element; - for(element=list_part;element!=NULL;element=element->next) - { - if(element->part->part_offset%(2048*512)==0 && element->part->part_size%(2048*512)==0) - search_vista_part=1; - } - if(search_vista_part==0) - { - log_info("Ask the user for vista mode\n"); - if(ask_confirmation("Should TestDisk search for partition created under Vista ? [Y/N] (answer Yes if unsure)")!=0) - search_vista_part=1; - } - if(search_vista_part==1) - allow_partial_last_cylinder=1; - if(old_allow_partial_last_cylinder!=allow_partial_last_cylinder) - hd_update_geometry(disk_car,allow_partial_last_cylinder,verbose); - log_info("Allow partial last cylinder : %s\n", allow_partial_last_cylinder>0?"Yes":"No"); - log_info("search_vista_part: %d\n", search_vista_part); - } - interface_recovery(disk_car, list_part, verbose, dump_ind, align, ask_part_order, expert, search_vista_part, current_cmd); - part_free_list(list_part); - } - break; - case 'd': - case 'D': - write_clean_table(disk_car); - break; - case 'c': - case 'C': - write_MBR_code(disk_car); - break; - case 'g': - case 'G': - change_geometry(disk_car, current_cmd); - break; - case 'o': - case 'O': - { - const int old_allow_partial_last_cylinder=allow_partial_last_cylinder; - interface_options(&dump_ind, &align,&allow_partial_last_cylinder,&expert, current_cmd); - if(old_allow_partial_last_cylinder!=allow_partial_last_cylinder) - hd_update_geometry(disk_car,allow_partial_last_cylinder,verbose); - } - break; - case 't': - case 'T': - interface_adv(disk_car, verbose, dump_ind, expert, current_cmd); - break; - case 'e': - case 'E': - interface_editor(disk_car); - break; - case 'q': - case 'Q': - return 0; - } - } -} -#endif - -static int menu_disk(disk_t *disk_car, const int verbose,int dump_ind, const int saveheader, char **current_cmd) -{ - if(*current_cmd!=NULL) - return menu_disk_cli(disk_car, verbose, dump_ind, saveheader, current_cmd); -#ifdef HAVE_NCURSES - return menu_disk_ncurses(disk_car, verbose, dump_ind, saveheader, current_cmd); -#else - return 0; -#endif -} - -static int testdisk_disk_selection_cli(int verbose,int dump_ind, const list_disk_t *list_disk, const int saveheader, const char *cmd_device, char **current_cmd) -{ - const list_disk_t *element_disk; - const list_disk_t *current_disk=NULL; - if(cmd_device!=NULL) - { - for(element_disk=list_disk;element_disk!=NULL;element_disk=element_disk->next) - { - if(strcmp(element_disk->disk->device,cmd_device)==0) - current_disk=element_disk; - } - } - else - current_disk=list_disk; - if(current_disk==NULL) - { - return intrf_no_disk("TestDisk"); - } - if(*current_cmd!=NULL) - { - while(*current_cmd[0]==',') - (*current_cmd)++; - { - disk_t *disk=current_disk->disk; - autodetect_arch(disk); - autoset_unit(disk); - if(interface_check_disk_capacity(disk)==0 && - interface_check_disk_access(disk, current_cmd)==0 && - interface_partition_type(disk, verbose, current_cmd)==0) - { - menu_disk(disk, verbose, dump_ind, saveheader, current_cmd); - } - } - } - return 0; -} - -#ifdef HAVE_NCURSES -static int testdisk_disk_selection_ncurses(int verbose,int dump_ind, const list_disk_t *list_disk, const int saveheader, char **current_cmd) -{ - int command='Q'; - unsigned int menu=0; - int offset=0; - int pos_num=0; - const list_disk_t *element_disk; - const list_disk_t *current_disk; - static struct MenuItem menuMain[]= - { - { 'P', "Previous",""}, - { 'N', "Next","" }, - { 'O',"Proceed",""}, - { 'Q',"Quit","Quit program"}, - { 0,NULL,NULL} - }; - current_disk=list_disk; - if(current_disk==NULL) - { - return intrf_no_disk("TestDisk"); - } - /* ncurses interface */ - while(1) - { - const char *options; - int i; -#ifdef HAVE_NCURSES - aff_copy(stdscr); - wmove(stdscr,4,0); - wprintw(stdscr," TestDisk is free software, and"); - wmove(stdscr,5,0); - wprintw(stdscr,"comes with ABSOLUTELY NO WARRANTY."); - wmove(stdscr,7,0); - wprintw(stdscr,"Select a media (use Arrow keys, then press Enter):"); -#endif - for(i=0,element_disk=list_disk;(element_disk!=NULL) && (inext,i++); - for(;element_disk!=NULL && (i-offset)<10;i++,element_disk=element_disk->next) - { - wmove(stdscr,8+i-offset,0); - if(element_disk!=current_disk) - wprintw(stdscr,"%s\n",element_disk->disk->description_short(element_disk->disk)); - else - { - wattrset(stdscr, A_REVERSE); - wprintw(stdscr,"%s\n",element_disk->disk->description_short(element_disk->disk)); - wattroff(stdscr, A_REVERSE); - } - } - if(i<=10 && element_disk==NULL) - options="OQ"; - else - options="PNOQ"; - { - int line=20; - mvwaddstr(stdscr,line++,0,"Note: "); -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(DJGPP) -#else -#ifdef HAVE_GETEUID - if(geteuid()!=0) - { - if(has_colors()) - wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(1)); - waddstr(stdscr,"Some disks won't appear unless you are root user."); - if(has_colors()) - wbkgdset(stdscr,' ' | COLOR_PAIR(0)); - wmove(stdscr,line++,0); - } -#endif -#endif - waddstr(stdscr,"Disk capacity must be correctly detected for a successful recovery."); - wmove(stdscr,line++,0); - wprintw(stdscr,"If a disk listed above has incorrect size, check HD jumper settings, BIOS"); - wmove(stdscr,line++,0); - wprintw(stdscr,"detection, and install the latest OS patches and disk drivers."); - } - command = wmenuSelect_ext(stdscr, 24, INTER_MAIN_Y, INTER_MAIN_X, menuMain, 8, - options, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, &menu,NULL); - switch(command) - { - case KEY_UP: - case 'P': - if(current_disk->prev!=NULL) - { - current_disk=current_disk->prev; - pos_num--; - } - if(pos_numnext!=NULL) - { - current_disk=current_disk->next; - pos_num++; - } - if(pos_num>=offset+10) - offset++; - break; - case KEY_PPAGE: - for(i=0;iprev!=NULL;i++) - { - current_disk=current_disk->prev; - pos_num--; - if(pos_numnext!=NULL;i++) - { - current_disk=current_disk->next; - pos_num++; - if(pos_num>=offset+10) - offset++; - } - break; - case 'o': - case 'O': - { - disk_t *disk=current_disk->disk; - autodetect_arch(disk); - autoset_unit(disk); - if(interface_check_disk_capacity(disk)==0 && - interface_check_disk_access(disk, current_cmd)==0 && - interface_partition_type(disk, verbose, current_cmd)==0) - { - if(menu_disk(disk, verbose, dump_ind, saveheader, current_cmd)) - return 0; - } - } - break; - case 'q': - case 'Q': - return 0; - } - } -} -#endif - -int do_curses_testdisk(int verbose,int dump_ind, const list_disk_t *list_disk, const int saveheader, const char *cmd_device, char **current_cmd) -{ - if(*current_cmd!=NULL) - return testdisk_disk_selection_cli(verbose, dump_ind, list_disk, saveheader, cmd_device, current_cmd); -#ifdef HAVE_NCURSES - return testdisk_disk_selection_ncurses(verbose, dump_ind, list_disk, saveheader, current_cmd); -#else - return 0; -#endif -} - -#ifdef HAVE_NCURSES -static int interface_check_disk_capacity_ncurses(disk_t *disk_car) -{ - static const struct MenuItem menuMain[]= - { - { 'C', "Continue","The HD is really 137 GB only."}, - { 'Q',"Quit","The HD is bigger, it's safer to enable LBA48 support first."}, - { 0,NULL,NULL} - }; - unsigned int menu=1; - int car; - aff_copy(stdscr); - wmove(stdscr,4,0); - wprintw(stdscr,"%s\n",disk_car->description(disk_car)); - wmove(stdscr,6,0); - wprintw(stdscr,"The Harddisk size seems to be 137GB."); - wmove(stdscr,7,0); - wprintw(stdscr,"Support for 48-bit Logical Block Addressing (LBA) is needed to access"); - wmove(stdscr,8,0); - wprintw(stdscr,"hard disks larger than 137 GB."); - wmove(stdscr,9,0); -#if defined(__CYGWIN__) || defined(__MINGW32__) - wprintw(stdscr,"Update Windows to support LBA48 (minimum: W2K SP4 or XP SP1)"); -#endif - car= wmenuSelect_ext(stdscr, 24, INTER_MAIN_Y, INTER_MAIN_X, menuMain, 10, - "CQ", MENU_VERT | MENU_VERT_WARN | MENU_BUTTON, &menu,NULL); - if(car=='c' || car=='C') - return 0; - return 1; -} -#endif - -static int interface_check_disk_capacity(disk_t *disk_car) -{ - /* Test for LBA28 limitation */ - if(disk_car->geom.sectors_per_head>0 && - disk_car->geom.cylinders == (((1<<28)-1) / disk_car->geom.heads_per_cylinder / disk_car->geom.sectors_per_head)) - { - log_warning("LBA28 limitation\n"); - log_flush(); -#ifdef HAVE_NCURSES - return interface_check_disk_capacity_ncurses(disk_car); -#endif - } - return 0; -} - -#ifdef HAVE_NCURSES -static int interface_check_disk_access_ncurses(disk_t *disk_car) -{ - static const struct MenuItem menuDiskAccess[]= - { - { 'C', "Continue", "Continue even if write access isn't available"}, - { 'Q', "Quit", "Return to disk selection"}, - { 0,NULL,NULL} - }; - unsigned int menu=0; - int car; - int line=9; - aff_copy(stdscr); - wmove(stdscr,4,0); - wprintw(stdscr,"%s\n",disk_car->description_short(disk_car)); - wmove(stdscr,6,0); - wprintw(stdscr,"Write access for this media is not available."); - wmove(stdscr,7,0); - wprintw(stdscr,"TestDisk won't be able to modify it."); -#ifdef DJGPP -#elif defined(__CYGWIN__) || defined(__MINGW32__) - wmove(stdscr,line++,0); - wprintw(stdscr,"- You may need to be administrator to have write access.\n"); - wmove(stdscr,line++,0); - wprintw(stdscr,"Under Vista, select TestDisk, right-click and choose \"Run as administrator\".\n"); -#elif defined HAVE_GETEUID - if(geteuid()!=0) - { - wmove(stdscr,line++,0); - wprintw(stdscr,"- You may need to be root to have write access.\n"); -#if defined(__APPLE__) - wmove(stdscr,line++,0); - wprintw(stdscr,"Use the sudo command to launch TestDisk.\n"); -#endif - wmove(stdscr,line++,0); - wprintw(stdscr,"- Check the OS permission for this file or device.\n"); - } -#endif -#if defined(__APPLE__) - wmove(stdscr,line++,0); - wprintw(stdscr,"- No partition from this disk must be mounted:\n"); - wmove(stdscr,line++,0); - wprintw(stdscr,"Open the Disk Utility (In Finder -> Application -> Utility folder)\n"); - wmove(stdscr,line++,0); - wprintw(stdscr,"and press Umount button for each volume from this disk\n"); -#endif - wmove(stdscr,line++,0); - wprintw(stdscr,"- This media may be physically write-protected, check the jumpers.\n"); - car= wmenuSelect_ext(stdscr, 24, INTER_MAIN_Y, INTER_MAIN_X, menuDiskAccess, 10, - "CQ", MENU_VERT | MENU_VERT_WARN | MENU_BUTTON, &menu,NULL); - if(car=='c' || car=='C') - return 0; - return 1; -} -#endif - -static int interface_check_disk_access(disk_t *disk_car, char **current_cmd) -{ - if((disk_car->access_mode&TESTDISK_O_RDWR)==TESTDISK_O_RDWR) - return 0; - if(*current_cmd!=NULL) - return 0; - log_warning("Media is opened in read-only.\n"); - log_flush(); -#ifdef HAVE_NCURSES - return interface_check_disk_access_ncurses(disk_car); -#else - return 0; -#endif -} - -static list_part_t *interface_analyse_ncurses(disk_t *disk_car, const int verbose, const int saveheader, char**current_cmd) -{ - list_part_t *list_part; - int command; -#ifdef HAVE_NCURSES - struct MenuItem menuAnalyse[]= - { - { 'P', "Previous",""}, - { 'N', "Next","" }, - { 'Q',"Quick Search","Try to locate partition"}, - { 'B', "Backup","Save current partition list to backup.log file and proceed"}, - { 0, NULL, NULL } - }; -#endif - screen_buffer_reset(); - /* ncurses interface */ -#ifdef HAVE_NCURSES - aff_copy(stdscr); - if(disk_car->arch->msg_part_type!=NULL) - mvwaddstr(stdscr,22,0,disk_car->arch->msg_part_type); - wmove(stdscr,4,0); - wprintw(stdscr,"%s\n",disk_car->description(disk_car)); - mvwaddstr(stdscr,5,0,"Checking current partition structure"); - wmove(stdscr,6,0); - wrefresh(stdscr); - wprintw(stdscr,msg_PART_HEADER_LONG); -#endif - list_part=disk_car->arch->read_part(disk_car,verbose,saveheader); - log_info("Current partition structure:\n"); - screen_buffer_to_log(); -#ifdef HAVE_NCURSES - wmove(stdscr,5,0); - wclrtoeol(stdscr); /* before addstr for BSD compatibility */ - waddstr(stdscr,"Current partition structure:"); -#endif - command='Q'; - if(*current_cmd!=NULL) - { - while(*current_cmd[0]==',') - (*current_cmd)++; - if(strncmp(*current_cmd,"backup",6)==0) - { - (*current_cmd)+=6; - if(list_part!=NULL) - command='B'; - } - } - else - { - log_flush(); -#ifdef HAVE_NCURSES - command=screen_buffer_display(stdscr, - (list_part!=NULL && disk_car->arch->add_partition!=NULL?"QB":"Q"), - menuAnalyse); -#endif - } - if(command=='B') - { - log_info("Backup partition structure\n"); - if(partition_save(disk_car,list_part,verbose)<0) - { - display_message("Can't create backup.log.\n"); - } - } - return list_part; -} - -static list_part_t *interface_analyse(disk_t *disk_car, const int verbose, const int saveheader, char**current_cmd) -{ - log_info("\nAnalyse "); - log_info("%s\n",disk_car->description(disk_car)); - return interface_analyse_ncurses(disk_car, verbose, saveheader, current_cmd); -} - -int interface_write(disk_t *disk_car,list_part_t *list_part,const int can_search_deeper, const int can_ask_minmax_ext, int *no_confirm, char **current_cmd, unsigned int *menu) -{ - list_part_t *parts; -#ifdef HAVE_NCURSES - struct MenuItem menuWrite[]= - { - { 'P', "Previous",""}, - { 'N', "Next","" }, - { 'Q', "Quit","Return to main menu"}, - { 'S', "Deeper Search","Try to find more partitions"}, - { 'W', "Write","Write partition structure to disk"}, - { 'E', "Extd Part","Maximize/Minimize extended partition"}, - { 0, NULL, NULL } - }; -#endif - int command; - log_info("\ninterface_write()\n"); - screen_buffer_reset(); -#ifdef HAVE_NCURSES - aff_copy(stdscr); - wmove(stdscr,4,0); - wprintw(stdscr,"%s",disk_car->description(disk_car)); - wmove(stdscr,5,0); - mvwaddstr(stdscr,6,0,msg_PART_HEADER_LONG); -#endif - for(parts=list_part;parts!=NULL;parts=parts->next) - if(parts->part->status!=STATUS_LOG) - aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,parts->part); - for(parts=list_part;parts!=NULL;parts=parts->next) - if(parts->part->status==STATUS_LOG) - aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,parts->part); - command='Q'; - if(list_part==NULL) - { - screen_buffer_add(" \nNo partition found or selected for recovery"); - screen_buffer_to_log(); - if(*current_cmd!=NULL) - { - while(*current_cmd[0]==',') - (*current_cmd)++; - if(strncmp(*current_cmd,"search",6)==0) - { - (*current_cmd)+=6; - command='S'; - } - } - else - { - log_flush(); -#ifdef HAVE_NCURSES - command=screen_buffer_display_ext(stdscr,(can_search_deeper?"S":""),menuWrite,menu); -#endif - } - } - else - { - if(*current_cmd!=NULL) - { - do - { - command='Q'; - while(*current_cmd[0]==',') - (*current_cmd)++; - if(strncmp(*current_cmd,"search",6)==0) - { - (*current_cmd)+=6; - if(can_search_deeper) - command='S'; - } - else if(strncmp(*current_cmd,"noconfirm",9)==0) - { - command=0; /* do nothing */ - (*no_confirm)=1; - (*current_cmd)+=9; - } - else if(strncmp(*current_cmd,"write",5)==0) - { - (*current_cmd)+=5; - if(disk_car->arch->write_part!=NULL) - command='W'; - } - } while(command==0); - screen_buffer_to_log(); - } - else - { - char options[10]; - options[0]=0; - if(can_search_deeper) - strcat(options,"S"); - if(disk_car->arch->write_part!=NULL) - strcat(options,"W"); - else - screen_buffer_add(" \nWrite isn't available because the partition table type \"%s\" has been selected.", - disk_car->arch->part_name); - if(can_ask_minmax_ext) - strcat(options,"E"); - screen_buffer_to_log(); - log_flush(); -#ifdef HAVE_NCURSES - command=screen_buffer_display_ext(stdscr,options,menuWrite,menu); -#else - command='Q'; -#endif - } - } - return command; -} - -#ifdef HAVE_NCURSES -static void interface_options_ncurses(int *dump_ind, int *align, int *allow_partial_last_cylinder, unsigned int *expert) -{ - unsigned int menu = 4; - /* ncurses interface */ - while (1) - { - int car; - int real_key; - struct MenuItem menuOptions[]= - { - { 'E',NULL,"Expert mode adds some functionalities"}, - { 'C',NULL,"Partitions are aligned on cylinder/head boundaries" }, - { 'A',NULL,""}, - { 'D',NULL,"Dump essential sectors" }, - { 'Q',"[ Ok ]","Done with changing options"}, - { 0, NULL, NULL } - }; - menuOptions[0].name=*expert?"Expert mode : Yes":"Expert mode : No"; - switch(*align) - { - case 0: - menuOptions[1].name="Cylinder boundary : No"; - break; - case 1: - menuOptions[1].name="Cylinder boundary : Head boundary only"; - break; - case 2: - menuOptions[1].name="Cylinder boundary : Yes"; - break; - } - menuOptions[2].name=*allow_partial_last_cylinder?"Allow partial last cylinder : Yes":"Allow partial last cylinder : No"; - menuOptions[3].name=*dump_ind?"Dump : Yes":"Dump : No"; - aff_copy(stdscr); - car=wmenuSelect_ext(stdscr, 24, INTER_OPTION_Y, INTER_OPTION_X, menuOptions, 0, "ECADQ", MENU_VERT|MENU_VERT_ARROW2VALID, &menu,&real_key); - switch(car) - { - case 'd': - case 'D': - *dump_ind=!*dump_ind; - break; - case 'c': - case 'C': - if(*align<2) - (*align)++; - else - *align=0; - break; - case 'a': - case 'A': - *allow_partial_last_cylinder=!*allow_partial_last_cylinder; - break; - case 'e': - case 'E': - *expert=!*expert; - break; - case key_ESC: - case 'q': - case 'Q': - return; - } - } -} -#endif - -static void interface_options(int *dump_ind, int *align, int *allow_partial_last_cylinder, unsigned int *expert, char**current_cmd) -{ - if(*current_cmd==NULL) - { -#ifdef HAVE_NCURSES - interface_options_ncurses(dump_ind, align, allow_partial_last_cylinder, expert); -#endif - } - /* write new options to log file */ - log_info("New options :\n Dump : %s\n ", (*dump_ind?"Yes":"No")); - switch(*align) - { - case 0: - log_info("Cylinder boundary : No"); - break; - case 1: - log_info("Cylinder boundary : Head boundary only"); - break; - case 2: - log_info("Cylinder boundary : Yes"); - break; - } - log_info("\n Allow partial last cylinder : %s\n Expert mode : %s\n", - *allow_partial_last_cylinder?"Yes":"No", - *expert?"Yes":"No"); -} - static list_part_t *ask_structure_cli(disk_t *disk_car,list_part_t *list_part, const int verbose, char **current_cmd) { list_part_t *pos=list_part; @@ -1001,6 +93,7 @@ static list_part_t *ask_structure_cli(disk_t *disk_car,list_part_t *list_part, c } #ifdef HAVE_NCURSES +#define INTER_STRUCTURE 13 static list_part_t *ask_structure_ncurses(disk_t *disk_car,list_part_t *list_part, const int verbose, char **current_cmd) { int offset=0; @@ -1165,8 +258,6 @@ static list_part_t *ask_structure_ncurses(disk_t *disk_car,list_part_t *list_par pos=pos->prev; pos_num--; } - if(pos_numnext; pos_num++; } - if(pos_num>=offset+INTER_STRUCTURE) - offset++; } break; case KEY_PPAGE: if(list_part!=NULL) { only_one_bootable(list_part,pos); - for(i=0;(iprev!=NULL);i++) + for(i=0; iprev!=NULL; i++) { pos=pos->prev; pos_num--; - if(pos_numnext!=NULL);i++) + for(i=0; inext!=NULL; i++) { pos=pos->next; pos_num++; - if(pos_num>=offset+INTER_STRUCTURE) - offset++; } } break; @@ -1287,6 +372,10 @@ static list_part_t *ask_structure_ncurses(disk_t *disk_car,list_part_t *list_par /* log_trace("ask_structure command=%x\n",command); */ break; } + if(pos_num=offset+INTER_STRUCTURE) + offset=pos_num-INTER_STRUCTURE+1; } } #endif @@ -1301,313 +390,3 @@ list_part_t *ask_structure(disk_t *disk_car,list_part_t *list_part, const int ve return list_part; #endif } - -#ifdef HAVE_NCURSES -static list_part_t *merge_partition_list(list_part_t *list_part,list_part_t *backup_part, const int verbose) -{ - list_part_t *partition; - for(partition=backup_part;partition!=NULL;partition=partition->next) - { - int insert_error=0; - partition_t *new_partition=partition_new(NULL); - dup_partition_t(new_partition,partition->part); - list_part=insert_new_partition(list_part, new_partition, 0, &insert_error); - if(insert_error>0) - free(new_partition); - } - return list_part; -} -#endif - -#ifdef HAVE_NCURSES -static struct td_list_head *interface_load_ncurses(disk_t *disk_car, backup_disk_t *backup_list, const int verbose) -{ - int offset=0; - int backup_current_num=0; - int rewrite=1; - unsigned int menu=3; /* default : quit */ - struct td_list_head *backup_current=backup_list->list.next; - struct td_list_head *backup_walker=NULL; - struct MenuItem menuLoadBackup[]= - { - { 'P', "Previous",""}, - { 'N', "Next","" }, - { 'L',"Load","Load partition structure from backup and try to locate partition"}, - { 'Q',"Cancel","Don't use backup and try to locate partition"}, - { 0, NULL, NULL } - }; - char options[20]; - while(1) - { - int i; - if(rewrite) - { - aff_copy(stdscr); - mvwaddstr(stdscr,4,0,disk_car->description(disk_car)); - if(backup_list!=NULL) - { - mvwaddstr(stdscr,5,0,"Choose the backup you want to restore:"); - mvwaddstr(stdscr,20,0,"PS: Don't worry you will have to confirm the partition restoration."); - } - else - { - mvwaddstr(stdscr,5,0,"No backup found!"); - } - rewrite=0; - } - if(backup_list!=NULL) - { - backup_disk_t *backup=NULL; - for(i=0,backup_walker=backup_list->list.next;(backup_walker!=&backup_list->list) && (inext,i++); - for(i=offset;(backup_walker!=&backup_list->list) &&((i-offset)next) - { - backup=td_list_entry(backup_walker, backup_disk_t, list); - wmove(stdscr,8+i-offset,0); - wclrtoeol(stdscr); /* before addstr for BSD compatibility */ - if(backup_walker==backup_current) - { - wattrset(stdscr, A_REVERSE); - wprintw(stdscr,"%s %s",backup->description,ctime(&backup->my_time)); - wattroff(stdscr, A_REVERSE); - } else - { - wprintw(stdscr,"%s %s",backup->description,ctime(&backup->my_time)); - } - } - if(i<=INTER_STRUCTURE && backup==NULL) - { - strncpy(options,"LQ",sizeof(options)); - menu=0; - } - else - { - strncpy(options,"PNLQ",sizeof(options)); - menu=2; - } - } - else - { - menu=0; - strncpy(options,"Q",sizeof(options)); - } - switch(wmenuSelect(stdscr, 24, INTER_DUMP_Y,INTER_DUMP_X, menuLoadBackup, 8, options, MENU_HORIZ| MENU_BUTTON | MENU_ACCEPT_OTHERS, menu)) - { - case 'q': - case 'Q': - return NULL; - case 'l': - case 'L': - if(backup_current==&backup_list->list) - return NULL; - return backup_current; - case KEY_UP: - if(backup_current->prev!=&backup_list->list) - { - backup_current=backup_current->prev; - backup_current_num--; - if(backup_current_numnext!=&backup_list->list) - { - backup_current=backup_current->next; - backup_current_num++; - if(backup_current_num>=offset+INTER_STRUCTURE) - offset++; - } - break; - case KEY_PPAGE: - { - for(i=0;(iprev!=&backup_list->list);i++) - { - backup_current=backup_current->prev; - backup_current_num--; - if(backup_current_numnext!=&backup_list->list);i++) - { - backup_current=backup_current->next; - backup_current_num++; - if(backup_current_num>=offset+INTER_STRUCTURE) - offset++; - } - } - break; - default: - /* log_trace("ask_structure car=%x\n",car); */ - break; - } - } -} -#endif - -#ifdef HAVE_NCURSES -static list_part_t *interface_load(disk_t *disk_car,list_part_t *list_part, const int verbose) -{ - struct td_list_head *backup_walker=NULL; - struct td_list_head *backup_current=NULL; - backup_disk_t *backup_list=partition_load(disk_car,verbose); - log_info("interface_load\n"); - td_list_for_each(backup_walker,&backup_list->list) - { - list_part_t *element; - backup_disk_t *backup; - backup=td_list_entry(backup_walker, backup_disk_t, list); - log_info("%s %s",backup->description,ctime(&backup->my_time)); - for(element=backup->list_part;element!=NULL;element=element->next) - log_partition(disk_car,element->part); - } -#ifdef HAVE_NCURSES - backup_current=interface_load_ncurses(disk_car, backup_list, verbose); -#endif - if(backup_current!=NULL) - { - list_part_t *partition; - backup_disk_t *backup; - backup=td_list_entry(backup_current, backup_disk_t, list); - for(partition=backup->list_part;partition!=NULL;partition=partition->next) - { - /* Check partition and load partition name */ - disk_car->arch->check_part(disk_car,verbose,partition->part,0); - } - list_part=merge_partition_list(list_part,backup->list_part,verbose); - } - { /* Cleanup */ - struct td_list_head *backup_walker_next = NULL; - td_list_for_each_safe(backup_walker,backup_walker_next,&backup_list->list) - { - backup_disk_t *backup; - backup=td_list_entry(backup_walker, backup_disk_t, list); - part_free_list(backup->list_part); - free(backup); - } - free(backup_list); - } - return list_part; -} -#endif - -int interface_superblock(disk_t *disk_car,list_part_t *list_part, char**current_cmd) -{ - const list_part_t *parts; - const partition_t *old_part=NULL; -#ifdef HAVE_NCURSES - struct MenuItem menuSuperblock[]= - { - { 'P', "Previous",""}, - { 'N', "Next","" }, - { 'Q',"Quit","Return to Advanced menu"}, - { 0, NULL, NULL } - }; -#endif - screen_buffer_reset(); -#ifdef HAVE_NCURSES - aff_copy(stdscr); - wmove(stdscr,4,0); - wprintw(stdscr,"%s",disk_car->description(disk_car)); - wmove(stdscr,5,0); - mvwaddstr(stdscr,6,0,msg_PART_HEADER_LONG); -#endif - for(parts=list_part;parts!=NULL;parts=parts->next) - { - const partition_t *partition=parts->part; - if(old_part==NULL || - old_part->part_offset!=partition->part_offset || - old_part->part_size!=partition->part_size || - guid_cmp(old_part->part_type_gpt, partition->part_type_gpt)!=0 || - old_part->part_type_i386!=partition->part_type_i386 || - old_part->part_type_sun!=partition->part_type_sun || - old_part->part_type_mac!=partition->part_type_mac || - old_part->upart_type!=partition->upart_type) - { - aff_part_buffer(AFF_PART_BASE, disk_car, partition); - old_part=partition; - } - if(partition->blocksize!=0) - screen_buffer_add("superblock %lu, blocksize=%u\n", - (long unsigned)(partition->sb_offset/partition->blocksize), - partition->blocksize); - } - screen_buffer_to_log(); - if(*current_cmd==NULL) - { - log_flush(); -#ifdef HAVE_NCURSES - screen_buffer_display(stdscr,"",menuSuperblock); -#endif - } - return 0; -} - -#ifdef HAVE_NCURSES -int ask_testdisk_log_creation() -{ - unsigned int menu=0; - static struct MenuItem menuLogCreation[]= - { - {'C',"Create","Create a new log file"}, - {'A',"Append","Append information to log file"}, - {'Q',"No Log","Don't record anything"}, - {0,NULL,NULL} - }; - aff_copy(stdscr); - wmove(stdscr,5,0); - wprintw(stdscr,"TestDisk is a free data recovery software designed to help recover lost"); - wmove(stdscr,6,0); - wprintw(stdscr,"partitions and/or make non-booting disks bootable again when these symptoms"); - wmove(stdscr,7,0); - wprintw(stdscr,"are caused by faulty software, certain types of viruses or human error."); - wmove(stdscr,8,0); - wprintw(stdscr,"It can also be used to repair some filesystem errors."); - wmove(stdscr,10,0); - wprintw(stdscr,"Information gathered during TestDisk use can be recorded for later"); - wmove(stdscr,11,0); - wprintw(stdscr,"review. If you choose to create the text file, "); - if(has_colors()) - wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); - wprintw(stdscr,"testdisk.log"); - if(has_colors()) - wbkgdset(stdscr,' ' | COLOR_PAIR(0)); - wprintw(stdscr," , it"); - wmove(stdscr,12,0); - wprintw(stdscr,"will contain TestDisk options, technical information and various"); - wmove(stdscr,13,0); - wprintw(stdscr,"outputs; including any folder/file names TestDisk was used to find and"); - wmove(stdscr,14,0); - wprintw(stdscr,"list onscreen."); - wmove(stdscr,16,0); - wprintw(stdscr,"Use arrow keys to select, then press Enter key:"); - while(1) - { - int command; - command = wmenuSelect_ext(stdscr, 24, 17, 0, menuLogCreation, 8, - "CAQ", MENU_VERT | MENU_VERT_WARN | MENU_BUTTON, &menu,NULL); - switch(command) - { - case 'C': - case 'c': - return TD_LOG_CREATE; - case 'A': - case 'a': - return TD_LOG_APPEND; - case 'Q': - case 'q': - return TD_LOG_REFUSED; - default: - break; - } - } -} -#else -int ask_testdisk_log_creation() -{ - return TD_LOG_REFUSED; -} -#endif diff --git a/src/intrface.h b/src/intrface.h index 6af561d7..104c8bfe 100644 --- a/src/intrface.h +++ b/src/intrface.h @@ -22,13 +22,7 @@ #define ANALYSE_X 0 #define ANALYSE_Y 5 -#define INTER_STRUCTURE 13 #define INTER_BAD_PART 10 -int do_curses_testdisk(int verbose, int dump_ind, const list_disk_t *list_disk, const int saveheader, const char *cmd_device, char **current_cmd); -int interface_write(disk_t *disk_car,list_part_t *list_part,const int can_search_deeper, const int can_ask_minmax_ext, int *no_confirm, char **current_cmd, unsigned int *menu); - list_part_t *ask_structure(disk_t *disk_car,list_part_t *list_part, const int verbose, char **current_cmd); void interface_list(disk_t *disk_car, const int verbose, const int saveheader, const int backup, char **current_cmd); -int interface_superblock(disk_t *disk_car,list_part_t *list_part,char**current_cmd); -int ask_testdisk_log_creation(void); diff --git a/src/ntfs_udl.c b/src/ntfs_udl.c index dfb2db30..9d90cbb9 100644 --- a/src/ntfs_udl.c +++ b/src/ntfs_udl.c @@ -1279,8 +1279,6 @@ static void ntfs_undelete_menu_ncurses(disk_t *disk_car, const partition_t *part { current_file=current_file->prev; pos_num--; - if(pos_numnext; pos_num++; - if(pos_num>=offset+INTER_DIR) - offset++; } break; case KEY_PPAGE: @@ -1298,8 +1294,6 @@ static void ntfs_undelete_menu_ncurses(disk_t *disk_car, const partition_t *part { current_file=current_file->prev; pos_num--; - if(pos_numnext; pos_num++; - if(pos_num>=offset+INTER_DIR) - offset++; } break; case 'c': @@ -1366,6 +1358,10 @@ static void ntfs_undelete_menu_ncurses(disk_t *disk_car, const partition_t *part } break; } + if(pos_num=offset+INTER_DIR) + offset=pos_num-INTER_DIR+1; } while(old_LINES==LINES); } } diff --git a/src/phrecn.c b/src/phrecn.c index b17bb384..11fda234 100644 --- a/src/phrecn.c +++ b/src/phrecn.c @@ -1919,27 +1919,31 @@ static void menu_photorec(disk_t *disk_car, const int verbose, const char *recup switch(command) { case KEY_UP: - if(current_element!=NULL) + if(current_element!=NULL && current_element->prev!=NULL) { - if(current_element->prev!=NULL) - { - current_element=current_element->prev; - current_element_num--; - } - if(current_element_numprev; + current_element_num--; + } + break; + case KEY_PPAGE: + for(i=0; iprev!=NULL; i++) + { + current_element=current_element->prev; + current_element_num--; } break; case KEY_DOWN: - if(current_element!=NULL) + if(current_element->next!=NULL) { - if(current_element->next!=NULL) - { - current_element=current_element->next; - current_element_num++; - } - if(current_element_num>=offset+INTER_SELECT) - offset++; + current_element=current_element->next; + current_element_num++; + } + break; + case KEY_NPAGE: + for(i=0; inext!=NULL; i++) + { + current_element=current_element->next; + current_element_num++; } break; case 's': @@ -2008,6 +2012,10 @@ static void menu_photorec(disk_t *disk_car, const int verbose, const char *recup done = 1; break; } + if(current_element_num=offset+INTER_SELECT) + offset=current_element_num-INTER_SELECT+1; } #endif } @@ -2102,8 +2110,6 @@ static void photorec_disk_selection_ncurses(int verbose, const char *recup_dir, current_disk=current_disk->prev; pos_num--; } - if(pos_numnext; pos_num++; } - if(pos_num>=offset+INTER_MENU_DISK) - offset++; break; case KEY_PPAGE: for(i=0;iprev!=NULL;i++) { current_disk=current_disk->prev; pos_num--; - if(pos_numnext; pos_num++; - if(pos_num>=offset+INTER_MENU_DISK) - offset++; } break; case 'o': @@ -2147,6 +2147,10 @@ static void photorec_disk_selection_ncurses(int verbose, const char *recup_dir, done=1; break; } + if(pos_num=offset+INTER_MENU_DISK) + offset=pos_num-INTER_MENU_DISK+1; } } #endif @@ -2462,38 +2466,22 @@ static void interface_file_select_ncurses(file_enable_t *files_enable) case KEY_UP: case '8': if(current_element_num>0) - { current_element_num--; - if(current_element_num0;i++) - { + for(i=0; i0; i++) current_element_num--; - if(current_element_num=offset+INTER_FSELECT) - offset++; - } break; case KEY_NPAGE: case '3': - for(i=0;i=offset+INTER_FSELECT) - offset++; - } break; case KEY_RIGHT: case '+': @@ -2536,6 +2524,10 @@ static void interface_file_select_ncurses(file_enable_t *files_enable) case 'Q': return; } + if(current_element_num=offset+INTER_FSELECT) + offset=current_element_num-INTER_FSELECT+1; } } #endif diff --git a/src/tanalyse.c b/src/tanalyse.c new file mode 100644 index 00000000..0b0743e7 --- /dev/null +++ b/src/tanalyse.c @@ -0,0 +1,115 @@ +/* + + File: tanalyse.c + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif +#include "types.h" +#include "common.h" +#include "lang.h" +#include "intrf.h" +#ifdef HAVE_NCURSES +#include "intrfn.h" +#else +#include +#endif +#include "savehdr.h" +#include "log.h" +#include "tanalyse.h" + +static list_part_t *interface_analyse_ncurses(disk_t *disk_car, const int verbose, const int saveheader, char**current_cmd) +{ + list_part_t *list_part; + int command; +#ifdef HAVE_NCURSES + struct MenuItem menuAnalyse[]= + { + { 'P', "Previous",""}, + { 'N', "Next","" }, + { 'Q',"Quick Search","Try to locate partition"}, + { 'B', "Backup","Save current partition list to backup.log file and proceed"}, + { 0, NULL, NULL } + }; +#endif + screen_buffer_reset(); + /* ncurses interface */ +#ifdef HAVE_NCURSES + aff_copy(stdscr); + wmove(stdscr,4,0); + wprintw(stdscr,"%s\n",disk_car->description(disk_car)); + mvwaddstr(stdscr,5,0,"Checking current partition structure"); + wrefresh(stdscr); +#endif + list_part=disk_car->arch->read_part(disk_car,verbose,saveheader); + log_info("Current partition structure:\n"); + screen_buffer_to_log(); +#ifdef HAVE_NCURSES + wmove(stdscr,5,0); + wclrtoeol(stdscr); /* before addstr for BSD compatibility */ + waddstr(stdscr,"Current partition structure:"); + wmove(stdscr,6,0); + wprintw(stdscr,msg_PART_HEADER_LONG); + if(disk_car->arch->msg_part_type!=NULL) + mvwaddstr(stdscr,LINES-3,0,disk_car->arch->msg_part_type); +#endif + command='Q'; + if(*current_cmd!=NULL) + { + while(*current_cmd[0]==',') + (*current_cmd)++; + if(strncmp(*current_cmd,"backup",6)==0) + { + (*current_cmd)+=6; + if(list_part!=NULL) + command='B'; + } + } + else + { + log_flush(); +#ifdef HAVE_NCURSES + command=screen_buffer_display(stdscr, + (list_part!=NULL && disk_car->arch->add_partition!=NULL?"QB":"Q"), + menuAnalyse); +#endif + } + if(command=='B') + { + log_info("Backup partition structure\n"); + if(partition_save(disk_car,list_part,verbose)<0) + { + display_message("Can't create backup.log.\n"); + } + } + return list_part; +} + +list_part_t *interface_analyse(disk_t *disk_car, const int verbose, const int saveheader, char**current_cmd) +{ + log_info("\nAnalyse "); + log_info("%s\n",disk_car->description(disk_car)); + return interface_analyse_ncurses(disk_car, verbose, saveheader, current_cmd); +} + diff --git a/src/tanalyse.h b/src/tanalyse.h new file mode 100644 index 00000000..128c2fb3 --- /dev/null +++ b/src/tanalyse.h @@ -0,0 +1,23 @@ +/* + + File: tanalyse.h + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ + +list_part_t *interface_analyse(disk_t *disk_car, const int verbose, const int saveheader, char**current_cmd); diff --git a/src/tdelete.c b/src/tdelete.c new file mode 100644 index 00000000..20197802 --- /dev/null +++ b/src/tdelete.c @@ -0,0 +1,82 @@ +/* + + File: tdelete.c + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "types.h" +#include "common.h" +#include "lang.h" +#include "intrf.h" +#ifdef HAVE_NCURSES +#include "intrfn.h" +#else +#include +#endif +#include "tdelete.h" + +#ifdef HAVE_NCURSES +#define INTER_DISK_X 0 +#define INTER_DISK_Y 7 + +int write_clean_table(disk_t *disk_car) +{ + aff_copy(stdscr); + wmove(stdscr,5,0); + wprintw(stdscr,"%s\n",disk_car->description(disk_car)); + wmove(stdscr,INTER_DISK_Y,INTER_DISK_X); + if(disk_car->arch->erase_list_part==NULL) + { + display_message("Clear partition table not implemented for this partition type.\n"); + return 1; + } + wprintw(stdscr,msg_WRITE_CLEAN_TABLE); + if(ask_YN(stdscr)!=0 && ask_confirmation("Clear partition table, confirm ? (Y/N)")!=0) + { + if(disk_car->arch->erase_list_part(disk_car)) + { + display_message("Write error: Can't clear partition table.\n"); + return 2; + } + else + display_message("Partition table has been cleared.\nYou have to reboot for the change to take effect.\n"); + } + return 0; +} +#else +int write_clean_table(disk_t *disk_car) +{ + if(disk_car->arch->erase_list_part==NULL) + { + log_error("Clear partition table not implemented for this partition type.\n"); + return 1; + } + if(disk_car->arch->erase_list_part(disk_car)) + { + log_error("Write error: Can't clear partition table.\n"); + return 2; + } + else + log_info("Partition table has been cleared.\nYou have to reboot for the change to take effect.\n"); + return 0; +} +#endif diff --git a/src/tdelete.h b/src/tdelete.h new file mode 100644 index 00000000..98f8e1b9 --- /dev/null +++ b/src/tdelete.h @@ -0,0 +1,22 @@ +/* + + File: tdelete.c + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +int write_clean_table(disk_t *disk_car); diff --git a/src/tdiskop.c b/src/tdiskop.c new file mode 100644 index 00000000..939637c6 --- /dev/null +++ b/src/tdiskop.c @@ -0,0 +1,257 @@ +/* + + File: tdiskop.c + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif +#include "types.h" +#include "common.h" +#include "intrf.h" +#ifdef HAVE_NCURSES +#include "intrfn.h" +#else +#include +#endif +#include "godmode.h" +#include "fnctdsk.h" +#include "testdisk.h" +#include "adv.h" +#include "chgtype.h" +#include "edit.h" +#include "log.h" +#include "hdaccess.h" +#include "toptions.h" +#include "tanalyse.h" +#include "tmbrcode.h" +#include "tdelete.h" +#include "tdiskop.h" + +extern const arch_fnct_t arch_i386; +#define INTER_DISK_X 0 +#define INTER_DISK_Y 7 + + +static int menu_disk_cli(disk_t *disk_car, const int verbose,int dump_ind, const int saveheader, char **current_cmd) +{ + int align=2; + int allow_partial_last_cylinder=0; + int ask_part_order=0; + unsigned int expert=0; + char options[16]; + strcpy(options, "AGOPTQ"); + while(1) + { + while(*current_cmd[0]==',') + (*current_cmd)++; + if(strncmp(*current_cmd,"analyze",7)==0 || strncmp(*current_cmd,"analyse",7)==0) + { + (*current_cmd)+=7; + { + int search_vista_part=0; + list_part_t *list_part; + list_part=interface_analyse(disk_car, verbose, saveheader, current_cmd); + if(disk_car->arch==&arch_i386) + { + const int old_allow_partial_last_cylinder=allow_partial_last_cylinder; + const list_part_t *element; + for(element=list_part;element!=NULL;element=element->next) + { + if(element->part->part_offset%(2048*512)==0 && element->part->part_size%(2048*512)==0) + search_vista_part=1; + } + while(*current_cmd[0]==',') + (*current_cmd)++; + if(strncmp(*current_cmd,"mode_vista",10)==0) + { + (*current_cmd)+=10; + search_vista_part=1; + } + if(search_vista_part==1) + allow_partial_last_cylinder=1; + if(old_allow_partial_last_cylinder!=allow_partial_last_cylinder) + hd_update_geometry(disk_car,allow_partial_last_cylinder,verbose); + log_info("Allow partial last cylinder : %s\n", allow_partial_last_cylinder>0?"Yes":"No"); + log_info("search_vista_part: %d\n", search_vista_part); + } + interface_recovery(disk_car, list_part, verbose, dump_ind, align, ask_part_order, expert, search_vista_part, current_cmd); + part_free_list(list_part); + } + } + else if(strncmp(*current_cmd,"geometry,",9)==0) + { + (*current_cmd)+=9; + change_geometry(disk_car, current_cmd); + } + else if(strncmp(*current_cmd,"advanced",8)==0) + { + (*current_cmd)+=8; + interface_adv(disk_car, verbose, dump_ind, expert,current_cmd); + } + else if(strncmp(*current_cmd,"options,",8)==0) + { + const int old_allow_partial_last_cylinder=allow_partial_last_cylinder; + (*current_cmd)+=8; + interface_options(&dump_ind, &align,&allow_partial_last_cylinder,&expert,current_cmd); + if(old_allow_partial_last_cylinder!=allow_partial_last_cylinder) + hd_update_geometry(disk_car,allow_partial_last_cylinder,verbose); + } + else if(strncmp(*current_cmd,"delete",6)==0) + { + (*current_cmd)+=6; + write_clean_table(disk_car); + } + else if(strncmp(*current_cmd,"mbr_code",8)==0) + { + (*current_cmd)+=8; + write_MBR_code(disk_car); + } + else + { + return 0; + } + } +} + +#ifdef HAVE_NCURSES +static int menu_disk_ncurses(disk_t *disk_car, const int verbose,int dump_ind, const int saveheader, char **current_cmd) +{ + int align=2; + int allow_partial_last_cylinder=0; + int ask_part_order=0; + int command; + unsigned int menu=0; + int real_key; + unsigned int expert=0; + char options[16]; + static struct MenuItem menuMain[]= + { + {'A',"Analyse","Analyse current partition structure and search for lost partitions"}, + {'T',"Advanced","Filesystem Utils"}, + {'G',"Geometry", "Change disk geometry" }, + {'O',"Options","Modify options"}, + {'C',"MBR Code","Write TestDisk MBR code to first sector"}, + {'D',"Delete","Delete all data in the partition table"}, + {'Q',"Quit","Return to disk selection"}, + {'E',"Editor","Basic disk editor"}, + {0,NULL,NULL} + }; + strcpy(options, "AGOPTQ"); + if(disk_car->arch->write_MBR_code!=NULL) + strcat(options,"C"); + if(disk_car->arch->erase_list_part!=NULL) + strcat(options,"D"); + while(1) + { + aff_copy(stdscr); + wmove(stdscr,5,0); + wprintw(stdscr,"%s\n",disk_car->description(disk_car)); + wmove(stdscr,20,0); + wprintw(stdscr,"Note: Correct disk geometry is required for a successful recovery. 'Analyse'"); + wmove(stdscr,21,0); + wprintw(stdscr,"process may give some warnings if it thinks the logical geometry is mismatched."); + command = wmenuSelect_ext(stdscr, 24, INTER_DISK_Y, INTER_DISK_X, menuMain, 10, + options, MENU_VERT | MENU_VERT_WARN | MENU_BUTTON | MENU_ACCEPT_OTHERS, &menu,&real_key); + /* e for editor will be added when the editor will be better */ + switch(command) + { + case 'a': + case 'A': + { + int search_vista_part=0; + list_part_t *list_part; + list_part=interface_analyse(disk_car, verbose, saveheader, current_cmd); + if(disk_car->arch==&arch_i386) + { + const int old_allow_partial_last_cylinder=allow_partial_last_cylinder; + const list_part_t *element; + for(element=list_part;element!=NULL;element=element->next) + { + if(element->part->part_offset%(2048*512)==0 && element->part->part_size%(2048*512)==0) + search_vista_part=1; + } + if(search_vista_part==0) + { + log_info("Ask the user for vista mode\n"); + if(ask_confirmation("Should TestDisk search for partition created under Vista ? [Y/N] (answer Yes if unsure)")!=0) + search_vista_part=1; + } + if(search_vista_part==1) + allow_partial_last_cylinder=1; + if(old_allow_partial_last_cylinder!=allow_partial_last_cylinder) + hd_update_geometry(disk_car,allow_partial_last_cylinder,verbose); + log_info("Allow partial last cylinder : %s\n", allow_partial_last_cylinder>0?"Yes":"No"); + log_info("search_vista_part: %d\n", search_vista_part); + } + interface_recovery(disk_car, list_part, verbose, dump_ind, align, ask_part_order, expert, search_vista_part, current_cmd); + part_free_list(list_part); + } + break; + case 'd': + case 'D': + write_clean_table(disk_car); + break; + case 'c': + case 'C': + write_MBR_code(disk_car); + break; + case 'g': + case 'G': + change_geometry(disk_car, current_cmd); + break; + case 'o': + case 'O': + { + const int old_allow_partial_last_cylinder=allow_partial_last_cylinder; + interface_options(&dump_ind, &align,&allow_partial_last_cylinder,&expert, current_cmd); + if(old_allow_partial_last_cylinder!=allow_partial_last_cylinder) + hd_update_geometry(disk_car,allow_partial_last_cylinder,verbose); + } + break; + case 't': + case 'T': + interface_adv(disk_car, verbose, dump_ind, expert, current_cmd); + break; + case 'e': + case 'E': + interface_editor(disk_car); + break; + case 'q': + case 'Q': + return 0; + } + } +} +#endif + +int menu_disk(disk_t *disk_car, const int verbose,int dump_ind, const int saveheader, char **current_cmd) +{ + if(*current_cmd!=NULL) + return menu_disk_cli(disk_car, verbose, dump_ind, saveheader, current_cmd); +#ifdef HAVE_NCURSES + return menu_disk_ncurses(disk_car, verbose, dump_ind, saveheader, current_cmd); +#else + return 0; +#endif +} diff --git a/src/tdiskop.h b/src/tdiskop.h new file mode 100644 index 00000000..2d005a52 --- /dev/null +++ b/src/tdiskop.h @@ -0,0 +1,23 @@ +/* + + File: tdiskop.h + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +int menu_disk(disk_t *disk_car, const int verbose,int dump_ind, const int saveheader, char **current_cmd); + diff --git a/src/tdisksel.c b/src/tdisksel.c new file mode 100644 index 00000000..eddf12d1 --- /dev/null +++ b/src/tdisksel.c @@ -0,0 +1,236 @@ +/* + + File: tdisksel.c + + Copyright (C) 1998-2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include "types.h" +#include "common.h" +#include "intrf.h" +#ifdef HAVE_NCURSES +#include "intrfn.h" +#else +#include +#endif +#include "fnctdsk.h" +#include "testdisk.h" +#include "partauto.h" +#include "log.h" +#include "hdaccess.h" +#include "diskcapa.h" +#include "diskacc.h" +#include "tdiskop.h" +#include "tdisksel.h" + +#ifdef HAVE_NCURSES +#define NBR_DISK_MAX 10 +static int testdisk_disk_selection_ncurses(int verbose,int dump_ind, const list_disk_t *list_disk, const int saveheader, char **current_cmd) +{ + int command='Q'; + unsigned int menu=0; + int offset=0; + int pos_num=0; + const list_disk_t *element_disk; + const list_disk_t *current_disk; + static struct MenuItem menuMain[]= + { + { 'P', "Previous",""}, + { 'N', "Next","" }, + { 'O',"Proceed",""}, + { 'Q',"Quit","Quit program"}, + { 0,NULL,NULL} + }; + current_disk=list_disk; + if(current_disk==NULL) + { + return intrf_no_disk("TestDisk"); + } + /* ncurses interface */ + while(1) + { + const char *options; + int i; +#ifdef HAVE_NCURSES + aff_copy(stdscr); + wmove(stdscr,4,0); + wprintw(stdscr," TestDisk is free software, and"); + wmove(stdscr,5,0); + wprintw(stdscr,"comes with ABSOLUTELY NO WARRANTY."); + wmove(stdscr,7,0); + wprintw(stdscr,"Select a media (use Arrow keys, then press Enter):"); +#endif + for(i=0,element_disk=list_disk;(element_disk!=NULL) && (inext,i++); + for(;element_disk!=NULL && (i-offset)next) + { + wmove(stdscr,8+i-offset,0); + if(element_disk!=current_disk) + wprintw(stdscr,"%s\n",element_disk->disk->description_short(element_disk->disk)); + else + { + wattrset(stdscr, A_REVERSE); + wprintw(stdscr,"%s\n",element_disk->disk->description_short(element_disk->disk)); + wattroff(stdscr, A_REVERSE); + } + } + if(i<=NBR_DISK_MAX && element_disk==NULL) + options="OQ"; + else + options="PNOQ"; + { + int line=20; + mvwaddstr(stdscr,line++,0,"Note: "); +#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(DJGPP) +#else +#ifdef HAVE_GETEUID + if(geteuid()!=0) + { + if(has_colors()) + wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(1)); + waddstr(stdscr,"Some disks won't appear unless you are root user."); + if(has_colors()) + wbkgdset(stdscr,' ' | COLOR_PAIR(0)); + wmove(stdscr,line++,0); + } +#endif +#endif + waddstr(stdscr,"Disk capacity must be correctly detected for a successful recovery."); + wmove(stdscr,line++,0); + wprintw(stdscr,"If a disk listed above has incorrect size, check HD jumper settings, BIOS"); + wmove(stdscr,line++,0); + wprintw(stdscr,"detection, and install the latest OS patches and disk drivers."); + } + command = wmenuSelect_ext(stdscr, LINES-1, INTER_MAIN_Y, INTER_MAIN_X, menuMain, 8, + options, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, &menu,NULL); + switch(command) + { + case 'p': + case 'P': + case KEY_UP: + if(current_disk->prev!=NULL) + { + current_disk=current_disk->prev; + pos_num--; + } + break; + case 'n': + case 'N': + case KEY_DOWN: + if(current_disk->next!=NULL) + { + current_disk=current_disk->next; + pos_num++; + } + break; + case KEY_PPAGE: + for(i=0;iprev!=NULL;i++) + { + current_disk=current_disk->prev; + pos_num--; + } + break; + case KEY_NPAGE: + for(i=0;inext!=NULL;i++) + { + current_disk=current_disk->next; + pos_num++; + } + break; + case 'o': + case 'O': + { + disk_t *disk=current_disk->disk; + autodetect_arch(disk); + autoset_unit(disk); + if(interface_check_disk_capacity(disk)==0 && + interface_check_disk_access(disk, current_cmd)==0 && + interface_partition_type(disk, verbose, current_cmd)==0) + { + if(menu_disk(disk, verbose, dump_ind, saveheader, current_cmd)) + return 0; + } + } + break; + case 'q': + case 'Q': + return 0; + } + if(pos_num=offset+NBR_DISK_MAX) + offset=pos_num-NBR_DISK_MAX+1; + } +} +#endif + +static int testdisk_disk_selection_cli(int verbose,int dump_ind, const list_disk_t *list_disk, const int saveheader, const char *cmd_device, char **current_cmd) +{ + const list_disk_t *element_disk; + const list_disk_t *current_disk=NULL; + if(cmd_device!=NULL) + { + for(element_disk=list_disk;element_disk!=NULL;element_disk=element_disk->next) + { + if(strcmp(element_disk->disk->device,cmd_device)==0) + current_disk=element_disk; + } + } + else + current_disk=list_disk; + if(current_disk==NULL) + { + return intrf_no_disk("TestDisk"); + } + if(*current_cmd!=NULL) + { + while(*current_cmd[0]==',') + (*current_cmd)++; + { + disk_t *disk=current_disk->disk; + autodetect_arch(disk); + autoset_unit(disk); + if(interface_check_disk_capacity(disk)==0 && + interface_check_disk_access(disk, current_cmd)==0 && + interface_partition_type(disk, verbose, current_cmd)==0) + { + menu_disk(disk, verbose, dump_ind, saveheader, current_cmd); + } + } + } + return 0; +} + +int do_curses_testdisk(int verbose,int dump_ind, const list_disk_t *list_disk, const int saveheader, const char *cmd_device, char **current_cmd) +{ + if(*current_cmd!=NULL) + return testdisk_disk_selection_cli(verbose, dump_ind, list_disk, saveheader, cmd_device, current_cmd); +#ifdef HAVE_NCURSES + return testdisk_disk_selection_ncurses(verbose, dump_ind, list_disk, saveheader, current_cmd); +#else + return 0; +#endif +} diff --git a/src/tdisksel.h b/src/tdisksel.h new file mode 100644 index 00000000..aae6f6fc --- /dev/null +++ b/src/tdisksel.h @@ -0,0 +1,24 @@ +/* + + File: tdisksel.h + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ + +int do_curses_testdisk(int verbose, int dump_ind, const list_disk_t *list_disk, const int saveheader, const char *cmd_device, char **current_cmd); + diff --git a/src/testdisk.c b/src/testdisk.c index 96c1960c..a44bd521 100644 --- a/src/testdisk.c +++ b/src/testdisk.c @@ -63,6 +63,8 @@ #include "sudo.h" #include "partauto.h" #include "misc.h" +#include "tdisksel.h" +#include "tlog.h" extern const arch_fnct_t arch_i386; extern const arch_fnct_t arch_mac; diff --git a/src/tload.c b/src/tload.c new file mode 100644 index 00000000..efb139b6 --- /dev/null +++ b/src/tload.c @@ -0,0 +1,254 @@ +/* + + File: tload.c + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#include "types.h" +#include "common.h" +#include "lang.h" +#include "intrf.h" +#ifdef HAVE_NCURSES +#include "intrfn.h" +#else +#include +#endif +#include "intrface.h" +#include "godmode.h" +#include "fnctdsk.h" +#include "testdisk.h" +#include "adv.h" +#include "analyse.h" +#include "chgtype.h" +#include "edit.h" +#include "savehdr.h" +#include "dirpart.h" +#include "fat.h" +#include "partauto.h" +#include "log.h" +#include "guid_cmp.h" +#include "hdaccess.h" +#include "io_redir.h" +#include "tload.h" + +#ifdef HAVE_NCURSES +static list_part_t *merge_partition_list(list_part_t *list_part,list_part_t *backup_part, const int verbose); + +#define INTER_STRUCTURE 13 +static struct td_list_head *interface_load_ncurses(disk_t *disk_car, backup_disk_t *backup_list, const int verbose) +{ + int offset=0; + int backup_current_num=0; + int rewrite=1; + unsigned int menu=3; /* default : quit */ + struct td_list_head *backup_current=backup_list->list.next; + struct td_list_head *backup_walker=NULL; + struct MenuItem menuLoadBackup[]= + { + { 'P', "Previous",""}, + { 'N', "Next","" }, + { 'L',"Load","Load partition structure from backup and try to locate partition"}, + { 'Q',"Cancel","Don't use backup and try to locate partition"}, + { 0, NULL, NULL } + }; + char options[20]; + while(1) + { + int i; + if(rewrite) + { + aff_copy(stdscr); + mvwaddstr(stdscr,4,0,disk_car->description(disk_car)); + if(backup_list!=NULL) + { + mvwaddstr(stdscr,5,0,"Choose the backup you want to restore:"); + mvwaddstr(stdscr,20,0,"PS: Don't worry you will have to confirm the partition restoration."); + } + else + { + mvwaddstr(stdscr,5,0,"No backup found!"); + } + rewrite=0; + } + if(backup_list!=NULL) + { + backup_disk_t *backup=NULL; + for(i=0,backup_walker=backup_list->list.next;(backup_walker!=&backup_list->list) && (inext,i++); + for(i=offset;(backup_walker!=&backup_list->list) &&((i-offset)next) + { + backup=td_list_entry(backup_walker, backup_disk_t, list); + wmove(stdscr,8+i-offset,0); + wclrtoeol(stdscr); /* before addstr for BSD compatibility */ + if(backup_walker==backup_current) + { + wattrset(stdscr, A_REVERSE); + wprintw(stdscr,"%s %s",backup->description,ctime(&backup->my_time)); + wattroff(stdscr, A_REVERSE); + } else + { + wprintw(stdscr,"%s %s",backup->description,ctime(&backup->my_time)); + } + } + if(i<=INTER_STRUCTURE && backup==NULL) + { + strncpy(options,"LQ",sizeof(options)); + menu=0; + } + else + { + strncpy(options,"PNLQ",sizeof(options)); + menu=2; + } + } + else + { + menu=0; + strncpy(options,"Q",sizeof(options)); + } + switch(wmenuSelect(stdscr, 24, INTER_DUMP_Y,INTER_DUMP_X, menuLoadBackup, 8, options, MENU_HORIZ| MENU_BUTTON | MENU_ACCEPT_OTHERS, menu)) + { + case 'q': + case 'Q': + return NULL; + case 'l': + case 'L': + if(backup_current==&backup_list->list) + return NULL; + return backup_current; + case KEY_UP: + if(backup_current->prev!=&backup_list->list) + { + backup_current=backup_current->prev; + backup_current_num--; + } + break; + case KEY_DOWN: + if(backup_current->next!=&backup_list->list) + { + backup_current=backup_current->next; + backup_current_num++; + } + break; + case KEY_PPAGE: + for(i=0;(iprev!=&backup_list->list);i++) + { + backup_current=backup_current->prev; + backup_current_num--; + } + break; + case KEY_NPAGE: + for(i=0;(inext!=&backup_list->list);i++) + { + backup_current=backup_current->next; + backup_current_num++; + } + break; + default: + /* log_trace("ask_structure car=%x\n",car); */ + break; + } + if(backup_current_num=offset+INTER_STRUCTURE) + offset=backup_current_num-INTER_STRUCTURE+1; + } +} + +static list_part_t *merge_partition_list(list_part_t *list_part,list_part_t *backup_part, const int verbose) +{ + list_part_t *partition; + for(partition=backup_part;partition!=NULL;partition=partition->next) + { + int insert_error=0; + partition_t *new_partition=partition_new(NULL); + dup_partition_t(new_partition,partition->part); + list_part=insert_new_partition(list_part, new_partition, 0, &insert_error); + if(insert_error>0) + free(new_partition); + } + return list_part; +} + +list_part_t *interface_load(disk_t *disk_car,list_part_t *list_part, const int verbose) +{ + struct td_list_head *backup_walker=NULL; + struct td_list_head *backup_current=NULL; + backup_disk_t *backup_list=partition_load(disk_car,verbose); + log_info("interface_load\n"); + td_list_for_each(backup_walker,&backup_list->list) + { + list_part_t *element; + backup_disk_t *backup; + backup=td_list_entry(backup_walker, backup_disk_t, list); + log_info("%s %s",backup->description,ctime(&backup->my_time)); + for(element=backup->list_part;element!=NULL;element=element->next) + log_partition(disk_car,element->part); + } +#ifdef HAVE_NCURSES + backup_current=interface_load_ncurses(disk_car, backup_list, verbose); +#endif + if(backup_current!=NULL) + { + list_part_t *partition; + backup_disk_t *backup; + backup=td_list_entry(backup_current, backup_disk_t, list); + for(partition=backup->list_part;partition!=NULL;partition=partition->next) + { + /* Check partition and load partition name */ + disk_car->arch->check_part(disk_car,verbose,partition->part,0); + } + list_part=merge_partition_list(list_part,backup->list_part,verbose); + } + { /* Cleanup */ + struct td_list_head *backup_walker_next = NULL; + td_list_for_each_safe(backup_walker,backup_walker_next,&backup_list->list) + { + backup_disk_t *backup; + backup=td_list_entry(backup_walker, backup_disk_t, list); + part_free_list(backup->list_part); + free(backup); + } + free(backup_list); + } + return list_part; +} +#endif diff --git a/src/tload.h b/src/tload.h new file mode 100644 index 00000000..4d2d7969 --- /dev/null +++ b/src/tload.h @@ -0,0 +1,24 @@ +/* + + File: tload.h + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_NCURSES +list_part_t *interface_load(disk_t *disk_car,list_part_t *list_part, const int verbose); +#endif diff --git a/src/tlog.c b/src/tlog.c new file mode 100644 index 00000000..90a4e4a4 --- /dev/null +++ b/src/tlog.c @@ -0,0 +1,101 @@ +/* + + File: tlog.c + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "types.h" +#include "common.h" +#include "intrf.h" +#ifdef HAVE_NCURSES +#include "intrfn.h" +#else +#include +#endif +#include "log.h" +#include "tlog.h" + +#ifdef HAVE_NCURSES +int ask_testdisk_log_creation() +{ + unsigned int menu=0; + static struct MenuItem menuLogCreation[]= + { + {'C',"Create","Create a new log file"}, + {'A',"Append","Append information to log file"}, + {'Q',"No Log","Don't record anything"}, + {0,NULL,NULL} + }; + aff_copy(stdscr); + wmove(stdscr,5,0); + wprintw(stdscr,"TestDisk is a free data recovery software designed to help recover lost"); + wmove(stdscr,6,0); + wprintw(stdscr,"partitions and/or make non-booting disks bootable again when these symptoms"); + wmove(stdscr,7,0); + wprintw(stdscr,"are caused by faulty software, certain types of viruses or human error."); + wmove(stdscr,8,0); + wprintw(stdscr,"It can also be used to repair some filesystem errors."); + wmove(stdscr,10,0); + wprintw(stdscr,"Information gathered during TestDisk use can be recorded for later"); + wmove(stdscr,11,0); + wprintw(stdscr,"review. If you choose to create the text file, "); + if(has_colors()) + wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); + wprintw(stdscr,"testdisk.log"); + if(has_colors()) + wbkgdset(stdscr,' ' | COLOR_PAIR(0)); + wprintw(stdscr," , it"); + wmove(stdscr,12,0); + wprintw(stdscr,"will contain TestDisk options, technical information and various"); + wmove(stdscr,13,0); + wprintw(stdscr,"outputs; including any folder/file names TestDisk was used to find and"); + wmove(stdscr,14,0); + wprintw(stdscr,"list onscreen."); + wmove(stdscr,16,0); + wprintw(stdscr,"Use arrow keys to select, then press Enter key:"); + while(1) + { + int command; + command = wmenuSelect_ext(stdscr, 24, 17, 0, menuLogCreation, 8, + "CAQ", MENU_VERT | MENU_VERT_WARN | MENU_BUTTON, &menu,NULL); + switch(command) + { + case 'C': + case 'c': + return TD_LOG_CREATE; + case 'A': + case 'a': + return TD_LOG_APPEND; + case 'Q': + case 'q': + return TD_LOG_REFUSED; + default: + break; + } + } +} +#else +int ask_testdisk_log_creation() +{ + return TD_LOG_REFUSED; +} +#endif diff --git a/src/tlog.h b/src/tlog.h new file mode 100644 index 00000000..3b01904e --- /dev/null +++ b/src/tlog.h @@ -0,0 +1,22 @@ +/* + + File: tlog.h + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +int ask_testdisk_log_creation(void); diff --git a/src/tmbrcode.c b/src/tmbrcode.c new file mode 100644 index 00000000..440b5a77 --- /dev/null +++ b/src/tmbrcode.c @@ -0,0 +1,84 @@ +/* + + File: mbrcode.c + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif +#include "types.h" +#include "common.h" +#include "lang.h" +#include "intrf.h" +#ifdef HAVE_NCURSES +#include "intrfn.h" +#else +#include +#endif +#include "tmbrcode.h" + +#ifdef HAVE_NCURSES +#define INTER_DISK_X 0 +#define INTER_DISK_Y 7 +int write_MBR_code(disk_t *disk_car) +{ + aff_copy(stdscr); + wmove(stdscr,5,0); + wprintw(stdscr,"%s\n",disk_car->description(disk_car)); + wmove(stdscr,INTER_DISK_Y,INTER_DISK_X); + if(disk_car->arch->write_MBR_code==NULL) + { + display_message("Function to write a new MBR code not implemented for this partition type.\n"); + return 1; + } + wprintw(stdscr,msg_WRITE_MBR_CODE); + if(ask_YN(stdscr)!=0 && ask_confirmation("Write a new copy of MBR code, confirm ? (Y/N)")!=0) + { + if(disk_car->arch->write_MBR_code(disk_car)) + { + display_message("Write error: Can't write new MBR code.\n"); + return 2; + } + else + display_message("A new copy of MBR code has been written.\nYou have to reboot for the change to take effect.\n"); + } + return 0; +} +#else +static int write_MBR_code(disk_t *disk_car) +{ + if(disk_car->arch->write_MBR_code==NULL) + { + log_error("Function to write a new MBR code not implemented for this partition type.\n"); + return 1; + } + if(disk_car->arch->write_MBR_code(disk_car)) + { + log_error("Write error: Can't write new MBR code.\n"); + return 2; + } + else + log_info("A new copy of MBR code has been written.\nYou have to reboot for the change to take effect.\n"); + return 0; +} +#endif diff --git a/src/tmbrcode.h b/src/tmbrcode.h new file mode 100644 index 00000000..21af6ba7 --- /dev/null +++ b/src/tmbrcode.h @@ -0,0 +1,2 @@ +int write_MBR_code(disk_t *disk_car); + diff --git a/src/toptions.c b/src/toptions.c new file mode 100644 index 00000000..64aa12de --- /dev/null +++ b/src/toptions.c @@ -0,0 +1,127 @@ +/* + + File: toptions.c + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "types.h" +#include "common.h" +#include "intrf.h" +#ifdef HAVE_NCURSES +#include "intrfn.h" +#else +#include +#endif +#include "log.h" +#include "toptions.h" + +#ifdef HAVE_NCURSES +static void interface_options_ncurses(int *dump_ind, int *align, int *allow_partial_last_cylinder, unsigned int *expert) +{ + unsigned int menu = 4; + /* ncurses interface */ + while (1) + { + int car; + int real_key; + struct MenuItem menuOptions[]= + { + { 'E',NULL,"Expert mode adds some functionalities"}, + { 'C',NULL,"Partitions are aligned on cylinder/head boundaries" }, + { 'A',NULL,""}, + { 'D',NULL,"Dump essential sectors" }, + { 'Q',"[ Ok ]","Done with changing options"}, + { 0, NULL, NULL } + }; + menuOptions[0].name=*expert?"Expert mode : Yes":"Expert mode : No"; + switch(*align) + { + case 0: + menuOptions[1].name="Cylinder boundary : No"; + break; + case 1: + menuOptions[1].name="Cylinder boundary : Head boundary only"; + break; + case 2: + menuOptions[1].name="Cylinder boundary : Yes"; + break; + } + menuOptions[2].name=*allow_partial_last_cylinder?"Allow partial last cylinder : Yes":"Allow partial last cylinder : No"; + menuOptions[3].name=*dump_ind?"Dump : Yes":"Dump : No"; + aff_copy(stdscr); + car=wmenuSelect_ext(stdscr, 24, INTER_OPTION_Y, INTER_OPTION_X, menuOptions, 0, "ECADQ", MENU_VERT|MENU_VERT_ARROW2VALID, &menu,&real_key); + switch(car) + { + case 'd': + case 'D': + *dump_ind=!*dump_ind; + break; + case 'c': + case 'C': + if(*align<2) + (*align)++; + else + *align=0; + break; + case 'a': + case 'A': + *allow_partial_last_cylinder=!*allow_partial_last_cylinder; + break; + case 'e': + case 'E': + *expert=!*expert; + break; + case key_ESC: + case 'q': + case 'Q': + return; + } + } +} +#endif + +void interface_options(int *dump_ind, int *align, int *allow_partial_last_cylinder, unsigned int *expert, char**current_cmd) +{ + if(*current_cmd==NULL) + { +#ifdef HAVE_NCURSES + interface_options_ncurses(dump_ind, align, allow_partial_last_cylinder, expert); +#endif + } + /* write new options to log file */ + log_info("New options :\n Dump : %s\n ", (*dump_ind?"Yes":"No")); + switch(*align) + { + case 0: + log_info("Cylinder boundary : No"); + break; + case 1: + log_info("Cylinder boundary : Head boundary only"); + break; + case 2: + log_info("Cylinder boundary : Yes"); + break; + } + log_info("\n Allow partial last cylinder : %s\n Expert mode : %s\n", + *allow_partial_last_cylinder?"Yes":"No", + *expert?"Yes":"No"); +} diff --git a/src/toptions.h b/src/toptions.h new file mode 100644 index 00000000..96dd2aa9 --- /dev/null +++ b/src/toptions.h @@ -0,0 +1,22 @@ +/* + + File: toptions.h + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +void interface_options(int *dump_ind, int *align, int *allow_partial_last_cylinder, unsigned int *expert, char**current_cmd); diff --git a/src/tpartwr.c b/src/tpartwr.c new file mode 100644 index 00000000..95b882a1 --- /dev/null +++ b/src/tpartwr.c @@ -0,0 +1,150 @@ +/* + + File: tpartwr.c + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif +#include "types.h" +#include "common.h" +#include "lang.h" +#include "intrf.h" +#ifdef HAVE_NCURSES +#include "intrfn.h" +#else +#include +#endif +#include "log.h" +#include "tpartwr.h" + +int interface_write(disk_t *disk_car,list_part_t *list_part,const int can_search_deeper, const int can_ask_minmax_ext, int *no_confirm, char **current_cmd, unsigned int *menu) +{ + list_part_t *parts; +#ifdef HAVE_NCURSES + struct MenuItem menuWrite[]= + { + { 'P', "Previous",""}, + { 'N', "Next","" }, + { 'Q', "Quit","Return to main menu"}, + { 'S', "Deeper Search","Try to find more partitions"}, + { 'W', "Write","Write partition structure to disk"}, + { 'E', "Extd Part","Maximize/Minimize extended partition"}, + { 0, NULL, NULL } + }; +#endif + int command; + log_info("\ninterface_write()\n"); + screen_buffer_reset(); +#ifdef HAVE_NCURSES + aff_copy(stdscr); + wmove(stdscr,4,0); + wprintw(stdscr,"%s",disk_car->description(disk_car)); + wmove(stdscr,5,0); + mvwaddstr(stdscr,6,0,msg_PART_HEADER_LONG); +#endif + for(parts=list_part;parts!=NULL;parts=parts->next) + if(parts->part->status!=STATUS_LOG) + aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,parts->part); + for(parts=list_part;parts!=NULL;parts=parts->next) + if(parts->part->status==STATUS_LOG) + aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,parts->part); + command='Q'; + if(list_part==NULL) + { + screen_buffer_add(" \nNo partition found or selected for recovery"); + screen_buffer_to_log(); + if(*current_cmd!=NULL) + { + while(*current_cmd[0]==',') + (*current_cmd)++; + if(strncmp(*current_cmd,"search",6)==0) + { + (*current_cmd)+=6; + command='S'; + } + } + else + { + log_flush(); +#ifdef HAVE_NCURSES + command=screen_buffer_display_ext(stdscr,(can_search_deeper?"S":""),menuWrite,menu); +#endif + } + } + else + { + if(*current_cmd!=NULL) + { + do + { + command='Q'; + while(*current_cmd[0]==',') + (*current_cmd)++; + if(strncmp(*current_cmd,"search",6)==0) + { + (*current_cmd)+=6; + if(can_search_deeper) + command='S'; + } + else if(strncmp(*current_cmd,"noconfirm",9)==0) + { + command=0; /* do nothing */ + (*no_confirm)=1; + (*current_cmd)+=9; + } + else if(strncmp(*current_cmd,"write",5)==0) + { + (*current_cmd)+=5; + if(disk_car->arch->write_part!=NULL) + command='W'; + } + } while(command==0); + screen_buffer_to_log(); + } + else + { + char options[10]; + options[0]=0; + if(can_search_deeper) + strcat(options,"S"); + if(disk_car->arch->write_part!=NULL) + strcat(options,"W"); + else + screen_buffer_add(" \nWrite isn't available because the partition table type \"%s\" has been selected.", + disk_car->arch->part_name); + if(can_ask_minmax_ext) + strcat(options,"E"); + screen_buffer_to_log(); + log_flush(); +#ifdef HAVE_NCURSES + command=screen_buffer_display_ext(stdscr,options,menuWrite,menu); +#else + command='Q'; +#endif + } + } + return command; +} + + diff --git a/src/tpartwr.h b/src/tpartwr.h new file mode 100644 index 00000000..459b25f0 --- /dev/null +++ b/src/tpartwr.h @@ -0,0 +1,22 @@ +/* + + File: tpartwr.c + + Copyright (C) 2008 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +int interface_write(disk_t *disk_car,list_part_t *list_part,const int can_search_deeper, const int can_ask_minmax_ext, int *no_confirm, char **current_cmd, unsigned int *menu);