summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fdisks/fdisk.c32
-rw-r--r--fdisks/gpt.c51
-rw-r--r--libfdisk/src/alignment.c2
-rw-r--r--libfdisk/src/context.c71
-rw-r--r--libfdisk/src/fdiskP.h3
-rw-r--r--libfdisk/src/label.c31
-rw-r--r--libfdisk/src/libfdisk.h6
-rw-r--r--libfdisk/src/utils.c1
8 files changed, 128 insertions, 69 deletions
diff --git a/fdisks/fdisk.c b/fdisks/fdisk.c
index 866d8fe21..c771f6e6d 100644
--- a/fdisks/fdisk.c
+++ b/fdisks/fdisk.c
@@ -1387,12 +1387,10 @@ static int is_ide_cdrom_or_tape(char *device)
}
/* Print disk geometry and partition table of a specified device (-l option) */
-static void print_partition_table_from_option(char *device, unsigned long sector_size)
+static void print_partition_table_from_option(struct fdisk_context *cxt,
+ char *device, unsigned long sector_size)
{
- struct fdisk_context *cxt;
-
- cxt = fdisk_new_context_from_filename(device, 1); /* read-only */
- if (!cxt)
+ if (fdisk_context_assign_device(cxt, device, 1) != 0) /* read-only */
err(EXIT_FAILURE, _("cannot open %s"), device);
if (sector_size) /* passed -b option, override autodiscovery */
@@ -1413,9 +1411,6 @@ static void print_partition_table_from_option(char *device, unsigned long sector
btrydev(cxt);
} else
list_table(cxt, 0);
-
- fdisk_free_context(cxt);
- cxt = NULL;
}
/*
@@ -1423,7 +1418,8 @@ static void print_partition_table_from_option(char *device, unsigned long sector
* try all things in /proc/partitions that look like a full disk
*/
static void
-print_all_partition_table_from_option(unsigned long sector_size)
+print_all_partition_table_from_option(struct fdisk_context *cxt,
+ unsigned long sector_size)
{
FILE *procpt;
char line[128 + 1], ptname[128 + 1], devname[256];
@@ -1445,7 +1441,7 @@ print_all_partition_table_from_option(unsigned long sector_size)
char *cn = canonicalize_path(devname);
if (cn) {
if (!is_ide_cdrom_or_tape(cn))
- print_partition_table_from_option(cn, sector_size);
+ print_partition_table_from_option(cxt, cn, sector_size);
free(cn);
}
}
@@ -1593,13 +1589,18 @@ int main(int argc, char **argv)
{
int c, optl = 0, opts = 0;
unsigned long sector_size = 0;
- struct fdisk_context *cxt = NULL;
+ struct fdisk_context *cxt;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
atexit(close_stdout);
+ fdisk_init_debug(0);
+ cxt = fdisk_new_context();
+ if (!cxt)
+ err(EXIT_FAILURE, _("failed to allocate libfdisk context"));
+
while ((c = getopt(argc, argv, "b:c::C:hH:lsS:u::vV")) != -1) {
switch (c) {
case 'b':
@@ -1657,7 +1658,6 @@ int main(int argc, char **argv)
}
}
- fdisk_init_debug(0);
if (sector_size && argc-optind != 1)
printf(_("Warning: the -b (set sector size) option should"
@@ -1668,9 +1668,9 @@ int main(int argc, char **argv)
if (argc > optind) {
int k;
for (k = optind; k < argc; k++)
- print_partition_table_from_option(argv[k], sector_size);
+ print_partition_table_from_option(cxt, argv[k], sector_size);
} else
- print_all_partition_table_from_option(sector_size);
+ print_all_partition_table_from_option(cxt, sector_size);
exit(EXIT_SUCCESS);
}
@@ -1692,8 +1692,7 @@ int main(int argc, char **argv)
if (argc-optind != 1)
usage(stderr);
- cxt = fdisk_new_context_from_filename(argv[optind], 0);
- if (!cxt)
+ if (fdisk_context_assign_device(cxt, argv[optind], 0) != 0)
err(EXIT_FAILURE, _("cannot open %s"), argv[optind]);
if (sector_size) /* passed -b option, override autodiscovery */
@@ -1714,5 +1713,6 @@ int main(int argc, char **argv)
command_prompt(cxt);
+ fdisk_free_context(cxt);
return 0;
}
diff --git a/fdisks/gpt.c b/fdisks/gpt.c
index 4f70f962d..f9ba9f072 100644
--- a/fdisks/gpt.c
+++ b/fdisks/gpt.c
@@ -248,6 +248,8 @@ static struct fdisk_parttype gpt_parttypes[] =
DEF_GUID("85D5E45C-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD Vinum")),
};
+/* FIXME: move these global variables to fdisk_gpt_label */
+
/* primary GPT header */
static struct gpt_header *pheader = NULL;
/* backup GPT header */
@@ -1009,21 +1011,6 @@ static void gpt_init(struct fdisk_context *cxt)
partitions = le32_to_cpu(pheader->npartition_entries);
}
-/*
- * Deinitialize fdisk-specific variables
- */
-static void gpt_deinit(struct fdisk_context *cxt)
-{
- free(ents);
- free(pheader);
- free(bheader);
- ents = NULL;
- pheader = NULL;
- bheader = NULL;
-
- cxt->disklabel = FDISK_DISKLABEL_ANY;
- partitions = 0;
-}
static int gpt_probe_label(struct fdisk_context *cxt)
{
@@ -1062,6 +1049,7 @@ static int gpt_probe_label(struct fdisk_context *cxt)
return 1;
failed:
+ DBG(LABEL, dbgprint("GPT probe failed"));
return 0;
}
@@ -1580,17 +1568,15 @@ static int gpt_create_disklabel(struct fdisk_context *cxt)
int rc = 0;
ssize_t entry_sz = 0;
+ /* labe private stuff has to be empty, see gpt_deinit() */
+ assert(pheader == NULL);
+ assert(bheader == NULL);
+
/*
- * Reset space or clear data from headers, pt entries and
- * protective MBR. Big fat warning: any previous content is
- * overwritten, so ask users to be sure!.
- *
* When no header, entries or pmbr is set, we're probably
* dealing with a new, empty disk - so always allocate memory
* to deal with the data structures whatever the case is.
*/
- gpt_deinit(cxt);
-
rc = gpt_mknew_pmbr(cxt);
if (rc < 0)
goto done;
@@ -1663,6 +1649,25 @@ static int gpt_set_partition_type(struct fdisk_context *cxt, int i,
return 0;
}
+/*
+ * Deinitialize fdisk-specific variables
+ */
+static void gpt_deinit(struct fdisk_label *lb)
+{
+ free(ents);
+ free(pheader);
+ free(bheader);
+
+ ents = NULL;
+ pheader = NULL;
+ bheader = NULL;
+
+ if (lb->cxt && lb->cxt->disklabel == FDISK_DISKLABEL_GPT)
+ lb->cxt->disklabel = FDISK_DISKLABEL_ANY;
+
+ partitions = 0;
+}
+
static const struct fdisk_label_operations gpt_operations =
{
.probe = gpt_probe_label,
@@ -1672,7 +1677,9 @@ static const struct fdisk_label_operations gpt_operations =
.part_add = gpt_add_partition,
.part_delete = gpt_delete_partition,
.part_get_type = gpt_get_partition_type,
- .part_set_type = gpt_set_partition_type
+ .part_set_type = gpt_set_partition_type,
+
+ .deinit = gpt_deinit
};
/*
diff --git a/libfdisk/src/alignment.c b/libfdisk/src/alignment.c
index 1ef5796a4..25323d1b5 100644
--- a/libfdisk/src/alignment.c
+++ b/libfdisk/src/alignment.c
@@ -185,7 +185,7 @@ int fdisk_discover_geometry(struct fdisk_context *cxt)
unsigned int h = 0, s = 0;
assert(cxt);
- assert(!cxt->geom.heads);
+ assert(cxt->geom.heads == 0);
/* get number of 512-byte sectors, and convert it the real sectors */
if (!blkdev_get_sectors(cxt->dev_fd, &nsects))
diff --git a/libfdisk/src/context.c b/libfdisk/src/context.c
index 83420a977..b2929f351 100644
--- a/libfdisk/src/context.c
+++ b/libfdisk/src/context.c
@@ -1,7 +1,7 @@
#include "fdiskP.h"
-static struct fdisk_context *fdisk_new_context(void)
+struct fdisk_context *fdisk_new_context(void)
{
struct fdisk_context *cxt;
size_t i;
@@ -10,6 +10,9 @@ static struct fdisk_context *fdisk_new_context(void)
if (!cxt)
return NULL;
+ DBG(LABEL, dbgprint("new context %p allocated", cxt));
+ cxt->dev_fd = -1;
+
/*
* Allocate label specific structs.
*
@@ -47,8 +50,37 @@ struct fdisk_label *fdisk_context_get_label(struct fdisk_context *cxt, const cha
return NULL;
}
+static void reset_context(struct fdisk_context *cxt)
+{
+ size_t nlbs;
+ struct fdisk_label *lbs[ ARRAY_SIZE(cxt->labels) ];
+
+ DBG(CONTEXT, dbgprint("\n-----\nresetting context %p", cxt));
+ fdisk_deinit_label(cxt); /* reset the current label */
+
+ /* remember permanent setting */
+ memcpy(lbs, cxt->labels, sizeof(lbs));
+ nlbs = cxt->nlabels;
+
+ /* free device specific stuff */
+ if (cxt->dev_fd > -1)
+ close(cxt->dev_fd);
+ free(cxt->dev_path);
+ free(cxt->firstsector);
+
+ /* the reset */
+ memset(cxt, 0, sizeof(*cxt));
+
+ /* initialize */
+ cxt->dev_fd = -1;
+
+ /* set permanent setting */
+ memcpy(cxt->labels, lbs, sizeof(lbs));
+ cxt->nlabels = nlbs;
+}
+
/**
- * fdisk_new_context_from_filename:
+ * fdisk_context_assign_device:
* @fname: path to the device to be handled
* @readonly: how to open the device
*
@@ -56,25 +88,24 @@ struct fdisk_label *fdisk_context_get_label(struct fdisk_context *cxt, const cha
* the device with read-write mode and will fallback to read-only if
* unsuccessful.
*
- * Returns: newly allocated fdisk context or NULL upon failure.
+ * Returns: 0 on sucess, < 0 on error.
*/
-struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int readonly)
+int fdisk_context_assign_device(struct fdisk_context *cxt,
+ const char *fname, int readonly)
{
- int fd, errsv = 0;
- struct fdisk_context *cxt = NULL;
+ int fd;
- DBG(CONTEXT, dbgprint("initializing context for %s", fname));
+ DBG(CONTEXT, dbgprint("assigning device %s", fname));
+ assert(cxt);
+
+ reset_context(cxt);
if (readonly == 1 || (fd = open(fname, O_RDWR)) < 0) {
if ((fd = open(fname, O_RDONLY)) < 0)
- return NULL;
+ return -errno;
readonly = 1;
}
- cxt = fdisk_new_context();
- if (!cxt)
- goto fail;
-
cxt->dev_fd = fd;
cxt->dev_path = strdup(fname);
if (!cxt->dev_path)
@@ -89,20 +120,15 @@ struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int rea
/* detect labels and apply labes specific stuff (e.g geomery)
* to the context */
fdisk_probe_labels(cxt);
-
fdisk_reset_alignment(cxt);
DBG(CONTEXT, dbgprint("context %p initialized for %s [%s]",
cxt, fname,
readonly ? "READ-ONLY" : "READ-WRITE"));
- return cxt;
+ return 0;
fail:
- errsv = errno;
- fdisk_free_context(cxt);
- errno = errsv;
-
- DBG(CONTEXT, dbgprint("failed to initialize context for %s: %m", fname));
- return NULL;
+ DBG(CONTEXT, dbgprint("failed to assign device"));
+ return -errno;
}
/**
@@ -119,10 +145,7 @@ void fdisk_free_context(struct fdisk_context *cxt)
return;
DBG(CONTEXT, dbgprint("freeing context %p for %s", cxt, cxt->dev_path));
- if (cxt->dev_fd > -1)
- close(cxt->dev_fd);
- free(cxt->dev_path);
- free(cxt->firstsector);
+ reset_context(cxt);
/* deallocate label's private stuff */
for (i = 0; i < cxt->nlabels; i++) {
diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h
index 01dd71f51..4d352b5d4 100644
--- a/libfdisk/src/fdiskP.h
+++ b/libfdisk/src/fdiskP.h
@@ -143,6 +143,8 @@ struct fdisk_label_operations {
/* free in-memory label stuff */
void (*free)(struct fdisk_label *lb);
+ /* deinit in-memory label stuff */
+ void (*deinit)(struct fdisk_label *lb);
};
/*
@@ -231,5 +233,6 @@ extern int fdisk_read_firstsector(struct fdisk_context *cxt);
/* label.c */
extern int fdisk_probe_labels(struct fdisk_context *cxt);
+extern void fdisk_deinit_label(struct fdisk_context *cxt);
#endif /* _LIBFDISK_PRIVATE_H */
diff --git a/libfdisk/src/label.c b/libfdisk/src/label.c
index 8f9934835..5fb40adc7 100644
--- a/libfdisk/src/label.c
+++ b/libfdisk/src/label.c
@@ -9,15 +9,23 @@ int fdisk_probe_labels(struct fdisk_context *cxt)
size_t i;
cxt->disklabel = FDISK_DISKLABEL_ANY;
+ cxt->label = NULL;
for (i = 0; i < cxt->nlabels; i++) {
- if (!cxt->labels[i]->op->probe ||
- cxt->labels[i]->op->probe(cxt) != 1)
+ struct fdisk_label *lb = cxt->labels[i];
+
+ if (!lb->op->probe)
continue;
- cxt->label = cxt->labels[i];
+ DBG(LABEL, dbgprint("probing for %s", lb->name));
+ if (lb->op->probe(cxt) != 1) {
+ if (lb->op->deinit)
+ lb->op->deinit(lb); /* for sure */
+ continue;
+ }
- DBG(LABEL, dbgprint("detected a %s label", cxt->label->name));
+ cxt->label = lb;
+ DBG(LABEL, dbgprint("detected a %s label", lb->name));
return 0;
}
@@ -151,6 +159,8 @@ int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name)
#endif
}
+ fdisk_deinit_label(cxt); /* deinitialize the current label */
+
cxt->label = fdisk_context_get_label(cxt, name);
if (!cxt->label)
return -EINVAL;
@@ -210,3 +220,16 @@ size_t fdisk_get_nparttypes(struct fdisk_context *cxt)
return cxt->label->nparttypes;
}
+
+/*
+ * Resets the current used label driver to initial state
+ */
+void fdisk_deinit_label(struct fdisk_context *cxt)
+{
+ assert(cxt);
+
+ if (!cxt->label || !cxt->label->op->deinit)
+ return;
+
+ cxt->label->op->deinit(cxt->label);
+}
diff --git a/libfdisk/src/libfdisk.h b/libfdisk/src/libfdisk.h
index d72a60889..d803fc2dc 100644
--- a/libfdisk/src/libfdisk.h
+++ b/libfdisk/src/libfdisk.h
@@ -47,10 +47,12 @@ enum fdisk_labeltype {
extern void fdisk_init_debug(int mask);
/* context.h */
-extern struct fdisk_context *fdisk_new_context_from_filename(
- const char *fname, int readonly);
+extern struct fdisk_context *fdisk_new_context(void);
extern void fdisk_free_context(struct fdisk_context *cxt);
+extern int fdisk_context_assign_device(struct fdisk_context *cxt,
+ const char *fname, int readonly);
+
extern struct fdisk_label *fdisk_context_get_label(struct fdisk_context *cxt,
const char *name);
diff --git a/libfdisk/src/utils.c b/libfdisk/src/utils.c
index 6668e23e3..1360e8467 100644
--- a/libfdisk/src/utils.c
+++ b/libfdisk/src/utils.c
@@ -35,6 +35,7 @@ int fdisk_read_firstsector(struct fdisk_context *cxt)
if (r != cxt->sector_size) {
if (!errno)
errno = EINVAL; /* probably too small file/device */
+ DBG(TOPOLOGY, dbgprint("failed to read first sector %m"));
return -errno;
}