summaryrefslogtreecommitdiffstats
path: root/src/chgtypen.c
diff options
context:
space:
mode:
authorChristophe Grenier <grenier@cgsecurity.org>2009-01-14 22:13:47 +0100
committerChristophe Grenier <grenier@cgsecurity.org>2009-01-14 22:13:47 +0100
commit1650fe5b8b6cea638c280df13605aea816718a00 (patch)
treefed11bd9361236aba47157d859607c109db05814 /src/chgtypen.c
parent56e1c29b2c0614b0b3230946d72e1eaf37618bcc (diff)
Split ncurses text interface from functions
Diffstat (limited to 'src/chgtypen.c')
-rw-r--r--src/chgtypen.c439
1 files changed, 439 insertions, 0 deletions
diff --git a/src/chgtypen.c b/src/chgtypen.c
new file mode 100644
index 0000000..c5b7e1d
--- /dev/null
+++ b/src/chgtypen.c
@@ -0,0 +1,439 @@
+/*
+
+ File: chgtypen.c
+
+ Copyright (C) 1998-2009 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
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include "types.h"
+#include "common.h"
+#include "lang.h"
+#include "intrf.h"
+#include "intrfn.h"
+#include "fnctdsk.h"
+#include "chgtype.h"
+#include "chgtypen.h"
+#include "log.h"
+#include "log_part.h"
+#include "guid_cmp.h"
+#include "guid_cpy.h"
+#include "partgpt.h"
+#include "hdaccess.h"
+
+extern const arch_fnct_t arch_gpt;
+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 struct systypes_gtp gpt_sys_types[];
+
+#ifdef HAVE_NCURSES
+struct part_name_struct
+{
+ unsigned int index;
+ const char *name;
+};
+
+static void change_part_type_ncurses(const disk_t *disk_car,partition_t *partition)
+{
+ partition_t *new_partition;
+ char response[100];
+ int size=0;
+ int i;
+ unsigned int last[3], done = 0, next = 0;
+ struct part_name_struct part_name[0x100];
+ struct MenuItem menuType[]=
+ {
+ { 'P', "Previous",""},
+ { 'N', "Next","" },
+ { 'Q', "Proceed","Go set the partition type"},
+ { 0, NULL, NULL }
+ };
+ if(partition->arch->set_part_type==NULL)
+ return ;
+ /* Create an index of all partition type except Intel extended */
+ new_partition=partition_new(NULL);
+ dup_partition_t(new_partition,partition);
+ for(i=0;i<=0xFF;i++)
+ {
+ if(partition->arch->set_part_type(new_partition,i)==0)
+ {
+ part_name[size].name=new_partition->arch->get_partition_typename(new_partition);
+ if(part_name[size].name!=NULL)
+ part_name[size++].index=i;
+ }
+ }
+ free(new_partition);
+
+ /* Display the list of partition type in 3 columns */
+ screen_buffer_reset();
+ screen_buffer_add("List of partition type\n");
+ for (i = 2; i >= 0; i--)
+ last[2 - i] = done += (size + i - done) / (i + 1);
+ i = done = 0;
+ while (done < last[0])
+ {
+ screen_buffer_add( "%02x %-20s%c", part_name[next].index, part_name[next].name,(i==2 ? '\n' : ' '));
+ next = last[i++] + done;
+ if (i > 2 || next >= last[i]) {
+ i = 0;
+ next = ++done;
+ }
+ }
+
+ /* Ask for the new partition type*/
+ aff_copy(stdscr);
+ wmove(stdscr,4,0);
+ aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition);
+ screen_buffer_display(stdscr,"",menuType);
+ 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);
+ partition->arch->set_part_type(partition,tmp_val);
+ }
+}
+#define INTER_CHGTYPE 15
+#define INTER_CHGTYPE_X 0
+#define INTER_CHGTYPE_Y 23
+
+static void change_part_type_ncurses2(const disk_t *disk_car, partition_t *partition)
+{
+ partition_t *new_partition;
+ unsigned int intr_nbr_line=0;
+ unsigned int offset=0;
+ unsigned int i;
+ unsigned int current_element_num=0;
+ struct part_name_struct part_name[0x100];
+ if(partition->arch->set_part_type==NULL)
+ return ;
+ aff_copy(stdscr);
+ wmove(stdscr,4,0);
+ aff_part(stdscr, AFF_PART_ORDER|AFF_PART_STATUS, disk_car, partition);
+ wmove(stdscr,INTER_CHGTYPE_Y, INTER_CHGTYPE_X);
+ wattrset(stdscr, A_REVERSE);
+ wprintw(stdscr, "[ Proceed ]");
+ wattroff(stdscr, A_REVERSE);
+ /* Create an index of all partition type except Intel extended */
+ new_partition=partition_new(NULL);
+ dup_partition_t(new_partition,partition);
+ for(i=0;i<=0xFF;i++)
+ {
+ if(partition->arch->set_part_type(new_partition,i)==0)
+ {
+ part_name[intr_nbr_line].name=new_partition->arch->get_partition_typename(new_partition);
+ if(part_name[intr_nbr_line].name!=NULL)
+ {
+ if(partition->arch->get_part_type(partition)==i)
+ current_element_num=intr_nbr_line;
+ part_name[intr_nbr_line++].index=i;
+ }
+ }
+ }
+ free(new_partition);
+ while(1)
+ {
+ wmove(stdscr,5,0);
+ wprintw(stdscr, "Please choose the partition type, press Enter when done.");
+ wmove(stdscr,5+1,1);
+ wclrtoeol(stdscr);
+ if(offset>0)
+ wprintw(stdscr, "Previous");
+ for(i=offset;i<intr_nbr_line && (i-offset)<3*INTER_CHGTYPE;i++)
+ {
+ if(i-offset<INTER_CHGTYPE)
+ wmove(stdscr,5+2+i-offset,0);
+ else if(i-offset<2*INTER_CHGTYPE)
+ wmove(stdscr,5+2+i-offset-INTER_CHGTYPE,26);
+ else
+ wmove(stdscr,5+2+i-offset-2*INTER_CHGTYPE,52);
+ wclrtoeol(stdscr); /* before addstr for BSD compatibility */
+ if(i==current_element_num)
+ {
+ wattrset(stdscr, A_REVERSE);
+ wprintw(stdscr,"%s", part_name[i].name);
+ wattroff(stdscr, A_REVERSE);
+ } else
+ {
+ wprintw(stdscr,"%s", part_name[i].name);
+ }
+ }
+ if(i-offset<INTER_CHGTYPE)
+ wmove(stdscr,5+2+i-offset,1);
+ else if(i-offset<2*INTER_CHGTYPE)
+ wmove(stdscr,5+2+i-offset-INTER_CHGTYPE,27);
+ else
+ wmove(stdscr,5+2+i-offset-2*INTER_CHGTYPE,53);
+ wclrtoeol(stdscr);
+ if(i<intr_nbr_line)
+ wprintw(stdscr, "Next");
+ switch(wgetch(stdscr))
+ {
+ case 'p':
+ case 'P':
+ case KEY_UP:
+ if(current_element_num>0)
+ current_element_num--;
+ break;
+ case 'n':
+ case 'N':
+ case KEY_DOWN:
+ if(current_element_num < intr_nbr_line-1)
+ current_element_num++;
+ break;
+ case KEY_LEFT:
+ if(current_element_num > INTER_CHGTYPE)
+ current_element_num-=INTER_CHGTYPE;
+ else
+ current_element_num=0;
+ break;
+ case KEY_PPAGE:
+ if(current_element_num > 3*INTER_CHGTYPE-1)
+ current_element_num-=3*INTER_CHGTYPE-1;
+ else
+ current_element_num=0;
+ 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;
+ 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;
+ break;
+ case 'Q':
+ case 'q':
+ case key_CR:
+#ifdef PADENTER
+ case PADENTER:
+#endif
+ 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;
+ }
+}
+
+static void gpt_change_part_type(const disk_t *disk_car, partition_t *partition)
+{
+ unsigned int offset=0;
+ unsigned int i,j;
+ unsigned int current_element_num=0;
+ log_info("gpt_change_part_type\n");
+ aff_copy(stdscr);
+ wmove(stdscr,4,0);
+ aff_part(stdscr, AFF_PART_ORDER|AFF_PART_STATUS, disk_car, partition);
+ wmove(stdscr,INTER_CHGTYPE_Y, INTER_CHGTYPE_X);
+ wattrset(stdscr, A_REVERSE);
+ wprintw(stdscr, "[ Proceed ]");
+ wattroff(stdscr, A_REVERSE);
+ /* By default, select the current type */
+ for(i=0;gpt_sys_types[i].name!=NULL;i++)
+ {
+ if(guid_cmp(partition->part_type_gpt, gpt_sys_types[i].part_type)==0)
+ {
+ current_element_num=i;
+ while(current_element_num >= offset+3*INTER_CHGTYPE)
+ offset++;
+ }
+ }
+ while(1)
+ {
+ wmove(stdscr,5,0);
+ wprintw(stdscr, "Please choose the partition type, press Enter when done.");
+ wmove(stdscr,5+1,1);
+ wclrtoeol(stdscr);
+ if(offset>0)
+ wprintw(stdscr, "Previous");
+ for(i=offset;gpt_sys_types[i].name!=NULL && (i-offset)<3*INTER_CHGTYPE;i++)
+ {
+ if(i-offset<INTER_CHGTYPE)
+ wmove(stdscr,5+2+i-offset,0);
+ else if(i-offset<2*INTER_CHGTYPE)
+ wmove(stdscr,5+2+i-offset-INTER_CHGTYPE,26);
+ else
+ wmove(stdscr,5+2+i-offset-2*INTER_CHGTYPE,52);
+ wclrtoeol(stdscr); /* before addstr for BSD compatibility */
+ if(i==current_element_num)
+ {
+ wattrset(stdscr, A_REVERSE);
+ wprintw(stdscr,"%s", gpt_sys_types[i].name);
+ wattroff(stdscr, A_REVERSE);
+ } else
+ {
+ wprintw(stdscr,"%s", gpt_sys_types[i].name);
+ }
+ }
+ if(i-offset<INTER_CHGTYPE)
+ wmove(stdscr,5+2+i-offset,1);
+ else if(i-offset<2*INTER_CHGTYPE)
+ wmove(stdscr,5+2+i-offset-INTER_CHGTYPE,27);
+ else
+ wmove(stdscr,5+2+i-offset-2*INTER_CHGTYPE,53);
+ wclrtoeol(stdscr);
+ if(gpt_sys_types[i].name!=NULL)
+ wprintw(stdscr, "Next");
+ switch(wgetch(stdscr))
+ {
+ case 'p':
+ case 'P':
+ case KEY_UP:
+ if(current_element_num>0)
+ 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++;
+ break;
+ case KEY_LEFT:
+ if(current_element_num > INTER_CHGTYPE)
+ current_element_num-=INTER_CHGTYPE;
+ else
+ current_element_num=0;
+ break;
+ case KEY_PPAGE:
+ if(current_element_num > 3*INTER_CHGTYPE-1)
+ current_element_num-=3*INTER_CHGTYPE-1;
+ else
+ current_element_num=0;
+ 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++;
+ }
+ break;
+ case KEY_NPAGE:
+ for(j=0;j<3*INTER_CHGTYPE;j++)
+ {
+ if(gpt_sys_types[current_element_num].name!=NULL && gpt_sys_types[current_element_num+1].name!=NULL)
+ current_element_num++;
+ }
+ break;
+ case 'Q':
+ case 'q':
+ case key_CR:
+#ifdef PADENTER
+ case PADENTER:
+#endif
+ 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;
+ }
+}
+
+void change_part_type(const disk_t *disk_car,partition_t *partition, char **current_cmd)
+{
+ if(*current_cmd!=NULL)
+ return change_part_type_cli(disk_car, partition, current_cmd);
+ if(partition->arch==NULL)
+ {
+ log_error("change_part_type arch==NULL\n");
+ return;
+ }
+ if(partition->arch==&arch_gpt)
+ {
+ gpt_change_part_type(disk_car, partition);
+ log_info("Change partition type:\n");
+ log_partition(disk_car,partition);
+ partition->arch=&arch_none;
+ change_part_type_ncurses2(disk_car, partition);
+ log_info("Change partition type:\n");
+ log_partition(disk_car,partition);
+ partition->arch=&arch_gpt;
+ return ;
+ }
+ if(partition->arch->set_part_type==NULL)
+ {
+ log_error("change_part_type set_part_type==NULL\n");
+ return;
+ }
+ if(partition->arch==&arch_i386 || partition->arch==&arch_sun)
+ change_part_type_ncurses(disk_car, partition);
+ else
+ change_part_type_ncurses2(disk_car, partition);
+ log_info("Change partition type:\n");
+ log_partition(disk_car,partition);
+}
+#endif
+
+int interface_partition_type(disk_t *disk_car, const int verbose, char**current_cmd)
+{
+ const arch_fnct_t *arch_list[]={&arch_i386, &arch_gpt, &arch_none, &arch_sun, &arch_mac, NULL};
+ int ask_user=1;
+ if(*current_cmd!=NULL)
+ {
+ int keep_asking;
+ do
+ {
+ int i;
+ ask_user=0;
+ 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];
+ autoset_unit(disk_car);
+ keep_asking=1;
+ }
+ if(strncmp(*current_cmd, "ask_type", 8)==0)
+ {
+ (*current_cmd)+=8;
+ ask_user=1;
+ }
+ } while(keep_asking>0);
+ }
+ if(ask_user>0)
+ {
+#ifdef HAVE_NCURSES
+ if(interface_partition_type_ncurses(disk_car))
+ return 1;
+#endif
+ }
+ 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, 0,verbose);
+ return 0;
+}