summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak2014-10-03 12:40:04 +0200
committerKarel Zak2014-10-07 14:55:32 +0200
commitfff8ad5882308825a131c645e4d28bcaef943351 (patch)
tree93c86191fb81b0787a01628bce9ffef1eeb1fba6
parentlibfdisk: add fdisk_label_get_field_by_name() and const for labels (diff)
downloadkernel-qcow2-util-linux-fff8ad5882308825a131c645e4d28bcaef943351.tar.gz
kernel-qcow2-util-linux-fff8ad5882308825a131c645e4d28bcaef943351.tar.xz
kernel-qcow2-util-linux-fff8ad5882308825a131c645e4d28bcaef943351.zip
fdisk: add --output <list> for print command(s)
Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--disk-utils/fdisk-list.c118
-rw-r--r--disk-utils/fdisk-list.h3
-rw-r--r--disk-utils/fdisk.88
-rw-r--r--disk-utils/fdisk.c11
4 files changed, 137 insertions, 3 deletions
diff --git a/disk-utils/fdisk-list.c b/disk-utils/fdisk-list.c
index 708e6939a..42dfda8cb 100644
--- a/disk-utils/fdisk-list.c
+++ b/disk-utils/fdisk-list.c
@@ -12,9 +12,16 @@
#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;
+}
+
diff --git a/disk-utils/fdisk-list.h b/disk-utils/fdisk-list.h
index 0a6ff734c..9dbdbadd1 100644
--- a/disk-utils/fdisk-list.h
+++ b/disk-utils/fdisk-list.h
@@ -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 */
diff --git a/disk-utils/fdisk.8 b/disk-utils/fdisk.8
index 1da15d903..2ee5f6448 100644
--- a/disk-utils/fdisk.8
+++ b/disk-utils/fdisk.8
@@ -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
diff --git a/disk-utils/fdisk.c b/disk-utils/fdisk.c
index b7063b81d..ee4dd6c61 100644
--- a/disk-utils/fdisk.c
+++ b/disk-utils/fdisk.c
@@ -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);
}