[PATCH 2/5] fdisk: move DOS new/add partition code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Davidlohr Bueso <dave@xxxxxxx>
 
Since this is DOS specific logic, it belongs in its own label file. Additionally, a dos_new_partition() function is created
that asks the user for partition type and then calls the actual dos_add_partition().

This patch passed fdisk regression tests, builds without problems and it was locally tested against adding and removing DOS partitions.

Signed-off-by: Davidlohr Bueso <dave@xxxxxxx>
---
 fdisk/fdisk.c         |  354 ++-----------------------------------------------
 fdisk/fdisk.h         |   22 +++-
 fdisk/fdiskdoslabel.c |  332 ++++++++++++++++++++++++++++++++++++++++++++++
 fdisk/fdiskdoslabel.h |    5 +-
 4 files changed, 365 insertions(+), 348 deletions(-)

diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c
index 3543745..8c2a162 100644
--- a/fdisk/fdisk.c
+++ b/fdisk/fdisk.c
@@ -64,19 +64,9 @@ int MBRbuffer_changed;
 			})
 

-#define LINE_LENGTH	800
 #define sector(s)	((s) & 0x3f)
 #define cylinder(s, c)	((c) | (((s) & 0xc0) << 2))
 
-#define set_hsc(h,s,c,sector) { \
-				s = sector % sectors + 1;	\
-				sector /= sectors;	\
-				h = sector % heads;	\
-				sector /= heads;	\
-				c = sector & 0xff;	\
-				s |= (sector >> 2) & 0xc0;	\
-			}
-
 /* menu list description */
 
 struct menulist_descr {
@@ -154,7 +144,7 @@ int	fd,				/* the disk */
 unsigned int	user_cylinders, user_heads, user_sectors;
 unsigned int   pt_heads, pt_sectors;
 
-unsigned long long sector_offset = 1, /* extended_offset = 0, */ sectors;
+unsigned long long sector_offset = 1, sectors;
 
 unsigned int	heads,
 	cylinders,
@@ -319,43 +309,6 @@ void list_types(struct systypes *sys)
 }
 
 static int
-is_cleared_partition(struct partition *p) {
-	return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
-		 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
-		 get_start_sect(p) || get_nr_sects(p));
-}
-
-static void
-set_partition(int i, int doext, unsigned long long start,
-	      unsigned long long stop, int sysid) {
-	struct partition *p;
-	unsigned long long offset;
-
-	if (doext) {
-		p = ptes[i].ext_pointer;
-		offset = extended_offset;
-	} else {
-		p = ptes[i].part_table;
-		offset = ptes[i].offset;
-	}
-	p->boot_ind = 0;
-	p->sys_ind = sysid;
-	set_start_sect(p, start - offset);
-	set_nr_sects(p, stop - start + 1);
-
-	if (!doext)
-		print_partition_size(i + 1, start, stop, sysid);
-
-	if (dos_compatible_flag && (start/(sectors*heads) > 1023))
-		start = heads*sectors*1024 - 1;
-	set_hsc(p->head, p->sector, p->cyl, start);
-	if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
-		stop = heads*sectors*1024 - 1;
-	set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
-	ptes[i].changed = 1;
-}
-
-static int
 test_c(char **m, char *mesg) {
 	int val = 0;
 	if (!*m)
@@ -368,8 +321,6 @@ test_c(char **m, char *mesg) {
 	return val;
 }
 
-#define alignment_required	(grain != sector_size)
-
 static int
 lba_is_aligned(unsigned long long lba)
 {
@@ -379,12 +330,7 @@ lba_is_aligned(unsigned long long lba)
 	return !((granularity + alignment_offset - offset) & (granularity - 1));
 }
 
-#define ALIGN_UP	1
-#define ALIGN_DOWN	2
-#define ALIGN_NEAREST	3
-
-static unsigned long long
-align_lba(unsigned long long lba, int direction)
+unsigned long long align_lba(unsigned long long lba, int direction)
 {
 	unsigned long long res;
 
@@ -435,23 +381,6 @@ align_lba(unsigned long long lba, int direction)
 	return res;
 }
 
-static unsigned long long
-align_lba_in_range(	unsigned long long lba,
-			unsigned long long start,
-			unsigned long long stop)
-{
-	start = align_lba(start, ALIGN_UP);
-	stop = align_lba(stop, ALIGN_DOWN);
-
-	lba = align_lba(lba, ALIGN_NEAREST);
-
-	if (lba < start)
-		return start;
-	else if (lba > stop)
-		return stop;
-	return lba;
-}
-
 int warn_geometry(void)
 {
 	char *m = NULL;
@@ -881,7 +810,7 @@ read_hex(struct systypes *sys)
         }
 }
 
