From 41715771b5de07cbfcb1f7b75f324e824dfa1728 Mon Sep 17 00:00:00 2001 From: Mohamed Tawfik Date: Tue, 8 Nov 2022 20:08:21 +0200 Subject: [PATCH] Adds the `-p` option to `zfs holds` This allows for printing a machine-readable, accurate to the second, hold creation time in the form of a unix epoch timestamp. Additionally, updates relevant documentation and man pages accordingly. Reviewed-by: Allan Jude Reviewed-by: Brian Behlendorf Signed-off-by: Mohamed Tawfik Closes #13690 Closes #14152 --- cmd/zfs/zfs_main.c | 37 ++++++++++++++++++++++++++++--------- man/man8/zfs-hold.8 | 6 ++++-- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index bdbd0bfc6..6e79a73b9 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -392,7 +392,7 @@ get_usage(zfs_help_t idx) case HELP_HOLD: return (gettext("\thold [-r] ...\n")); case HELP_HOLDS: - return (gettext("\tholds [-rH] ...\n")); + return (gettext("\tholds [-rHp] ...\n")); case HELP_RELEASE: return (gettext("\trelease [-r] ...\n")); case HELP_DIFF: @@ -6456,7 +6456,8 @@ typedef struct holds_cbdata { * */ static void -print_holds(boolean_t scripted, int nwidth, int tagwidth, nvlist_t *nvl) +print_holds(boolean_t scripted, int nwidth, int tagwidth, nvlist_t *nvl, + boolean_t parsable) { int i; nvpair_t *nvp = NULL; @@ -6493,11 +6494,23 @@ print_holds(boolean_t scripted, int nwidth, int tagwidth, nvlist_t *nvl) gettext(STRFTIME_FMT_STR), &t); if (scripted) { - (void) printf("%s\t%s\t%s\n", zname, - tagname, tsbuf); + if (parsable) { + (void) printf("%s\t%s\t%ld\n", zname, + tagname, time); + } else { + (void) printf("%s\t%s\t%s\n", zname, + tagname, tsbuf); + } } else { - (void) printf("%-*s %-*s %s\n", nwidth, - zname, tagwidth, tagname, tsbuf); + if (parsable) { + (void) printf("%-*s %-*s %ld\n", + nwidth, zname, tagwidth, + tagname, time); + } else { + (void) printf("%-*s %-*s %s\n", + nwidth, zname, tagwidth, + tagname, tsbuf); + } } } } @@ -6544,10 +6557,11 @@ holds_callback(zfs_handle_t *zhp, void *data) } /* - * zfs holds [-rH] ... + * zfs holds [-rHp] ... * * -r Lists holds that are set on the named snapshots recursively. * -H Scripted mode; elide headers and separate columns by tabs. + * -p Display values in parsable (literal) format. */ static int zfs_do_holds(int argc, char **argv) @@ -6556,6 +6570,7 @@ zfs_do_holds(int argc, char **argv) boolean_t errors = B_FALSE; boolean_t scripted = B_FALSE; boolean_t recursive = B_FALSE; + boolean_t parsable = B_FALSE; int types = ZFS_TYPE_SNAPSHOT; holds_cbdata_t cb = { 0 }; @@ -6565,7 +6580,7 @@ zfs_do_holds(int argc, char **argv) int flags = 0; /* check options */ - while ((c = getopt(argc, argv, "rH")) != -1) { + while ((c = getopt(argc, argv, "rHp")) != -1) { switch (c) { case 'r': recursive = B_TRUE; @@ -6573,6 +6588,9 @@ zfs_do_holds(int argc, char **argv) case 'H': scripted = B_TRUE; break; + case 'p': + parsable = B_TRUE; + break; case '?': (void) fprintf(stderr, gettext("invalid option '%c'\n"), optopt); @@ -6626,7 +6644,8 @@ zfs_do_holds(int argc, char **argv) /* * 2. print holds data */ - print_holds(scripted, cb.cb_max_namelen, cb.cb_max_taglen, nvl); + print_holds(scripted, cb.cb_max_namelen, cb.cb_max_taglen, nvl, + parsable); if (nvlist_empty(nvl)) (void) fprintf(stderr, gettext("no datasets available\n")); diff --git a/man/man8/zfs-hold.8 b/man/man8/zfs-hold.8 index c2c7b7dc2..4bc36cb47 100644 --- a/man/man8/zfs-hold.8 +++ b/man/man8/zfs-hold.8 @@ -43,7 +43,7 @@ .Ar tag Ar snapshot Ns … .Nm zfs .Cm holds -.Op Fl rH +.Op Fl rHp .Ar snapshot Ns … .Nm zfs .Cm release @@ -76,7 +76,7 @@ of all descendent file systems. .It Xo .Nm zfs .Cm holds -.Op Fl rH +.Op Fl rHp .Ar snapshot Ns … .Xc Lists all existing user references for the given snapshot or snapshots. @@ -86,6 +86,8 @@ Lists the holds that are set on the named descendent snapshots, in addition to listing the holds on the named snapshot. .It Fl H Do not print headers, use tab-delimited output. +.It Fl p +Prints holds timestamps as unix epoch timestamps. .El .It Xo .Nm zfs