Anonymous avatar Anonymous committed 01e20a6

Move some functions that are not specific to cfdisk out of cfdisk.c. Fix some issues and implement some missing things. (fdisk@sv.gnu.org/fdisk--main--0--patch-32)
fdisk@sv.gnu.org/fdisk--main--0--patch-32
Keywords:

Comments (0)

Files changed (5)

 #if ENABLE_NLS
 #  include <libintl.h>
 #  include <locale.h>
+/* TODO: Fix some localizing issues */
 #  define _(String) dgettext (PACKAGE, String)
 #  define P_(String) dgettext ("parted", String)
 #else
 
 int new_table = 0;
 int arrow_cursor = 0;
+int is_devicefile = 0;
 
 
 static void
 
 
 
-void
+static void
 set_status(const char *status, int warn_line) {
 	clear_status(warn_line);
 	/*attron(A_REVERSE);*/
 	/*attroff(A_REVERSE);*/
 }
 
-void
+static void
 print_warning(const char *status, int status_line) {
 	set_status(status,!status_line);
 	putchar(BELL);
 }
 
-void
+static void
 menu_title (const char *title) {
 	move(LINES - 2 - MENUSIZE, 0);
 	clrtoeol();
 }
 
 /* Menu drawing function */
-void
+static void
 menu_draw (const MenuItem *items, int item_len, MenuOptions opts, const char *keys, int selected) {
 	int i, y = LINES - 2 - MENUSIZE + (opts & MENU_TITLE ? 1 : 0), x = MENUDIV;
 	int item_size = item_len + (opts & MENU_BUTTON ? 2 : 0);
 	return key;
 }
 