-static unsigned int
+unsigned int
 read_int_with_suffix(unsigned int low, unsigned int dflt, unsigned int high,
 	 unsigned int base, char *mesg, int *is_suffix_used)
 {
@@ -1024,7 +953,6 @@ read_int(unsigned int low, unsigned int dflt, unsigned int high,
 	return read_int_with_suffix(low, dflt, high, base, mesg, NULL);
 }
 
-
 int
 get_partition_dflt(int warn, int max, int dflt) {
 	struct pte *pe;
@@ -1085,35 +1013,6 @@ not_unique:
 	return get_partition(warn, max);
 }
 
-static int
-get_nonexisting_partition(int warn, int max) {
-	int pno = -1;
-	int i;
-	int dflt = 0;
-
-	for (i = 0; i < max; i++) {
-		struct pte *pe = &ptes[i];
-		struct partition *p = pe->part_table;
-
-		if (p && is_cleared_partition(p)) {
-			if (pno >= 0) {
-				dflt = pno + 1;
-				goto not_unique;
-			}
-			pno = i;
-		}
-	}
-	if (pno >= 0) {
-		printf(_("Selected partition %d\n"), pno+1);
-		return pno;
-	}
-	printf(_("All primary partitions have been defined already!\n"));
-	return -1;
-
- not_unique:
-	return get_partition_dflt(warn, max, dflt);
-}
-
 const char *
 str_units(int n)
 {
@@ -1604,8 +1503,8 @@ x_list_table(int extend) {
 	}
 }
 
-static void
-fill_bounds(unsigned long long *first, unsigned long long *last) {
+void fill_bounds(unsigned long long *first, unsigned long long *last)
+{
 	int i;
 	struct pte *pe = &ptes[0];
 	struct partition *p;
@@ -1724,27 +1623,6 @@ verify(void) {
 		       n_sectors - total, sector_size);
 }
 
-static unsigned long long
-get_unused_start(int part_n,
-		unsigned long long start,
-		unsigned long long first[],
-		unsigned long long last[])
-{
-	int i;
-
-	for (i = 0; i < partitions; i++) {
-		unsigned long long lastplusoff;
-
-		if (start == ptes[i].offset)
-			start += sector_offset;
-		lastplusoff = last[i] + ((part_n < 4) ? 0 : sector_offset);
-		if (start >= first[i] && start <= lastplusoff)
-			start = lastplusoff + 1;
-	}
-
-	return start;
-}
-
 void print_partition_size(int num, unsigned long long start, unsigned long long stop, int sysid)
 {
 	char *str = size_to_human_string(SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE,
@@ -1753,171 +1631,8 @@ void print_partition_size(int num, unsigned long long start, unsigned long long
 	free(str);
 }
 
-static void
-add_partition(int n, int sys) {
-	char mesg[256];		/* 48 does not suffice in Japanese */
-	int i, read = 0;
-	struct partition *p = ptes[n].part_table;
-	struct partition *q = ptes[ext_index].part_table;
-	unsigned long long start, stop = 0, limit, temp,
-		first[partitions], last[partitions];
-
-	if (p && p->sys_ind) {
-		printf(_("Partition %d is already defined.  Delete "
-			 "it before re-adding it.\n"), n + 1);
-		return;
-	}
-	fill_bounds(first, last);
-	if (n < 4) {
-		start = sector_offset;
-		if (display_in_cyl_units || !total_number_of_sectors)
-			limit = heads * sectors * cylinders - 1;
-		else
-			limit = total_number_of_sectors - 1;
-
-		if (limit > UINT_MAX)
-			limit = UINT_MAX;
-
-		if (extended_offset) {
-			first[ext_index] = extended_offset;
-			last[ext_index] = get_start_sect(q) +
-				get_nr_sects(q) - 1;
-		}
-	} else {
-		start = extended_offset + sector_offset;
-		limit = get_start_sect(q) + get_nr_sects(q) - 1;
-	}
-	if (display_in_cyl_units)
-		for (i = 0; i < partitions; i++)
-			first[i] = (cround(first[i]) - 1) * units_per_sector;
-
-	snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
-	do {
-		unsigned long long dflt, aligned;
-
-		temp = start;
-		dflt = start = get_unused_start(n, start, first, last);
-
-		/* the default sector should be aligned and unused */
-		do {
-			aligned = align_lba_in_range(dflt, dflt, limit);
-			dflt = get_unused_start(n, aligned, first, last);
-		} while (dflt != aligned && dflt > aligned && dflt < limit);
-
-		if (dflt >= limit)
-			dflt = start;
-		if (start > limit)
-			break;
-		if (start >= temp+units_per_sector && read) {
-			printf(_("Sector %llu is already allocated\n"), temp);
-			temp = start;
-			read = 0;
-		}
-		if (!read && start == temp) {
-			unsigned long long i = start;
-
-			start = read_int(cround(i), cround(dflt), cround(limit),
-					 0, mesg);
-			if (display_in_cyl_units) {
-				start = (start - 1) * units_per_sector;
-				if (start < i) start = i;
-			}
-			read = 1;
-		}
-	} while (start != temp || !read);
-	if (n > 4) {			/* NOT for fifth partition */
-		struct pte *pe = &ptes[n];
-
-		pe->offset = start - sector_offset;
-		if (pe->offset == extended_offset) { /* must be corrected */
-			pe->offset++;
-			if (sector_offset == 1)
-				start++;
-		}
-	}
-
-	for (i = 0; i < partitions; i++) {
-		struct pte *pe = &ptes[i];
-
-		if (start < pe->offset && limit >= pe->offset)
-			limit = pe->offset - 1;
-		if (start < first[i] && limit >= first[i])
-			limit = first[i] - 1;
-	}
-	if (start > limit) {
-		printf(_("No free sectors available\n"));
-		if (n > 4)
-			partitions--;
-		return;
-	}
-	if (cround(start) == cround(limit)) {
-		stop = limit;
-	} else {
-		int is_suffix_used = 0;
-
-		snprintf(mesg, sizeof(mesg),
-			_("Last %1$s, +%2$s or +size{K,M,G}"),
-			 str_units(SINGULAR), str_units(PLURAL));
-
-		stop = read_int_with_suffix(cround(start), cround(limit), cround(limit),
-				cround(start), mesg, &is_suffix_used);
-		if (display_in_cyl_units) {
-			stop = stop * units_per_sector - 1;
-			if (stop >limit)
-				stop = limit;
-		}
-
-		if (is_suffix_used && alignment_required) {
-			/* the last sector has not been exactly requested (but
-			 * defined by +size{K,M,G} convention), so be smart
-			 * and align the end of the partition. The next
-			 * partition will start at phy.block boundary.
-			 */
-			stop = align_lba_in_range(stop, start, limit) - 1;
-			if (stop > limit)
-				stop = limit;
-		}
-	}
-
-	set_partition(n, 0, start, stop, sys);
-	if (n > 4)
-		set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
-
-	if (IS_EXTENDED (sys)) {
-		struct pte *pe4 = &ptes[4];
-		struct pte *pen = &ptes[n];
-
-		ext_index = n;
-		pen->ext_pointer = p;
-		pe4->offset = extended_offset = start;
-		pe4->sectorbuffer = xcalloc(1, sector_size);
-		pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
-		pe4->ext_pointer = pe4->part_table + 1;
-		pe4->changed = 1;
-		partitions = 5;
-	}
-}
-
-static void
-add_logical(void) {
-	if (partitions > 5 || ptes[4].part_table->sys_ind) {
-		struct pte *pe = &ptes[partitions];
-
-		pe->sectorbuffer = xcalloc(1, sector_size);
-		pe->part_table = pt_offset(pe->sectorbuffer, 0);
-		pe->ext_pointer = pe->part_table + 1;
-		pe->offset = 0;
-		pe->changed = 1;
-		partitions++;
-	}
-	printf(_("Adding logical partition %d\n"), partitions);
-	add_partition(partitions - 1, LINUX_NATIVE);
-}
-
-static void
-new_partition(void) {
-	int i, free_primary = 0;
-
+static void new_partition(void)
+{
 	if (warn_geometry())
 		return;
 
@@ -1949,59 +1664,8 @@ new_partition(void) {
 		 return;
 	}
 
-	for (i = 0; i < 4; i++)
-		free_primary += !ptes[i].part_table->sys_ind;
-
-	if (!free_primary && partitions >= MAXIMUM_PARTS) {
-		printf(_("The maximum number of partitions has been created\n"));
-		return;
-	}
-
-	if (!free_primary) {
-		if (extended_offset) {
-			printf(_("All primary partitions are in use\n"));
-			add_logical();
-		} else
-			printf(_("If you want to create more than four partitions, you must replace a\n"
-				 "primary partition with an extended partition first.\n"));
-	} else if (partitions >= MAXIMUM_PARTS) {
-		printf(_("All logical partitions are in use\n"));
-		printf(_("Adding a primary partition\n"));
-		add_partition(get_partition(0, 4), LINUX_NATIVE);
-	} else {
-		char c, dflt, line[LINE_LENGTH];
-
-		dflt = (free_primary == 1 && !extended_offset) ? 'e' : 'p';
-		snprintf(line, sizeof(line),
-			 _("Partition type:\n"
-			   "   p   primary (%d primary, %d extended, %d free)\n"
-			   "%s\n"
-			   "Select (default %c): "),
-			 4 - (extended_offset ? 1 : 0) - free_primary, extended_offset ? 1 : 0, free_primary,
-			 extended_offset ? _("   l   logical (numbered from 5)") : _("   e   extended"),
-			 dflt);
-
-		c = tolower(read_chars(line));
-		if (c == '\n') {
-			c = dflt;
-			printf(_("Using default response %c\n"), c);
-		}
-		if (c == 'p') {
-			int i = get_nonexisting_partition(0, 4);
-			if (i >= 0)
-				add_partition(i, LINUX_NATIVE);
-			return;
-		} else if (c == 'l' && extended_offset) {
-			add_logical();
-			return;
-		} else if (c == 'e' && !extended_offset) {
-			int i = get_nonexisting_partition(0, 4);
-			if (i >= 0)
-				add_partition(i, EXTENDED);
-			return;
-		} else
-			printf(_("Invalid partition type `%c'\n"), c);
-	}
+	/* default to DOS/BSD */
+	dos_new_partition();
 }
 
 static void
diff --git a/fdisk/fdisk.h b/fdisk/fdisk.h
index 3a1cfd7..0dafbf8 100644
--- a/fdisk/fdisk.h
+++ b/fdisk/fdisk.h
@@ -20,6 +20,12 @@
 #define LINUX_LVM       0x8e
 #define LINUX_RAID      0xfd
 
+#define ALIGN_UP	1
+#define ALIGN_DOWN	2
+#define ALIGN_NEAREST	3
+
+#define LINE_LENGTH	800
+
 #define IS_EXTENDED(i) \
 	((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
 
@@ -78,7 +84,7 @@ extern void print_menu(enum menutype);
 extern void print_partition_size(int num, unsigned long long start, unsigned long long stop, int sysid);
 
 extern void zeroize_mbr_buffer(void);
-
+extern void fill_bounds(unsigned long long *first, unsigned long long *last);
 extern unsigned int heads, cylinders, sector_size;
 extern unsigned long long sectors;
 extern char *partition_type(unsigned char type);
@@ -89,6 +95,10 @@ extern void set_all_unchanged(void);
 extern int warn_geometry(void);
 extern void warn_limits(void);
 extern void warn_alignment(void);
+extern unsigned int read_int_with_suffix(unsigned int low, unsigned int dflt, unsigned int high,
+				  unsigned int base, char *mesg, int *is_suffix_used);
+extern unsigned long long align_lba(unsigned long long lba, int direction);
+extern int get_partition_dflt(int warn, int max, int dflt);
 
 #define PLURAL	0
 #define SINGULAR 1
@@ -114,7 +124,8 @@ extern enum labeltype disklabel;
  */
 extern unsigned char *MBRbuffer;
 extern int MBRbuffer_changed;
-
+extern unsigned long long total_number_of_sectors;
+extern unsigned long grain;
 /* start_sect and nr_sects are stored little endian on all machines */
 /* moreover, they are not aligned correctly */
 static inline void
@@ -168,6 +179,13 @@ static inline unsigned long long get_start_sect(struct partition *p)
 	return read4_little_endian(p->start4);
 }
 
+static inline int is_cleared_partition(struct partition *p)
+{
+	return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
+		 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
+		 get_start_sect(p) || get_nr_sects(p));
+}
+
 /* prototypes for fdiskbsdlabel.c */
 extern void bsd_command_prompt(void);
 extern int check_osf_label(void);
diff --git a/fdisk/fdiskdoslabel.c b/fdisk/fdiskdoslabel.c
index 4dfe876..3f820db 100644
--- a/fdisk/fdiskdoslabel.c
+++ b/fdisk/fdiskdoslabel.c
@@ -4,6 +4,7 @@
  */
 
 #include <unistd.h>
+#include <ctype.h>
 
 #include "nls.h"
 #include "xalloc.h"
@@ -12,10 +13,51 @@
 #include "fdisk.h"
 #include "fdiskdoslabel.h"
 
+#define set_hsc(h,s,c,sector) { \
+		s = sector % sectors + 1;			\
+		sector /= sectors;				\
+		h = sector % heads;				\
+		sector /= heads;				\
+		c = sector & 0xff;				\
+		s |= (sector >> 2) & 0xc0;			\
+	}
+
+#define alignment_required	(grain != sector_size)
+
 struct pte ptes[MAXIMUM_PARTS];
 unsigned long long extended_offset;
 int ext_index;
 
+static int get_nonexisting_partition(int warn, int max)
+{
+	int pno = -1;
+	int i;
+	int dflt = 0;
+
+	for (i = 0; i < max; i++) {
+		struct pte *pe = &ptes[i];
+		struct partition *p = pe->part_table;
+
+		if (p && is_cleared_partition(p)) {
+			if (pno >= 0) {
+				dflt = pno + 1;
+				goto not_unique;
+			}
+			pno = i;
+		}
+	}
+	if (pno >= 0) {
+		printf(_("Selected partition %d\n"), pno+1);
+		return pno;
+	}
+	printf(_("All primary partitions have been defined already!\n"));
+	return -1;
+
+ not_unique:
+	return get_partition_dflt(warn, max, dflt);
+}
+
+
 /* Allocate a buffer and read a partition table sector */
 static void read_pte(int fd, int pno, unsigned long long offset)
 {
@@ -325,3 +367,293 @@ int is_dos_partition(int t)
 		t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
 		t == 0xc1 || t == 0xc4 || t == 0xc6);
 }
+
+static void set_partition(int i, int doext, unsigned long long start,
+			  unsigned long long stop, int sysid)
+{
+	struct partition *p;
+	unsigned long long offset;
+
+	if (doext) {
+		p = ptes[i].ext_pointer;
+		offset = extended_offset;
+	} else {
+		p = ptes[i].part_table;
+		offset = ptes[i].offset;
+	}
+	p->boot_ind = 0;
+	p->sys_ind = sysid;
+	set_start_sect(p, start - offset);
+	set_nr_sects(p, stop - start + 1);
+
+	if (!doext)
+		print_partition_size(i + 1, start, stop, sysid);
+
+	if (dos_compatible_flag && (start/(sectors*heads) > 1023))
+		start = heads*sectors*1024 - 1;
+	set_hsc(p->head, p->sector, p->cyl, start);
+	if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
+		stop = heads*sectors*1024 - 1;
+	set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
+	ptes[i].changed = 1;
+}
+
+static unsigned long long get_unused_start(int part_n,
+					   unsigned long long start,
+					   unsigned long long first[],
+					   unsigned long long last[])
+{
+	int i;
+
+	for (i = 0; i < partitions; i++) {
+		unsigned long long lastplusoff;
+
+		if (start == ptes[i].offset)
+			start += sector_offset;
+		lastplusoff = last[i] + ((part_n < 4) ? 0 : sector_offset);
+		if (start >= first[i] && start <= lastplusoff)
+			start = lastplusoff + 1;
+	}
+
+	return start;
+}
+
+static unsigned long long align_lba_in_range(	unsigned long long lba,
+						unsigned long long start,
+						unsigned long long stop)
+{
+	start = align_lba(start, ALIGN_UP);
+	stop = align_lba(stop, ALIGN_DOWN);
+
+	lba = align_lba(lba, ALIGN_NEAREST);
+
+	if (lba < start)
+		return start;
+	else if (lba > stop)
+		return stop;
+	return lba;
+}
+
+void dos_add_partition(int n, int sys)
+{
+	char mesg[256];		/* 48 does not suffice in Japanese */
+	int i, read = 0;
+	struct partition *p = ptes[n].part_table;
+	struct partition *q = ptes[ext_index].part_table;
+	unsigned long long start, stop = 0, limit, temp,
+		first[partitions], last[partitions];
+
+	if (p && p->sys_ind) {
+		printf(_("Partition %d is already defined.  Delete "
+			 "it before re-adding it.\n"), n + 1);
+		return;
+	}
+	fill_bounds(first, last);
+	if (n < 4) {
+		start = sector_offset;
+		if (display_in_cyl_units || !total_number_of_sectors)
+			limit = heads * sectors * cylinders - 1;
+		else
+			limit = total_number_of_sectors - 1;
+
+		if (limit > UINT_MAX)
+			limit = UINT_MAX;
+
+		if (extended_offset) {
+			first[ext_index] = extended_offset;
+			last[ext_index] = get_start_sect(q) +
+				get_nr_sects(q) - 1;
+		}
+	} else {
+		start = extended_offset + sector_offset;
+		limit = get_start_sect(q) + get_nr_sects(q) - 1;
+	}
+	if (display_in_cyl_units)
+		for (i = 0; i < partitions; i++)
+			first[i] = (cround(first[i]) - 1) * units_per_sector;
+
+	snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
+	do {
+		unsigned long long dflt, aligned;
+
+		temp = start;
+		dflt = start = get_unused_start(n, start, first, last);
+
+		/* the default sector should be aligned and unused */
+		do {
+			aligned = align_lba_in_range(dflt, dflt, limit);
+			dflt = get_unused_start(n, aligned, first, last);
+		} while (dflt != aligned && dflt > aligned && dflt < limit);
+
+		if (dflt >= limit)
+			dflt = start;
+		if (start > limit)
+			break;
+		if (start >= temp+units_per_sector && read) {
+			printf(_("Sector %llu is already allocated\n"), temp);
+			temp = start;
+			read = 0;
+		}
+		if (!read && start == temp) {
+			unsigned long long i = start;
+
+			start = read_int(cround(i), cround(dflt), cround(limit),
+					 0, mesg);
+			if (display_in_cyl_units) {
+				start = (start - 1) * units_per_sector;
+				if (start < i) start = i;
+			}
+			read = 1;
+		}
+	} while (start != temp || !read);
+	if (n > 4) {			/* NOT for fifth partition */
+		struct pte *pe = &ptes[n];
+
+		pe->offset = start - sector_offset;
+		if (pe->offset == extended_offset) { /* must be corrected */
+			pe->offset++;
+			if (sector_offset == 1)
+				start++;
+		}
+	}
+
+	for (i = 0; i < partitions; i++) {
+		struct pte *pe = &ptes[i];
+
+		if (start < pe->offset && limit >= pe->offset)
+			limit = pe->offset - 1;
+		if (start < first[i] && limit >= first[i])
+			limit = first[i] - 1;
+	}
+	if (start > limit) {
+		printf(_("No free sectors available\n"));
+		if (n > 4)
+			partitions--;
+		return;
+	}
+	if (cround(start) == cround(limit)) {
+		stop = limit;
+	} else {
+		int is_suffix_used = 0;
+
+		snprintf(mesg, sizeof(mesg),
+			_("Last %1$s, +%2$s or +size{K,M,G}"),
+			 str_units(SINGULAR), str_units(PLURAL));
+
+		stop = read_int_with_suffix(cround(start), cround(limit), cround(limit),
+				cround(start), mesg, &is_suffix_used);
+		if (display_in_cyl_units) {
+			stop = stop * units_per_sector - 1;
+			if (stop >limit)
+				stop = limit;
+		}
+
+		if (is_suffix_used && alignment_required) {
+			/* the last sector has not been exactly requested (but
+			 * defined by +size{K,M,G} convention), so be smart
+			 * and align the end of the partition. The next
+			 * partition will start at phy.block boundary.
+			 */
+			stop = align_lba_in_range(stop, start, limit) - 1;
+			if (stop > limit)
+				stop = limit;
+		}
+	}
+
+	set_partition(n, 0, start, stop, sys);
+	if (n > 4)
+		set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
+
+	if (IS_EXTENDED (sys)) {
+		struct pte *pe4 = &ptes[4];
+		struct pte *pen = &ptes[n];
+
+		ext_index = n;
+		pen->ext_pointer = p;
+		pe4->offset = extended_offset = start;
+		pe4->sectorbuffer = xcalloc(1, sector_size);
+		pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
+		pe4->ext_pointer = pe4->part_table + 1;
+		pe4->changed = 1;
+		partitions = 5;
+	}
+}
+
+static void add_logical(void)
+{
+	if (partitions > 5 || ptes[4].part_table->sys_ind) {
+		struct pte *pe = &ptes[partitions];
+
+		pe->sectorbuffer = xcalloc(1, sector_size);
+		pe->part_table = pt_offset(pe->sectorbuffer, 0);
+		pe->ext_pointer = pe->part_table + 1;
+		pe->offset = 0;
+		pe->changed = 1;
+		partitions++;
+	}
+	printf(_("Adding logical partition %d\n"), partitions);
+	dos_add_partition(partitions - 1, LINUX_NATIVE);
+}
+
+/*
+ * Ask the user for new partition type information (logical, extended).
+ * This function calls the actual partition adding logic - dos_add_partition.
+ */
+void dos_new_partition(void)
+{
+	int i, free_primary = 0;
+
+	for (i = 0; i < 4; i++)
+		free_primary += !ptes[i].part_table->sys_ind;
+
+	if (!free_primary && partitions >= MAXIMUM_PARTS) {
+		printf(_("The maximum number of partitions has been created\n"));
+		return;
+	}
+
+	if (!free_primary) {
+		if (extended_offset) {
+			printf(_("All primary partitions are in use\n"));
+			add_logical();
+		} else
+			printf(_("If you want to create more than four partitions, you must replace a\n"
+				 "primary partition with an extended partition first.\n"));
+	} else if (partitions >= MAXIMUM_PARTS) {
+		printf(_("All logical partitions are in use\n"));
+		printf(_("Adding a primary partition\n"));
+		dos_add_partition(get_partition(0, 4), LINUX_NATIVE);
+	} else {
+		char c, dflt, line[LINE_LENGTH];
+
+		dflt = (free_primary == 1 && !extended_offset) ? 'e' : 'p';
+		snprintf(line, sizeof(line),
+			 _("Partition type:\n"
+			   "   p   primary (%d primary, %d extended, %d free)\n"
+			   "%s\n"
+			   "Select (default %c): "),
+			 4 - (extended_offset ? 1 : 0) - free_primary, extended_offset ? 1 : 0, free_primary,
+			 extended_offset ? _("   l   logical (numbered from 5)") : _("   e   extended"),
+			 dflt);
+
+		c = tolower(read_chars(line));
+		if (c == '\n') {
+			c = dflt;
+			printf(_("Using default response %c\n"), c);
+		}
+		if (c == 'p') {
+			int i = get_nonexisting_partition(0, 4);
+			if (i >= 0)
+				dos_add_partition(i, LINUX_NATIVE);
+			return;
+		} else if (c == 'l' && extended_offset) {
+			add_logical();
+			return;
+		} else if (c == 'e' && !extended_offset) {
+			int i = get_nonexisting_partition(0, 4);
+			if (i >= 0)
+				dos_add_partition(i, EXTENDED);
+			return;
+		} else
+			printf(_("Invalid partition type `%c'\n"), c);
+	}
+}
diff --git a/fdisk/fdiskdoslabel.h b/fdisk/fdiskdoslabel.h
index 1897b6c..e45a026 100644
--- a/fdisk/fdiskdoslabel.h
+++ b/fdisk/fdiskdoslabel.h
@@ -18,12 +18,13 @@ struct pte {
 };
 
 extern struct pte ptes[MAXIMUM_PARTS];
+extern int dos_compatible_flag;
 
 #define pt_offset(b, n)	((struct partition *)((b) + 0x1be + \
 					      (n) * sizeof(struct partition)))
 
 extern int ext_index; /* the prime extended partition */
-extern unsigned long long extended_offset;
+extern unsigned long long extended_offset, sector_offset;
 
 static inline void write_part_table_flag(unsigned char *b)
 {
@@ -49,5 +50,7 @@ extern void dos_delete_partition(int i);
 extern int check_dos_label(void);
 extern int is_dos_partition(int t);
 extern void dos_init(void);
+extern void dos_add_partition(int n, int sys);
+extern void dos_new_partition(void);
 
 #endif
-- 
1.7.4.1




--
To unsubscribe from this list: send the line "unsubscribe util-linux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux