/* File: intrf.c Copyright (C) 1998-2007 Christophe GRENIER This software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #include #ifdef HAVE_TIME_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_CYGWIN_H #include #endif #ifdef HAVE_LIBGEN_H #include #endif #ifdef HAVE_DIRENT_H #include #endif #include #include "types.h" #include "common.h" #include "lang.h" #include "intrf.h" #include "intrfn.h" #include "fnctdsk.h" #include "dir.h" #include "log.h" /* Use COLS (actual number of columns) or COLUMNS (number of columns the program has been designed for) ? */ #define GS_DEFAULT -1 #define GS_key_ESCAPE -2 extern const arch_fnct_t arch_i386; extern const arch_fnct_t arch_mac; extern const arch_fnct_t arch_none; extern const arch_fnct_t arch_sun; extern const arch_fnct_t arch_xbox; extern const char *monstr[]; static void set_parent_directory(char *dst_directory); static void dir_aff_entry(WINDOW *window, struct file_info *dir_info); int get_string(char *str, int len, char *def) { int c; int i = 0; int x, y; int use_def = FALSE; curs_set(1); getyx(stdscr, y, x); wclrtoeol(stdscr); str[0] = 0; if (def != NULL) { mvwaddstr(stdscr,y, x, def); wmove(stdscr,y, x); use_def = TRUE; } wrefresh(stdscr); while ((c = wgetch(stdscr)) != '\n' && c != key_CR #ifdef PADENTER && c!= PADENTER #endif ) { switch (c) { /* escape is generated by enter from keypad */ /* case key_ESC: wmove(stdscr,y, x); wclrtoeol(stdscr); curs_set(0); wrefresh(stdscr); return GS_key_ESCAPE; */ case KEY_DC: case KEY_BACKSPACE: if (i > 0) { str[--i] = 0; mvaddch(y, x+i, ' '); wmove(stdscr,y, x+i); } else if (use_def) { wclrtoeol(stdscr); use_def = FALSE; } break; default: if (i < len && isprint(c)) { mvaddch(y, x+i, c); if (use_def) { wclrtoeol(stdscr); use_def = FALSE; } str[i++] = c; str[i] = 0; } } wrefresh(stdscr); } curs_set(0); wrefresh(stdscr); if (use_def) return GS_DEFAULT; else return i; } int wgetch_nodelay(WINDOW *window) { int res; nodelay(window,TRUE); res=wgetch(window); nodelay(window,FALSE); return res; } /* * Actual function which prints the button bar and highlights the active button * Should not be called directly. Call function menuSelect instead. */ int wmenuUpdate(WINDOW *window, int y, int x, const struct MenuItem *menuItems, const unsigned int itemLength, const char *available, const int menuType, unsigned int current) { unsigned int i, lmargin = x, ymargin = y; const char *mcd; unsigned int lenNameMax=0; for( i = 0; menuItems[i].key!=0; i++ ) if(strchr(available, menuItems[i].key)!=NULL ) { unsigned int lenName = strlen( menuItems[i].name ); if(lenNameMax=sizeof(buff)) { log_critical("\nBUG: %s\n",mi); } if(lenName > itemLength) { if( menuType & MENU_BUTTON ) snprintf(buff, sizeof(buff),"[%s]",mi); else snprintf(buff, sizeof(buff),"%s",mi); } else { if( menuType & MENU_BUTTON ) { if(menuType & MENU_VERT) snprintf( buff, sizeof(buff),"[%*s%-*s]", (itemLength - lenNameMax) / 2, "", (itemLength - lenNameMax + 1) / 2 + lenNameMax, mi ); else snprintf( buff, sizeof(buff),"[%*s%-*s]", (itemLength - lenName) / 2, "", (itemLength - lenName + 1) / 2 + lenName, mi ); } else snprintf( buff, sizeof(buff),"%*s%-*s", (itemLength - lenName) / 2, "", (itemLength - lenName + 1) / 2 + lenName, mi ); } mvwaddstr(window, y, x, buff ); /* Lowlight after selected item */ if( current == i ) { wattroff(window, A_REVERSE); } mcd = menuItems[i].desc; if(menuType & MENU_VERT_WARN) mvwaddstr(window, y, x+itemLength+4, mcd ); /* Calculate position for the next item */ if( menuType & MENU_VERT ) { y += 1; if( y >= WARNING_START ) { y = ymargin; x += itemLength + MENU_SPACING; if( menuType & MENU_BUTTON ) x += 2; } } else { x += itemLength + MENU_SPACING; if( menuType & MENU_BUTTON ) x += 2; if( x > COLUMNS - lmargin - 12 ) { x = lmargin; y ++ ; } } } /* Print the description of selected item */ mcd = menuItems[current].desc; if(!(menuType & MENU_VERT_WARN)) mvwaddstr(window, WARNING_START + 1, (COLUMNS - strlen( mcd )) / 2, mcd ); return y; } /* This function takes a list of menu items, lets the user choose one * * and returns the value keyboard shortcut of the selected menu item */ int wmenuSelect(WINDOW *window, int y, int x, const struct MenuItem *menuItems, const unsigned int itemLength, const char *available, int menuType, unsigned int menuDefault) { unsigned int current=menuDefault; return wmenuSelect_ext(window, y, x, menuItems, itemLength, available, menuType, ¤t,NULL); } int wmenuSelect_ext(WINDOW *window, int y, int x, const struct MenuItem *menuItems, const unsigned int itemLength, const char *available, int menuType, unsigned int *current, int *real_key) { int i, ylast = y, key = 0; /* if( ( menuType & ( MENU_HORIZ | MENU_VERT ) )==0 ) { wdoprintf(window,"Menu without direction. Defaulting horizontal."); menuType |= MENU_HORIZ; } */ /* Warning: current may be out of bound, not checked */ /* Make sure that the current is one of the available items */ while(strchr(available, menuItems[*current].key)==NULL) { (*current)++ ; if( menuItems[*current].key==0 ) { *current = 0; } } /* Repeat until allowable choice has been made */ while( key==0 ) { /* Display the menu */ ylast = wmenuUpdate( window, y, x, menuItems, itemLength, available, menuType, *current ); wrefresh(window); /* Don't put wgetch after the following wclrtoeol */ key = wgetch(window); if(real_key!=NULL) *real_key=key; /* Clear out all prompts and such */ for( i = y; i < ylast; i ++ ) { wmove(window, i, x ); wclrtoeol(window); } wmove(window, WARNING_START + 1, 0 ); wclrtoeol(window); /* Cursor keys */ switch(key) { case KEY_UP: if( (menuType & MENU_VERT)!=0 ) { do { if( (*current)-- == 0 ) { while( menuItems[(*current)+1].key ) (*current) ++ ; } } while( strchr( available, menuItems[*current].key )==NULL ); key = 0; } break; case KEY_DOWN: if( (menuType & MENU_VERT)!=0 ) { do { (*current) ++ ; if( menuItems[*current].key==0 ) *current = 0 ; } while( strchr( available, menuItems[*current].key )==NULL ); key = 0; } break; case KEY_RIGHT: if( (menuType & MENU_HORIZ)!=0 ) { do { (*current) ++ ; if( menuItems[*current].key==0 ) { *current = 0 ; } } while( strchr( available, menuItems[*current].key )==NULL ); key = 0; } break; case KEY_LEFT: if( (menuType & MENU_HORIZ) !=0) { do { if( (*current)-- == 0 ) { while( menuItems[(*current) + 1].key ) (*current) ++ ; } } while( strchr( available, menuItems[*current].key )==NULL ); key = 0; } break; } /* Enter equals to the keyboard shortcut of current menu item */ if((key==13) || (key==10) || (key==KEY_ENTER) || (((menuType & MENU_VERT) != 0) && ((menuType & MENU_VERT_ARROW2VALID) != 0) && (key==KEY_RIGHT || key==KEY_LEFT))) key = menuItems[*current].key; #ifdef PADENTER if(key==PADENTER) key = menuItems[*current].key; #endif /* Is pressed key among acceptable ones */ if( key!=0 && (strchr(available, toupper(key))!=NULL || strchr(available, key)!=NULL)) break; /* Should all keys to be accepted? */ if( key && (menuType & MENU_ACCEPT_OTHERS)!=0 ) break; /* The key has not been accepted so far -> let's reject it */ #ifdef DEBUG if( key ) { wmove(window,5,0); wdoprintf(window,"key %03X",key); putchar( BELL ); } #endif key = 0; } /* Clear out prompts and such */ for( i = y; i <= ylast; i ++ ) { wmove(window, i, x ); wclrtoeol(window); } wmove(window, WARNING_START + 1, 0 ); wclrtoeol(window); return key; } /* Function menuSelect takes way too many parameters * * Luckily, most of time we can do with this function */ int wmenuSimple(WINDOW *window,const struct MenuItem *menuItems, unsigned int menuDefault) { unsigned int i, j, itemLength = 0; char available[MENU_MAX_ITEMS]; for(i = 0; menuItems[i].key; i++) { j = strlen(menuItems[i].name); if( j > itemLength ) itemLength = j; available[i] = menuItems[i].key; } available[i] = 0; return wmenuSelect(window,18, 0, menuItems, itemLength, available, MENU_HORIZ | MENU_BUTTON, menuDefault); } /* End of command menu support code */ unsigned long long int ask_number(const unsigned long long int val_cur, const unsigned long long int val_min, const unsigned long long int val_max, const char * _format, ...) { char res[200]; char res2[200]; char response[LINE_LENGTH]; char def[LINE_LENGTH]; unsigned long int tmp_val; va_list ap; va_start(ap,_format); vsnprintf(res,sizeof(res),_format,ap); if(val_min!=val_max) snprintf(res2,sizeof(res2),"(%llu-%llu) :",val_min,val_max); else res2[0]='\0'; va_end(ap); waddstr(stdscr, res); waddstr(stdscr, res2); sprintf(def, "%llu", val_cur); if (get_string(response, LINE_LENGTH, def) > 0) { #ifdef HAVE_ATOLL tmp_val = atoll(response); #else tmp_val = atol(response); #endif if (val_min==val_max || (tmp_val >= val_min && tmp_val <= val_max)) return tmp_val; } return val_cur; } void dump_ncurses(const void *nom_dump, unsigned int lng) { WINDOW *window=newwin(0,0,0,0); /* full screen */ keypad(window, TRUE); /* Need it to get arrow key */ aff_copy(window); dump(window, nom_dump, lng); delwin(window); (void) clearok(stdscr, TRUE); #ifdef HAVE_TOUCHWIN touchwin(stdscr); #endif } void dump(WINDOW *window, const void *nom_dump,unsigned int lng) { unsigned int i,j; unsigned int nbr_line; unsigned char car; unsigned int pos=0; int done=0; unsigned int menu=2; /* default : quit */ const char *options="PNQ"; struct MenuItem menuDump[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'Q',"Quit","Quit dump section"}, { 0, NULL, NULL } }; dump_log(nom_dump,lng); nbr_line=(lng+0x10-1)/0x10; if(nbr_line<=DUMP_MAX_LINES) { options="Q"; } /* ncurses interface */ mvwaddstr(window,DUMP_Y,DUMP_X,msg_DUMP_HEXA); /* On pourrait utiliser wscrl */ do { for (i=pos; (i= 127)) wdoprintf(window,"."); else wdoprintf(window,"%c", car); } else wdoprintf(window," "); } } switch (wmenuSelect(window,INTER_DUMP_Y, INTER_DUMP_X, menuDump, 8, options, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, menu)) { case 'p': case 'P': case KEY_UP: if(strchr(options,'N')!=NULL) { menu=0; if(pos>0) pos--; } break; case 'n': case 'N': case KEY_DOWN: if(strchr(options,'N')!=NULL) { menu=1; if(posDUMP_MAX_LINES-1) pos-=DUMP_MAX_LINES-1; else pos=0; } break; case KEY_NPAGE: if(strchr(options,'N')!=NULL) { menu=1; if(pos= 127)) wdoprintf(window,"."); else wdoprintf(window,"%c", car1); if(car1!=car2) wattroff(window, A_REVERSE); } else wdoprintf(window," "); } wdoprintf(window," "); for(j=0; j<0x08;j++) { if(i*0x08+j= 127)) wdoprintf(window,"."); else wdoprintf(window,"%c", car2); if(car1!=car2) wattroff(window, A_REVERSE); } else wdoprintf(window," "); } } switch (wmenuSelect(window,INTER_DUMP_Y, INTER_DUMP_X, menuDump, 8, options, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, menu)) { case 'p': case 'P': case KEY_UP: if(strchr(options,'N')!=NULL) { menu=0; if(pos>0) pos--; } break; case 'n': case 'N': case KEY_DOWN: if(strchr(options,'N')!=NULL) { menu=1; if(posDUMP_MAX_LINES-1) pos-=DUMP_MAX_LINES-1; else pos=0; } break; case KEY_NPAGE: if(strchr(options,'N')!=NULL) { menu=1; if(pos0) */ intr_nbr_line++; ret_ligne++; } else { strncat(intr_buffer_screen[intr_nbr_line],pos_in_tmp_line,LINE_LENGTH-strlen(intr_buffer_screen[intr_nbr_line])); } pos_in_tmp_line=ret_ligne; } /* log_trace("aff_intr_buffer_screen %d =>%s<=\n",intr_nbr_line,tmp_line); */ if(intr_nbr_line>=MAX_LINES) { log_warning("aff_intr_buffer_screen too much lines =>%s<=\n",tmp_line); } } break; case BUFFER_SHOW: { int i; int pos=intr_nbr_line-DUMP_MAX_LINES<0?0:intr_nbr_line-DUMP_MAX_LINES; if(intr_buffer_screen[intr_nbr_line][0]!='\0') intr_nbr_line++; /* curses interface */ for (i=pos; (i0) wdoprintf(window, "Previous"); for (i=first_line_to_display; (iINTER_MAX_LINES && has_colors()) wattrset(window, A_REVERSE); wdoprintf(window,"%s",intr_buffer_screen[i]); if(i==current_line && intr_nbr_line>INTER_MAX_LINES && has_colors()) wattroff(window, A_REVERSE); } wmove(window, INTER_ANALYSE_Y+INTER_MAX_LINES, INTER_ANALYSE_X+4); wclrtoeol(window); if(i0) current_line--; if(current_line=first_line_to_display+INTER_MAX_LINES) first_line_to_display=current_line-INTER_MAX_LINES+1; break; case KEY_PPAGE: if(current_line>INTER_MAX_LINES-1) current_line-=INTER_MAX_LINES-1; else current_line=0; if(current_line=first_line_to_display+INTER_MAX_LINES) first_line_to_display=current_line-INTER_MAX_LINES+1; break; default: if(strchr(options,toupper(key))!=NULL) return toupper(key); break; } } while(done!=TRUE); return 0; } void aff_CHS(const CHS_t * CHS) { wdoprintf(stdscr,"%5u %3u %2u ", CHS->cylinder, CHS->head, CHS->sector); } void aff_CHS_buffer(const CHS_t * CHS) { aff_buffer(BUFFER_ADD,"%5u %3u %2u ", CHS->cylinder, CHS->head, CHS->sector); } const char *aff_part_aux(const aff_part_type_t newline, const disk_t *disk_car, const partition_t *partition) { char status=' '; static char msg[200]; unsigned int pos=0; const arch_fnct_t *arch=(partition->arch!=NULL?partition->arch:disk_car->arch); msg[sizeof(msg)-1]=0; switch(newline) { case AFF_PART_ORDER: if((partition->status!=STATUS_EXT_IN_EXT) && (partition->order!=NO_ORDER)) pos+=snprintf(&msg[pos],sizeof(msg)-pos-1,"%2d ", partition->order); else pos+=snprintf(&msg[pos],sizeof(msg)-pos-1," "); break; case AFF_PART_NONL: case AFF_PART_SHORT: break; } if(newline!=AFF_PART_SHORT) { switch(partition->status) { case STATUS_PRIM: status='P'; break; case STATUS_PRIM_BOOT: status='*'; break; case STATUS_EXT: status='E'; break; case STATUS_EXT_IN_EXT: status='X'; break; case STATUS_LOG: status='L'; break; case STATUS_DELETED: status='D'; break; default: status=' '; break; } } pos+=snprintf(&msg[pos],sizeof(msg)-pos-1,"%c", status); if(arch->get_partition_name(partition)!=NULL) pos+=snprintf(&msg[pos],sizeof(msg)-pos-1, " %-20s ", arch->get_partition_name(partition)); else pos+=snprintf(&msg[pos],sizeof(msg)-pos-1, " Sys=%02X ", arch->get_part_type(partition)); if(disk_car->arch==&arch_mac || (disk_car->CHS.head==0 && disk_car->CHS.sector==1)) { pos+=snprintf(&msg[pos],sizeof(msg)-pos-1, " %10lu ", (long unsigned)(partition->part_offset/disk_car->sector_size)); pos+=snprintf(&msg[pos],sizeof(msg)-pos-1, "%10lu ", (long unsigned)((partition->part_offset+partition->part_size-1)/disk_car->sector_size)); } else { pos+=snprintf(&msg[pos],sizeof(msg)-pos-1,"%5u %3u %2u ", offset2cylinder(disk_car,partition->part_offset), offset2head( disk_car,partition->part_offset), offset2sector( disk_car,partition->part_offset)); pos+=snprintf(&msg[pos],sizeof(msg)-pos-1, "%5u %3u %2u ", offset2cylinder(disk_car,partition->part_offset+partition->part_size-1), offset2head( disk_car,partition->part_offset+partition->part_size-1), offset2sector( disk_car,partition->part_offset+partition->part_size-1)); } pos+=snprintf(&msg[pos],sizeof(msg)-pos-1,"%10lu", (long unsigned)(partition->part_size/disk_car->sector_size)); if(partition->name[0]!='\0') pos+=snprintf(&msg[pos],sizeof(msg)-pos-1, " [%s]",partition->name); return msg; } void aff_part(WINDOW *window,const aff_part_type_t newline,const disk_t *disk_car,const partition_t *partition) { const char *msg; msg=aff_part_aux(newline, disk_car, partition); wdoprintf(window,"%s",msg); } void aff_part_buffer(const aff_part_type_t newline,const disk_t *disk_car,const partition_t *partition) { const char *msg; msg=aff_part_aux(newline, disk_car, partition); aff_buffer(BUFFER_ADD,"%s\n", msg); } void aff_LBA2CHS(const disk_t *disk_car, const unsigned long int pos_LBA) { unsigned long int tmp; unsigned long int cylinder, head, sector; tmp=disk_car->CHS.sector; sector=(pos_LBA%tmp)+1; tmp=pos_LBA/tmp; cylinder=tmp/(disk_car->CHS.head+1); head=tmp%(disk_car->CHS.head+1); wdoprintf(stdscr,"%lu/%lu/%lu", cylinder,head,sector); } void log_CHS_from_LBA(const disk_t *disk_car, const unsigned long int pos_LBA) { unsigned long int tmp; unsigned long int cylinder, head, sector; tmp=disk_car->CHS.sector; sector=(pos_LBA%tmp)+1; tmp=pos_LBA/tmp; cylinder=tmp/(disk_car->CHS.head+1); head=tmp%(disk_car->CHS.head+1); log_info("%lu/%lu/%lu", cylinder,head,sector); } int ask_YN(WINDOW *window) { char res; curs_set(1); wrefresh(window); do { res=toupper(wgetch(window)); } while((res!=c_NO)&&(res!=c_YES)); curs_set(0); wdoprintf(window,"%c\n",res); return (res==c_YES); } int ask_confirmation(const char*_format, ...) { va_list ap; int res; WINDOW *window=newwin(0,0,0,0); /* full screen */ aff_copy(window); va_start(ap,_format); vaff_txt(4, window, _format, ap); va_end(ap); res=ask_YN(window); delwin(window); (void) clearok(stdscr, TRUE); #ifdef HAVE_TOUCHWIN touchwin(stdscr); #endif return res; } int wdoprintf(WINDOW *window, const char *_format, ...) { char res[800]; va_list ap; va_start(ap,_format); vsnprintf(res,sizeof(res),_format,ap); va_end(ap); res[sizeof(res)-1]='\0'; #ifdef __MINGW32__ { int len=strlen(res); if(res[len-1]=='\n' && len=0) { buf[len]='\0'; } else { strncpy(buf,real_prog_name,sizeof(buf)-1); buf[sizeof(buf)-1]='\0'; } } #else // HAVE_READLINK { strncpy(buf,real_prog_name,sizeof(buf)-1); buf[sizeof(buf)-1]='\0'; } #endif // HAVE_READLINK setenv("TERMINFO",dirname(buf),1); sp=newterm(NULL,stdout,stdin); } #endif // HAVE_DIRNAME if(sp==NULL) { setenv("TERMINFO",".",1); sp=newterm(NULL,stdout,stdin); } #endif } #endif } if(sp==NULL) { #if defined(DJGPP) || defined(__MINGW32__) log_critical("initscr() has failed. Exiting\n"); printf("initscr() has failed. Exiting\n"); #elif defined(__CYGWIN__) log_critical("Terminfo file is missing.\n"); printf("Terminfo file c\\cygwin is missing.\n"); printf("Extract all files and subdirectories before running the program.\n"); #else log_critical("Terminfo file is missing.\n"); printf("Terminfo file is missing.\n"); printf("Extract all files and subdirectories before running the program.\n"); #endif printf("Press Enter key to quit.\n"); getchar(); return 1; } } noecho(); #ifndef DJGPP nonl(); /*don't use for Dos version but enter will work with it... dilema */ #endif /* intrflush(stdscr, FALSE); */ cbreak(); /* Should solve a problem with users who redefined the colors */ if(has_colors()) { start_color(); init_pair(1, COLOR_RED, COLOR_BLACK); init_pair(2, COLOR_GREEN, COLOR_BLACK); } curs_set(0); { int quit=0; while(LINES<25 && quit==0) { if(LINES>=8) { aff_copy(stdscr); wmove(stdscr,4,0); wdoprintf(stdscr,"%s need 25 lines to work.", prog_name); wmove(stdscr,5,0); wdoprintf(stdscr,"Please enlarge the terminal."); wmove(stdscr,LINES-2,0); wattrset(stdscr, A_REVERSE); wdoprintf(stdscr,"[ Quit ]"); wattroff(stdscr, A_REVERSE); wrefresh(stdscr); switch(wgetch(stdscr)) { case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif case '\n': case '\r': quit=1; break; } } else quit=1; } } if(LINES<25) { end_ncurses(); printf("%s need 25 lines to work.\nPlease enlarge the terminal and restart %s.\n",prog_name,prog_name); log_critical("Terminal has only %u lines\n",LINES); return 1; } return 0; } int end_ncurses() { wclear(stdscr); wrefresh(stdscr); nl(); endwin(); return 0; } char *ask_log_location(const char*filename) { static char response[LINE_LENGTH]; aff_copy(stdscr); wmove(stdscr,6,0); wdoprintf(stdscr,"Cannot open %s: %s\n",filename, strerror(errno)); wmove(stdscr,8,0); wdoprintf(stdscr,"Please enter the full log filename or press "); if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); wdoprintf(stdscr,"Enter"); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); wmove(stdscr,9,0); wdoprintf(stdscr,"to abort log file creation.\n"); if (get_string(response, LINE_LENGTH, NULL) > 0) return response; return NULL; } /* 0: no log 1: append 2: create */ int ask_log_creation() { int command; 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); wdoprintf(stdscr,"TestDisk is a data recovery designed to help recover lost partitions"); wmove(stdscr,6,0); wdoprintf(stdscr,"and/or make non-booting disks bootable again when these symptoms"); wmove(stdscr,7,0); wdoprintf(stdscr,"are caused by faulty software, certain types of viruses or human error."); wmove(stdscr,8,0); wdoprintf(stdscr,"It can also be used to repair some filesystem errors."); wmove(stdscr,10,0); wdoprintf(stdscr,"Information gathered during TestDisk use can be recorded for later"); wmove(stdscr,11,0); wdoprintf(stdscr,"review. If you choose to create the text file, "); if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); wdoprintf(stdscr,"testdisk.log"); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); wdoprintf(stdscr," , it"); wmove(stdscr,12,0); wdoprintf(stdscr,"will contain TestDisk options, technical information and various"); wmove(stdscr,13,0); wdoprintf(stdscr,"outputs; including any folder/file names TestDisk was used to find and"); wmove(stdscr,14,0); wdoprintf(stdscr,"list onscreen."); wmove(stdscr,16,0); wdoprintf(stdscr,"Use arrow keys to select, then press Enter key:"); while(1) { command = wmenuSelect_ext(stdscr,17, 0, menuLogCreation, 8, "CAQ", MENU_VERT | MENU_VERT_WARN | MENU_BUTTON, &menu,NULL); switch(command) { case 'C': case 'c': return 2; case 'A': case 'a': return 1; case 'Q': case 'q': return 0; default: break; } } } void intrf_no_disk(const char *prog_name) { aff_copy(stdscr); wmove(stdscr,4,0); wdoprintf(stdscr," %s is free software, and",prog_name); wmove(stdscr,5,0); wdoprintf(stdscr,"comes with ABSOLUTELY NO WARRANTY."); wmove(stdscr,7,0); wdoprintf(stdscr,"No harddisk found\n"); wmove(stdscr,8,0); #if defined(__CYGWIN__) || defined(__MINGW32__) wdoprintf(stdscr,"You need to be administrator to use %s.\n", prog_name); wmove(stdscr,9,0); wdoprintf(stdscr,"Under Win9x, use the DOS version instead.\n"); wmove(stdscr,10,0); wdoprintf(stdscr,"Under Vista, select %s, right-click and choose \"Run as administrator\".\n", prog_name); log_critical("You need to be administrator to use %s.\n", prog_name); #else #ifndef DJGPP #ifdef HAVE_GETEUID if(geteuid()!=0) { wdoprintf(stdscr,"You need to be root to use %s.\n", prog_name); log_critical("You need to be root to use %s.\n", prog_name); #if defined(__APPLE__) wmove(stdscr,9,0); wdoprintf(stdscr,"Use the sudo command to launch %s.\n", prog_name); #endif } #endif #endif #endif wmove(stdscr,22,0); wattrset(stdscr, A_REVERSE); wdoprintf(stdscr,"[ Quit ]"); wattroff(stdscr, A_REVERSE); wrefresh(stdscr); while(wgetch(stdscr)==ERR); } int check_enter_or_s(WINDOW *window) { switch(wgetch_nodelay(window)) { case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif case '\n': case '\r': case 's': case 'S': return 1; break; } return 0; } int interface_partition_type(disk_t *disk_car, const int allow_partial_last_cylinder, const int debug, char**current_cmd) { const arch_fnct_t *arch_list[]={&arch_i386, &arch_mac, &arch_none, &arch_sun, &arch_mac, NULL}; if(*current_cmd!=NULL) { int keep_asking; do { int i; keep_asking=0; while(*current_cmd[0]==',') (*current_cmd)++; for(i=0;arch_list[i]!=NULL;i++) if(strncmp(*current_cmd, arch_list[i]->part_name_option, strlen(arch_list[i]->part_name_option))==0) { (*current_cmd)+=strlen(arch_list[i]->part_name_option); disk_car->arch=arch_list[i]; keep_asking=1; } } while(keep_asking>0); } else { unsigned int menu; for(menu=0;arch_list[menu]!=NULL && disk_car->arch!=arch_list[menu];menu++); if(arch_list[menu]==NULL) { menu=0; disk_car->arch=arch_list[menu]; } /* ncurses interface */ { int car; int real_key; struct MenuItem menuOptions[]= { { 'I', arch_i386.part_name, "Intel/PC partition" }, { 'M', arch_mac.part_name, "Apple partition map" }, { 'N', arch_none.part_name, "Non partitioned media" }, { 'S', arch_sun.part_name, "Sun Solaris partition"}, { 'X', arch_xbox.part_name, "XBox partition"}, { 'Q', "Return", "Return to disk selection"}, { 0, NULL, NULL } }; aff_copy(stdscr); wmove(stdscr,5,0); wdoprintf(stdscr,"%s\n",disk_car->description_short(disk_car)); wmove(stdscr,INTER_PARTITION_Y-1,0); wdoprintf(stdscr,"Please select the partition table type, press Enter when done."); wmove(stdscr,20,0); wdoprintf(stdscr,"Note: Do NOT select 'None' for media with only a single partition. It's very"); wmove(stdscr,21,0); wdoprintf(stdscr,"rare for a drive to be 'Non-partitioned'."); car=wmenuSelect_ext(stdscr,INTER_PARTITION_Y, INTER_PARTITION_X, menuOptions, 7, "IMNSXQ", MENU_BUTTON | MENU_VERT | MENU_VERT_WARN, &menu,&real_key); switch(car) { case 'i': case 'I': disk_car->arch=&arch_i386; break; case 'm': case 'M': disk_car->arch=&arch_mac; break; case 'n': case 'N': disk_car->arch=&arch_none; break; case 's': case 'S': disk_car->arch=&arch_sun; break; case 'x': case 'X': disk_car->arch=&arch_xbox; break; case 'q': case 'Q': return 1; } } } log_info("%s\n",disk_car->description_short(disk_car)); log_info("Partition table type: %s\n",disk_car->arch->part_name); hd_update_geometry(disk_car,allow_partial_last_cylinder,debug); return 0; } #define PATH_SEP '/' #define SPATH_SEP "/" #if defined(__CYGWIN__) #define PATH_DRIVE_LENGTH 9 #elif defined(DJGPP) || defined(__OS2__) #define PATH_DRIVE_LENGTH 3 #endif static void set_parent_directory(char *dst_directory) { int i; int last_sep=-1; for(i=0;dst_directory[i]!='\0';i++) if(dst_directory[i]==PATH_SEP) last_sep=i; #ifdef __CYGWIN__ /* /cygdrive */ if(last_sep>PATH_DRIVE_LENGTH) dst_directory[last_sep]='\0'; else dst_directory[PATH_DRIVE_LENGTH]='\0'; #elif defined(DJGPP) || defined(__OS2__) if(last_sep>PATH_DRIVE_LENGTH) dst_directory[last_sep]='\0'; else dst_directory[0]='\0'; #else if(last_sep>1) dst_directory[last_sep]='\0'; else dst_directory[1]='\0'; #endif } char *ask_location(const char*msg, const char *src_dir) { char dst_directory[4096]; char *res=NULL; int quit; WINDOW *window=newwin(0,0,0,0); /* full screen */ aff_copy(window); #ifdef HAVE_GETCWD if(getcwd(dst_directory, sizeof(dst_directory))==NULL) strncpy(dst_directory,".",sizeof(dst_directory)); #else strncpy(dst_directory,".",sizeof(dst_directory)); #endif do { DIR* dir; struct list_head *dir_current; int offset=0; int pos_num=0; static struct file_info dir_list = { .list = LIST_HEAD_INIT(dir_list.list), .name = {0} }; wmove(window,7,0); wclrtoeol(window); /* before addstr for BSD compatibility */ if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"Directory listing in progress..."); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); wrefresh(window); #if defined(DJGPP) || defined(__OS2__) if(dst_directory[0]=='\0') { int i; for(i='a';i<='z';i++) { struct file_info *new_drive; new_drive=(struct file_info*)MALLOC(sizeof(*new_drive)); new_drive->name[0]=i; new_drive->name[1]=':'; new_drive->name[2]=PATH_SEP; new_drive->name[3]='\0'; new_drive->stat.st_mode=LINUX_S_IFDIR|LINUX_S_IRWXUGO; list_add_tail(&new_drive->list,&dir_list.list); } dir=NULL; } else dir=opendir(dst_directory); #else dir=opendir(dst_directory); #endif if(dir!=NULL) { struct dirent *dir_entrie; struct file_info *dir_info; dir_info=(struct file_info*)MALLOC(sizeof(*dir_info)); do { char current_file[4096]; dir_entrie=readdir(dir); if(dir_entrie!=NULL && strlen(dst_directory)+1+strlen(dir_info->name)+1<=sizeof(current_file) && (dir_entrie->d_name[0]!='.' || dir_entrie->d_name[1]=='\0' || (dir_entrie->d_name[1]=='.' && dir_entrie->d_name[2]=='\0')) #ifdef __CYGWIN__ && (strlen(dst_directory)>PATH_DRIVE_LENGTH || dir_entrie->d_name[0]!='.') #endif ) { strcpy(current_file,dst_directory); #if defined(DJGPP) || defined(__OS2__) if(current_file[0]!='\0'&¤t_file[1]!='\0'&¤t_file[2]!='\0'&¤t_file[3]!='\0') #else if(current_file[1]!='\0') #endif strcat(current_file,SPATH_SEP); strcat(current_file,dir_entrie->d_name); #ifdef HAVE_LSTAT if(lstat(current_file,&dir_info->stat)==0) #else if(stat(current_file,&dir_info->stat)==0) #endif { if(S_ISDIR(dir_info->stat.st_mode)) { /* If the C compiler doesn't use posix definition, st_mode need to be fixed */ #if defined(DJGPP) || defined(__OS2__) dir_info->stat.st_mode=LINUX_S_IFDIR|LINUX_S_IRWXUGO; #elif defined(__CYGWIN__) if(strlen(dst_directory)<=PATH_DRIVE_LENGTH) { dir_info->stat.st_mode=LINUX_S_IFDIR|LINUX_S_IRWXUGO; dir_info->stat.st_mtime=0; dir_info->stat.st_uid=0; dir_info->stat.st_gid=0; } #endif strncpy(dir_info->name,dir_entrie->d_name,sizeof(dir_info->name)); list_add_tail(&dir_info->list,&dir_list.list); dir_info=(struct file_info*)MALLOC(sizeof(*dir_info)); } } } } while(dir_entrie!=NULL); free(dir_info); closedir(dir); } dir_current=dir_list.list.next; if(dir_list.list.next!=&dir_list.list) { do { aff_copy(window); wmove(window,7,0); #ifdef PATH_DRIVE_LENGTH #ifdef __CYGWIN__ if(strlen(dst_directory)<=PATH_DRIVE_LENGTH) wdoprintf(window,"To select a drive, use the arrow keys."); else wdoprintf(window,"To select another directory, use the arrow keys."); #else if(strlen(dst_directory)PATH_DRIVE_LENGTH) { cygwin_conv_to_win32_path(dst_directory,beautifull_dst_directory); line=aff_txt(line,window,msg,src_dir,beautifull_dst_directory); } #else #ifdef PATH_DRIVE_LENGTH if(strlen(dst_directory)>=PATH_DRIVE_LENGTH) #endif { strncpy(beautifull_dst_directory,dst_directory,sizeof(beautifull_dst_directory)); line=aff_txt(line,window,msg,src_dir,beautifull_dst_directory); } #endif } } wclrtoeol(window); /* before addstr for BSD compatibility */ wrefresh(window); do { quit=0; switch(wgetch(window)) { case 'y': case 'Y': #if defined __CYGWIN__ if(strlen(dst_directory)>=PATH_DRIVE_LENGTH) #endif { res=strdup(dst_directory); quit=3; } break; case 'n': case 'N': res=NULL; quit=3; break; case KEY_UP: if(dir_current->prev!=&dir_list.list) { dir_current=dir_current->prev; pos_num--; if(pos_numnext!=&dir_list.list) { dir_current=dir_current->next; pos_num++; if(pos_num>=offset+INTER_DIR) offset++; quit=1; } break; case KEY_PPAGE: { int i; for(i=0;(iprev!=&dir_list.list);i++) { dir_current=dir_current->prev; pos_num--; if(pos_numnext!=&dir_list.list);i++) { dir_current=dir_current->next; pos_num++; if(pos_num>=offset+INTER_DIR) offset++; quit=1; } } break; case KEY_RIGHT: case '\r': case '\n': case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif if(dir_current!=&dir_list.list) { struct file_info *dir_info; dir_info=list_entry(dir_current, struct file_info, list); if(strcmp(dir_info->name,".")==0) { } else if(strcmp(dir_info->name,"..")==0) { set_parent_directory(dst_directory); quit=2; } else if(strlen(dst_directory)+1+strlen(dir_info->name)+1<=sizeof(dst_directory)) { #if defined(DJGPP) || defined(__OS2__) if(dst_directory[0]!='\0'&&dst_directory[1]!='\0'&&dst_directory[2]!='\0'&&dst_directory[3]!='\0') #else if(dst_directory[1]!='\0') #endif strcat(dst_directory,SPATH_SEP); strcat(dst_directory,dir_info->name); quit=2; } } break; } } while(quit==0); } while(quit==1); { struct list_head *dir_walker = NULL; struct list_head *dir_walker_next = NULL; list_for_each_safe(dir_walker,dir_walker_next,&dir_list.list) { struct file_info *dir_info; dir_info=list_entry(dir_walker, struct file_info, list); list_del(dir_walker); free(dir_info); } } } else { set_parent_directory(dst_directory); quit=2; } } while(quit==2); delwin(window); (void) clearok(stdscr, TRUE); #ifdef HAVE_TOUCHWIN touchwin(stdscr); #endif return res; } int vaff_txt(int line, WINDOW *window, const char *_format, va_list ap) { char buffer[1024]; int i; vsnprintf(buffer,sizeof(buffer),_format,ap); buffer[sizeof(buffer)-1]='\0'; for(i=0;buffer[i]!='\0';) { char buffer2[1024]; int j,end=i,end2=i; for(j=i;buffer[j]!='\0' && (j-i)end && end-istat.st_mtime!=0) { tm_p = localtime(&dir_info->stat.st_mtime); snprintf(datestr, sizeof(datestr),"%2d-%s-%4d %02d:%02d", tm_p->tm_mday, monstr[tm_p->tm_mon], 1900 + tm_p->tm_year, tm_p->tm_hour, tm_p->tm_min); /* May have to use %d instead of %e */ } else { strncpy(datestr, " ",sizeof(datestr)); } mode_string(dir_info->stat.st_mode,str); wdoprintf(window, "%s %5u %5u ", str, (unsigned int)dir_info->stat.st_uid, (unsigned int)dir_info->stat.st_gid); wdoprintf(window, "%7llu", (long long unsigned int)dir_info->stat.st_size); /* screen may overlap due to long filename */ wdoprintf(window, " %s %s", datestr, dir_info->name); }