testdisk/src/pdiskseln.c
2020-03-20 16:57:57 +01:00

336 lines
9 KiB
C

/*
File: pdiskseln.c
Copyright (C) 1998-2008 Christophe GRENIER <grenier@cgsecurity.org>
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
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(DJGPP) || !defined(HAVE_GETEUID)
#undef SUDO_BIN
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* geteuid */
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "types.h"
#include "common.h"
#include "intrf.h"
#ifdef HAVE_NCURSES
#include "intrfn.h"
#endif
#include "dir.h"
#include "list.h"
#include "filegen.h"
#include "photorec.h"
#include "sessionp.h"
#include "partauto.h"
#include "log.h"
#include "pdisksel.h"
#include "pdiskseln.h"
#include "ppartseln.h"
#include "hidden.h"
#include "hiddenn.h"
#include "nodisk.h"
#include "chgarch.h"
#include "chgarchn.h"
#ifdef HAVE_NCURSES
#define NBR_DISK_MAX (LINES-6-8)
#define INTER_DISK_X 0
#define INTER_DISK_Y (8+NBR_DISK_MAX)
#define INTER_NOTE_Y (LINES-4)
#endif
extern const arch_fnct_t arch_none;
#ifdef HAVE_NCURSES
static int photorec_disk_selection_ncurses(struct ph_param *params, struct ph_options *options, const list_disk_t *list_disk, alloc_data_t *list_search_space)
{
int command;
int real_key;
unsigned int menu=0;
int offset=0;
int pos_num=0;
#ifdef SUDO_BIN
int use_sudo=0;
#endif
const list_disk_t *element_disk;
const list_disk_t *current_disk=list_disk;
static const struct MenuItem menuMain[]=
{
{ 'P', "Previous",""},
{ 'N', "Next","" },
{ 'O',"Proceed",""},
{ 'S', "Sudo", "Use the sudo command to restart as root"},
{ 'Q',"Quit","Quit program"},
{ 0,NULL,NULL}
};
if(list_disk==NULL)
{
log_critical("No disk found\n");
return intrf_no_disk_ncurses("PhotoRec");
}
/* ncurses interface */
while(1)
{
const char *menu_options;
int i;
aff_copy(stdscr);
wmove(stdscr,4,0);
wprintw(stdscr," PhotoRec 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):");
#if defined(KEY_MOUSE) && defined(ENABLE_MOUSE)
mousemask(ALL_MOUSE_EVENTS, NULL);
#endif
for(i=0,element_disk=list_disk;
element_disk!=NULL && i<offset+NBR_DISK_MAX;
i++, element_disk=element_disk->next)
{
if(i<offset)
continue;
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);
}
}
{
mvwaddstr(stdscr, INTER_NOTE_Y,0,"Note: ");
#if defined(HAVE_GETEUID) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(DJGPP)
if(geteuid()!=0)
{
if(has_colors())
wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(1));
wprintw(stdscr,"Some disks won't appear unless you're root user.");
if(has_colors())
wbkgdset(stdscr,' ' | COLOR_PAIR(0));
#ifdef SUDO_BIN
use_sudo=1;
#endif
}
#endif
wmove(stdscr, INTER_NOTE_Y+1, 0);
wprintw(stdscr,"Disk capacity must be correctly detected for a successful recovery.");
wmove(stdscr, INTER_NOTE_Y+2, 0);
wprintw(stdscr,"If a disk listed above has an incorrect size, check HD jumper settings and BIOS");
wmove(stdscr, INTER_NOTE_Y+3, 0);
wprintw(stdscr,"detection, and install the latest OS patches and disk drivers.");
}
#ifdef SUDO_BIN
if(use_sudo > 0)
{
if(i<=NBR_DISK_MAX && element_disk==NULL)
menu_options="OSQ";
else
menu_options="PNOSQ";
}
else
#endif
{
if(i<=NBR_DISK_MAX && element_disk==NULL)
menu_options="OQ";
else
menu_options="PNOQ";
}
command = wmenuSelect_ext(stdscr, INTER_NOTE_Y-1, INTER_DISK_Y, INTER_DISK_X, menuMain, 8,
menu_options, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, &menu,&real_key);
#if defined(KEY_MOUSE) && defined(ENABLE_MOUSE)
if(command == KEY_MOUSE)
{
MEVENT event;
if(getmouse(&event) == OK)
{ /* When the user clicks left mouse button */
if((event.bstate & BUTTON1_CLICKED) || (event.bstate & BUTTON1_DOUBLE_CLICKED))
{
if(event.y >=8 && event.y<8+NBR_DISK_MAX)
{
const int pos_num_old=pos_num;
/* Disk selection */
while(pos_num > event.y-(8-offset) && current_disk->prev!=NULL)
{
current_disk=current_disk->prev;
pos_num--;
}
while(pos_num < event.y-(8-offset) && current_disk->next!=NULL)
{
current_disk=current_disk->next;
pos_num++;
}
if(((event.bstate & BUTTON1_CLICKED) && pos_num==pos_num_old) ||
(event.bstate & BUTTON1_DOUBLE_CLICKED))
command='O';
}
else
command = menu_to_command(INTER_NOTE_Y-1, INTER_DISK_Y, INTER_DISK_X, menuMain, 8,
menu_options, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, event.y, event.x);
}
}
}
#endif
switch(command)
{
case KEY_UP:
case 'P':
if(current_disk->prev!=NULL)
{
current_disk=current_disk->prev;
pos_num--;
}
break;
case KEY_DOWN:
case 'N':
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;
const int hpa_dco=is_hpa_or_dco(disk);
autodetect_arch(disk, &arch_none);
params->disk=disk;
if((hpa_dco==0 || interface_check_hidden_ncurses(disk, hpa_dco)==0) &&
(options->expert == 0 ||
change_arch_type_ncurses(disk, options->verbose)==0))
menu_photorec(params, options, list_search_space);
}
break;
case 's':
case 'S':
return 1;
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
int do_curses_photorec(struct ph_param *params, struct ph_options *options, const list_disk_t *list_disk)
{
static alloc_data_t list_search_space={
.list = TD_LIST_HEAD_INIT(list_search_space.list)
};
const int resume_session=(params->cmd_device!=NULL && strcmp(params->cmd_device,"resume")==0);
if(params->cmd_device==NULL || resume_session!=0)
{
char *saved_device=NULL;
char *saved_cmd=NULL;
session_load(&saved_device, &saved_cmd,&list_search_space);
if(saved_device!=NULL && saved_cmd!=NULL && !td_list_empty(&list_search_space.list)
#ifdef HAVE_NCURSES
&& ( resume_session!=0 || ask_confirmation("Continue previous session ? (Y/N)")!=0)
#endif
)
{
#ifdef HAVE_NCURSES
{
WINDOW *window=newwin(LINES, COLS, 0, 0); /* full screen */
aff_copy(window);
mvwaddstr(window,5,0,"Resuming the recovery. Please wait...");
wrefresh(window);
delwin(window);
(void) clearok(stdscr, TRUE);
#ifdef HAVE_TOUCHWIN
touchwin(stdscr);
#endif
}
#endif
params->cmd_run=saved_cmd;
params->cmd_device=saved_device;
}
else
{
free(saved_device);
free(saved_cmd);
free_list_search_space(&list_search_space);
rename("photorec.ses", "photorec.se2");
}
}
if(params->cmd_device!=NULL && params->cmd_run!=NULL)
{
params->disk=photorec_disk_selection_cli(params->cmd_device, list_disk, &list_search_space);
#ifdef HAVE_NCURSES
if(params->disk==NULL)
{
log_critical("No disk found\n");
return intrf_no_disk_ncurses("PhotoRec");
}
if(change_arch_type_cli(params->disk, options->verbose, &params->cmd_run)==0 ||
change_arch_type_ncurses(params->disk, options->verbose)==0)
{
menu_photorec(params, options, &list_search_space);
}
return 0;
#else
if(params->disk==NULL)
{
log_critical("No disk found\n");
return 0;
}
change_arch_type_cli(params->disk, options->verbose, &params->cmd_run);
menu_photorec(params, options, &list_search_space);
return 0;
#endif
}
#ifdef HAVE_NCURSES
return photorec_disk_selection_ncurses(params, options, list_disk, &list_search_space);
#else
return 0;
#endif
}