From fdedb45e3105a2d1cb6baf41b792d955ccd7a0bb Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 6 Apr 2010 16:16:27 +0200 Subject: [PATCH] findmnt: rewrite to use lib/tt.c Signed-off-by: Karel Zak --- misc-utils/Makefile.am | 1 + misc-utils/findmnt.c | 713 ++++++++++------------------------------- 2 files changed, 167 insertions(+), 547 deletions(-) diff --git a/misc-utils/Makefile.am b/misc-utils/Makefile.am index 218a2103..b5029166 100644 --- a/misc-utils/Makefile.am +++ b/misc-utils/Makefile.am @@ -47,6 +47,7 @@ wipefs_LDADD = $(ul_libblkid_la) wipefs_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir) findmnt_LDADD = $(ul_libmount_la) findmnt_CFLAGS = $(AM_CFLAGS) -I$(ul_libmount_incdir) +findmnt_SOURCES = findmnt.c $(top_srcdir)/lib/tt.c if HAVE_STATIC_BLKID sbin_PROGRAMS += blkid.static blkid_static_SOURCES = $(blkid_SOURCES) diff --git a/misc-utils/findmnt.c b/misc-utils/findmnt.c index 0fdb16c9..70678235 100644 --- a/misc-utils/findmnt.c +++ b/misc-utils/findmnt.c @@ -18,7 +18,6 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - #include #include #include @@ -33,14 +32,14 @@ #ifdef HAVE_SYS_IOCTL_H #include #endif -#include - #include +#include + #include "pathnames.h" #include "nls.h" -#include "widechar.h" #include "c.h" +#include "tt.h" /* flags */ enum { @@ -48,10 +47,7 @@ enum { FL_CANONICALIZE = (1 << 2), FL_FIRSTONLY = (1 << 3), FL_INVERT = (1 << 4), - FL_NOHEADINGS = (1 << 5), FL_NOSWAPMATCH = (1 << 6), - FL_TREE = (1 << 7), - FL_RAW = (1 << 8) }; /* column IDs */ @@ -66,101 +62,42 @@ enum { __NCOLUMNS }; -struct treenode { - mnt_fs *fs; /* filesystem */ - - struct treenode *parent; - struct treenode *first; /* first child */ - struct treenode *last; /* last child */ - - struct treenode *next; /* next node in the same level */ -}; - /* column names */ struct colinfo { const char *name; /* header */ double whint; /* width hint (N < 1 is in percent of termwidth) */ - int wrap; /* boolean (FALSE = truncate the column) */ - - int width; /* real column width */ + int truncate; /* boolean */ const char *match; /* pattern for match_func() */ }; /* columns descriptions */ struct colinfo infos[__NCOLUMNS] = { - [COL_SOURCE] = { "SOURCE", 0.25, TRUE }, - [COL_TARGET] = { "TARGET", 0.30, TRUE }, - [COL_FSTYPE] = { "FSTYPE", 0.10, FALSE }, - [COL_OPTIONS] = { "OPTIONS", 0.10, FALSE }, - [COL_LABEL] = { "LABEL", 0.10, TRUE }, - [COL_UUID] = { "UUID", 36, TRUE }, + [COL_SOURCE] = { "SOURCE", 0.25, FALSE }, + [COL_TARGET] = { "TARGET", 0.30, FALSE }, + [COL_FSTYPE] = { "FSTYPE", 0.10, TRUE }, + [COL_OPTIONS] = { "OPTIONS", 0.10, TRUE }, + [COL_LABEL] = { "LABEL", 0.10, FALSE }, + [COL_UUID] = { "UUID", 36, FALSE }, }; -struct treesym { - const char *branch; - const char *vert; - const char *right; -}; -const struct treesym ascii_tree_symbols = { - .branch = "|-", - .vert = "| ", - .right = "`-", -}; - -#ifdef HAVE_WIDECHAR - -#define mbs_width(_s) mbstowcs(NULL, _s, 0) - -#define UTF_V "\342\224\202" /* U+2502, Vertical line drawing char */ -#define UTF_VR "\342\224\234" /* U+251C, Vertical and right */ -#define UTF_H "\342\224\200" /* U+2500, Horizontal */ -#define UTF_UR "\342\224\224" /* U+2514, Up and right */ - -const struct treesym utf_tree_symbols = { - .branch = UTF_VR UTF_H, - .vert = UTF_V " ", - .right = UTF_UR UTF_H, -}; - -const struct treesym *tree_symbols = &utf_tree_symbols; - -#else /* !HAVE_WIDECHAR */ - -# define mbs_width strlen(_s) -const struct treesym *tree_symbols = &ascii_tree_symbols; - -#endif /* !HAVE_WIDECHAR */ - /* global flags */ int flags; -/* array IDs of with enabled columns */ +/* array with IDs of enabled columns */ int columns[__NCOLUMNS]; int ncolumns; -int termwidth; /* terminal width */ -char *treebuf; /* buffer for target column in tree mode */ - /* libmount cache */ mnt_cache *cache; - -static inline int is_last_column(int num) -{ - return num + 1 == ncolumns; -} - static inline int get_column_id(int num) { - int id; assert(num < ncolumns); - - id = columns[num]; - assert(id < __NCOLUMNS); - return id; + assert(columns[num] < __NCOLUMNS); + return columns[num]; } -static inline struct colinfo *get_column_desc(int num) +static inline struct colinfo *get_column_info(int num) { return &infos[ get_column_id(num) ]; } @@ -173,27 +110,17 @@ static inline const char *column_id_to_name(int id) static inline const char *get_column_name(int num) { - return get_column_desc(num)->name; + return get_column_info(num)->name; } static inline float get_column_whint(int num) { - return get_column_desc(num)->whint; + return get_column_info(num)->whint; } -static inline int get_column_width(int num) +static inline int get_column_truncate(int num) { - return get_column_desc(num)->width; -} - -static inline void set_column_width(int num, int width) -{ - get_column_desc(num)->width = width; -} - -static inline int get_column_wrap(int num) -{ - return get_column_desc(num)->wrap; + return get_column_info(num)->truncate; } static inline const char *get_match(int id) @@ -236,12 +163,12 @@ static inline int is_mount_compatible_mode(void) return 1; /* ok */ } -static void set_all_columns_wrap(int set) +static void set_all_columns_truncate(int set) { int i; for (i = 0; i < __NCOLUMNS; i++) - infos[i].wrap = set; + infos[i].truncate = set; } /* @@ -257,8 +184,7 @@ static int column_name_to_id(const char *name, size_t namesz) if (!strncasecmp(name, cn, namesz) && !*(cn + namesz)) return i; } - - errx(EXIT_FAILURE, _("unknown column: %s"), name); + warnx(_("unknown column: %s"), name); return -1; } @@ -278,6 +204,7 @@ static int set_columns(const char *str) for (p = str; p && *p; p++) { const char *end = NULL; + int id; if (!begin) begin = p; /* begin of the column name */ @@ -290,7 +217,10 @@ static int set_columns(const char *str) if (end <= begin) return -1; - columns[ ncolumns++ ] = column_name_to_id(begin, end - begin); + id = column_name_to_id(begin, end - begin); + if (id == -1) + return -1; + columns[ ncolumns++ ] = id; begin = NULL; if (end && !*end) break; @@ -298,136 +228,7 @@ static int set_columns(const char *str) return 0; } -/* TODO: move to lib/terminal.c */ -static int terminal_get_width(void) -{ -#ifdef TIOCGSIZE - struct ttysize t_win; -#endif -#ifdef TIOCGWINSZ - struct winsize w_win; -#endif - const char *cp; - -#ifdef TIOCGSIZE - if (ioctl (0, TIOCGSIZE, &t_win) == 0) - return t_win.ts_cols; -#endif -#ifdef TIOCGWINSZ - if (ioctl (0, TIOCGWINSZ, &w_win) == 0) - return w_win.ws_col; -#endif - cp = getenv("COLUMNS"); - if (cp) - return strtol(cp, NULL, 10); - return 80; -} - -static void recount_widths(void) -{ - int i, width = 0, ignore_wraps; - - /* set minimal width (= size of column header) */ - for (i = 0; i < ncolumns; i++) { - const char *name = get_column_name(i); - size_t len = mbs_width(name); - float hint = get_column_whint(i); - - if (get_column_width(i) < len) - /* enlarge to small columns */ - set_column_width(i, len); - - else if (hint >= 1) - /* set absolute widths */ - set_column_width(i, (int) hint); - } - - /* count used space */ - for (i = 0; i < ncolumns; i++) - width += get_column_width(i) + (is_last_column(i) ? 0 : 1); - - if (width == termwidth) - return; - - if (width < termwidth) { - /* cool, use the extra space for the last column */ - i = ncolumns - 1; - set_column_width(i, get_column_width(i) + (termwidth - width)); - - return; - } - - /* bad, we have to reduce output width, this is done in two steps: - * 1/ reduce columns with a relative width (see colinfo.whint) and - * without wrap flag (this columns could be truncated) - * 2) reduce columns with a relative width with wrap flag - */ - ignore_wraps = 1; - while(width > termwidth) { - int org = width; - for (i = ncolumns - 1; i >= 0 && width > termwidth; i--) { - float hint = get_column_whint(i); - int w = get_column_width(i); - - if (hint > 1) - /* never truncate columns with absolute sizes */ - continue; - - if (get_column_id(i) == COL_TARGET && (flags & FL_TREE)) - /* never truncate the tree */ - continue; - - if (ignore_wraps && get_column_wrap(i)) - continue; - - if (w > hint * termwidth) { - set_column_width(i, w - 1); - width--; - } - } - - if (org == width) { - if (ignore_wraps) - ignore_wraps = 0; - else - break; - } - } -/* - fprintf(stderr, "terminal: %d, output: %d\n", termwidth, width); - for (i = 0; i < ncolumns; i++) - fprintf(stderr, "width: %s=%d [%d]\n", - get_column_name(i), - get_column_width(i), - (int) (get_column_whint(i) * termwidth)); -*/ -} - -static char *get_treenode_ascii_art(struct treenode *node, - char *buf, size_t *bufsz) -{ - const char *sym; - size_t len; - - if (!node->parent) - return buf; - else { - buf = get_treenode_ascii_art(node->parent, buf, bufsz); - if (!buf) - return NULL; - sym = node->next ? tree_symbols->vert : " "; - } - len = strlen(sym); - - if (*bufsz < len) - return NULL; /* no space, internal error */ - - memcpy(buf, sym, len); - *bufsz -= len; - return buf + len; -} - -/* Returns LABEl or UUID */ +/* Returns LABEL or UUID */ static const char *get_tag(mnt_fs *fs, const char *tagname) { const char *t, *v, *res; @@ -445,37 +246,8 @@ static const char *get_tag(mnt_fs *fs, const char *tagname) return res; } -static const char *get_tree_target(mnt_fs *fs, char *buf, size_t bufsz) -{ - struct treenode *node; - const char *target; - char *p = buf; - - node = (struct treenode *) mnt_fs_get_userdata(fs); - if (!node) - return NULL; - - target = mnt_fs_get_target(fs); - if (!target) - return NULL; - - if (node->parent) { - p = get_treenode_ascii_art(node->parent, buf, &bufsz); - if (!p) - return NULL; - } - - if (node->next) - snprintf(p, bufsz, "%s%s", tree_symbols->branch, target); - else if (node->parent) - snprintf(p, bufsz, "%s%s", tree_symbols->right, target); - else - snprintf(p, bufsz, "%s", target); /* root node */ - - return buf; -} - -static const char *get_column_data(mnt_fs *fs, int num) +/* reads FS data from libmount */ +static const char *get_data(mnt_fs *fs, int num) { const char *str = NULL; @@ -494,8 +266,7 @@ static const char *get_column_data(mnt_fs *fs, int num) } break; case COL_TARGET: - str = flags & FL_TREE ? get_tree_target(fs, treebuf, termwidth) : - mnt_fs_get_target(fs); + str = mnt_fs_get_target(fs); break; case COL_FSTYPE: str = mnt_fs_get_fstype(fs); @@ -512,180 +283,85 @@ static const char *get_column_data(mnt_fs *fs, int num) default: break; } - - return str ? str : "-"; -} - -/* TODO: move to lib/mbalign.c */ -#ifdef HAVE_WIDECHAR -static size_t wc_truncate (wchar_t *wc, size_t width) -{ - size_t cells = 0; - int next_cells = 0; - - while (*wc) - { - next_cells = wcwidth (*wc); - if (next_cells == -1) /* non printable */ - { - *wc = 0xFFFD; /* L'\uFFFD' (replacement char) */ - next_cells = 1; - } - if (cells + next_cells > width) - break; - cells += next_cells; - wc++; - } - *wc = L'\0'; - return cells; -} -#endif - -/* TODO: move to lib/mbalign.c */ -static size_t mbs_truncate(char *str, size_t width) -{ - size_t bytes = strlen(str) + 1; -#ifdef HAVE_WIDECHAR - size_t sz = mbs_width(str); - wchar_t *wcs = NULL; - int rc = -1; - - if (sz <= width) - return sz; /* truncate is unnecessary */ - - if (sz == (size_t) -1) - goto done; - - wcs = malloc(sz * sizeof(wchar_t)); - if (!wcs) - goto done; - - if (!mbstowcs(wcs, str, sz)) - goto done; - rc = wc_truncate(wcs, width); - wcstombs(str, wcs, bytes); -done: - free(wcs); - return rc; -#else - if (width < bytes) { - str[width] = '\0'; - return width; - } - return bytes; /* truncate is unnecessary */ -#endif + return str; } -static void print_column_data(const char *data0, int num) +/* adds one line to the output @tab */ +static struct tt_line *add_line(struct tt *tt, mnt_fs *fs, + struct tt_line *parent) { - size_t len, wrap, i; - int width; - char *data = (char *) data0; - - if (flags & FL_RAW) { - fputs(data, stdout); - if (!is_last_column(num)) - fputc(' ', stdout); - return; - } - - /* note that 'len' and 'width' is number of cells, not bytes */ - len = mbs_width(data); + int i; + struct tt_line *line = tt_add_line(tt, parent); - if (!len || len == (size_t) -1) { - len = 0; - data = NULL; + if (!line) { + warn(_("failed to add line to output")); + return NULL; } + for (i = 0; i < ncolumns; i++) + tt_line_set_data(line, i, get_data(fs, i)); - width = get_column_width(num); - wrap = get_column_wrap(num); - - if (is_last_column(num) && len < width) - width = len; - - if (len > width && !wrap) { - data = strdup(data); - if (data) - len = mbs_truncate(data, width); - if (!data || len == (size_t) -1) { - len = 0; - data = NULL; - } - } - if (data) - fputs(data, stdout); - for (i = len; i < width; i++) /* padding */ - fputc(' ', stdout); - - if (!is_last_column(num)) { - if (len > width && wrap) { - fputc('\n', stdout); - - for (i = 0; i <= num; i++) - printf("%*s ", - -get_column_width(i), " "); - } else - fputc(' ', stdout); /* columns separator */ - } - if (data != data0) - free(data); + return line; } -static void print_fs(mnt_fs *fs, int line) +/* reads filesystems from @tb (libmount) and fillin @tab (output table) */ +static int create_treenode(struct tt *tt, mnt_tab *tb, + mnt_fs *fs, struct tt_line *parent_line) { - int i; - - /* print header */ - if (!(flags & FL_NOHEADINGS) && !line) { - for (i = 0; i < ncolumns; i++) - print_column_data(get_column_name(i), i); - printf("\n"); - } + mnt_fs *chld = NULL; + mnt_iter *itr = NULL; + struct tt_line *line; + int rc = -1; - /* print data */ - for (i = 0; i < ncolumns; i++) { - const char *data = get_column_data(fs, i); - print_column_data(data, i); + if (!fs) { + /* first call, get root FS */ + if (mnt_tab_get_root_fs(tb, &fs)) + goto leave; + parent_line = NULL; } - printf("\n"); -} -static void set_widths(mnt_fs *fs) -{ - int i; + itr = mnt_new_iter(MNT_ITER_FORWARD); + if (!itr) + goto leave; - for (i = 0; i < ncolumns; i++) { - const char *data = get_column_data(fs, i); - size_t len = data ? mbs_width(data) : 0; - int old = get_column_width(i); + line = add_line(tt, fs, parent_line); + if (!line) + goto leave; - if (old < len) - set_column_width(i, len); + /* + * add all children to the output table + */ + while(mnt_tab_next_child_fs(tb, itr, fs, &chld) == 0) { + if (create_treenode(tt, tb, chld, line)) + goto leave; } + rc = 0; +leave: + mnt_free_iter(itr); + return rc; } +/* calls libmount fstab/mtab/mountinfo parser */ static mnt_tab *parse_tabfile(const char *path) { mnt_tab *tb = mnt_new_tab(path); - if (!tb) + if (!tb) { + warn(_("failed to initialize libmount tab")); return NULL; - - if (mnt_tab_parse_file(tb) != 0) - goto err; - + } + if (mnt_tab_parse_file(tb) != 0) { + mnt_free_tab(tb); + warn(_("can't read: %s"), path); + return NULL; + } if (mnt_tab_get_nerrs(tb)) { char buf[BUFSIZ]; mnt_tab_strerror(tb, buf, sizeof(buf)); warnx(_("%s: parse error: %s"), path, buf); } return tb; -err: - mnt_free_tab(tb); - err(EXIT_FAILURE, _("can't read: %s"), path); - - return NULL; } +/* filter function for libmount (mnt_tab_find_next_fs()) */ static int match_func(mnt_fs *fs, void *data) { int rc = flags & FL_INVERT ? 1 : 0; @@ -710,6 +386,7 @@ static int match_func(mnt_fs *fs, void *data) return !rc; } +/* iterate over filesystems in @tb */ static mnt_fs *get_next_fs(mnt_tab *tb, mnt_iter *itr) { mnt_fs *fs = NULL; @@ -753,89 +430,8 @@ again: goto again; } } - return fs; -} - -static struct treenode *create_treenode(mnt_tab *tb, mnt_fs *fs) -{ - mnt_fs *chld = NULL; - mnt_iter *itr = NULL; - struct treenode *node = NULL; - - if (!fs) { - /* first call - start with root FS and initialize tree buffer */ - if (mnt_tab_get_root_fs(tb, &fs)) - goto err; - - treebuf = malloc(termwidth); - if (!treebuf) - goto err; - } - - itr = mnt_new_iter(MNT_ITER_FORWARD); - if (!itr) - goto err; - - node = calloc(1, sizeof(*node)); - if (!node) - goto err; - - node->fs = fs; - mnt_fs_set_userdata(fs, (void *) node); - - while(mnt_tab_next_child_fs(tb, itr, fs, &chld) == 0) { - struct treenode *chnode; - - chnode = create_treenode(tb, chld); - if (!chnode) - break; - - chnode->parent = node; - - if (node->last) - node->last->next = chnode; - else - node->first = chnode; - - node->last = chnode; - } - - return node; - -err: - if (!fs) - free(treebuf); - free(node); - mnt_free_iter(itr); - return NULL; -} - -static void print_treenode(struct treenode *node, int line) -{ - print_fs(node->fs, line++); - - /* print children */ - node = node->first; - while(node) { - print_treenode(node, line++); - node = node->next; - } -} - -static void free_treenode(struct treenode *node) -{ - struct treenode *chld = node->first; - - if (!node->parent) /* root node */ - free(treebuf); - while(chld) { - struct treenode *next = chld->next; - free_treenode(chld); - chld = next; - } - - free(node); + return fs; } static int __attribute__((__noreturn__)) usage(FILE *out) @@ -884,12 +480,18 @@ errx_mutually_exclusive(const char *opts) int main(int argc, char *argv[]) { + /* libmount */ + mnt_tab *tb = NULL; + mnt_iter *itr = NULL; + mnt_fs *fs = NULL; char *tabfile = NULL; int direction = MNT_ITER_FORWARD; - mnt_tab *tb; - mnt_iter *itr; - mnt_fs *fs = NULL; - int c, ct = 0; + + /* table.h */ + struct tt *tt = NULL; + int tt_flags = 0; + + int i, c, rc = EXIT_FAILURE; struct option longopts[] = { { "ascii", 0, 0, 'a' }, @@ -928,13 +530,13 @@ int main(int argc, char *argv[]) columns[ncolumns++] = COL_OPTIONS; /* default output format */ - flags |= FL_TREE; + tt_flags |= TT_FL_TREE; while ((c = getopt_long(argc, argv, "cd:ehifo:O:klmnrst:uS:T:", longopts, NULL)) != -1) { switch(c) { case 'a': - tree_symbols = &ascii_tree_symbols; + tt_flags |= TT_FL_ASCII; break; case 'c': flags |= FL_CANONICALIZE; @@ -961,27 +563,28 @@ int main(int argc, char *argv[]) flags |= FL_FIRSTONLY; break; case 'u': - set_all_columns_wrap(TRUE); + set_all_columns_truncate(FALSE); break; case 'o': - set_columns(optarg); + if (set_columns(optarg)) + exit(EXIT_FAILURE); break; case 'O': set_match(COL_OPTIONS, optarg); break; - case 'm': + case 'm': /* mtab */ if (tabfile) errx_mutually_exclusive("--{fstab,mtab,kernel}"); tabfile = _PATH_MOUNTED; - flags &= ~FL_TREE; /* disable the default */ + tt_flags &= ~TT_FL_TREE; break; - case 's': + case 's': /* fstab */ if (tabfile) errx_mutually_exclusive("--{fstab,mtab,kernel}"); tabfile = _PATH_MNTTAB; - flags &= ~FL_TREE; /* disable the default */ + flags &= ~TT_FL_TREE; break; - case 'k': + case 'k': /* kernel (mountinfo) */ if (tabfile) errx_mutually_exclusive("--{fstab,mtab,kernel}"); tabfile = _PATH_PROC_MOUNTINFO; @@ -990,20 +593,21 @@ int main(int argc, char *argv[]) set_match(COL_FSTYPE, optarg); break; case 'r': - if (!(flags & FL_TREE) && !(flags & FL_RAW)) + if (!(tt_flags & TT_FL_TREE) && + !(tt_flags & TT_FL_RAW)) errx_mutually_exclusive("--{raw,list}"); - flags &= ~FL_TREE; /* disable the default */ - flags |= FL_RAW; /* enable raw */ + tt_flags &= ~TT_FL_TREE; /* disable the default */ + tt_flags |= TT_FL_RAW; /* enable raw */ break; case 'l': - if (flags & FL_RAW) + if (tt_flags & TT_FL_RAW) errx_mutually_exclusive("--{raw,list}"); - flags &= ~FL_TREE; /* disable the default */ + tt_flags &= ~TT_FL_TREE; /* disable the default */ break; case 'n': - flags |= FL_NOHEADINGS; + tt_flags |= TT_FL_NOHEADINGS; break; case 'S': set_match(COL_SOURCE, optarg); @@ -1019,16 +623,14 @@ int main(int argc, char *argv[]) } } - if (!tabfile) + if (!tabfile) { tabfile = _PATH_PROC_MOUNTINFO; -#ifdef HAVE_WIDECHAR - /* non-UTF terminal */ - if ((flags & FL_TREE) && tree_symbols != &ascii_tree_symbols && - strcmp(nl_langinfo(CODESET), "UTF-8")) - tree_symbols = &ascii_tree_symbols; -#endif - + if (access(tabfile, R_OK)) { /* old kernel? */ + tabfile = _PATH_PROC_MOUNTS; + tt_flags &= ~TT_FL_TREE; + } + } if (optind < argc && (get_match(COL_SOURCE) || get_match(COL_TARGET))) errx(EXIT_FAILURE, _( "options --target and --source can't be used together " @@ -1039,58 +641,75 @@ int main(int argc, char *argv[]) if (optind < argc) set_match(COL_TARGET, argv[optind++]); /* mountpoint */ + if (!is_listall_mode() || (flags & FL_FIRSTONLY)) + tt_flags &= ~TT_FL_TREE; + + /* + * initialize libmount + */ tb = parse_tabfile(tabfile); if (!tb) - return EXIT_FAILURE; + goto leave; itr = mnt_new_iter(direction); - if (!itr) - err(EXIT_FAILURE, _("failed to initialize libmount iterator")); - + if (!itr) { + warn(_("failed to initialize libmount iterator")); + goto leave; + } cache = mnt_new_cache(); - if (!cache) - err(EXIT_FAILURE, _("failed to initialize libmount cache")); - + if (!cache) { + warn(_("failed to initialize libmount cache")); + goto leave; + } mnt_tab_set_cache(tb, cache); - termwidth = terminal_get_width(); + /* + * initialize output formatting (table.h) + */ + tt = tt_new_table(tt_flags); + if (!tt) { + warn(_("failed to initialize output table")); + goto leave; + } + for (i = 0; i < ncolumns; i++) { + int fl = get_column_truncate(i) ? TT_FL_TRUNCATE : 0; - if (flags & FL_TREE) { - struct treenode *tree = create_treenode(tb, NULL); - if (!tree) - err(EXIT_FAILURE, _("failed to create tree")); + if (get_column_id(i) == COL_TARGET && (tt_flags & TT_FL_TREE)) + fl |= TT_FL_TREE; - while (mnt_tab_next_fs(tb, itr, &fs) == 0) { - set_widths(fs); - ct++; - } - recount_widths(); - print_treenode(tree, 0); - free_treenode(tree); - } else { - /* set width */ - - if (!(flags & FL_RAW)) { - while((fs = get_next_fs(tb, itr))) { - set_widths(fs); - if (flags & FL_FIRSTONLY) - break; - } - ct = 0; - mnt_reset_iter(itr, -1); - recount_widths(); + if (!tt_define_column(tt, get_column_name(i), + get_column_whint(i), fl)) { + warn(_("failed to initialize output column")); + goto leave; } + } - /* Print */ + /* + * Fill in data to the output table + */ + if (tt_flags & TT_FL_TREE) { + if (create_treenode(tt, tb, NULL, NULL)) + goto leave; + } else { while((fs = get_next_fs(tb, itr))) { - print_fs(fs, ct++); + if (!add_line(tt, fs, NULL)) + goto leave; if (flags & FL_FIRSTONLY) break; } } + + /* + * Print the output table + */ + tt_print_table(tt); + rc = EXIT_SUCCESS; +leave: + tt_free_table(tt); + mnt_free_tab(tb); mnt_free_cache(cache); mnt_free_iter(itr); - return ct ? EXIT_SUCCESS : 2; + return rc; } -- 2.39.5