summaryrefslogtreecommitdiffstats
path: root/libfdisk/src/dos.c
diff options
context:
space:
mode:
authorKarel Zak2013-11-25 12:00:55 +0100
committerKarel Zak2013-11-25 12:00:55 +0100
commitd0a870c5b3f57309edd81021ca4c9174380cfb56 (patch)
tree30073ef6e63240dd8ea3d352b23a142cbee6c8b3 /libfdisk/src/dos.c
parentfdisk: fix nasty coding style (diff)
downloadkernel-qcow2-util-linux-d0a870c5b3f57309edd81021ca4c9174380cfb56.tar.gz
kernel-qcow2-util-linux-d0a870c5b3f57309edd81021ca4c9174380cfb56.tar.xz
kernel-qcow2-util-linux-d0a870c5b3f57309edd81021ca4c9174380cfb56.zip
fdisk: don't care about partition type
fdisk allows to overwrite existing partition if the partition has partition type set to zero (very unusual, but possible). This is incorrect because such partition is pretty valid (and Linux kernel does not care about the type at all). For example: Device Boot Start End Blocks Id System /dev/sdb1 2048 22527 10240 83 Linux /dev/sdb2 22528 227327 102400 0 Empty ^^^^^ ^^^^^^^^ Command (m for help): n Partition type: p primary (1 primary, 0 extended, 3 free) e extended Select (default p): Using default response p Partition number (3,4, default 3): First sector (22528-1228799, default 22528): ^^^^^^^ .. if user follows the default then the result are overlapping partitions: Device Boot Start End Blocks Id System /dev/sdb1 2048 22527 10240 83 Linux /dev/sdb2 22528 227327 102400 0 Empty /dev/sdb3 22528 1228799 603136 83 Linux ^^^^^ ... and if you call "mkfs /dev/sdb3" then you lost data on sdb2. Sad thing. Reported-by: Marc MERLIN <marc@merlins.org> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk/src/dos.c')
-rw-r--r--libfdisk/src/dos.c38
1 files changed, 22 insertions, 16 deletions
diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c
index 4c2b7f78b..92dc3b995 100644
--- a/libfdisk/src/dos.c
+++ b/libfdisk/src/dos.c
@@ -148,6 +148,15 @@ static sector_t get_abs_partition_start(struct pte *pe)
return pe->offset + dos_partition_get_start(pe->pt_entry);
}
+/*
+ * Linux kernel cares about partition size only. Things like
+ * partition type or so are completely irrelevant -- kzak Nov-2013
+ */
+static int is_used_partition(struct dos_partition *p)
+{
+ return p && dos_partition_get_size(p) != 0;
+}
+
static int is_cleared_partition(struct dos_partition *p)
{
return !(!p || p->boot_ind || p->bh || p->bs || p->bc ||
@@ -672,7 +681,7 @@ static int dos_probe_label(struct fdisk_context *cxt)
for (i = 0; i < 4; i++) {
struct pte *pe = self_pte(cxt, i);
- if (!is_cleared_partition(pe->pt_entry))
+ if (is_used_partition(pe->pt_entry))
cxt->label->nparts_cur++;
if (IS_EXTENDED (pe->pt_entry->sys_ind)) {
@@ -784,7 +793,7 @@ static void fill_bounds(struct fdisk_context *cxt,
for (i = 0; i < cxt->label->nparts_max; pe++,i++) {
p = pe->pt_entry;
- if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
+ if (is_cleared_partition(p) || IS_EXTENDED (p->sys_ind)) {
first[i] = 0xffffffff;
last[i] = 0;
} else {
@@ -810,7 +819,7 @@ static int add_partition(struct fdisk_context *cxt, size_t n, struct fdisk_partt
sys = t ? t->type : MBR_LINUX_DATA_PARTITION;
- if (p && p->sys_ind) {
+ if (is_used_partition(p)) {
fdisk_warnx(cxt, _("Partition %zu is already defined. "
"Delete it before re-adding it."),
n + 1);
@@ -1019,7 +1028,7 @@ static int add_logical(struct fdisk_context *cxt)
assert(cxt);
assert(cxt->label);
- if (cxt->label->nparts_max > 5 || p4->sys_ind) {
+ if (cxt->label->nparts_max > 5 || !is_cleared_partition(p4)) {
struct pte *pe = self_pte(cxt, cxt->label->nparts_max);
pe->sectorbuffer = calloc(1, cxt->sector_size);
@@ -1159,7 +1168,7 @@ static int dos_verify_disklabel(struct fdisk_context *cxt)
struct pte *pe = self_pte(cxt, i);
p = self_partition(cxt, i);
- if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
+ if (is_used_partition(p) && !IS_EXTENDED(p->sys_ind)) {
check_consistency(cxt, p, i);
fdisk_warn_alignment(cxt, get_abs_partition_start(pe), i);
if (get_abs_partition_start(pe) < first[i])
@@ -1243,7 +1252,7 @@ static int dos_add_partition(
for (i = 0; i < 4; i++) {
struct dos_partition *p = self_partition(cxt, i);
- free_primary += !p->sys_ind;
+ free_primary += is_used_partition(p);
}
if (!free_primary && cxt->label->nparts_max >= MAXIMUM_PARTS) {
@@ -1490,7 +1499,7 @@ static int wrong_p_order(struct fdisk_context *cxt, size_t *prev)
last_i = 4;
last_p_start_pos = 0;
}
- if (p->sys_ind) {
+ if (is_used_partition(p)) {
p_start_pos = get_abs_partition_start(pe);
if (last_p_start_pos > p_start_pos) {
@@ -1596,11 +1605,8 @@ static int dos_fulllist_disklabel(struct fdisk_context *cxt, int ext)
if (asprintf(&str, "%02x", p->sys_ind) > 0)
tt_line_set_data(ln, 10, str); /* Id */
- if (p->sys_ind) {
- check_consistency(cxt, p, i);
- fdisk_warn_alignment(cxt,
- get_abs_partition_start(pe), i);
- }
+ check_consistency(cxt, p, i);
+ fdisk_warn_alignment(cxt, get_abs_partition_start(pe), i);
}
rc = fdisk_print_table(cxt, tb);
@@ -1658,7 +1664,7 @@ static int dos_list_disklabel(struct fdisk_context *cxt)
struct tt_line *ln;
char *str;
- if (!p || is_cleared_partition(p))
+ if (!is_used_partition(p))
continue;
ln = tt_add_line(tb, NULL);
if (!ln)
@@ -1840,7 +1846,7 @@ int fdisk_dos_move_begin(struct fdisk_context *cxt, size_t i)
pe = self_pte(cxt, i);
p = pe->pt_entry;
- if (!p->sys_ind || !dos_partition_get_size(p) || IS_EXTENDED (p->sys_ind)) {
+ if (!is_used_partition(p) || IS_EXTENDED (p->sys_ind)) {
fdisk_warnx(cxt, _("Partition %zu: no data area."), i + 1);
return 0;
}
@@ -1863,7 +1869,7 @@ int fdisk_dos_move_begin(struct fdisk_context *cxt, size_t i)
end = get_abs_partition_start(prev_pe)
+ dos_partition_get_size(prev_p);
- if (!is_cleared_partition(prev_p) &&
+ if (is_used_partition(prev_p) &&
end > free_start && end <= curr_start)
free_start = end;
}
@@ -1906,7 +1912,7 @@ static int dos_get_partition_status(
p = self_partition(cxt, i);
- if (p && !is_cleared_partition(p))
+ if (is_used_partition(p))
*status = FDISK_PARTSTAT_USED;
else
*status = FDISK_PARTSTAT_NONE;