]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
fdisk: add --output <list> for print command(s)
authorKarel Zak <kzak@redhat.com>
Fri, 3 Oct 2014 10:40:04 +0000 (12:40 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 7 Oct 2014 12:55:32 +0000 (14:55 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
disk-utils/fdisk-list.c
disk-utils/fdisk-list.h
disk-utils/fdisk.8
disk-utils/fdisk.c

index 708e6939a94678f4f5eb81a551488258052f66e2..42dfda8cb7309cfbc55ef8b85a17dad0afda1d05 100644 (file)
 #include "strutils.h"
 #include "sysfs.h"
 #include "colors.h"
+#include "ttyutils.h"
 
 #include "fdisk-list.h"
 
+/* see init_fields() */
+static const char *fields_string;
+static int *fields_ids;
+static size_t fields_nids;
+static const struct fdisk_label *fields_label;
+
 static int is_ide_cdrom_or_tape(char *device)
 {
        int fd, ret;
@@ -90,7 +97,8 @@ void list_disklabel(struct fdisk_context *cxt)
        if (fdisk_get_partitions(cxt, &tb) || fdisk_table_get_nents(tb) <= 0)
                goto done;
 
-       if (fdisk_label_get_fields_ids(NULL, cxt, &ids, &nids))
+       ids = init_fields(cxt, NULL, &nids);
+       if (!ids)
                goto done;
 
        itr = fdisk_new_iter(FDISK_ITER_FORWARD);
@@ -171,7 +179,6 @@ void list_disklabel(struct fdisk_context *cxt)
        if (fdisk_table_wrong_order(tb))
                fdisk_info(cxt, _("Partition table entries are not in disk order."));
 done:
-       free(ids);
        scols_unref_table(out);
        fdisk_unref_table(tb);
        fdisk_free_iter(itr);
@@ -254,3 +261,110 @@ void print_all_devices_pt(struct fdisk_context *cxt, int verify)
        }
 }
 
+/* usable for example in usage() */
+void list_available_columns(FILE *out)
+{
+       size_t i;
+       int termwidth;
+       struct fdisk_label *lb = NULL;
+       struct fdisk_context *cxt = fdisk_new_context();
+
+       if (!cxt)
+               return;
+
+       termwidth = get_terminal_width();
+       if (termwidth <= 0)
+               termwidth = 80;
+
+       fprintf(out, _("\nAvailable columns: (for -o)\n"));
+
+       while (fdisk_next_label(cxt, &lb) == 0) {
+               size_t width = 6;       /* label name and separators */
+
+               fprintf(out, " %s:", fdisk_label_get_name(lb));
+               for (i = 1; i < FDISK_NFIELDS; i++) {
+                       const struct fdisk_field *fl = fdisk_label_get_field(lb, i);
+                       const char *name = fl ? fdisk_field_get_name(fl) : NULL;
+                       size_t len;
+
+                       if (!name)
+                               continue;
+                       len = strlen(name) + 1;
+                       if (width + len > (size_t) termwidth) {
+                               fputs("\n     ", out);
+                               width = 6;
+                       }
+                       fprintf(out, " %s", name);
+                       width += len;
+               }
+               fputc('\n', out);
+       }
+
+       fdisk_unref_context(cxt);
+}
+
+static int fieldname_to_id(const char *name, size_t namesz)
+{
+       const struct fdisk_field *fl;
+       char buf[namesz + 1];
+
+       assert(name);
+       assert(namesz);
+       assert(fields_label);
+
+       memcpy(buf, name, namesz);
+       buf[namesz] = '\0';
+
+       fl = fdisk_label_get_field_by_name(fields_label, buf);
+       if (!fl) {
+               warnx(_("%s unknown column: %s"),
+                               fdisk_label_get_name(fields_label), buf);
+               return -1;
+       }
+       return fdisk_field_get_id(fl);
+}
+
+/*
+ * Initialize array with output columns (fields_ids[]) according to
+ * comma delimited list of columns (@str). If the list string is not
+ * defined then use library defaults. This function is "-o <list>"
+ * backend.
+ *
+ * If the columns are already initialized then returns already existing columns.
+ */
+int *init_fields(struct fdisk_context *cxt, const char *str, size_t *n)
+{
+       int *dflt_ids = NULL;
+
+       if (!fields_string)
+               fields_string = str;
+
+       if (!cxt || fields_nids)
+               goto done;
+
+       fields_label = fdisk_get_label(cxt, NULL);
+       if (!fields_label)
+               goto done;
+
+       /* library default */
+       if (fdisk_label_get_fields_ids(NULL, cxt, &dflt_ids, &fields_nids))
+               goto done;
+
+       fields_ids = xcalloc(sizeof(int), FDISK_NFIELDS * 2);
+
+       /* copy defaults to the list with wanted fields */
+       memcpy(fields_ids, dflt_ids, fields_nids * sizeof(int));
+       free(dflt_ids);
+
+       /* extend or replace fields_nids[] according to fields_string */
+       if (fields_string &&
+           string_add_to_idarray(fields_string, fields_ids, FDISK_NFIELDS * 2,
+                             (int *) &fields_nids, fieldname_to_id) < 0)
+               exit(EXIT_FAILURE);
+done:
+       fields_label = NULL;
+       if (n)
+               *n = fields_nids;
+       return fields_ids;
+}
+
index 0a6ff734c91ab981bb8a9fb06d129bebecec47a2..9dbdbadd15610d4ffccf02569ce529ca17403e00 100644 (file)
@@ -8,4 +8,7 @@ extern char *next_proc_partition(FILE **f);
 extern int print_device_pt(struct fdisk_context *cxt, char *device, int warnme, int verify);
 extern void print_all_devices_pt(struct fdisk_context *cxt, int verify);
 
+extern void list_available_columns(FILE *out);
+extern int *init_fields(struct fdisk_context *cxt, const char *str, size_t *n);
+
 #endif /* UTIL_LINUX_FDISK_LIST_H */
index 1da15d903428d9437e45af83919c549b63e4d8ed..2ee5f6448343f0b1167e11d84364338bd9082513 100644 (file)
@@ -73,6 +73,14 @@ If no devices are given, those mentioned in
 .I /proc/partitions
 (if that file exists) are used.
 .TP
+.BR \-o , " \-\-output " \fIlist\fP
+Specify which output columns to print.  Use
+.B \-\-help
+to get a list of all supported columns.
+
+The default list of columns may be extended if \fIlist\fP is
+specified in the format \fI+list\fP (e.g. \fB-o +UUID\fP).
+.TP
 \fB\-s\fR, \fB\-\-getsz\fR
 Print the size in 512-byte sectors of each given block device.  This option is DEPRECATED
 in favour of
index b7063b81d6eeac6e925a634127e16677c73a5953..ee4dd6c615658011e93e2e88697a826804564b35 100644 (file)
@@ -654,6 +654,8 @@ static void __attribute__ ((__noreturn__)) usage(FILE *out)
        fputs(USAGE_HELP, out);
        fputs(USAGE_VERSION, out);
 
+       list_available_columns(out);
+
        fprintf(out, USAGE_MAN_TAIL("fdisk(8)"));
        exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
 }
