]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: add support to list free space
authorKarel Zak <kzak@redhat.com>
Thu, 12 Dec 2013 16:22:52 +0000 (17:22 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 11 Mar 2014 10:35:12 +0000 (11:35 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
libfdisk/src/context.c
libfdisk/src/fdiskP.h
libfdisk/src/label.c
libfdisk/src/libfdisk.h
libfdisk/src/partition.c

index c4054034e5f2ba418990b6a57429960e078708f8..0db21c81e069138ae036dd58cc1cb8b12ef70bae 100644 (file)
@@ -381,6 +381,28 @@ int fdisk_context_display_details(struct fdisk_context *cxt)
        return cxt->display_details == 1;
 }
 
+/**
+ * fdisk_context_enable_freespace
+ * cxt: context
+ * enable: true/flase
+ *
+ * Enables or disables "free space" in list() output
+ *
+ * Returns: 0 on success, < 0 on error.
+ */
+int fdisk_context_enable_freespace(struct fdisk_context *cxt, int enable)
+{
+       assert(cxt);
+       cxt->display_freespace = enable ? 1 : 0;
+       return 0;
+}
+
+int fdisk_context_display_freespace(struct fdisk_context *cxt)
+{
+       assert(cxt);
+       return cxt->display_freespace == 1;
+}
+
 /**
  * fdisk_context_enable_listonly:
  * cxt: context
index fbeaf7ee209fb67b58334b4db5c0e4fede61bb5f..881e1b2b6a8dcf4a3a240b5070e2e0594b5af28a 100644 (file)
@@ -156,12 +156,14 @@ struct fdisk_partition {
        unsigned int    partno_follow_default : 1,
                        start_follow_default : 1,
                        end_follow_default : 1,
+                       freespace : 1,          /* describes gap between partitions*/
                        nested : 1,             /* logical partition */
                        used   : 1,             /* partition used */
                        endrel : 1;             /* end is specified as relative number */
 };
 
 #define FDISK_EMPTY_PARTNO     ((size_t) -1)
+#define FDISK_EMPTY_PARTITION  { .partno = FDISK_EMPTY_PARTNO }
 
 /*
  * Legacy CHS based geometry
@@ -338,6 +340,7 @@ struct fdisk_context {
 
        unsigned int display_in_cyl_units : 1,  /* for obscure labels */
                     display_details : 1,       /* expert display mode */
+                    display_freespace : 1,     /* freesapce in list() output */
                     listonly : 1;              /* list partition, nothing else */
 
        /* alignment */
@@ -369,8 +372,6 @@ struct fdisk_context {
 extern int __fdisk_context_switch_label(struct fdisk_context *cxt,
                                    struct fdisk_label *lb);
 
-extern int fdisk_context_use_cylinders(struct fdisk_context *cxt);
-extern int fdisk_context_display_details(struct fdisk_context *cxt);
 extern int fdisk_context_enable_listonly(struct fdisk_context *cxt, int enable);
 extern int fdisk_context_listonly(struct fdisk_context *cxt);
 
index 358162c57ed3cda590f59b9b4b3f6d4546e2de4c..e243dc05f0b7b4d3b774244b723068ec1b443b8b 100644 (file)
@@ -258,6 +258,64 @@ int fdisk_list_disklabel(struct fdisk_context *cxt)
        return cxt->label->op->list(cxt);
 }
 
