summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorBryan Cantrill <bryan@joyent.com>2017-07-14 18:27:31 +0000
committerRobert Mustacchi <rm@joyent.com>2017-09-25 18:48:01 +0000
commitb2f2652061ea587b1b2b4e246659e1d7e7313f42 (patch)
tree163a3b75f1ea2b41537a1913ff506dbc309c8378 /usr/src
parent745cad278f6b2e392001dd1bf6b4e95d3f250a8d (diff)
downloadillumos-gate-b2f2652061ea587b1b2b4e246659e1d7e7313f42.tar.gz
8507 dladm show-link segfaults if you specify too many fields
Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Ryan Zezeski <ryan.zeseski@joyent.com> Reviewed by: Yuri Pankov <yuripv@gmx.com> Approved by: Richard Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c38
-rw-r--r--usr/src/cmd/dladm/dladm.c56
-rw-r--r--usr/src/cmd/dlstat/dlstat.c39
-rw-r--r--usr/src/cmd/flowadm/flowadm.c32
-rw-r--r--usr/src/cmd/flowstat/flowstat.c32
-rw-r--r--usr/src/lib/libofmt/common/mapfile-vers2
-rw-r--r--usr/src/lib/libofmt/common/ofmt.c94
-rw-r--r--usr/src/lib/libofmt/common/ofmt.h8
8 files changed, 126 insertions, 175 deletions
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c b/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c
index 14f8a70c72..23d665cec1 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2017 Nexenta Systems, Inc.
+ * Copyright 2017 Joyent, Inc.
* Copyright 2017 Gary Mills
* Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
*/
@@ -65,6 +66,9 @@ static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr;
static cmdfunc_t do_enable_addr, do_disable_addr;
static cmdfunc_t do_up_addr, do_down_addr, do_refresh_addr;
+static void warn(const char *, ...);
+static void die(const char *, ...);
+
typedef struct cmd {
char *c_name;
cmdfunc_t *c_fn;
@@ -339,7 +343,6 @@ static char *progname;
static void die(const char *, ...);
static void die_opterr(int, int, const char *);
static void warn_ipadmerr(ipadm_status_t, const char *, ...);
-static void ipadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
static void ipadm_check_propstr(const char *, boolean_t, const char *);
static void process_misc_addrargs(int, char **, const char *, int *,
uint32_t *);
@@ -727,7 +730,7 @@ do_show_ifprop(int argc, char **argv, const char *use)
if (state.sps_parsable)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, intfprop_fields, ofmtflags, 0, &ofmt);
- ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
+ ofmt_check(oferr, state.sps_parsable, ofmt, die, warn);
state.sps_ofmt = ofmt;
/* retrieve interface(s) and print the properties */
@@ -906,7 +909,7 @@ do_show_prop(int argc, char **argv, const char *use)
else
ofmtflags |= OFMT_WRAP;
oferr = ofmt_open(fields_str, modprop_fields, ofmtflags, 0, &ofmt);
- ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
+ ofmt_check(oferr, state.sps_parsable, ofmt, die, warn);
state.sps_ofmt = ofmt;
/* handles all the errors */
@@ -1851,7 +1854,7 @@ do_show_addr(int argc, char *argv[], const char *use)
fields_str = def_fields_str;
oferr = ofmt_open(fields_str, show_addr_fields, ofmtflags, 0, &ofmt);
- ipadm_ofmt_check(oferr, state.sa_parsable, ofmt);
+ ofmt_check(oferr, state.sa_parsable, ofmt, die, warn);
state.sa_ofmt = ofmt;
status = ipadm_addr_info(iph, ifname, &ainfo, 0, LIFC_DEFAULT);
@@ -1986,7 +1989,7 @@ do_show_if(int argc, char *argv[], const char *use)
if (state.si_parsable)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, show_if_fields, ofmtflags, 0, &ofmt);
- ipadm_ofmt_check(oferr, state.si_parsable, ofmt);
+ ofmt_check(oferr, state.si_parsable, ofmt, die, warn);
state.si_ofmt = ofmt;
bzero(&sargs, sizeof (sargs));
sargs.si_state = &state;
@@ -2144,7 +2147,7 @@ do_show_addrprop(int argc, char *argv[], const char *use)
if (state.sps_parsable)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, addrprop_fields, ofmtflags, 0, &ofmt);
- ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
+ ofmt_check(oferr, state.sps_parsable, ofmt, die, warn);
state.sps_ofmt = ofmt;
status = ipadm_addr_info(iph, ifname, &ainfop, 0, LIFC_DEFAULT);
@@ -2190,29 +2193,6 @@ do_show_addrprop(int argc, char *argv[], const char *use)
}
}
-static void
-ipadm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
- ofmt_handle_t ofmt)
-{
- char buf[OFMT_BUFSIZE];
-
- if (oferr == OFMT_SUCCESS)
- return;
- (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
- /*
- * All errors are considered fatal in parsable mode.
- * NOMEM errors are always fatal, regardless of mode.
- * For other errors, we print diagnostics in human-readable
- * mode and processs what we can.
- */
- if (parsable || oferr == OFMT_ENOFIELDS) {
- ofmt_close(ofmt);
- die(buf);
- } else {
- warn(buf);
- }
-}
-
/*
* check if the `pstr' adheres to following syntax
* - prop=<value[,...]> (for set)
diff --git a/usr/src/cmd/dladm/dladm.c b/usr/src/cmd/dladm/dladm.c
index d5b3bd0951..8678c0939e 100644
--- a/usr/src/cmd/dladm/dladm.c
+++ b/usr/src/cmd/dladm/dladm.c
@@ -194,7 +194,6 @@ static ofmt_cb_t print_lacp_cb, print_phys_one_mac_cb;
static ofmt_cb_t print_xaggr_cb, print_aggr_stats_cb;
static ofmt_cb_t print_phys_one_hwgrp_cb, print_wlan_attr_cb;
static ofmt_cb_t print_wifi_status_cb, print_link_attr_cb;
-static void dladm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
typedef void cmdfunc_t(int, char **, const char *);
@@ -1754,7 +1753,7 @@ do_show_usage(int argc, char *argv[], const char *use)
&ofmt);
}
- dladm_ofmt_check(oferr, state.us_parsable, ofmt);
+ ofmt_check(oferr, state.us_parsable, ofmt, die, warn);
state.us_ofmt = ofmt;
if (d_arg) {
@@ -3507,7 +3506,7 @@ do_show_link(int argc, char *argv[], const char *use)
ofmtflags |= OFMT_WRAP;
oferr = ofmt_open(fields_str, link_fields, ofmtflags, 0, &ofmt);
- dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
+ ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
state.ls_ofmt = ofmt;
if (linkid == DATALINK_ALL_LINKID) {
@@ -3673,7 +3672,7 @@ do_show_aggr(int argc, char *argv[], const char *use)
if (state.gs_parsable)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
- dladm_ofmt_check(oferr, state.gs_parsable, ofmt);
+ ofmt_check(oferr, state.gs_parsable, ofmt, die, warn);
state.gs_ofmt = ofmt;
if (s_arg) {
@@ -4143,7 +4142,7 @@ do_show_iptun(int argc, char *argv[], const char *use)
oferr = ofmt_open(fields_str, iptun_fields, ofmtflags,
DLADM_DEFAULT_COL, &ofmt);
- dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
+ ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
state.ls_ofmt = ofmt;
state.ls_flags = flags;
@@ -4508,7 +4507,7 @@ do_show_phys(int argc, char *argv[], const char *use)
if (state.ls_parsable)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
- dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
+ ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
state.ls_ofmt = ofmt;
if (linkid == DATALINK_ALL_LINKID) {
@@ -4587,7 +4586,7 @@ do_show_vlan(int argc, char *argv[], const char *use)
if (state.ls_parsable)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, vlan_fields, ofmtflags, 0, &ofmt);
- dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
+ ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
state.ls_ofmt = ofmt;
if (linkid == DATALINK_ALL_LINKID) {
@@ -5204,7 +5203,7 @@ do_show_vnic_common(int argc, char *argv[], const char *use,
if (state.vs_parsable)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
- dladm_ofmt_check(oferr, state.vs_parsable, ofmt);
+ ofmt_check(oferr, state.vs_parsable, ofmt, die, warn);
state.vs_ofmt = ofmt;
if (s_arg) {
@@ -5589,7 +5588,7 @@ do_show_simnet(int argc, char *argv[], const char *use)
if (state.ls_parsable)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, simnet_fields, ofmtflags, 0, &ofmt);
- dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
+ ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
state.ls_ofmt = ofmt;
if (linkid == DATALINK_ALL_LINKID) {
@@ -5617,7 +5616,7 @@ link_stats(datalink_id_t linkid, uint_t interval, char *fields_str,
if (state->ls_parsable)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, link_s_fields, ofmtflags, 0, &ofmt);
- dladm_ofmt_check(oferr, state->ls_parsable, ofmt);
+ ofmt_check(oferr, state->ls_parsable, ofmt, die, warn);
state->ls_ofmt = ofmt;
/*
@@ -5928,7 +5927,7 @@ parse_wifi_fields(char *str, ofmt_handle_t *ofmt, uint_t cmdtype,
oferr = ofmt_open(str, template, (parsable ? OFMT_PARSABLE : 0),
0, ofmt);
- dladm_ofmt_check(oferr, parsable, *ofmt);
+ ofmt_check(oferr, parsable, *ofmt, die, warn);
return (0);
}
@@ -6738,7 +6737,7 @@ do_show_linkprop(int argc, char **argv, const char *use)
ofmtflags |= OFMT_WRAP;
oferr = ofmt_open(fields_str, linkprop_fields, ofmtflags, 0, &ofmt);
- dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
+ ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
state.ls_ofmt = ofmt;
if (linkid == DATALINK_ALL_LINKID) {
@@ -7509,7 +7508,7 @@ do_show_secobj(int argc, char **argv, const char *use)
if (state.ss_parsable)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, secobj_fields, ofmtflags, 0, &ofmt);
- dladm_ofmt_check(oferr, state.ss_parsable, ofmt);
+ ofmt_check(oferr, state.ss_parsable, ofmt, die, warn);
state.ss_ofmt = ofmt;
flags = state.ss_persist ? DLADM_OPT_PERSIST : 0;
@@ -7641,7 +7640,7 @@ do_show_ether(int argc, char **argv, const char *use)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, ether_fields, ofmtflags,
DLADM_DEFAULT_COL, &ofmt);
- dladm_ofmt_check(oferr, state.es_parsable, ofmt);
+ ofmt_check(oferr, state.es_parsable, ofmt, die, warn);
state.es_ofmt = ofmt;
if (state.es_link == NULL) {
@@ -8715,7 +8714,7 @@ do_show_bridge(int argc, char **argv, const char *use)
if (parsable)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, field_arr, ofmtflags, 0, &ofmt);
- dladm_ofmt_check(oferr, brstate.state.ls_parsable, ofmt);
+ ofmt_check(oferr, brstate.state.ls_parsable, ofmt, die, warn);
brstate.state.ls_ofmt = ofmt;
for (;;) {
@@ -9043,29 +9042,6 @@ print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
return (B_TRUE);
}
-static void
-dladm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
- ofmt_handle_t ofmt)
-{
- char buf[OFMT_BUFSIZE];
-
- if (oferr == OFMT_SUCCESS)
- return;
- (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
- /*
- * All errors are considered fatal in parsable mode.
- * NOMEM errors are always fatal, regardless of mode.
- * For other errors, we print diagnostics in human-readable
- * mode and processs what we can.
- */
- if (parsable || oferr == OFMT_ENOFIELDS) {
- ofmt_close(ofmt);
- die(buf);
- } else {
- warn(buf);
- }
-}
-
/*
* Called from the walker dladm_walk_datalink_id() for each IB partition to
* display IB partition specific information.
@@ -9263,7 +9239,7 @@ do_show_part(int argc, char *argv[], const char *use)
if (state.ps_parsable)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, part_fields, ofmtflags, 0, &ofmt);
- dladm_ofmt_check(oferr, state.ps_parsable, ofmt);
+ ofmt_check(oferr, state.ps_parsable, ofmt, die, warn);
state.ps_ofmt = ofmt;
/*
@@ -9435,7 +9411,7 @@ do_show_ib(int argc, char *argv[], const char *use)
if (state.is_parsable)
ofmtflags |= OFMT_PARSABLE;
oferr = ofmt_open(fields_str, ib_fields, ofmtflags, 0, &ofmt);
- dladm_ofmt_check(oferr, state.is_parsable, ofmt);
+ ofmt_check(oferr, state.is_parsable, ofmt, die, warn);
state.is_ofmt = ofmt;
/*
diff --git a/usr/src/cmd/dlstat/dlstat.c b/usr/src/cmd/dlstat/dlstat.c
index a931ba82ff..63e844a895 100644
--- a/usr/src/cmd/dlstat/dlstat.c
+++ b/usr/src/cmd/dlstat/dlstat.c
@@ -23,6 +23,10 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright 2017 Joyent, Inc.
+ */
+
#include <stdio.h>
#include <ctype.h>
#include <locale.h>
@@ -88,8 +92,6 @@ typedef struct show_history_state_s {
*/
static ofmt_cb_t print_default_cb;
-static void dlstat_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
-
typedef void cmdfunc_t(int, char **, const char *);
static cmdfunc_t do_show, do_show_history, do_show_phys, do_show_link;
@@ -779,7 +781,7 @@ do_show_history(int argc, char *argv[], const char *use)
&ofmt);
}
- dlstat_ofmt_check(oferr, state.hs_parsable, ofmt);
+ ofmt_check(oferr, state.hs_parsable, ofmt, die, warn);
state.hs_ofmt = ofmt;
if (d_arg) {
@@ -1800,7 +1802,7 @@ do_show(int argc, char *argv[], const char *use)
}
oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
- dlstat_ofmt_check(oferr, state.ls_parsable, ofmt);
+ ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
state.ls_ofmt = ofmt;
show_link_stats(linkid, state, interval);
@@ -1979,7 +1981,7 @@ do_show_phys(int argc, char *argv[], const char *use)
}
oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
- dlstat_ofmt_check(oferr, state.ls_parsable, ofmt);
+ ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
state.ls_ofmt = ofmt;
show_link_stats(linkid, state, interval);
@@ -2189,7 +2191,7 @@ do_show_link(int argc, char *argv[], const char *use)
}
oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
- dlstat_ofmt_check(oferr, state.ls_parsable, ofmt);
+ ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
state.ls_ofmt = ofmt;
@@ -2326,7 +2328,7 @@ do_show_aggr(int argc, char *argv[], const char *use)
}
oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
- dlstat_ofmt_check(oferr, state.ls_parsable, ofmt);
+ ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
state.ls_ofmt = ofmt;
show_link_stats(linkid, state, interval);
@@ -2432,26 +2434,3 @@ print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
(void) strlcpy(buf, value, bufsize);
return (B_TRUE);
}
-
-static void
-dlstat_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
- ofmt_handle_t ofmt)
-{
- char buf[OFMT_BUFSIZE];
-
- if (oferr == OFMT_SUCCESS)
- return;
- (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
- /*
- * All errors are considered fatal in parsable mode.
- * NOMEM errors are always fatal, regardless of mode.
- * For other errors, we print diagnostics in human-readable
- * mode and processs what we can.
- */
- if (parsable || oferr == OFMT_ENOFIELDS) {
- ofmt_close(ofmt);
- die(buf);
- } else {
- warn(buf);
- }
-}
diff --git a/usr/src/cmd/flowadm/flowadm.c b/usr/src/cmd/flowadm/flowadm.c
index 374fa1675c..058c1e03d8 100644
--- a/usr/src/cmd/flowadm/flowadm.c
+++ b/usr/src/cmd/flowadm/flowadm.c
@@ -23,6 +23,10 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright 2017 Joyent, Inc.
+ */
+
#include <stdio.h>
#include <locale.h>
#include <stdarg.h>
@@ -81,7 +85,6 @@ static void warn_dlerr(dladm_status_t, const char *, ...);
/* callback functions for printing output */
static ofmt_cb_t print_flowprop_cb, print_default_cb;
-static void flowadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
typedef struct cmd {
char *c_name;
@@ -642,7 +645,7 @@ do_show_flow(int argc, char *argv[])
}
oferr = ofmt_open(fields_str, flow_fields, ofmtflags, 0, &ofmt);
- flowadm_ofmt_check(oferr, state.fs_parsable, ofmt);
+ ofmt_check(oferr, state.fs_parsable, ofmt, die, warn);
state.fs_ofmt = ofmt;
/* Show attributes of one flow */
@@ -1186,7 +1189,7 @@ do_show_flowprop(int argc, char **argv)
state.fs_status = DLADM_STATUS_OK;
oferr = ofmt_open(fields_str, flowprop_fields, ofmtflags, 0, &ofmt);
- flowadm_ofmt_check(oferr, state.fs_parsable, ofmt);
+ ofmt_check(oferr, state.fs_parsable, ofmt, die, warn);
state.fs_ofmt = ofmt;
/* Show properties for one flow */
@@ -1277,26 +1280,3 @@ print_default_cb(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
(void) strlcpy(buf, value, bufsize);
return (B_TRUE);
}
-
-static void
-flowadm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
- ofmt_handle_t ofmt)
-{
- char buf[OFMT_BUFSIZE];
-
- if (oferr == OFMT_SUCCESS)
- return;
- (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
- /*
- * All errors are considered fatal in parsable mode.
- * NOMEM errors are always fatal, regardless of mode.
- * For other errors, we print diagnostics in human-readable
- * mode and processs what we can.
- */
- if (parsable || oferr == OFMT_ENOFIELDS) {
- ofmt_close(ofmt);
- die(buf);
- } else {
- warn(buf);
- }
-}
diff --git a/usr/src/cmd/flowstat/flowstat.c b/usr/src/cmd/flowstat/flowstat.c
index 1f8c65c957..757fcb5149 100644
--- a/usr/src/cmd/flowstat/flowstat.c
+++ b/usr/src/cmd/flowstat/flowstat.c
@@ -23,6 +23,10 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright 2017 Joyent, Inc.
+ */
+
#include <stdio.h>
#include <locale.h>
#include <stdarg.h>
@@ -86,7 +90,6 @@ static void warn(const char *, ...);
/* callback functions for printing output */
static ofmt_cb_t print_default_cb, print_flow_stats_cb;
-static void flowstat_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
#define NULL_OFMT {NULL, 0, 0, NULL}
@@ -710,7 +713,7 @@ main(int argc, char *argv[])
}
oferr = ofmt_open(fields_str, flow_s_fields, ofmtflags, 0, &ofmt);
- flowstat_ofmt_check(oferr, state.fs_parsable, ofmt);
+ ofmt_check(oferr, state.fs_parsable, ofmt, die, warn);
state.fs_ofmt = ofmt;
for (;;) {
@@ -978,7 +981,7 @@ do_show_history(int argc, char *argv[])
0, &ofmt);
}
- flowstat_ofmt_check(oferr, state.us_parsable, ofmt);
+ ofmt_check(oferr, state.us_parsable, ofmt, die, warn);
state.us_ofmt = ofmt;
if (F_arg && d_arg)
@@ -1107,26 +1110,3 @@ print_default_cb(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
(void) strlcpy(buf, value, bufsize);
return (B_TRUE);
}
-
-static void
-flowstat_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
- ofmt_handle_t ofmt)
-{
- char buf[OFMT_BUFSIZE];
-
- if (oferr == OFMT_SUCCESS)
- return;
- (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
- /*
- * All errors are considered fatal in parsable mode.
- * NOMEM errors are always fatal, regardless of mode.
- * For other errors, we print diagnostics in human-readable
- * mode and processs what we can.
- */
- if (parsable || oferr == OFMT_ENOFIELDS) {
- ofmt_close(ofmt);
- die(buf);
- } else {
- warn(buf);
- }
-}
diff --git a/usr/src/lib/libofmt/common/mapfile-vers b/usr/src/lib/libofmt/common/mapfile-vers
index b2a87b3ecc..fa94086eb6 100644
--- a/usr/src/lib/libofmt/common/mapfile-vers
+++ b/usr/src/lib/libofmt/common/mapfile-vers
@@ -11,6 +11,7 @@
#
# Copyright 2017 Nexenta Systems, Inc.
+# Copyright 2017 Joyent, Inc.
#
#
@@ -36,6 +37,7 @@ SYMBOL_VERSION ILLUMOSprivate {
ofmt_print;
ofmt_strerror;
ofmt_update_winsize;
+ ofmt_check;
local:
*;
diff --git a/usr/src/lib/libofmt/common/ofmt.c b/usr/src/lib/libofmt/common/ofmt.c
index bab3da7311..27765b0430 100644
--- a/usr/src/lib/libofmt/common/ofmt.c
+++ b/usr/src/lib/libofmt/common/ofmt.c
@@ -23,6 +23,11 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+
+/*
+ * Copyright 2017 Joyent, Inc.
+ */
+
#include <errno.h>
#include <sys/types.h>
#include <stdlib.h>
@@ -34,6 +39,7 @@
#include <unistd.h>
#include <sys/sysmacros.h>
#include <libintl.h>
+#include <assert.h>
/*
* functions and structures to internally process a comma-separated string
@@ -45,9 +51,8 @@ typedef struct {
uint_t s_nfields; /* the number of fields in s_buf */
uint_t s_currfield; /* the current field being processed */
} split_t;
+
static void splitfree(split_t *);
-static split_t *split_str(const char *, uint_t);
-static split_t *split_fields(const ofmt_field_t *, uint_t, uint_t);
/*
* The state of the output is tracked in a ofmt_state_t structure.
@@ -122,26 +127,30 @@ fail:
}
/*
- * Split `fields' into at most `maxfields' fields. Return a pointer to
- * a split_t containing the split fields, or NULL on failure. Invoked
- * when all fields are implicitly selected at handle creation by
- * passing in a NULL fields_str
+ * Split a template into its maximum number of fields (capped by the maxcols
+ * if it's non-zero). Return a pointer to a split_t containing the split
+ * fields, or NULL on failure. Invoked when all fields are implicitly
+ * selected at handle creation.
*/
static split_t *
-split_fields(const ofmt_field_t *template, uint_t maxfields, uint_t maxcols)
+split_max(const ofmt_field_t *template, uint_t maxcols)
{
+ const ofmt_field_t *ofp;
split_t *sp;
- int i, cols;
+ int i, cols, nfields = 0;
sp = calloc(sizeof (split_t), 1);
if (sp == NULL)
return (NULL);
- sp->s_fields = malloc(sizeof (char *) * maxfields);
+ for (ofp = template; ofp->of_name != NULL; ofp++)
+ nfields++;
+
+ sp->s_fields = malloc(sizeof (char *) * nfields);
if (sp->s_fields == NULL)
goto fail;
cols = 0;
- for (i = 0; i < maxfields; i++) {
+ for (i = 0; i < nfields; i++) {
cols += template[i].of_width;
/*
* If all fields are implied without explicitly passing
@@ -179,11 +188,10 @@ ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags,
uint_t maxcols, ofmt_handle_t *ofmt)
{
split_t *sp;
- uint_t i, j, of_index;
+ uint_t i, of_index;
const ofmt_field_t *ofp;
ofmt_field_t *of;
ofmt_state_t *os = NULL;
- int nfields = 0;
ofmt_status_t error = OFMT_SUCCESS;
boolean_t parsable = (flags & OFMT_PARSABLE);
boolean_t wrap = (flags & OFMT_WRAP);
@@ -207,18 +215,29 @@ ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags,
}
if (template == NULL)
return (OFMT_ENOTEMPLATE);
- for (ofp = template; ofp->of_name != NULL; ofp++)
- nfields++;
+
/*
* split str into the columns selected, or construct the
* full set of columns (equivalent to -o all).
*/
if (str != NULL && strcasecmp(str, "all") != 0) {
+ const char *c;
+ int nfields = 1;
+
+ /*
+ * Get an upper bound on the number of fields by counting
+ * the commas.
+ */
+ for (c = str; *c != '\0'; c++) {
+ if (*c == ',')
+ nfields++;
+ }
+
sp = split_str(str, nfields);
} else {
if (parsable || (str != NULL && strcasecmp(str, "all") == 0))
maxcols = 0;
- sp = split_fields(template, nfields, maxcols);
+ sp = split_max(template, maxcols);
}
if (sp == NULL)
goto nomem;
@@ -238,13 +257,12 @@ ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags,
* nfields is the number of fields in template.
*/
for (i = 0; i < sp->s_nfields; i++) {
- for (j = 0; j < nfields; j++) {
- if (strcasecmp(sp->s_fields[i],
- template[j].of_name) == 0) {
+ for (ofp = template; ofp->of_name != NULL; ofp++) {
+ if (strcasecmp(sp->s_fields[i], ofp->of_name) == 0)
break;
- }
}
- if (j == nfields) {
+
+ if (ofp->of_name == NULL) {
int nbad = os->os_nbad++;
error = OFMT_EBADFIELDS;
@@ -259,7 +277,7 @@ ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags,
goto nomem;
continue;
}
- of[of_index].of_name = strdup(template[j].of_name);
+ of[of_index].of_name = strdup(ofp->of_name);
if (of[of_index].of_name == NULL)
goto nomem;
if (multiline) {
@@ -267,9 +285,9 @@ ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags,
os->os_maxnamelen = MAX(n, os->os_maxnamelen);
}
- of[of_index].of_width = template[j].of_width;
- of[of_index].of_id = template[j].of_id;
- of[of_index].of_cb = template[j].of_cb;
+ of[of_index].of_width = ofp->of_width;
+ of[of_index].of_id = ofp->of_id;
+ of[of_index].of_cb = ofp->of_cb;
of_index++;
}
splitfree(sp);
@@ -612,3 +630,31 @@ ofmt_strerror(ofmt_handle_t ofmt, ofmt_status_t error, char *buf,
(void) strlcat(buf, ebuf, bufsize);
return (buf);
}
+
+void
+ofmt_check(ofmt_status_t oferr, boolean_t parsable, ofmt_handle_t ofmt,
+ void (*die)(const char *, ...), void (*warn)(const char *, ...))
+{
+ char buf[OFMT_BUFSIZE];
+
+ assert(die != NULL);
+ assert(warn != NULL);
+
+ if (oferr == OFMT_SUCCESS)
+ return;
+
+ (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
+
+ /*
+ * All errors are considered fatal in parsable mode. OFMT_ENOMEM and
+ * OFMT_ENOFIELDS errors are always fatal, regardless of mode. For
+ * other errors, we print diagnostics in human-readable mode and
+ * processs what we can.
+ */
+ if (parsable || oferr == OFMT_ENOFIELDS || oferr == OFMT_ENOMEM) {
+ ofmt_close(ofmt);
+ die(buf);
+ } else {
+ warn(buf);
+ }
+}
diff --git a/usr/src/lib/libofmt/common/ofmt.h b/usr/src/lib/libofmt/common/ofmt.h
index a1146e51dc..6048367a84 100644
--- a/usr/src/lib/libofmt/common/ofmt.h
+++ b/usr/src/lib/libofmt/common/ofmt.h
@@ -24,6 +24,10 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright 2017 Joyent, Inc.
+ */
+
#ifndef _OFMT_H
#define _OFMT_H
@@ -205,6 +209,10 @@ extern void ofmt_update_winsize(ofmt_handle_t);
*/
extern char *ofmt_strerror(ofmt_handle_t, ofmt_status_t, char *, uint_t);
+extern void ofmt_check(ofmt_status_t oferr, boolean_t parsable,
+ ofmt_handle_t ofmt,
+ void (*die)(const char *, ...), void (*warn)(const char *, ...));
+
#ifdef __cplusplus
}
#endif