@@ -670,6 +672,7 @@ int main(int argc, char **argv)
        int rc, i, c, act = ACT_FDISK;
        int colormode = UL_COLORMODE_UNDEF;
        struct fdisk_context *cxt;
+       char *outarg = NULL;
 
        static const struct option longopts[] = {
                { "color",          optional_argument, NULL, 'L' },
@@ -701,7 +704,7 @@ int main(int argc, char **argv)
 
        fdisk_set_ask(cxt, ask_callback, NULL);
 
-       while ((c = getopt_long(argc, argv, "b:c::C:hH:lL::sS:t:u::vV",
+       while ((c = getopt_long(argc, argv, "b:c::C:hH:lL::o:sS:t:u::vV",
                                longopts, NULL)) != -1) {
                switch (c) {
                case 'b':
@@ -759,6 +762,9 @@ int main(int argc, char **argv)
                                colormode = colormode_or_err(optarg,
                                                _("unsupported color mode"));
                        break;
+               case 'o':
+                       outarg = optarg;
+                       break;
                case 's':
                        act = ACT_SHOWSIZE;
                        break;
@@ -800,6 +806,7 @@ int main(int argc, char **argv)
        switch (act) {
        case ACT_LIST:
                fdisk_enable_listonly(cxt, 1);
+               init_fields(cxt, outarg, NULL);
 
                if (argc > optind) {
                        int k;
@@ -853,6 +860,8 @@ int main(int argc, char **argv)
                                  "A hybrid GPT was detected. You have to sync "
                                  "the hybrid MBR manually (expert command 'M')."));
 
+               init_fields(cxt, outarg, NULL);         /* -o <columns> */
+
                while (1)
                        process_fdisk_menu(&cxt);
        }