static int other_endian = 0;
static short volumes=1;
+/*
+ * in-memory fdisk AIX stuff
+ */
+struct fdisk_aix_label {
+ struct fdisk_label head; /* generic part */
+};
+
+
/*
* only dealing with free blocks here
*/
return -ENOSYS;
}
-const struct fdisk_label aix_label =
+static const struct fdisk_label_operations aix_operations =
{
- .name = "aix",
- .probe = aix_probe_label,
- .write = NULL,
- .verify = NULL,
- .create = NULL,
- .part_add = aix_add_partition,
- .part_delete = NULL,
+ .probe = aix_probe_label,
+ .part_add = aix_add_partition
};
+
+
+/*
+ * allocates AIX label driver
+ */
+struct fdisk_label *fdisk_new_aix_label(struct fdisk_context *cxt)
+{
+ struct fdisk_label *lb;
+ struct fdisk_aix_label *aix;
+
+ assert(cxt);
+
+ aix = calloc(1, sizeof(*aix));
+ if (!aix)
+ return NULL;
+
+ /* initialize generic part of the driver */
+ lb = (struct fdisk_label *) aix;
+ lb->name = "aix";
+ lb->op = &aix_operations;
+
+ return lb;
+}
#include "fdiskbsdlabel.h"
#include "fdiskdoslabel.h"
+/*
+ * in-memory fdisk BSD stuff
+ */
+struct fdisk_bsd_label {
+ struct fdisk_label head; /* generic part */
+};
+
+
static int xbsd_delete_part (struct fdisk_context *cxt, int partnum);
static void xbsd_edit_disklabel (void);
static void xbsd_write_bootstrap (struct fdisk_context *cxt);
return 0;
}
-const struct fdisk_label bsd_label =
+static const struct fdisk_label_operations bsd_operations =
{
- .name = "bsd",
- .parttypes = xbsd_fstypes,
- .nparttypes = ARRAY_SIZE(xbsd_fstypes),
-
- .probe = osf_probe_label,
- .write = xbsd_write_disklabel,
- .verify = NULL,
- .create = xbsd_create_disklabel,
- .part_add = xbsd_add_part,
- .part_delete = xbsd_delete_part,
- .part_get_type = xbsd_get_parttype,
- .part_set_type = xbsd_set_parttype,
+ .probe = osf_probe_label,
+ .write = xbsd_write_disklabel,
+ .create = xbsd_create_disklabel,
+ .part_add = xbsd_add_part,
+ .part_delete = xbsd_delete_part,
+ .part_get_type = xbsd_get_parttype,
+ .part_set_type = xbsd_set_parttype
};
+
+
+/*
+ * allocates BSD label driver
+ */
+struct fdisk_label *fdisk_new_bsd_label(struct fdisk_context *cxt)
+{
+ struct fdisk_label *lb;
+ struct fdisk_bsd_label *bsd;
+
+ assert(cxt);
+
+ bsd = calloc(1, sizeof(*bsd));
+ if (!bsd)
+ return NULL;
+
+ /* initialize generic part of the driver */
+ lb = (struct fdisk_label *) bsd;
+ lb->name = "bsd";
+ lb->op = &bsd_operations;
+ lb->parttypes = xbsd_fstypes;
+ lb->nparttypes = ARRAY_SIZE(xbsd_fstypes);
+
+ return lb;
+}
#include "fdisk.h"
#include "fdiskdoslabel.h"
+
+/*
+ * in-memory fdisk GPT stuff
+ */
+struct fdisk_dos_label {
+ struct fdisk_label head; /* generic part */
+};
+
+/*
+ * Partition types
+ */
static struct fdisk_parttype dos_parttypes[] = {
#include "dos_part_types.h"
};
return 0;
}
-const struct fdisk_label dos_label =
+static const struct fdisk_label_operations dos_operations =
{
- .name = "dos",
- .parttypes = dos_parttypes,
- .nparttypes = ARRAY_SIZE(dos_parttypes),
-
- .probe = dos_probe_label,
- .write = dos_write_disklabel,
- .verify = dos_verify_disklabel,
- .create = dos_create_disklabel,
- .part_add = dos_add_partition,
- .part_delete = dos_delete_partition,
- .part_get_type = dos_get_parttype,
- .part_set_type = dos_set_parttype,
+ .probe = dos_probe_label,
+ .write = dos_write_disklabel,
+ .verify = dos_verify_disklabel,
+ .create = dos_create_disklabel,
+ .part_add = dos_add_partition,
+ .part_delete = dos_delete_partition,
+ .part_get_type = dos_get_parttype,
+ .part_set_type = dos_set_parttype,
.reset_alignment = dos_reset_alignment,
};
+
+/*
+ * allocates DOS in-memory stuff
+ */
+struct fdisk_label *fdisk_new_dos_label(struct fdisk_context *cxt)
+{
+ struct fdisk_label *lb;
+ struct fdisk_dos_label *dos;
+
+ assert(cxt);
+
+ dos = calloc(1, sizeof(*dos));
+ if (!dos)
+ return NULL;
+
+ /* initialize generic part of the driver */
+ lb = (struct fdisk_label *) dos;
+ lb->name = "dos";
+ lb->op = &dos_operations;
+ lb->parttypes = dos_parttypes;
+ lb->nparttypes = ARRAY_SIZE(dos_parttypes);
+
+ return lb;
+}
#define MAC_BITMASK 0xffff0000
+/*
+ * in-memory fdisk mac stuff
+ */
+struct fdisk_mac_label {
+ struct fdisk_label head; /* generic part */
+};
+
static int other_endian = 0;
static short volumes=1;
return -ENOSYS;
}
-const struct fdisk_label mac_label =
+static const struct fdisk_label_operations mac_operations =
{
- .name = "mac",
- .probe = mac_probe_label,
- .write = NULL,
- .verify = NULL,
- .create = NULL,
- .part_add = mac_add_partition,
- .part_delete = NULL,
+ .probe = mac_probe_label,
+ .part_add = mac_add_partition
};
+
+
+/*
+ * allocates MAC label driver
+ */
+struct fdisk_label *fdisk_new_mac_label(struct fdisk_context *cxt)
+{
+ struct fdisk_label *lb;
+ struct fdisk_mac_label *mac;
+
+ assert(cxt);
+
+ mac = calloc(1, sizeof(*mac));
+ if (!mac)
+ return NULL;
+
+ /* initialize generic part of the driver */
+ lb = (struct fdisk_label *) mac;
+ lb->name = "mac";
+ lb->op = &mac_operations;
+
+ return lb;
+}
#include "fdisksgilabel.h"
#include "fdiskdoslabel.h"
+
+/*
+ * in-memory fdisk SGI stuff
+ */
+struct fdisk_sgi_label {
+ struct fdisk_label head; /* generic part */
+};
+
+
static int other_endian = 0;
static int debug = 0;
static short volumes=1;
return 0;
}
-const struct fdisk_label sgi_label =
+static const struct fdisk_label_operations sgi_operations =
{
- .name = "sgi",
- .parttypes = sgi_parttypes,
- .nparttypes = ARRAY_SIZE(sgi_parttypes),
-
- .probe = sgi_probe_label,
- .write = sgi_write_disklabel,
- .verify = sgi_verify_disklabel,
- .create = sgi_create_disklabel,
- .part_add = sgi_add_partition,
- .part_delete = sgi_delete_partition,
- .part_get_type = sgi_get_parttype,
- .part_set_type = sgi_set_parttype,
+ .probe = sgi_probe_label,
+ .write = sgi_write_disklabel,
+ .verify = sgi_verify_disklabel,
+ .create = sgi_create_disklabel,
+ .part_add = sgi_add_partition,
+ .part_delete = sgi_delete_partition,
+ .part_get_type = sgi_get_parttype,
+ .part_set_type = sgi_set_parttype
};
+
+/*
+ * allocates SGI label driver
+ */
+struct fdisk_label *fdisk_new_sgi_label(struct fdisk_context *cxt)
+{
+ struct fdisk_label *lb;
+ struct fdisk_sgi_label *sgi;
+
+ assert(cxt);
+
+ sgi = calloc(1, sizeof(*sgi));
+ if (!sgi)
+ return NULL;
+
+ /* initialize generic part of the driver */
+ lb = (struct fdisk_label *) sgi;
+ lb->name = "sgi";
+ lb->op = &sgi_operations;
+ lb->parttypes = sgi_parttypes;
+ lb->nparttypes = ARRAY_SIZE(sgi_parttypes);
+
+ return lb;
+}
static int other_endian = 0;
+/*
+ * in-memory fdisk SUN stuff
+ */
+struct fdisk_sun_label {
+ struct fdisk_label head; /* generic part */
+};
+
+
static struct fdisk_parttype sun_parttypes[] = {
{SUN_TAG_UNASSIGNED, N_("Unassigned")},
{SUN_TAG_BOOT, N_("Boot")},
return 0;
}
-const struct fdisk_label sun_label =
+const struct fdisk_label_operations sun_operations =
{
- .name = "sun",
- .parttypes = sun_parttypes,
- .nparttypes = ARRAY_SIZE(sun_parttypes),
-
- .probe = sun_probe_label,
- .write = sun_write_disklabel,
- .verify = sun_verify_disklabel,
- .create = sun_create_disklabel,
- .part_add = sun_add_partition,
- .part_delete = sun_delete_partition,
- .part_get_type = sun_get_parttype,
- .part_set_type = sun_set_parttype,
- .reset_alignment = sun_reset_alignment,
+ .probe = sun_probe_label,
+ .write = sun_write_disklabel,
+ .verify = sun_verify_disklabel,
+ .create = sun_create_disklabel,
+ .part_add = sun_add_partition,
+ .part_delete = sun_delete_partition,
+ .part_get_type = sun_get_parttype,
+ .part_set_type = sun_set_parttype,
+ .reset_alignment = sun_reset_alignment
};
+
+/*
+ * allocates SUN label driver
+ */
+struct fdisk_label *fdisk_new_sun_label(struct fdisk_context *cxt)
+{
+ struct fdisk_label *lb;
+ struct fdisk_sun_label *sun;
+
+ assert(cxt);
+
+ sun = calloc(1, sizeof(*sun));
+ if (!sun)
+ return NULL;
+
+ /* initialize generic part of the driver */
+ lb = (struct fdisk_label *) sun;
+ lb->name = "sun";
+ lb->op = &sun_operations;
+ lb->parttypes = sun_parttypes;
+ lb->nparttypes = ARRAY_SIZE(sun_parttypes);
+
+ return lb;
+}
#include "strutils.h"
#include "all-io.h"
+/*
+ * in-memory fdisk GPT stuff
+ */
+struct fdisk_gpt_label {
+ struct fdisk_label head; /* generic part */
+};
+
+
#define GPT_HEADER_SIGNATURE 0x5452415020494645LL /* EFI PART */
#define GPT_HEADER_REVISION_V1_02 0x00010200
#define GPT_HEADER_REVISION_V1_00 0x00010000
return 0;
}
-const struct fdisk_label gpt_label =
+static const struct fdisk_label_operations gpt_operations =
{
- .name = "gpt",
- .parttypes = gpt_parttypes,
- .nparttypes = ARRAY_SIZE(gpt_parttypes),
-
- .probe = gpt_probe_label,
- .write = gpt_write_disklabel,
- .verify = gpt_verify_disklabel,
- .create = gpt_create_disklabel,
- .part_add = gpt_add_partition,
- .part_delete = gpt_delete_partition,
- .part_get_type = gpt_get_partition_type,
- .part_set_type = gpt_set_partition_type
+ .probe = gpt_probe_label,
+ .write = gpt_write_disklabel,
+ .verify = gpt_verify_disklabel,
+ .create = gpt_create_disklabel,
+ .part_add = gpt_add_partition,
+ .part_delete = gpt_delete_partition,
+ .part_get_type = gpt_get_partition_type,
+ .part_set_type = gpt_set_partition_type
};
+
+/*
+ * allocates GPT in-memory stuff
+ */
+struct fdisk_label *fdisk_new_gpt_label(struct fdisk_context *cxt)
+{
+ struct fdisk_label *lb;
+ struct fdisk_gpt_label *gpt;
+
+ assert(cxt);
+
+ gpt = calloc(1, sizeof(*gpt));
+ if (!gpt)
+ return NULL;
+
+ /* initialize generic part of the driver */
+ lb = (struct fdisk_label *) gpt;
+ lb->name = "gpt";
+ lb->op = &gpt_operations;
+ lb->parttypes = gpt_parttypes;
+ lb->nparttypes = ARRAY_SIZE(gpt_parttypes);
+
+ return lb;
+}
cxt->first_lba = fdisk_topology_get_first_lba(cxt);
/* overwrite default by label stuff */
- if (cxt->label && cxt->label->reset_alignment)
- rc = cxt->label->reset_alignment(cxt);
+ if (cxt->label && cxt->label->op->reset_alignment)
+ rc = cxt->label->op->reset_alignment(cxt);
DBG(LABEL, dbgprint("%s alignment reseted to: "
"first LBA=%ju, grain=%lu [rc=%d]",
#include "fdiskP.h"
+static struct fdisk_context *fdisk_new_context(void)
+{
+ struct fdisk_context *cxt;
+ size_t i;
+
+ cxt = calloc(1, sizeof(*cxt));
+ if (!cxt)
+ return NULL;
+
+ /*
+ * Allocate label specific structs.
+ *
+ * This is necessary (for example) to store label specific
+ * context setting.
+ */
+ cxt->labels[ cxt->nlabels++ ] = fdisk_new_gpt_label(cxt);
+ cxt->labels[ cxt->nlabels++ ] = fdisk_new_dos_label(cxt);
+ cxt->labels[ cxt->nlabels++ ] = fdisk_new_aix_label(cxt);
+ cxt->labels[ cxt->nlabels++ ] = fdisk_new_bsd_label(cxt);
+ cxt->labels[ cxt->nlabels++ ] = fdisk_new_mac_label(cxt);
+ cxt->labels[ cxt->nlabels++ ] = fdisk_new_sgi_label(cxt);
+ cxt->labels[ cxt->nlabels++ ] = fdisk_new_sun_label(cxt);
+
+ DBG(CONTEXT, dbgprint("supported labels:"));
+ for (i = 0; i < cxt->nlabels; i++) {
+ DBG(CONTEXT, dbgprint(" %s", cxt->labels[i]->name));
+ cxt->labels[i]->cxt = cxt;
+ }
+
+ return cxt;
+}
+
+struct fdisk_label *fdisk_context_get_label(struct fdisk_context *cxt, const char *name)
+{
+ size_t i;
+
+ assert(cxt);
+
+ for (i = 0; i < cxt->nlabels; i++)
+ if (strcmp(cxt->labels[i]->name, name) == 0)
+ return cxt->labels[i];
+
+ DBG(LABEL, dbgprint("failed to found %s label driver\n", name));
+ return NULL;
+}
+
/**
- * fdisk_new_context:
+ * fdisk_new_context_from_filename:
* @fname: path to the device to be handled
* @readonly: how to open the device
*
readonly = 1;
}
- cxt = calloc(1, sizeof(*cxt));
+ cxt = fdisk_new_context();
if (!cxt)
goto fail;
*/
void fdisk_free_context(struct fdisk_context *cxt)
{
+ int i;
+
if (!cxt)
return;
DBG(CONTEXT, dbgprint("freeing context %p for %s", cxt, cxt->dev_path));
- close(cxt->dev_fd);
+ if (cxt->dev_fd > -1)
+ close(cxt->dev_fd);
free(cxt->dev_path);
free(cxt->firstsector);
+
+ /* deallocate label's private stuff */
+ for (i = 0; i < cxt->nlabels; i++) {
+ if (!cxt->labels[i])
+ continue;
+ if (cxt->labels[i]->op->free)
+ cxt->labels[i]->op->free(cxt->labels[i]);
+ else
+ free(cxt->labels[i]);
+ }
+
free(cxt);
}
sector_t cylinders;
};
+/*
+ * Label specific operations
+ */
+struct fdisk_label_operations {
+ /* probe disk label */
+ int (*probe)(struct fdisk_context *cxt);
+ /* write in-memory changes to disk */
+ int (*write)(struct fdisk_context *cxt);
+ /* verify the partition table */
+ int (*verify)(struct fdisk_context *cxt);
+ /* create new disk label */
+ int (*create)(struct fdisk_context *cxt);
+ /* new partition */
+ int (*part_add)(struct fdisk_context *cxt, int partnum, struct fdisk_parttype *t);
+ /* delete partition */
+ int (*part_delete)(struct fdisk_context *cxt, int partnum);
+ /* get partition type */
+ struct fdisk_parttype *(*part_get_type)(struct fdisk_context *cxt, int partnum);
+ /* set partition type */
+ int (*part_set_type)(struct fdisk_context *cxt, int partnum, struct fdisk_parttype *t);
+ /* refresh alignment setting */
+ int (*reset_alignment)(struct fdisk_context *cxt);
+
+ /* free in-memory label stuff */
+ void (*free)(struct fdisk_label *lb);
+};
+
+/*
+ * Generic label
+ */
+struct fdisk_label {
+ const char *name;
+
+ struct fdisk_parttype *parttypes;
+ size_t nparttypes; /* number of items in parttypes[] */
+
+ const struct fdisk_label_operations *op;
+
+ struct fdisk_context *cxt;
+};
+
+/* label allocators */
+extern struct fdisk_label *fdisk_new_gpt_label(struct fdisk_context *cxt);
+extern struct fdisk_label *fdisk_new_dos_label(struct fdisk_context *cxt);
+extern struct fdisk_label *fdisk_new_aix_label(struct fdisk_context *cxt);
+extern struct fdisk_label *fdisk_new_bsd_label(struct fdisk_context *cxt);
+extern struct fdisk_label *fdisk_new_mac_label(struct fdisk_context *cxt);
+extern struct fdisk_label *fdisk_new_sgi_label(struct fdisk_context *cxt);
+extern struct fdisk_label *fdisk_new_sun_label(struct fdisk_context *cxt);
+
struct fdisk_context {
int dev_fd; /* device descriptor */
char *dev_path; /* device path */
sector_t total_sectors; /* in logical sectors */
struct fdisk_geometry geom;
- /* label operations and description */
- const struct fdisk_label *label;
-};
+ struct fdisk_label *label; /* current label, pointer to labels[] */
-/*
- * Label specific operations
- */
-struct fdisk_label {
- const char *name;
+ size_t nlabels; /* number of initialized label drivers */
+ struct fdisk_label *labels[8]; /* all supported labels,
+ * FIXME: use any enum rather than hardcoded number */
+};
- /* array with partition types */
- struct fdisk_parttype *parttypes;
- size_t nparttypes; /* number of items in parttypes[] */
- /* probe disk label */
- int (*probe)(struct fdisk_context *cxt);
- /* write in-memory changes to disk */
- int (*write)(struct fdisk_context *cxt);
- /* verify the partition table */
- int (*verify)(struct fdisk_context *cxt);
- /* create new disk label */
- int (*create)(struct fdisk_context *cxt);
- /* new partition */
- int (*part_add)(struct fdisk_context *cxt, int partnum, struct fdisk_parttype *t);
- /* delete partition */
- int (*part_delete)(struct fdisk_context *cxt, int partnum);
- /* get partition type */
- struct fdisk_parttype *(*part_get_type)(struct fdisk_context *cxt, int partnum);
- /* set partition type */
- int (*part_set_type)(struct fdisk_context *cxt, int partnum, struct fdisk_parttype *t);
- /* refresh alignment setting */
- int (*reset_alignment)(struct fdisk_context *cxt);
-};
/* alignment.c */
extern sector_t fdisk_topology_get_first_lba(struct fdisk_context *cxt);
#include "fdiskP.h"
-/*
- * Label probing functions.
- */
-extern const struct fdisk_label aix_label;
-extern const struct fdisk_label dos_label;
-extern const struct fdisk_label bsd_label;
-extern const struct fdisk_label mac_label;
-extern const struct fdisk_label sun_label;
-extern const struct fdisk_label sgi_label;
-extern const struct fdisk_label gpt_label;
-
-static const struct fdisk_label *labels[] =
-{
- &gpt_label,
- &dos_label,
- &sun_label,
- &sgi_label,
- &aix_label,
- &bsd_label,
- &mac_label,
-};
-
/*
* Don't use this function derectly, use fdisk_new_context_from_filename()
*/
cxt->disklabel = FDISK_DISKLABEL_ANY;
- for (i = 0; i < ARRAY_SIZE(labels); i++) {
- if (!labels[i]->probe || labels[i]->probe(cxt) != 1)
+ for (i = 0; i < cxt->nlabels; i++) {
+ if (!cxt->labels[i]->op->probe ||
+ cxt->labels[i]->op->probe(cxt) != 1)
continue;
- cxt->label = labels[i];
+ cxt->label = cxt->labels[i];
DBG(LABEL, dbgprint("detected a %s label", cxt->label->name));
return 0;
{
if (!cxt || !cxt->label)
return -EINVAL;
- if (!cxt->label->write)
+ if (!cxt->label->op->write)
return -ENOSYS;
- return cxt->label->write(cxt);
+ return cxt->label->op->write(cxt);
}
/**
{
if (!cxt || !cxt->label)
return -EINVAL;
- if (!cxt->label->verify)
+ if (!cxt->label->op->verify)
return -ENOSYS;
- return cxt->label->verify(cxt);
+ return cxt->label->op->verify(cxt);
}
/**
{
if (!cxt || !cxt->label)
return -EINVAL;
- if (!cxt->label->part_add)
+ if (!cxt->label->op->part_add)
return -ENOSYS;
DBG(LABEL, dbgprint("adding new partition number %d", partnum));
- cxt->label->part_add(cxt, partnum, t);
+ cxt->label->op->part_add(cxt, partnum, t);
return 0;
}
{
if (!cxt || !cxt->label)
return -EINVAL;
- if (!cxt->label->part_delete)
+ if (!cxt->label->op->part_delete)
return -ENOSYS;
DBG(LABEL, dbgprint("deleting %s partition number %d",
cxt->label->name, partnum));
- return cxt->label->part_delete(cxt, partnum);
+ return cxt->label->op->part_delete(cxt, partnum);
}
/**
if (!cxt)
return -EINVAL;
- cxt->label = NULL;
-
if (!name) { /* use default label creation */
#ifdef __sparc__
- cxt->label = &sun_label;
+ name = "sun";
#else
- cxt->label = &dos_label;
+ name = "dos";
#endif
- } else {
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(labels); i++) {
- if (strcmp(name, labels[i]->name) != 0)
- continue;
-
- cxt->label = labels[i];
- DBG(LABEL, dbgprint("changing to %s label\n", cxt->label->name));
- break;
- }
}
+ cxt->label = fdisk_context_get_label(cxt, name);
if (!cxt->label)
return -EINVAL;
- if (!cxt->label->create)
+
+ DBG(LABEL, dbgprint("changing to %s label\n", cxt->label->name));
+ if (!cxt->label->op->create)
return -ENOSYS;
fdisk_reset_alignment(cxt);
-
- return cxt->label->create(cxt);
+ return cxt->label->op->create(cxt);
}
/**
*/
struct fdisk_parttype *fdisk_get_partition_type(struct fdisk_context *cxt, int partnum)
{
- if (!cxt || !cxt->label || !cxt->label->part_get_type)
+ if (!cxt || !cxt->label || !cxt->label->op->part_get_type)
return NULL;
DBG(LABEL, dbgprint("partition: %d: get type", partnum));
- return cxt->label->part_get_type(cxt, partnum);
+ return cxt->label->op->part_get_type(cxt, partnum);
}
/**
int fdisk_set_partition_type(struct fdisk_context *cxt, int partnum,
struct fdisk_parttype *t)
{
- if (!cxt || !cxt->label || !cxt->label->part_set_type)
+ if (!cxt || !cxt->label || !cxt->label->op->part_set_type)
return -EINVAL;
DBG(LABEL, dbgprint("partition: %d: set type", partnum));
- return cxt->label->part_set_type(cxt, partnum, t);
+ return cxt->label->op->part_set_type(cxt, partnum, t);
}
/**
#endif
struct fdisk_context;
+struct fdisk_label;
struct fdisk_parttype;
/*
const char *fname, int readonly);
extern void fdisk_free_context(struct fdisk_context *cxt);
+extern struct fdisk_label *fdisk_context_get_label(struct fdisk_context *cxt,
+ const char *name);
+
/* parttype.c */
extern struct fdisk_parttype *fdisk_get_parttype_from_code(struct fdisk_context *cxt,
unsigned int code);