+static int add_partition_to_tt(struct fdisk_context *cxt,
+                                struct tt *tb,
+                                int *cols,
+                                size_t ncols,
+                                struct fdisk_partition *pa)
+{
+       size_t j;
+       struct tt_line *ln = tt_add_line(tb, NULL);
+       const struct fdisk_column *col;
+
+       if (!ln)
+               return -ENOMEM;
+
+       /* set data for the columns */
+       for (j = 0; j < ncols; j++) {
+               char *data = NULL;
+               int id;
+
+               col = fdisk_label_get_column(cxt->label, cols[j]);
+               if (!col)
+                       continue;
+               id = (col->id == FDISK_COL_SECTORS &&
+                     fdisk_context_use_cylinders(cxt)) ?
+                               FDISK_COL_CYLINDERS :
+                               col->id;
+
+               if (fdisk_partition_to_string(pa, id, &data))
+                       continue;
+               tt_line_set_data(ln, j, data);
+       }
+
+       return 0;
+}
+
+static void gap_to_freespace(
+                       struct fdisk_context *cxt,
+                       struct tt *tb,
+                       int *cols,
+                       size_t ncols,
+                       uint64_t start,
+                       uint64_t end)
+{
+       struct fdisk_partition pa = FDISK_EMPTY_PARTITION;
+
+       pa.freespace = 1;
+       pa.cxt = cxt;
+
+       pa.start = start;
+       pa.end = end;
+       pa.size = pa.end - pa.start + 1ULL;
+
+       DBG(LABEL, dbgprint("gap->freespace [%ju, size=%ju]",
+                       pa.start, pa.size));
+
+       add_partition_to_tt(cxt, tb, cols, ncols, &pa);
+}
+
+
 /**
  * fdisk_list_partitions
  * @cxt: fdisk context
@@ -280,13 +338,15 @@ int fdisk_list_partitions(struct fdisk_context *cxt, int *cols, size_t ncols)
        const struct fdisk_column *col;
        struct fdisk_partition *pa = NULL;
        size_t i, j;
+       uint64_t last, grain;
 
        if (!cxt || !cxt->label)
                return -EINVAL;
        if (!cxt->label->op->get_part)
                return -ENOSYS;
 
-       DBG(LABEL, dbgprint("list partitions"));
+       DBG(LABEL, dbgprint("list partitions%s",
+               fdisk_context_display_freespace(cxt) ? " and free-space" : ""));
 
        if (!cols || !ncols) {
                rc = fdisk_get_columns(cxt, 0, &cols, &ncols);
@@ -300,6 +360,9 @@ int fdisk_list_partitions(struct fdisk_context *cxt, int *cols, size_t ncols)
                goto done;
        }
 
+       last = cxt->first_lba;
+       grain = cxt->grain / cxt->sector_size;
+
        /* define table columns */
        for (j = 0; j < ncols; j++) {
                col = fdisk_label_get_column(cxt->label, cols[j]);
@@ -314,35 +377,31 @@ int fdisk_list_partitions(struct fdisk_context *cxt, int *cols, size_t ncols)
 
        /* generate per-partition lines into table */
        for (i = 0; i < cxt->label->nparts_max; i++) {
-               struct tt_line *ln;
-
                rc = fdisk_get_partition(cxt, i, &pa);
                if (rc)
                        continue;
                if (!fdisk_partition_is_used(pa))
                        continue;
-               ln = tt_add_line(tb, NULL);
-               if (!ln)
-                       continue;
 
-               /* set data for the columns */
-               for (j = 0; j < ncols; j++) {
-                       char *data = NULL;
-                       int id;
-
-                       col = fdisk_label_get_column(cxt->label, cols[j]);
-                       if (!col)
-                               continue;
-                       id = (col->id == FDISK_COL_SECTORS &&
-                             fdisk_context_use_cylinders(cxt)) ?
-                                       FDISK_COL_CYLINDERS :
-                                       col->id;
-
-                       rc = fdisk_partition_to_string(pa, id, &data);
-                       if (rc)
-                               continue;
-                       tt_line_set_data(ln, j, data);
+               /* add free-space (before partition) to the list */
+               if (fdisk_context_display_freespace(cxt) &&
+                   last + grain < pa->start) {
+                       gap_to_freespace(cxt, tb, cols, ncols,
+                               last + (last > cxt->first_lba ? 1 : 0),
+                               pa->start - 1);
                }
+               last = pa->end;
+
+               /* add partition to the list */
+               add_partition_to_tt(cxt, tb, cols, ncols, pa);
+       }
+
+       /* add free-space (behind last partition) to the list */
+       if (fdisk_context_display_freespace(cxt) &&
+           last + grain < cxt->total_sectors - 1) {
+               gap_to_freespace(cxt, tb, cols, ncols,
+                       last + (last > cxt->first_lba ? 1 : 0),
+                       cxt->total_sectors - 1);
        }
 
        if (!tt_is_empty(tb))
index f493774718a2eb3e75ab31fb9fb90791cea28a34..22741d80fc98c9a15cd334fdd048c439477e8fed 100644 (file)
@@ -97,6 +97,10 @@ extern const char *fdisk_context_get_unit(struct fdisk_context *cxt, int n);
 extern unsigned int fdisk_context_get_units_per_sector(struct fdisk_context *cxt);
 
 extern int fdisk_context_enable_details(struct fdisk_context *cxt, int enable);
+extern int fdisk_context_enable_freespace(struct fdisk_context *cxt, int enable);
+extern int fdisk_context_use_cylinders(struct fdisk_context *cxt);
+extern int fdisk_context_display_details(struct fdisk_context *cxt);
+extern int fdisk_context_display_freespace(struct fdisk_context *cxt);
 
 /* parttype.c */
 extern struct fdisk_parttype *fdisk_get_parttype_from_code(struct fdisk_context *cxt,
@@ -178,6 +182,7 @@ extern int fdisk_partition_toggle_flag(struct fdisk_context *cxt, size_t partnum
 extern struct fdisk_partition *fdisk_new_partition(void);
 extern void fdisk_reset_partition(struct fdisk_partition *pa);
 extern void fdisk_free_partition(struct fdisk_partition *pa);
+extern int fdisk_partition_is_freespace(struct fdisk_partition *pa);
 extern int fdisk_partition_set_start(struct fdisk_partition *pa, uint64_t off);
 extern uint64_t fdisk_partition_get_start(struct fdisk_partition *pa);
 extern int fdisk_partition_set_end(struct fdisk_partition *pa, uint64_t off, int isrel);
index 65cdc9f48476427fa47dc4f63794ec79bb8ba917..57c5eb976447f31da07ad4daf16c3f9b73b8aac9 100644 (file)
@@ -170,6 +170,11 @@ int fdisk_partition_is_used(struct fdisk_partition *pa)
        return pa && pa->used;
 }
 
+int fdisk_partition_is_freespace(struct fdisk_partition *pa)
+{
+       return pa && pa->freespace;
+}
+
 int fdisk_partition_next_partno(
                struct fdisk_context *cxt,
                struct fdisk_partition *pa,
@@ -233,7 +238,9 @@ int fdisk_partition_to_string(struct fdisk_partition *pa,
 
        switch (id) {
        case FDISK_COL_DEVICE:
-               if (pa->cxt->label->flags & FDISK_LABEL_FL_INCHARS_PARTNO)
+               if (pa->freespace)
+                       p = strdup(_("Free space"));
+               else if (pa->cxt->label->flags & FDISK_LABEL_FL_INCHARS_PARTNO)
                        rc = asprintf(&p, "%c", (int) pa->partno + 'a');
                else
                        p = fdisk_partname(pa->cxt->dev_path, pa->partno + 1);