]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: add fdisk_new_context(), reuse context
authorKarel Zak <kzak@redhat.com>
Tue, 11 Dec 2012 13:41:57 +0000 (14:41 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 11 Mar 2013 11:47:29 +0000 (12:47 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
fdisks/fdisk.c
fdisks/gpt.c
libfdisk/src/alignment.c
libfdisk/src/context.c
libfdisk/src/fdiskP.h
libfdisk/src/label.c
libfdisk/src/libfdisk.h
libfdisk/src/utils.c

index 866d8fe21cbf4dc7a12d7263e251ab8d2b850389..c771f6e6d5b4043ec4d5db7020fa632c953bf492 100644 (file)
@@ -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;
 }
index 4f70f962d019f7e87085b99224b59fccdf468f5c..f9ba9f07246a39af89d083215dd11a054c7649f6 100644 (file)
@@ -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
 };
 
 /*
index 1ef5796a45a8e59bd36d1468444bdec54b2e4b32..25323d1b54e252c2dc77b1d39b6ee4416007a179 100644 (file)
@@ -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))
index 83420a9779a625627488e02b8ccc531840e7004e..b2929f351cfa5a2a80e9d1a89c1b42e8ab3f9624 100644 (file)
@@ -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++) {
index 01dd71f514cf279c3d18db0d9a5ecda84f1ec230..4d352b5d4e780b94406dec99332f0289066746ce 100644 (file)
@@ -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 */
index 8f9934835573935c8b21cca7efa7435209bedd87..5fb40adc7b60bc4cd0ec4f56b39c5ec5d758c7f1 100644 (file)
@@ -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);
+}
index d72a608899e9ff74d65b37da34f6bd7cea10558d..d803fc2dc9e126d644459bb05de8abee6d4ef75f 100644 (file)
@@ -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);
 
index 6668e23e34b5decb5042399bc27b62c346593817..1360e84677ba9ba01c2146ae7f2ab01827e583fc 100644 (file)
@@ -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;
        }