fdisk: (dos) remove global ptes[]

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2013-06-20 11:30:39 +02:00
parent e8bf93ded2
commit af0df606a2
4 changed files with 218 additions and 144 deletions

View File

@ -362,21 +362,17 @@ print_buffer(struct fdisk_context *cxt, unsigned char pbuffer[]) {
static void print_raw(struct fdisk_context *cxt)
{
size_t i;
assert(cxt);
assert(cxt->label);
printf(_("Device: %s\n"), cxt->dev_path);
if (fdisk_is_disklabel(cxt, SUN) ||
fdisk_is_disklabel(cxt, SGI) ||
fdisk_is_disklabel(cxt, GPT))
fdisk_is_disklabel(cxt, GPT) ||
fdisk_is_disklabel(cxt, DOS))
print_buffer(cxt, cxt->firstsector);
else if (fdisk_is_disklabel(cxt, DOS)) {
for (i = 3; i < cxt->label->nparts_max; i++)
print_buffer(cxt, ptes[i].sectorbuffer);
}
/* TODO: print also EBR (extended partition) buffer */
}
static void __attribute__ ((__noreturn__)) handle_quit(struct fdisk_context *cxt)

View File

@ -285,7 +285,7 @@ bsd_command_prompt (struct fdisk_context *cxt)
assert(cxt->parent);
for (t=0; t<4; t++) {
p = dos_get_pt_entry(t);
p = fdisk_dos_get_partition(cxt, t);
if (p && is_bsd_partition_type(p->sys_ind)) {
xbsd_part = p;
xbsd_part_index = t;
@ -949,7 +949,7 @@ xbsd_link_part (struct fdisk_context *cxt)
int i;
struct dos_partition *p;
if (!cxt->parent)
if (!cxt->parent || !fdisk_is_disklabel(cxt->parent, DOS))
return; /* not nested PT */
if (fdisk_ask_partnum(cxt->parent, &k, FALSE))
@ -958,7 +958,7 @@ xbsd_link_part (struct fdisk_context *cxt)
if (xbsd_check_new_partition(cxt, &i))
return;
p = dos_get_pt_entry(k);
p = fdisk_dos_get_partition(cxt->parent, k);
xbsd_dlabel.d_partitions[i].p_size = dos_partition_get_size(p);
xbsd_dlabel.d_partitions[i].p_offset = dos_partition_get_start(p);

View File

@ -13,6 +13,22 @@
#include "fdisk.h"
#include "fdiskdoslabel.h"
/*
* per partition table entry data
*
* The four primary partitions have the same sectorbuffer
* and have NULL ex_entry.
*
* Each logical partition table entry has two pointers, one for the
* partition and one link to the next one.
*/
struct pte {
struct dos_partition *pt_entry; /* on-disk MBR entry */
struct dos_partition *ex_entry; /* on-disk EBR entry */
char changed; /* boolean */
sector_t offset; /* disk sector number */
unsigned char *sectorbuffer; /* disk sector contents */
};
/*
* in-memory fdisk GPT stuff
@ -20,6 +36,7 @@
struct fdisk_dos_label {
struct fdisk_label head; /* generic part */
struct pte ptes[MAXIMUM_PARTS]; /* partition */
unsigned int compatible : 1; /* is DOS compatible? */
};
@ -45,7 +62,6 @@ static struct fdisk_parttype dos_parttypes[] = {
#define alignment_required(_x) ((_x)->grain != (_x)->sector_size)
struct pte ptes[MAXIMUM_PARTS];
sector_t extended_offset;
static size_t ext_index;
@ -55,6 +71,56 @@ static int MBRbuffer_changed;
#define cround(c, n) (fdisk_context_use_cylinders(c) ? \
((n) / fdisk_context_get_units_per_sector(c)) + 1 : (n))
static inline struct fdisk_dos_label *self_label(struct fdisk_context *cxt)
{
assert(cxt);
assert(cxt->label);
assert(fdisk_is_disklabel(cxt, DOS));
return (struct fdisk_dos_label *) cxt->label;
}
static inline struct pte *self_pte(struct fdisk_context *cxt, size_t i)
{
struct fdisk_dos_label *l = self_label(cxt);
if (i >= ARRAY_SIZE(l->ptes))
return NULL;
return &l->ptes[i];
}
static inline struct dos_partition *self_partition(
struct fdisk_context *cxt,
size_t i)
{
struct pte *pe = self_pte(cxt, i);
return pe ? pe->pt_entry : NULL;
}
struct dos_partition *fdisk_dos_get_partition(
struct fdisk_context *cxt,
size_t i)
{
return self_partition(cxt, i);
}
static void partition_set_changed(
struct fdisk_context *cxt,
size_t i,
int changed)
{
struct pte *pe = self_pte(cxt, i);
if (!pe)
return;
pe->changed = changed;
if (changed)
fdisk_label_set_changed(cxt->label, 1);
}
static sector_t get_abs_partition_start(struct pte *pe)
{
return pe->offset + dos_partition_get_start(pe->pt_entry);
@ -111,24 +177,26 @@ static int get_partition_unused_primary(struct fdisk_context *cxt)
}
}
struct dos_partition *dos_get_pt_entry(int i)
{
return ptes[i].pt_entry;
}
/* Allocate a buffer and read a partition table sector */
static void read_pte(struct fdisk_context *cxt, int pno, sector_t offset)
static int read_pte(struct fdisk_context *cxt, int pno, sector_t offset)
{
struct pte *pe = &ptes[pno];
unsigned char *buf;
struct pte *pe = self_pte(cxt, pno);
buf = calloc(1, cxt->sector_size);
if (!buf)
return -ENOMEM;
pe->offset = offset;
pe->sectorbuffer = xcalloc(1, cxt->sector_size);
pe->sectorbuffer = buf;
if (read_sector(cxt, offset, pe->sectorbuffer) != 0)
fprintf(stderr, _("Failed to read extended partition table (offset=%jd)\n"),
(uintmax_t) offset);
pe->changed = 0;
pe->pt_entry = pe->ex_entry = NULL;
return 0;
}
@ -157,7 +225,7 @@ void dos_init(struct fdisk_context *cxt)
extended_offset = 0;
for (i = 0; i < 4; i++) {
struct pte *pe = &ptes[i];
struct pte *pe = self_pte(cxt, i);
pe->pt_entry = mbr_get_partition(cxt->firstsector, i);
pe->ex_entry = NULL;
@ -188,57 +256,63 @@ void dos_init(struct fdisk_context *cxt)
static int dos_delete_partition(struct fdisk_context *cxt, size_t partnum)
{
struct pte *pe = &ptes[partnum];
struct dos_partition *p = pe->pt_entry;
struct dos_partition *q = pe->ex_entry;
struct fdisk_dos_label *l = self_label(cxt);
struct pte *pe = self_pte(cxt, partnum);
struct dos_partition *p;
struct dos_partition *q;
if (!pe)
return -EINVAL;
p = pe->pt_entry;
q = pe->ex_entry;
/* Note that for the fifth partition (partnum == 4) we don't actually
decrement partitions. */
if (partnum < 4) {
if (IS_EXTENDED(p->sys_ind) && partnum == ext_index) {
cxt->label->nparts_max = 4;
ptes[ext_index].ex_entry = NULL;
l->ptes[ext_index].ex_entry = NULL;
extended_offset = 0;
}
ptes[partnum].changed = 1;
partition_set_changed(cxt, partnum, 1);
clear_partition(p);
} else if (!q->sys_ind && partnum > 4) {
/* the last one in the chain - just delete */
--cxt->label->nparts_max;
--partnum;
clear_partition(ptes[partnum].ex_entry);
ptes[partnum].changed = 1;
clear_partition(l->ptes[partnum].ex_entry);
partition_set_changed(cxt, partnum, 1);
} else {
/* not the last one - further ones will be moved down */
if (partnum > 4) {
/* delete this link in the chain */
p = ptes[partnum-1].ex_entry;
p = l->ptes[partnum - 1].ex_entry;
*p = *q;
dos_partition_set_start(p, dos_partition_get_start(q));
dos_partition_set_size(p, dos_partition_get_size(q));
ptes[partnum-1].changed = 1;
partition_set_changed(cxt, partnum - 1, 1);
} else if (cxt->label->nparts_max > 5) { /* 5 will be moved to 4 */
/* the first logical in a longer chain */
struct pte *pete = &ptes[5];
pe = &l->ptes[5];
if (pete->pt_entry) /* prevent SEGFAULT */
dos_partition_set_start(pete->pt_entry,
get_abs_partition_start(pete) -
if (pe->pt_entry) /* prevent SEGFAULT */
dos_partition_set_start(pe->pt_entry,
get_abs_partition_start(pe) -
extended_offset);
pete->offset = extended_offset;
pete->changed = 1;
pe->offset = extended_offset;
partition_set_changed(cxt, 5, 1);
}
if (cxt->label->nparts_max > 5) {
cxt->label->nparts_max--;
while (partnum < cxt->label->nparts_max) {
ptes[partnum] = ptes[partnum+1];
l->ptes[partnum] = l->ptes[partnum + 1];
partnum++;
}
} else
/* the only logical: clear only */
clear_partition(ptes[partnum].pt_entry);
clear_partition(l->ptes[partnum].pt_entry);
}
fdisk_label_set_changed(cxt->label, 1);
@ -252,7 +326,7 @@ static void read_extended(struct fdisk_context *cxt, int ext)
struct dos_partition *p, *q;
ext_index = ext;
pex = &ptes[ext];
pex = self_pte(cxt, ext);
pex->ex_entry = pex->pt_entry;
p = pex->pt_entry;
@ -263,21 +337,22 @@ static void read_extended(struct fdisk_context *cxt, int ext)
}
while (IS_EXTENDED (p->sys_ind)) {
struct pte *pe = &ptes[cxt->label->nparts_max];
struct pte *pe = self_pte(cxt, cxt->label->nparts_max);
if (cxt->label->nparts_max >= MAXIMUM_PARTS) {
/* This is not a Linux restriction, but
this program uses arrays of size MAXIMUM_PARTS.
Do not try to `improve' this test. */
struct pte *pre = &ptes[cxt->label->nparts_max - 1];
struct pte *pre = self_pte(cxt,
cxt->label->nparts_max - 1);
fprintf(stderr,
_("Warning: omitting partitions after #%zd.\n"
"They will be deleted "
"if you save this partition table.\n"),
cxt->label->nparts_max);
clear_partition(pre->ex_entry);
pre->changed = 1;
partition_set_changed(cxt,
cxt->label->nparts_max - 1, 1);
return;
}
@ -327,11 +402,12 @@ static void read_extended(struct fdisk_context *cxt, int ext)
/* remove empty links */
remove:
q = self_partition(cxt, 4);
for (i = 4; i < cxt->label->nparts_max; i++) {
struct pte *pe = &ptes[i];
p = self_partition(cxt, i);
if (!dos_partition_get_size(pe->pt_entry) &&
(cxt->label->nparts_max > 5 || ptes[4].pt_entry->sys_ind)) {
if (!dos_partition_get_size(p) &&
(cxt->label->nparts_max > 5 || q->sys_ind)) {
printf(_("omitting empty partition (%zd)\n"), i+1);
dos_delete_partition(cxt, i);
goto remove; /* numbering changed */
@ -475,7 +551,7 @@ static int dos_probe_label(struct fdisk_context *cxt)
}
for (i = 0; i < 4; i++) {
struct pte *pe = &ptes[i];
struct pte *pe = self_pte(cxt, i);
if (!is_cleared_partition(pe->pt_entry))
cxt->label->nparts_cur++;
@ -490,7 +566,7 @@ static int dos_probe_label(struct fdisk_context *cxt)
}
for (i = 3; i < cxt->label->nparts_max; i++) {
struct pte *pe = &ptes[i];
struct pte *pe = self_pte(cxt, i);
if (!mbr_is_valid_magic(pe->sectorbuffer)) {
fprintf(stderr,
@ -499,8 +575,7 @@ static int dos_probe_label(struct fdisk_context *cxt)
pe->sectorbuffer[510],
pe->sectorbuffer[511],
i + 1);
pe->changed = 1;
fdisk_label_set_changed(cxt->label, 1);
partition_set_changed(cxt, 1, 1);
}
}
@ -526,15 +601,16 @@ static void set_partition(struct fdisk_context *cxt,
int i, int doext, sector_t start,
sector_t stop, int sysid)
{
struct pte *pe = self_pte(cxt, i);
struct dos_partition *p;
sector_t offset;
if (doext) {
p = ptes[i].ex_entry;
p = pe->ex_entry;
offset = extended_offset;
} else {
p = ptes[i].pt_entry;
offset = ptes[i].offset;
p = pe->pt_entry;
offset = pe->offset;
}
p->boot_ind = 0;
p->sys_ind = sysid;
@ -551,7 +627,7 @@ static void set_partition(struct fdisk_context *cxt,
if (is_dos_compatible(cxt) && (stop/(cxt->geom.sectors*cxt->geom.heads) > 1023))
stop = cxt->geom.heads*cxt->geom.sectors*1024 - 1;
set_hsc(p->eh, p->es, p->ec, stop);
ptes[i].changed = 1;
partition_set_changed(cxt, i, 1);
}
static sector_t get_unused_start(struct fdisk_context *cxt,
@ -562,8 +638,9 @@ static sector_t get_unused_start(struct fdisk_context *cxt,
for (i = 0; i < cxt->label->nparts_max; i++) {
sector_t lastplusoff;
struct pte *pe = self_pte(cxt, i);
if (start == ptes[i].offset)
if (start == pe->offset)
start += cxt->first_lba;
lastplusoff = last[i] + ((part_n < 4) ? 0 : cxt->first_lba);
if (start >= first[i] && start <= lastplusoff)
@ -577,7 +654,7 @@ static void fill_bounds(struct fdisk_context *cxt,
sector_t *first, sector_t *last)
{
size_t i;
struct pte *pe = &ptes[0];
struct pte *pe = self_pte(cxt, 0);
struct dos_partition *p;
for (i = 0; i < cxt->label->nparts_max; pe++,i++) {
@ -596,8 +673,9 @@ static int add_partition(struct fdisk_context *cxt, int n, struct fdisk_parttype
{
int sys, read = 0, rc;
size_t i;
struct dos_partition *p = ptes[n].pt_entry;
struct dos_partition *q = ptes[ext_index].pt_entry;
struct dos_partition *p = self_partition(cxt, n);
struct dos_partition *q = self_partition(cxt, ext_index);
sector_t start, stop = 0, limit, temp,
first[cxt->label->nparts_max],
last[cxt->label->nparts_max];
@ -689,7 +767,7 @@ static int add_partition(struct fdisk_context *cxt, int n, struct fdisk_parttype
} while (start != temp || !read);
if (n > 4) { /* NOT for fifth partition */
struct pte *pe = &ptes[n];
struct pte *pe = self_pte(cxt, n);
pe->offset = start - cxt->first_lba;
if (pe->offset == extended_offset) { /* must be corrected */
@ -700,7 +778,7 @@ static int add_partition(struct fdisk_context *cxt, int n, struct fdisk_parttype
}
for (i = 0; i < cxt->label->nparts_max; i++) {
struct pte *pe = &ptes[i];
struct pte *pe = self_pte(cxt, i);
if (start < pe->offset && limit >= pe->offset)
limit = pe->offset - 1;
@ -761,12 +839,14 @@ static int add_partition(struct fdisk_context *cxt, int n, struct fdisk_parttype
}
set_partition(cxt, n, 0, start, stop, sys);
if (n > 4)
set_partition(cxt, n - 1, 1, ptes[n].offset, stop, EXTENDED);
if (n > 4) {
struct pte *pe = self_pte(cxt, n);
set_partition(cxt, n - 1, 1, pe->offset, stop, EXTENDED);
}
if (IS_EXTENDED (sys)) {
struct pte *pe4 = &ptes[4];
struct pte *pen = &ptes[n];
struct pte *pe4 = self_pte(cxt, 4);
struct pte *pen = self_pte(cxt, n);
ext_index = n;
pen->ex_entry = p;
@ -774,7 +854,8 @@ static int add_partition(struct fdisk_context *cxt, int n, struct fdisk_parttype
pe4->sectorbuffer = xcalloc(1, cxt->sector_size);
pe4->pt_entry = mbr_get_partition(pe4->sectorbuffer, 0);
pe4->ex_entry = pe4->pt_entry + 1;
pe4->changed = 1;
partition_set_changed(cxt, 4, 1);
cxt->label->nparts_max = 5;
}
@ -784,17 +865,23 @@ static int add_partition(struct fdisk_context *cxt, int n, struct fdisk_parttype
static int add_logical(struct fdisk_context *cxt)
{
struct dos_partition *p4 = self_partition(cxt, 4);
assert(cxt);
assert(cxt->label);
if (cxt->label->nparts_max > 5 || ptes[4].pt_entry->sys_ind) {
struct pte *pe = &ptes[cxt->label->nparts_max];
if (cxt->label->nparts_max > 5 || p4->sys_ind) {
struct pte *pe = self_pte(cxt, cxt->label->nparts_max);
pe->sectorbuffer = calloc(1, cxt->sector_size);
if (!pe->sectorbuffer)
return -ENOMEM;
pe->sectorbuffer = xcalloc(1, cxt->sector_size);
pe->pt_entry = mbr_get_partition(pe->sectorbuffer, 0);
pe->ex_entry = pe->pt_entry + 1;
pe->offset = 0;
pe->changed = 1;
partition_set_changed(cxt, cxt->label->nparts_max, 1);
cxt->label->nparts_max++;
}
printf(_("Adding logical partition %zd\n"), cxt->label->nparts_max);
@ -911,9 +998,9 @@ static int dos_verify_disklabel(struct fdisk_context *cxt)
fill_bounds(cxt, first, last);
for (i = 0; i < cxt->label->nparts_max; i++) {
struct pte *pe = &ptes[i];
struct pte *pe = self_pte(cxt, i);
p = pe->pt_entry;
p = self_partition(cxt, i);
if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
check_consistency(cxt, p, i);
fdisk_warn_alignment(cxt, get_abs_partition_start(pe), i);
@ -937,13 +1024,15 @@ static int dos_verify_disklabel(struct fdisk_context *cxt)
}
if (extended_offset) {
struct pte *pex = &ptes[ext_index];
sector_t e_last = dos_partition_get_start(pex->pt_entry) +
dos_partition_get_size(pex->pt_entry) - 1;
p = self_partition(cxt, ext_index);
sector_t e_last = dos_partition_get_start(p)
+ dos_partition_get_size(p) - 1;
for (i = 4; i < cxt->label->nparts_max; i++) {
total++;
p = ptes[i].pt_entry;
p = self_partition(cxt, i);
if (!p->sys_ind) {
if (i != 4 || i + 1 < cxt->label->nparts_max)
printf(_("Warning: partition %zd "
@ -984,8 +1073,10 @@ static int dos_add_partition(
assert(cxt->label);
assert(fdisk_is_disklabel(cxt, DOS));
for (i = 0; i < 4; i++)
free_primary += !ptes[i].pt_entry->sys_ind;
for (i = 0; i < 4; i++) {
struct dos_partition *p = self_partition(cxt, i);
free_primary += !p->sys_ind;
}
if (!free_primary && cxt->label->nparts_max >= MAXIMUM_PARTS) {
printf(_("The maximum number of partitions has been created\n"));
@ -1084,9 +1175,11 @@ static int dos_write_disklabel(struct fdisk_context *cxt)
/* MBR (primary partitions) */
if (!MBRbuffer_changed) {
for (i = 0; i < 4; i++)
if (ptes[i].changed)
for (i = 0; i < 4; i++) {
struct pte *pe = self_pte(cxt, i);
if (pe->changed)
MBRbuffer_changed = 1;
}
}
if (MBRbuffer_changed) {
mbr_set_magic(cxt->firstsector);
@ -1096,7 +1189,7 @@ static int dos_write_disklabel(struct fdisk_context *cxt)
}
/* EBR (logical partitions) */
for (i = 4; i < cxt->label->nparts_max; i++) {
struct pte *pe = &ptes[i];
struct pte *pe = self_pte(cxt, i);
if (pe->changed) {
mbr_set_magic(pe->sectorbuffer);
@ -1124,7 +1217,7 @@ static struct fdisk_parttype *dos_get_parttype(
if (partnum >= cxt->label->nparts_max)
return NULL;
p = ptes[partnum].pt_entry;
p = self_partition(cxt, partnum);
t = fdisk_get_parttype_from_code(cxt, p->sys_ind);
if (!t)
t = fdisk_new_unknown_parttype(p->sys_ind, NULL);
@ -1145,7 +1238,7 @@ static int dos_set_parttype(
if (partnum >= cxt->label->nparts_max || !t || t->type > UINT8_MAX)
return -EINVAL;
p = ptes[partnum].pt_entry;
p = self_partition(cxt, partnum);
if (t->type == p->sys_ind)
return 0;
@ -1161,9 +1254,9 @@ static int dos_set_parttype(
"partitions, please see the fdisk manual page for additional "
"information.\n\n"));
ptes[partnum].changed = 1;
p->sys_ind = t->type;
fdisk_label_set_changed(cxt->label, 1);
partition_set_changed(cxt, partnum, 1);
return 0;
}
@ -1174,18 +1267,19 @@ static int dos_set_parttype(
*/
static int wrong_p_order(struct fdisk_context *cxt, size_t *prev)
{
struct pte *pe;
struct dos_partition *p;
size_t last_p_start_pos = 0, p_start_pos;
size_t i, last_i = 0;
for (i = 0 ; i < cxt->label->nparts_max; i++) {
struct pte *pe = self_pte(cxt, i);
struct dos_partition *p = pe->pt_entry;
if (i == 4) {
last_i = 4;
last_p_start_pos = 0;
}
pe = &ptes[i];
if ((p = pe->pt_entry)->sys_ind) {
if (p->sys_ind) {
p_start_pos = get_abs_partition_start(pe);
if (last_p_start_pos > p_start_pos) {
@ -1201,13 +1295,12 @@ static int wrong_p_order(struct fdisk_context *cxt, size_t *prev)
return 0;
}
static int is_garbage_table(void)
static int is_garbage_table(struct fdisk_context *cxt)
{
size_t i;
for (i = 0; i < 4; i++) {
struct pte *pe = &ptes[i];
struct dos_partition *p = pe->pt_entry;
struct dos_partition *p = self_partition(cxt, i);
if (p->boot_ind != 0 && p->boot_ind != 0x80)
return 1;
@ -1218,14 +1311,13 @@ static int is_garbage_table(void)
int dos_list_table(struct fdisk_context *cxt,
int xtra __attribute__ ((__unused__)))
{
struct dos_partition *p;
size_t i, w;
assert(cxt);
assert(cxt->label);
assert(fdisk_is_disklabel(cxt, DOS));
if (is_garbage_table()) {
if (is_garbage_table(cxt)) {
printf(_("This doesn't look like a partition table\n"
"Probably you selected the wrong device.\n\n"));
}
@ -1243,9 +1335,9 @@ int dos_list_table(struct fdisk_context *cxt,
(int) w + 1, _("Device"));
for (i = 0; i < cxt->label->nparts_max; i++) {
struct pte *pe = &ptes[i];
struct pte *pe = self_pte(cxt, i);
struct dos_partition *p = pe->pt_entry;
p = pe->pt_entry;
if (p && !is_cleared_partition(p)) {
unsigned int psects = dos_partition_get_size(p);
unsigned int pblocks = psects;
@ -1297,7 +1389,7 @@ void dos_list_table_expert(struct fdisk_context *cxt, int extend)
cxt->dev_path, cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders);
printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
for (i = 0 ; i < cxt->label->nparts_max; i++) {
pe = &ptes[i];
pe = self_pte(cxt, i);
p = (extend ? pe->ex_entry : pe->pt_entry);
if (p != NULL) {
printf("%2zd %02x%4d%4d%5d%4d%4d%5d%11lu%11lu %02x\n",
@ -1331,6 +1423,7 @@ void dos_list_table_expert(struct fdisk_context *cxt, int extend)
*/
static void fix_chain_of_logicals(struct fdisk_context *cxt)
{
struct fdisk_dos_label *l = self_label(cxt);
size_t j, oj, ojj, sj, sjj;
struct dos_partition *pj,*pjj,tmp;
@ -1338,18 +1431,18 @@ static void fix_chain_of_logicals(struct fdisk_context *cxt)
/* (Its sector is the global extended_offset.) */
stage1:
for (j = 5; j < cxt->label->nparts_max - 1; j++) {
oj = ptes[j].offset;
ojj = ptes[j+1].offset;
oj = l->ptes[j].offset;
ojj = l->ptes[j + 1].offset;
if (oj > ojj) {
ptes[j].offset = ojj;
ptes[j+1].offset = oj;
pj = ptes[j].pt_entry;
l->ptes[j].offset = ojj;
l->ptes[j + 1].offset = oj;
pj = l->ptes[j].pt_entry;
dos_partition_set_start(pj, dos_partition_get_start(pj)+oj-ojj);
pjj = ptes[j+1].pt_entry;
pjj = l->ptes[j + 1].pt_entry;
dos_partition_set_start(pjj, dos_partition_get_start(pjj)+ojj-oj);
dos_partition_set_start(ptes[j-1].ex_entry,
dos_partition_set_start(l->ptes[j - 1].ex_entry,
ojj-extended_offset);
dos_partition_set_start(ptes[j].ex_entry,
dos_partition_set_start(l->ptes[j].ex_entry,
oj-extended_offset);
goto stage1;
}
@ -1358,12 +1451,12 @@ static void fix_chain_of_logicals(struct fdisk_context *cxt)
/* Stage 2: sort starting sectors */
stage2:
for (j = 4; j < cxt->label->nparts_max - 1; j++) {
pj = ptes[j].pt_entry;
pjj = ptes[j+1].pt_entry;
pj = l->ptes[j].pt_entry;
pjj = l->ptes[j + 1].pt_entry;
sj = dos_partition_get_start(pj);
sjj = dos_partition_get_start(pjj);
oj = ptes[j].offset;
ojj = ptes[j+1].offset;
oj = l->ptes[j].offset;
ojj = l->ptes[j+1].offset;
if (oj+sj > ojj+sjj) {
tmp = *pj;
*pj = *pjj;
@ -1376,7 +1469,7 @@ static void fix_chain_of_logicals(struct fdisk_context *cxt)
/* Probably something was changed */
for (j = 4; j < cxt->label->nparts_max; j++)
ptes[j].changed = 1;
l->ptes[j].changed = 1;
}
void dos_fix_partition_table_order(struct fdisk_context *cxt)
@ -1393,8 +1486,8 @@ void dos_fix_partition_table_order(struct fdisk_context *cxt)
/* partition i should have come earlier, move it */
/* We have to move data in the MBR */
struct dos_partition *pi, *pk, *pe, pbuf;
pei = &ptes[i];
pek = &ptes[k];
pei = self_pte(cxt, i);
pek = self_pte(cxt, k);
pe = pei->ex_entry;
pei->ex_entry = pek->ex_entry;
@ -1407,7 +1500,8 @@ void dos_fix_partition_table_order(struct fdisk_context *cxt)
memmove(pi, pk, sizeof(struct dos_partition));
memmove(pk, &pbuf, sizeof(struct dos_partition));
pei->changed = pek->changed = 1;
partition_set_changed(cxt, i, 1);
partition_set_changed(cxt, k, 1);
}
if (i)
@ -1419,7 +1513,7 @@ void dos_fix_partition_table_order(struct fdisk_context *cxt)
void dos_move_begin(struct fdisk_context *cxt, int i)
{
struct pte *pe = &ptes[i];
struct pte *pe = self_pte(cxt, i);
struct dos_partition *p = pe->pt_entry;
unsigned int new, free_start, curr_start, last;
uintmax_t res = 0;
@ -1445,12 +1539,13 @@ void dos_move_begin(struct fdisk_context *cxt, int i)
/* look for a free space before the current start of the partition */
for (x = 0; x < cxt->label->nparts_max; x++) {
unsigned int end;
struct pte *prev_pe = &ptes[x];
struct pte *prev_pe = self_pte(cxt, x);
struct dos_partition *prev_p = prev_pe->pt_entry;
if (!prev_p)
continue;
end = get_abs_partition_start(prev_pe) + dos_partition_get_size(prev_p);
end = get_abs_partition_start(prev_pe)
+ dos_partition_get_size(prev_p);
if (!is_cleared_partition(prev_p) &&
end > free_start && end <= curr_start)
@ -1465,10 +1560,13 @@ void dos_move_begin(struct fdisk_context *cxt, int i)
new = res - pe->offset;
if (new != dos_partition_get_size(p)) {
unsigned int sects = dos_partition_get_size(p) + dos_partition_get_start(p) - new;
unsigned int sects = dos_partition_get_size(p)
+ dos_partition_get_start(p) - new;
dos_partition_set_size(p, sects);
dos_partition_set_start(p, new);
pe->changed = 1;
partition_set_changed(cxt, i, 1);
}
}
@ -1477,7 +1575,6 @@ static int dos_get_partition_status(
size_t i,
int *status)
{
struct pte *pe;
struct dos_partition *p;
assert(cxt);
@ -1487,12 +1584,12 @@ static int dos_get_partition_status(
if (!status || i >= cxt->label->nparts_max)
return -EINVAL;
*status = FDISK_PARTSTAT_NONE;
pe = &ptes[i];
p = pe->pt_entry;
p = self_partition(cxt, i);
if (p && !is_cleared_partition(p))
*status = FDISK_PARTSTAT_USED;
else
*status = FDISK_PARTSTAT_NONE;
return 0;
}
@ -1502,7 +1599,6 @@ static int dos_toggle_partition_flag(
size_t i,
unsigned long flag)
{
struct pte *pe;
struct dos_partition *p;
assert(cxt);
@ -1512,8 +1608,7 @@ static int dos_toggle_partition_flag(
if (i >= cxt->label->nparts_max)
return -EINVAL;
pe = &ptes[i];
p = pe->pt_entry;
p = self_partition(cxt, i);
switch (flag) {
case DOS_FLAG_ACTIVE:
@ -1521,8 +1616,7 @@ static int dos_toggle_partition_flag(
fdisk_warnx(cxt, _("WARNING: Partition %d is an extended partition"), i + 1);
p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
pe->changed = 1;
fdisk_label_set_changed(cxt->label, 1);
partition_set_changed(cxt, i, 1);
break;
default:
return 1;

View File

@ -3,29 +3,13 @@
#include "pt-mbr.h"
/*
* per partition table entry data
*
* The four primary partitions have the same sectorbuffer
* and have NULL ex_entry.
*
* Each logical partition table entry has two pointers, one for the
* partition and one link to the next one.
*/
struct pte {
struct dos_partition *pt_entry; /* on-disk MBR entry */
struct dos_partition *ex_entry; /* on-disk EBR entry */
char changed; /* boolean */
sector_t offset; /* disk sector number */
unsigned char *sectorbuffer; /* disk sector contents */
};
extern struct dos_partition *fdisk_dos_get_partition(
struct fdisk_context *cxt,
size_t i);
extern struct pte ptes[MAXIMUM_PARTS];
extern sector_t extended_offset;
extern struct dos_partition *dos_get_pt_entry(int);
extern void dos_print_mbr_id(struct fdisk_context *cxt);
extern int dos_set_mbr_id(struct fdisk_context *cxt);
extern void dos_init(struct fdisk_context *cxt);