-
+/* Lines at the top of the string list drawer */
+#define SLD_HEAD 5
 /* String list choice */
 /* The last two parameters specify the number of the selected element and the first element displayed 
    last time. If opts & 1, we assume it is a fullscreen text, not choice*/
 static void
 strlist_draw (const char *prompt, const StrList *strlist, int opts, const StrList* selected, 
               int selnum, int *start) {
-	/*char buf[SMALLBUF]; *//* FIXME: Not needed */
 	char *temp;
 	int n,x,y,i;
 	const StrList *current;
 
 	if (opts & 1) {
-		/* 5 are the additional lines, TODO: make this a #define */
-		*start = selnum - (LINES - 2 - 5);
+		*start = selnum - (LINES - 2 - SLD_HEAD);
 		*start = MAX(0,*start);
 		y = 0;
 		n = LINES - 2;
 		y = INFOSIZE;
 		if (selnum - *start < 0)
 			*start = selnum;
-		else if (selnum - *start >= n - INFOSIZE - 4)
-			*start = selnum - n + INFOSIZE + 5;
+		else if (selnum - *start > n - INFOSIZE - SLD_HEAD)
+			*start = selnum - n + INFOSIZE + SLD_HEAD;
 
 	}
 	move(y++,0); clrtoeol();
 	move(y,0); clrtoeol(); mvaddstr(y++,5,prompt);
-	/* FIXME: Using buf here not needed. This appears another time in source. */
-	mvaddch(y,0,' ');//' 'buf[0] = ' ';
+	mvaddch(y,0,' ');
 	for (x = 1; x < COLS-1; x++) {
-		mvaddch(y,x,'-'); //buf[i] = '-';
+		mvaddch(y,x,'-');
         }
 	mvaddch(y++,x,' ');
-	//if (i < SMALLBUF) buf[i++] = ' ';
-	//if (i < SMALLBUF) buf[i] = '\0';
-	//mvaddstr(y++,0,buf);
 	move(y++,0); clrtoeol();
 	x = (opts & 1 ? 1 : 7);
 	for (current = strlist, i = 0; current && y < n; current = current->next, i++) {
 do_strlist (const char *prompt, const StrList *strlist, int opts) {
 	const StrList *selected = strlist, *temp;
 	int redraw = 1, key = 0, done = 0, start = 0, selnum = 0;
-	const char* end_warning = opts & 1 ? _("No more text") : _("No more choices");
+	const char* end_warning = opts & 1 ? 
+	                              _("No more text") : _("No more choices");
 	if (opts & 1) {
 		for (selnum = 0, selected = strlist; 
-		     selnum < LINES-2-5 && selected->next;
+		     selnum < LINES-2-SLD_HEAD && selected->next;
 		     selnum++, selected = selected->next);
 	}
 	while (!done) {
 			key = getch();
 			if (key == '[' || key == 'O') {
 			key = getch();
-				if (key == 'B' && !(opts & 2)) { /* That's down arrow */
+				if (key == 'B' && !(opts & 2)) { /*Down arrow*/
 					if (!selected->next)
 						print_warning(end_warning,0);
 					else {
 						redraw = 1;
 					}
 				}
-				else if (key == 'A' && !(opts & 2)) { /* That's up arrow */
+				else
+				if (key == 'A' && !(opts & 2)) { /*Up arrow*/
 					if (strlist == selected || 
-					    ((opts & 1) && selnum <= LINES-2-5))
+					    ((opts & 1) && selnum <= LINES-2-SLD_HEAD))
 						print_warning(end_warning,0);
 					else {
 					/* FIXME: Edit strlist and make this faster */
 	}
 	if (*value) ped_free (*value);
 	*value = strdup(buf);
-	//n = strlen(buf);
-	//*value = (char *)calloc(n,sizeof(char));
-	//strncpy(*value,buf,n);
 	return 1;
 	
 }
 	return do_plist(disk,value,0,PED_PARTITION_EXTENDED | PED_PARTITION_FREESPACE);
 }
 
+static int
+getpartpos (const char* prompt, const void* context, const char *possibilities)
+{
+	return do_menu((MenuItem*) context, 11, MENU_BUTTON | MENU_TITLE,
+	               possibilities, NULL);
+}
 
 static PedExceptionOption
 exception_handler (PedException* ex) {
 	for (i = 0; ex_keys[i].key; i++)
 		if (ex->options & ex_keys[i].option) {
 #if 0
-			if (k >= TINYBUF) break; /* NOTE: This is not needed now, but have in mind */
+			/* NOTE: This is not needed now, but have in mind */
+			if (k >= TINYBUF) break; 
 #endif
 			keys[k++] = ex_keys[i].key;
 		}
 	uiquery.getbool = getbool;
 	uiquery.getstring = getstring;
 	uiquery.getpart = getpart;
+	uiquery.getpartpos = getpartpos;
 	uiquery.need_commit = 0;
 	uiquery.timer = ped_timer_new (_timer_handler, &timer_context);
 	ped_exception_set_handler(exception_handler);
 	return temp_a;
 }
 
-/* TODO: Move this to common? */
-/* TODO: This is not quite OK at the moment... */
-/* We ask the user where to put the partition in a region. Used for creating and resizing partitions */
-/* first and last mark the margins of the region, start and end mark the current values */
-static int
-_query_part_position(const MenuItem* menu, PedSector *start, PedSector *end, 
-		     PedSector first, PedSector last, PedConstraint *constraint, UIOpts *opts) {
-	
-	PedSector length = *end-*start+1, min_len = 0, max_len = dev->length;
-	int key,i,done;
-	char *temp,*temp2,*def_str, keys[6], buf[SMALLBUF];
-	i = 0;
-	/* If we have a constraint, check whether we can move the partition start */
-	if (constraint && (constraint->start_align->grain_size == 0 || constraint->start_range->length == 1))
-		key = 's';
-	else {
-		/* If there the first possible sector is not the start of the selected partition,
-			we need one choice in the menu to make the start fixed and one to move it back.
-			When it is, 'b' and 's' do the same. We ditch 'b' for more friendly resize menu,
-			action_new should use 's' as it doesn't matter there. 
-			FIXME: I wrote this fragment better, but ruined it. Now I'm too lazy to fix it */
-		if (first < *start) keys[i++] = 'b';
-		keys[i++] = 's'; keys[i++] = 'e'; keys[i++] = 'c';
-		keys [i++] = ESC;
-		keys [i] = '\0';
-		/* NOTE: Run menu_title before running this function */
-		//menu_title(_("Where do you want to put the partition"));
-		key = do_menu(menu, 11, MENU_BUTTON | MENU_TITLE, keys, NULL);
-	}
-	if (key == ESC)
-		return 0;
-	else {
-		if (key == 'c') {
-			*opts |= UI_CUSTOM_VALUES;
-		} else {
-			*opts &= ~UI_CUSTOM_VALUES;
-			if (key == 's')
-				max_len = last-*start+1;
-			else
-				max_len = last-first+1;
-			if (constraint) {
-				max_len = MIN(constraint->max_size,max_len);
-				min_len = constraint->min_size;
-			}
-			done = 0;
-			while (!done) {
-				/* Put the max and min size on the prompt */
-				temp = ped_unit_format(dev,min_len);
-				temp2 = ped_unit_format(dev,max_len);
-				if (temp && temp2) {
-					snprintf(buf,SMALLBUF,_("Size (min %s, max %s)"),
-						temp, temp2);
-				} else {
-					strncpy(buf,_("Size"),SMALLBUF);
-				}
-				if (temp) ped_free(temp);
-				if (temp2) ped_free(temp2);
-				def_str = ped_unit_format(dev,length);
-				if (def_str) temp = strdup(def_str);
-				if (!read_char(buf, &temp)) {
-					if (temp) ped_free(temp);
-					if (def_str) ped_free(def_str);
-					return 0;
-				}
-	
-				done = 1;
-				/* Get the new size only if the user modified it */
-				if(strcmp(temp,def_str)) {
-					if (!ped_unit_parse(temp,dev,&length,NULL)) {
-						warning_waitkey(N_("This is an invalid partition size"));
-						done = 0;
-					}
-					else if (length > max_len) {
-						length = max_len;
-					} else if (length < min_len) {
-						length = min_len;
-					}
-				}
-				if (temp) ped_free(temp);
-				if (def_str) ped_free(def_str);
-			}
-			if (key == 'b') {
-				*start = first;
-				*end = first+length-1;
-			}
-			else if (key == 'e') {
-				*end = last;
-				*start = last-length+1;
-			}
-			else if (key == 's') {
-				*end = *start+length-1;
-			}
-		}
-	}
-	return 1;
-	
-}
-/* TODO: Move to common? */
-/* This function returns the closest possible start and end for a partition
-   in the region fist-last */
-static int
-_fix_part_position(PedSector *start, PedSector *end, PedSector first,
-                   PedSector last)
-{
-	/* Current geometry */
-	PedGeometry *geom = ped_geometry_new (dev,*start,*end-*start+1);
-	if (!geom) return 0;
-	/* Possible range */
-	PedGeometry *range = ped_geometry_new (dev, first, last-first+1);
-	if (!range) {
-		ped_geometry_destroy(geom);
-		return 0;
-	}
-	PedConstraint *constraint = constraint_intersect_and_destroy(
-			constraint_from_start_end (dev, range, range),
-			ped_device_get_constraint (dev));
-
-	PedGeometry *new_geom = ped_constraint_solve_nearest(constraint, geom);
-
-	if (new_geom) {
-		if (*start != new_geom->start || *end != new_geom->end) {
-			/*char buf[SMALLBUF];
-			snprintf(buf,SMALLBUF,_("We changed the partition from %llds-%llds to %llds-%llds"),
-				*start,*end,new_geom->start,new_geom->end);
-			warning_waitkey(buf);*/
-			*start = new_geom->start;
-			*end = new_geom->end;
-			ped_geometry_destroy(new_geom);
-		}
-		return 1;
-	} 
-
-	return 0;
-
-}
-
-
-
 /* Emergency function. If some copy, move or resize fail, reread the disk from the device
    They commited it before failing, anyway. It is a bit like a hack, I might make the functions
    make it themselves. I actually did, but I had a little trouble with the UI, so for now it is this way
 
 	start = (*part)->geom.start;
 	end = (*part)->geom.end;
-	menu_title(_("Where do you want to put the partition"));
-	if(!_query_part_position(part_position,&start,&end,start,end,NULL,&opts))
+	if(!query_part_position(_("Where do you want to put the partition"),
+	                        part_position,&start,&end,start,end,dev,
+	                        NULL,&opts))
 		return 0;
 
 	if (!do_mkpart(disk,start,end,type,NULL,part,opts)) {
 	if ((*part)->next && (*part)->next->type & PED_PARTITION_FREESPACE)
 		last = (*part)->next->geom.end;
 	else last = end;
-
-	menu_title(_("Where to place the resized partition"));
-	if(!_query_part_position(part_position,&start,&end,first,last,
-	   constraint,&opts) || !_fix_part_position(&start,&end,first,last)) {
+	if(!query_part_position(_("Where to place the resized partition"),
+	                        part_position,&start,&end,first,last,dev,
+	                        constraint,&opts)) {
 		if (constraint) ped_constraint_destroy (constraint);
 		return 0;
 	}
 	length = MIN(length,(*part)->geom.length);
 	length = MAX(length,constraint->min_size);
 	end = start+length-1;
-	if(!_query_part_position(part_position,&start,&end,start,dst->geom.end,constraint,&opts)) {
+	if(!query_part_position(_("Where do you want to move the partition"),
+	                        part_position,&start,&end,start,dst->geom.end,
+	                        dev,constraint,&opts)) {
 		ped_constraint_destroy (constraint);
 		return 0;
 	}
 					}
 				}
 				else if (key == 'A') { /* That's up arrow */
-					/* You are not expected to understand this. */
+					/* Better try to solve a 5D rubic *
+					 * cube, than to figure this out. */
 					temp_a = 0;
 					temp_b = 0;
 					do { 
 	StrList *info = NULL;
 	char buf[SMALLBUF];
 	const char *temp;
-	int i;
+	int n;
 
 	unsigned int system_type;
 	int system_type_size;
 
 
-	/* TODO: This now displays bullshit */
-	snprintf(buf,SMALLBUF,"%30s: %s%d", _("Possible partition device"), dev->path, (*part)->num);
-	info = str_list_append(info,buf);
+	/* TODO: I did like it is done in Linux cfdisk. 
+	         This won't be always correct */
+	n = strlen(dev->path);
+	if (!is_devicefile) {
+		snprintf(buf,SMALLBUF,
+			isdigit(dev->path[n-1]) ? "%30s: %sp%d" : "%30s: %s%d",
+			_("Possible partition device"), dev->path, (*part)->num);
+		info = str_list_append(info,buf);
+	}
 
 	if ((*part)->type & PED_PARTITION_LOGICAL)
 		temp = _("Logical");
 			key = 0;
 			break;
 		default:
-			warning_waitkey("Unimplemented");	 /* TODO */
+			/* NOTE: I think this can't be reached */
+			warning_waitkey("Unimplemented");
 			key = 0;
 	}
 	return key;
 		}
 		else do_quit(0,NULL);
 	}
+	is_devicefile = !is_blockdev(dev->path);
 	if (!new_table) {
 		ped_exception_fetch_all ();
 		disk = ped_disk_new(dev);
 	info_size = calloc(n,sizeof(char));
 	strncpy(info_size,buf,n);
 
-	n = strlen(dev->model);
-	info_model = calloc(n,sizeof(char));
-	strncpy(info_model,dev->model,n);
+	/* FIXME: Isn't changing the pointer enough, why we cpy? */
+	if (is_devicefile) 
+		info_model = _("Device file");
+	else {
+		n = strlen(dev->model);
+		info_model = calloc(n,sizeof(char));
+		strncpy(info_model,dev->model,n);
+	}
 	
 	snprintf(buf,SMALLBUF,"%lldB/%lldB\n",dev->sector_size, dev->phys_sector_size);
 	n = strnlen(buf);
         return result;
 }
 
+/* This function returns the closest possible start and end for a partition
+   in the region first-last */
+int
+fix_part_position(PedDevice *dev, PedSector *start, PedSector *end,
+                  PedSector first, PedSector last)
+{
+	/* Current geometry */
+	PedGeometry *geom = ped_geometry_new (dev,*start,*end-*start+1);
+	if (!geom) return 0;
+	/* Possible range */
+	PedGeometry *range = ped_geometry_new (dev, first, last-first+1);
+	if (!range) {
+		ped_geometry_destroy(geom);
+		return 0;
+	}
+	PedConstraint *constraint = constraint_intersect_and_destroy(
+			constraint_from_start_end (dev, range, range),
+			ped_device_get_constraint (dev));
 
+	PedGeometry *new_geom = ped_constraint_solve_nearest(constraint, geom);
+
+	if (new_geom) {
+		if (*start != new_geom->start || *end != new_geom->end) {
+			*start = new_geom->start;
+			*end = new_geom->end;
+			ped_geometry_destroy(new_geom);
+		}
+		return 1;
+	} 
+
+	return 0;
+
+}
+
+#define ESC	'\033'	/* ^[ */
+/* TODO: This is not quite OK at the moment... */
+/* We ask the user where to put the partition in a region. Used for creating and resizing partitions */
+/* first and last mark the margins of the region, start and end mark the current values */
+int
+query_part_position(const char* prompt, const void* context, PedSector *start,
+                    PedSector *end,  PedSector first, PedSector last,
+                    PedDevice *dev, PedConstraint *constraint, UIOpts *opts) {
+	
+	PedSector length = *end-*start+1, min_len = 0, max_len = dev->length;
+	int where,i,done;
+	char *temp,*temp2,*def_str, possibilities[6], buf[SMALLBUF];
+	i = 0;
+	/* If we have a constraint, check whether we can move the partition start */
+	if (constraint && (constraint->start_align->grain_size == 0 || 
+	                   constraint->start_range->length == 1))
+		where = 's';
+	else {
+		/* If there the first possible sector is not the start of the selected partition,
+			we need one choice in the menu to make the start fixed and one to move it back.
+			When it is, 'b' and 's' do the same. We ditch 'b' for more friendly resize menu,
+			action_new should use 's' as it doesn't matter there. 
+			FIXME: I wrote this fragment better, but ruined it. Now I'm too lazy to fix it */
+		if (first < *start) possibilities[i++] = 'b';
+		possibilities[i++] = 's';
+		possibilities[i++] = 'e';
+		possibilities[i++] = 'c';
+		possibilities [i++] = ESC;
+		possibilities [i] = '\0';
+		where = uiquery->getpartpos(prompt, context, possibilities);
+	}
+	if (where == ESC)
+		return 0;
+	else {
+		if (where == 'c') {
+			*opts |= UI_CUSTOM_VALUES;
+		} else {
+			*opts &= ~UI_CUSTOM_VALUES;
+			if (where == 's')
+				max_len = last-*start+1;
+			else
+				max_len = last-first+1;
+			if (constraint) {
+				if (constraint->max_size < max_len)
+					max_len = constraint->max_size;
+				min_len = constraint->min_size;
+			}
+			done = 0;
+			while (!done) {
+				/* Put the max and min size on the prompt */
+				temp = ped_unit_format(dev,min_len);
+				temp2 = ped_unit_format(dev,max_len);
+				if (temp && temp2) {
+					snprintf(buf,SMALLBUF,_("Size (min %s, max %s)"),
+						temp, temp2);
+				} else {
+					strncpy(buf,_("Size"),SMALLBUF);
+				}
+				if (temp) ped_free(temp);
+				if (temp2) ped_free(temp2);
+				def_str = ped_unit_format(dev,length);
+				if (def_str) temp = strdup(def_str);
+				if (!uiquery->getstring(buf, &temp, NULL, NULL, 1)) {
+					if (temp) ped_free(temp);
+					if (def_str) ped_free(def_str);
+					return 0;
+				}
+	
+				done = 1;
+				/* Get the new size only if the user modified it */
+				if(strcmp(temp,def_str)) {
+					if (!ped_unit_parse(temp,dev,&length,NULL)) {
+						done = !ped_exception_throw(
+							PED_EXCEPTION_ERROR,
+							PED_EXCEPTION_RETRY_CANCEL,
+							"%s is an invalid partition size",
+							temp);
+						if (done)
+							return 0;
+					}
+					else if (length > max_len) {
+						length = max_len;
+					} else if (length < min_len) {
+						length = min_len;
+					}
+				}
+				if (temp) ped_free(temp);
+				if (def_str) ped_free(def_str);
+			}
+			if (where == 'b') {
+				*start = first;
+				*end = first+length-1;
+			}
+			else if (where == 'e') {
+				*end = last;
+				*start = last-length+1;
+			}
+			else if (where == 's') {
+				*end = *start+length-1;
+			}
+		}
+	}
+	return 1;
+	
+}
 
 static int
 get_device(const char* prompt, PedDevice** value)
 	int (*getpart)(const char* prompt, PedDisk**, PedPartition** value);
 	int (*getdisktype)(const char* prompt, PedDiskType** value);
 	int (*getfstype)(const char* prompt, PedFileSystemType** value);
+	int (*getpartpos)(const char* prompt, const void* context, 
+	                   const char *possibilities);
 	PedTimer* timer;
 	int need_commit;
 };
 				PedGeometry* range_end);
 extern PedConstraint*
 constraint_intersect_and_destroy (PedConstraint* a, PedConstraint* b);
+/* This function returns the closest possible start and end for a partition
+   in the region first-last */
+extern int fix_part_position(PedDevice *dev, PedSector *start, PedSector *end,
+                             PedSector first, PedSector last);
 
+/* Choose the partition position */
+extern int
+query_part_position(const char* prompt, const void* context, PedSector *start,
+                    PedSector *end,  PedSector first, PedSector last,
+                    PedDevice *dev, PedConstraint *constraint, UIOpts *opts);
 #endif
 #include "../config.h"
 #include <string.h>
 #include <stdint.h>
+#include <sys/stat.h>
 #include "hacks.h"
 
 #define MSDOS_HACK 1
 #define PC98_HACK 0
 #define AMIGA_HACK 0
 
+/* Check if it is a block device. Returns -1 if not found. */
+int is_blockdev(const char *file) {
+	struct stat file_stat;
+	if (stat(file,&file_stat) < 0)
+		return -1;
+	if(S_ISBLK(file_stat.st_mode))
+		return 1;
+	else
+		return 0;
+}
+
 /* We need a function to get disk type-specific info about filesystem */
 /* TODO: Decide if we actually need all these... I think we should leave them, at least for the 
    msdos partition type. */
 #define HACKS_H_INCLUDED
 #include <parted/parted.h>
 
+extern int is_blockdev(const char *file);
 extern const char* get_disk_specific_system_name (PedPartition*);
 extern unsigned int get_disk_specific_system_type (PedPartition *part, int *size);
 #endif
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.