summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Grenier <[email protected]>2008-08-24 13:36:34 +0200
committerChristophe Grenier <[email protected]>2008-08-24 13:36:34 +0200
commit9a58a494f354766e1bda5ca0f72e0af60f5124de (patch)
treebfabf63ee6684f79b6f724f2cda5de8b5fadbc76
parent05241d82968e9ee7195a424091e733b43d776945 (diff)
Split the interface in several files
Initial work to handle 24 lines and more than 25
-rw-r--r--src/Makefile.am2
-rw-r--r--src/adv.c225
-rw-r--r--src/chgtype.c34
-rw-r--r--src/dir.c12
-rw-r--r--src/diskacc.c142
-rw-r--r--src/diskacc.h23
-rw-r--r--src/diskcapa.c119
-rw-r--r--src/diskcapa.h1
-rw-r--r--src/diskcp.c254
-rw-r--r--src/ext2_sb.c92
-rw-r--r--src/ext2_sb.h22
-rw-r--r--src/fat_adv.c16
-rw-r--r--src/godmode.c17
-rw-r--r--src/intrf.c63
-rw-r--r--src/intrf.h5
-rw-r--r--src/intrface.c1241
-rw-r--r--src/intrface.h6
-rw-r--r--src/ntfs_udl.c12
-rw-r--r--src/phrecn.c76
-rw-r--r--src/tanalyse.c115
-rw-r--r--src/tanalyse.h23
-rw-r--r--src/tdelete.c82
-rw-r--r--src/tdelete.h22
-rw-r--r--src/tdiskop.c257
-rw-r--r--src/tdiskop.h23
-rw-r--r--src/tdisksel.c236
-rw-r--r--src/tdisksel.h24
-rw-r--r--src/testdisk.c2
-rw-r--r--src/tload.c254
-rw-r--r--src/tload.h24
-rw-r--r--src/tlog.c101
-rw-r--r--src/tlog.h22
-rw-r--r--src/tmbrcode.c84
-rw-r--r--src/tmbrcode.h2
-rw-r--r--src/toptions.c127
-rw-r--r--src/toptions.h22
-rw-r--r--src/tpartwr.c150
-rw-r--r--src/tpartwr.h22
38 files changed, 2475 insertions, 1479 deletions
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_num<offset)
- offset--;
- }
- break;
- case KEY_DOWN:
- if(current_element!=NULL)
- {
- if(current_element->next!=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))
- {
- 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))
+ }
+ if(current_element!=NULL)
+ {
+ switch(command)
+ {
+#ifdef HAVE_NCURSES
+ case 'p':
+ case 'P':
+ case KEY_UP:
+ if(current_element->prev!=NULL)
{
- ntfs_boot_sector(disk_car, partition, verbose, dump_ind, expert, current_cmd);
- rewrite=1;
+ current_element=current_element->prev;
+ current_element_num--;
}
- else if(partition->upart_type==UP_FAT32)
+ break;
+ case 'n':
+ case 'N':
+ case KEY_DOWN:
+ if(current_element->next!=NULL)
{
- fat32_boot_sector(disk_car, partition, verbose, dump_ind, expert,current_cmd);
- rewrite=1;
+ current_element=current_element->next;
+ current_element_num++;
}
- else if(partition->upart_type==UP_FAT12 || partition->upart_type==UP_FAT16)
+ break;
+ case KEY_PPAGE:
+ for(i=0;i<INTER_ADV-1 && current_element->prev!=NULL;i++)
{
- fat1x_boot_sector(disk_car, partition, verbose, dump_ind,expert,current_cmd);
- rewrite=1;
+ current_element=current_element->prev;
+ current_element_num--;
}
- else if(partition->upart_type==UP_NTFS)
+ break;
+ case KEY_NPAGE:
+ for(i=0;i<INTER_ADV-1 && current_element->next!=NULL;i++)
{
- ntfs_boot_sector(disk_car, partition, verbose, dump_ind, expert, current_cmd);
- rewrite=1;
+ current_element=current_element->next;
+ current_element_num++;
}
- }
- 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)
+ break;
+#endif
+ case 'b':
+ case 'B':
{
- 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;
+ 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;
+ }
}
- if(image_dd!=NULL)
+ break;
+ case 'c':
+ case 'C':
{
- disk_image(disk_car, current_element->part, image_dd);
- free(image_dd);
+ 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))
+ break;
+ case 'u':
+ case 'U':
+ case 'l':
+ case 'L':
{
- 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);
+ 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);
}
- if(is_hfs(current_element->part) || is_hfsp(current_element->part))
+ break;
+ case 's':
+ case 'S':
{
- HFS_HFSP_boot_sector(disk_car, current_element->part, verbose, dump_ind, expert, current_cmd);
+ 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;
}
- 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)
+ offset=current_element_num;
+ 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)
- offset=current_element_num;
break;
case 'n':
case 'N':
case KEY_DOWN:
if(current_element_num < intr_nbr_line-1)
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)
- offset=current_element_num;
break;
case 'n':
case 'N':
case KEY_DOWN:
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 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<INTER_CHGTYPE;j++)
{
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 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)
+ offset=current_element_num;
+ 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_num<offset)
- offset--;
break;
case KEY_DOWN:
case '2':
@@ -423,8 +421,6 @@ static long int dir_aff_ncurses(disk_t *disk_car, const partition_t *partition,
pos=pos->next;
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_num<offset)
- offset--;
}
break;
case KEY_NPAGE:
@@ -469,8 +463,6 @@ static long int dir_aff_ncurses(disk_t *disk_car, const partition_t *partition,
{
pos=pos->next;
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)
+ offset=pos_num;
+ 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 <[email protected]>
+
+ 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 <config.h>
+#endif
+
+#include <stdarg.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include <ctype.h>
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#include "types.h"
+#include "common.h"
+#include "lang.h"
+#include "intrf.h"
+#ifdef HAVE_NCURSES
+#include "intrfn.h"
+#else
+#include <stdio.h>
+#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 <[email protected]>
+
+ 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 <[email protected]>
+
+ 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 <config.h>
+#endif
+
+#include <stdarg.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include <ctype.h>
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#include "types.h"
+#include "common.h"
+#include "lang.h"
+#include "intrf.h"
+#ifdef HAVE_NCURSES
+#include "intrfn.h"
+#else
+#include <stdio.h>
+#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 <[email protected]>
+
+ 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 <config.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h> /* BLKFLSBUF */
+#endif
+#ifdef HAVE_SYS_DISK_H
+#include <sys/disk.h>
+#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<disk_size;)
+ {
+ int status;
+ lseek(disk_src[current_disk], location, SEEK_SET);
+ do
+ {
+ if(read(disk_src[current_disk],buffer,readsize)==readsize)
+ {
+ lseek(disk_dst, location, SEEK_SET);
+ write(disk_dst,buffer,readsize);
+ readok+=readsize;
+ status=STATUS_DONE;
+ }
+ else
+ {
+ status=((readsize==readsize_min)?STATUS_BAD_BLOCK:STATUS_NON_SPLIT);
+ if(status==STATUS_NON_SPLIT)
+ {
+ readsize=readsize_min;
+ }
+ }
+ } while(status==STATUS_NON_SPLIT);
+ if(location==0)
+ {
+ old_status=status;
+ }
+ if(status!=old_status && old_status_location < location)
+ {
+ fprintf(log,"%08llX - %08llX %c\n",
+ (unsigned long long)(old_status_location/sector_size),
+ (unsigned long long)((location-1)/sector_size),
+ old_status);
+ fflush(log);
+ old_status_location=location;
+ old_status=status;
+ }
+ if(status==STATUS_DONE)
+ {
+ gap=-1;
+ first_disk=current_disk;
+ first_disk_readsize=readsize;
+ location+=readsize;
+ if(readsize<readsize_max)
+ readsize*=2;
+ }
+ else
+ {
+ char buf[100];
+ printf("Sector %llu", (unsigned long long) (location/sector_size));
+ printf(" (%s)", size_to_unit(location), buf);
+ printf(" - Recovered %s\r", size_to_unit(readok, buf));
+ fflush(stdout);
+ current_disk=(current_disk+1)%nbr_disk;
+ readsize=readsize_min;
+ if(current_disk==first_disk)
+ {
+ location+=readsize;
+ /* Introduire les gaps */
+ fprintf(log,"%08llX - %08llX %c\n",
+ (unsigned long long)(old_status_location/sector_size),
+ (unsigned long long)((location-1)/sector_size),
+ old_status);
+ fflush(log);
+ old_status_location=location;
+ old_status=STATUS_NON_TRIED;
+ if(gap<0)
+ gap=2;
+ location+=readsize_min<<gap;
+ if(gap<16)
+ gap++;
+ }
+ }
+ }
+ printf("\n");
+ fprintf(log,"%08llX - %08llX %c\n",
+ (unsigned long long)(old_status_location/sector_size),
+ (unsigned long long)((disk_size-1)/sector_size),
+ old_status);
+ fclose(log);
+ }
+ /* Pass 2: lire depuis la fin jusqu'� ce qu'il y ai une erreur */
+ {
+ FILE *oldlog;
+ if((oldlog=fopen("diskcp.log","r"))==NULL)
+ {
+ printf("Can't read diskcp.log file\n");
+ return 1;
+ }
+ if((log=fopen("diskcp2.log","w"))==NULL)
+ {
+ printf("Can't create diskcp2.log file\n");
+ fclose(oldlog);
+ return 1;
+ }
+ {
+ long long unsigned start[3];
+ long long unsigned end[3];
+ char status[3];
+ int nbr=0;
+ while(fscanf(oldlog,"%llu - %llu %c", &start[nbr], &end[nbr], &status[nbr])==3)
+ {
+ printf("%llu - %llu %c\n", &start[nbr], &end[nbr], &status[nbr]);
+ if(nbr==3 && status[1]==STATUS_NON_TRIED && status[2]==STATUS_DONE)
+ {
+ for(location=end[nbr];location>=start[nbr];location-=readsize_min)
+ {
+
+ }
+ }
+ }
+ }
+ fclose(log);
+ fclose(oldlog);
+ }
+
+ /* Pass 3: read */
+ for(i=0;i<nbr_disk;i++)
+ close(disk_src[i]);
+ close(disk_dst);
+ return 0;
+}
diff --git a/src/ext2_sb.c b/src/ext2_sb.c
new file mode 100644
index 00000000..26b84ac3
--- /dev/null
+++ b/src/ext2_sb.c
@@ -0,0 +1,92 @@
+/*
+
+ File: ext2_sb.c
+
+ Copyright (C) 2008 Christophe GRENIER <[email protected]>
+
+ 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 <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include "types.h"
+#include "common.h"
+#include "lang.h"
+#include "intrf.h"
+#ifdef HAVE_NCURSES
+#include "intrfn.h"
+#else
+#include <stdio.h>
+#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 <[email protected]>
+
+ 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_num<offset)
- offset--;
break;
case KEY_DOWN:
if(pos->next!=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;(i<INTER_DIR-1)&&(pos->prev!=NULL);i++)
+ for(i=0; i<INTER_DIR-1 && pos->prev!=NULL; i++)
{
pos=pos->prev;
pos_num--;
- if(pos_num<offset)
- offset--;
}
break;
case KEY_NPAGE:
- for(i=0;(i<INTER_DIR-1)&&(pos->next!=NULL);i++)
+ for(i=0; i<INTER_DIR-1 && pos->next!=NULL; i++)
{
pos=pos->next;
pos_num++;
- if(pos_num>=offset+INTER_DIR)
- offset++;
}
break;
}
+ if(pos_num<offset)
+ offset=pos_num;
+ 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_num<offset)
- offset--;
}
break;
case KEY_DOWN:
@@ -221,37 +220,35 @@ static int interface_part_bad_ncurses(disk_t *disk_car, list_part_t *list_part)
pos=pos->next;
pos_num++;
}
- if(pos_num>=offset+INTER_BAD_PART)
- offset++;
}
break;
case KEY_PPAGE:
if(list_part!=NULL)
{
- for(i=0;(i<INTER_BAD_PART) && (pos->prev!=NULL);i++)
+ for(i=0; i<INTER_BAD_PART && pos->prev!=NULL; i++)
{
pos=pos->prev;
pos_num--;
- if(pos_num<offset)
- offset--;
}
}
break;
case KEY_NPAGE:
if(list_part!=NULL)
{
- for(i=0;(i<INTER_BAD_PART) && (pos->next!=NULL);i++)
+ for(i=0; i<INTER_BAD_PART && pos->next!=NULL; i++)
{
pos=pos->next;
pos_num++;
- if(pos_num>=offset+INTER_BAD_PART)
- offset++;
}
}
break;
default:
break;
}
+ if(pos_num<offset)
+ offset=pos_num;
+ 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; (i<intr_nbr_line)&&((i-first_line_to_display)<INTER_MAX_LINES); i++)
+ if(intr_nbr_line>INTER_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; i<intr_nbr_line && (i-first_line_to_display)<INTER_MAX_LINES; i++)
+ {
+ wmove(window,INTER_ANALYSE_Y+i-first_line_to_display,INTER_ANALYSE_X);
+ wclrtoeol(window);
+ if(i==current_line)
+ wattrset(window, A_REVERSE);
+ wprintw(window,"%s",intr_buffer_screen[i]);
+ if(i==current_line)
+ wattroff(window, A_REVERSE);
+ }
+ }
+ else
+ {
+ for (i=first_line_to_display; i<intr_nbr_line && (i-first_line_to_display)<INTER_MAX_LINES; i++)
+ {
+ wmove(window,INTER_ANALYSE_Y+i-first_line_to_display,INTER_ANALYSE_X);
+ wclrtoeol(window);
+ wprintw(window,"%s",intr_buffer_screen[i]);
+ }
}
wmove(window, INTER_ANALYSE_Y+INTER_MAX_LINES, INTER_ANALYSE_X+4);
wclrtoeol(window);
if(i<intr_nbr_line)
wprintw(window, "Next");
- key=wmenuSelect_ext(window, 24, INTER_ANALYSE_MENU_Y, INTER_ANALYSE_MENU_X, (menuItems!=NULL?menuItems:menuDefault),
- itemLength, options, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, menu,NULL);
+ key=wmenuSelect_ext(window, INTER_ANALYSE_MENU_Y+1,
+ INTER_ANALYSE_MENU_Y, INTER_ANALYSE_MENU_X,
+ (menuItems!=NULL?menuItems:menuDefault), itemLength, options,
+ MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, menu,NULL);
switch (key)
{
case key_ESC:
@@ -1021,38 +1040,34 @@ int screen_buffer_display_ext(WINDOW *window, const char *options_org, const str
case KEY_UP:
if(current_line>0)
current_line--;
- if(current_line<first_line_to_display)
- first_line_to_display=current_line;
break;
case 'n':
case 'N':
case KEY_DOWN:
if(current_line<intr_nbr_line-1)
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)
- first_line_to_display=current_line;
break;
case KEY_NPAGE:
if(current_line+INTER_MAX_LINES-1 < intr_nbr_line-1)
current_line+=INTER_MAX_LINES-1;
else
current_line=intr_nbr_line-1;
- 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)
+ first_line_to_display=current_line;
+ 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_num<offset)
- offset--;
quit=ASK_LOCATION_UPDATE;
}
break;
@@ -1733,8 +1746,6 @@ char *ask_location(const char*msg, const char *src_dir)
{
current_file=current_file->next;
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_num<offset)
- offset--;
quit=ASK_LOCATION_UPDATE;
}
}
@@ -1758,8 +1767,6 @@ char *ask_location(const char*msg, const char *src_dir)
{
current_file=current_file->next;
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)
+ offset=pos_num;
+ 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 <[email protected]>
+ Copyright (C) 1998-2008 Christophe GRENIER <[email protected]>
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 <config.h>
#endif
-#include <stdarg.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
-#include <ctype.h>
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
#include "types.h"
#include "common.h"
#include "lang.h"
@@ -52,38 +35,18 @@
#else
#include <stdio.h>
#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) && (i<offset);element_disk=element_disk->next,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_num<offset)
- offset--;
- break;
- case KEY_DOWN:
- case 'N':
- if(current_disk->next!=NULL)
- {
- current_disk=current_disk->next;
- pos_num++;
- }
- if(pos_num>=offset+10)
- offset++;
- break;
- case KEY_PPAGE:
- for(i=0;i<INTER_STRUCTURE && current_disk->prev!=NULL;i++)
- {
- current_disk=current_disk->prev;
- pos_num--;
- if(pos_num<offset)
- offset--;
- }
- break;
- case KEY_NPAGE:
- for(i=0;i<INTER_STRUCTURE && current_disk->next!=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_num<offset)
- offset--;
}
break;
case KEY_DOWN:
@@ -1178,20 +269,16 @@ static list_part_t *ask_structure_ncurses(disk_t *disk_car,list_part_t *list_par
pos=pos->next;
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;(i<INTER_STRUCTURE) && (pos->prev!=NULL);i++)
+ for(i=0; i<INTER_STRUCTURE && pos->prev!=NULL; i++)
{
pos=pos->prev;
pos_num--;
- if(pos_num<offset)
- offset--;
}
}
break;
@@ -1199,12 +286,10 @@ static list_part_t *ask_structure_ncurses(disk_t *disk_car,list_part_t *list_par
if(list_part!=NULL)
{
only_one_bootable(list_part,pos);
- for(i=0;(i<INTER_STRUCTURE) && (pos->next!=NULL);i++)
+ for(i=0; i<INTER_STRUCTURE && pos->next!=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)
+ offset=pos_num;
+ 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) && (i<offset);backup_walker=backup_walker->next,i++);
- for(i=offset;(backup_walker!=&backup_list->list) &&((i-offset)<INTER_STRUCTURE);i++,backup_walker=backup_walker->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_num<offset)
- offset--;
- }
- break;
- case KEY_DOWN:
- if(backup_current->next!=&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;(i<INTER_STRUCTURE) && (backup_current->prev!=&backup_list->list);i++)
- {
- backup_current=backup_current->prev;
- backup_current_num--;
- if(backup_current_num<offset)
- offset--;
- }
- }
- break;
- case KEY_NPAGE:
- {
- for(i=0;(i<INTER_STRUCTURE) && (backup_current->next!=&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_num<offset)
- offset--;
}
break;
case KEY_DOWN:
@@ -1289,8 +1287,6 @@ static void ntfs_undelete_menu_ncurses(disk_t *disk_car, const partition_t *part
{
current_file=current_file->next;
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_num<offset)
- offset--;
}
break;
case KEY_NPAGE:
@@ -1307,8 +1301,6 @@ static void ntfs_undelete_menu_ncurses(disk_t *disk_car, const partition_t *part
{
current_file=current_file->next;
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)
+ offset=pos_num;
+ 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_num<offset)
- offset--;
+ current_element=current_element->prev;
+ current_element_num--;
+ }
+ break;
+ case KEY_PPAGE:
+ for(i=0; i<INTER_SELECT && current_element->prev!=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; i<INTER_SELECT && current_element->next!=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)
+ offset=current_element_num;
+ 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_num<offset)
- offset--;
break;
case KEY_DOWN:
case 'N':
@@ -2112,16 +2118,12 @@ static void photorec_disk_selection_ncurses(int verbose, const char *recup_dir,
current_disk=current_disk->next;
pos_num++;
}
- if(pos_num>=offset+INTER_MENU_DISK)
- offset++;
break;
case KEY_PPAGE:
for(i=0;i<INTER_MENU_DISK && current_disk->prev!=NULL;i++)
{
current_disk=current_disk->prev;
pos_num--;
- if(pos_num<offset)
- offset--;
}
break;
case KEY_NPAGE:
@@ -2129,8 +2131,6 @@ static void photorec_disk_selection_ncurses(int verbose, const char *recup_dir,
{
current_disk=current_disk->next;
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)
+ offset=pos_num;
+ 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_num<offset)
- offset--;
- }
break;
case KEY_PPAGE:
case '9':
- for(i=0;i<INTER_FSELECT-1 && current_element_num>0;i++)
- {
+ for(i=0; i<INTER_FSELECT-1 && current_element_num>0; i++)
current_element_num--;
- if(current_element_num<offset)
- offset--;
- }
break;
case KEY_DOWN:
case '2':
if(files_enable[current_element_num+1].file_hint!=NULL)
- {
current_element_num++;
- if(current_element_num>=offset+INTER_FSELECT)
- offset++;
- }
break;
case KEY_NPAGE:
case '3':
- for(i=0;i<INTER_FSELECT-1 && (files_enable[current_element_num+1].file_hint!=NULL);i++)
- {
+ for(i=0; i<INTER_FSELECT-1 && files_enable[current_element_num+1].file_hint!=NULL; i++)
current_element_num++;
- if(current_element_num>=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)
+ offset=current_element_num;
+ 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 <[email protected]>
+
+ 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 <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include "types.h"
+#include "common.h"
+#include "lang.h"
+#include "intrf.h"
+#ifdef HAVE_NCURSES
+#include "intrfn.h"
+#else
+#include <stdio.h>
+#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 <[email protected]>
+
+ 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 <[email protected]>
+
+ 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 <config.h>
+#endif
+
+#include "types.h"
+#include "common.h"
+#include "lang.h"
+#include "intrf.h"
+#ifdef HAVE_NCURSES
+#include "intrfn.h"
+#else
+#include <stdio.h>
+#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 <[email protected]>
+
+ 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 <[email protected]>
+
+ 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 <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include "types.h"
+#include "common.h"
+#include "intrf.h"
+#ifdef HAVE_NCURSES
+#include "intrfn.h"
+#else
+#include <stdio.h>
+#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 <[email protected]>
+
+ 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 <[email protected]>
+
+ 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 <config.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include "types.h"
+#include "common.h"
+#include "intrf.h"
+#ifdef HAVE_NCURSES
+#include "intrfn.h"
+#else
+#include <stdio.h>
+#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) && (i<offset);element_disk=element_disk->next,i++);
+ for(;element_disk!=NULL && (i-offset)<NBR_DISK_MAX;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<=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;i<NBR_DISK_MAX-1 && current_disk->prev!=NULL;i++)
+ {
+ current_disk=current_disk->prev;
+ pos_num--;
+ }
+ break;
+ case KEY_NPAGE:
+ for(i=0;i<NBR_DISK_MAX-1 && current_disk->next!=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)
+ offset=pos_num;
+ 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 <[email protected]>
+
+ 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 <[email protected]>
+
+ 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 <config.h>
+#endif
+
+#include <stdarg.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include <ctype.h>
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#include "types.h"
+#include "common.h"
+#include "lang.h"
+#include "intrf.h"
+#ifdef HAVE_NCURSES
+#include "intrfn.h"
+#else
+#include <stdio.h>
+#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) && (i<offset);backup_walker=backup_walker->next,i++);
+ for(i=offset;(backup_walker!=&backup_list->list) &&((i-offset)<INTER_STRUCTURE);i++,backup_walker=backup_walker->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;(i<INTER_STRUCTURE) && (backup_current->prev!=&backup_list->list);i++)
+ {
+ backup_current=backup_current->prev;
+ backup_current_num--;
+ }
+ break;
+ case KEY_NPAGE:
+ for(i=0;(i<INTER_STRUCTURE) && (backup_current->next!=&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)
+ offset=backup_current_num;
+ 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 <[email protected]>
+
+ 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 <[email protected]>
+
+ 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 <config.h>
+#endif
+
+#include "types.h"
+#include "common.h"
+#include "intrf.h"
+#ifdef HAVE_NCURSES
+#include "intrfn.h"
+#else
+#include <stdio.h>
+#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 <[email protected]>
+
+ 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 <[email protected]>
+
+ 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 <config.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "types.h"
+#include "common.h"
+#include "lang.h"
+#include "intrf.h"
+#ifdef HAVE_NCURSES
+#include "intrfn.h"
+#else
+#include <stdio.h>
+#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 <[email protected]>
+
+ 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 <config.h>
+#endif
+
+#include "types.h"
+#include "common.h"
+#include "intrf.h"
+#ifdef HAVE_NCURSES
+#include "intrfn.h"
+#else
+#include <stdio.h>
+#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 <[email protected]>
+
+ 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 <[email protected]>
+
+ 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 <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include "types.h"
+#include "common.h"
+#include "lang.h"
+#include "intrf.h"
+#ifdef HAVE_NCURSES
+#include "intrfn.h"
+#else
+#include <stdio.h>
+#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 <[email protected]>
+
+ 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);