diff --git a/misc-utils/findmnt-verify.c b/misc-utils/findmnt-verify.c index ecb51d9cfcc..2a220dc5964 100644 --- a/misc-utils/findmnt-verify.c +++ b/misc-utils/findmnt-verify.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "nls.h" #include "c.h" @@ -69,13 +70,14 @@ static int __attribute__ ((__format__ (__printf__, 2, 3))) return 0; } -static int __attribute__ ((__format__ (__printf__, 2, 3))) +static int __attribute__ ((__format__ (__printf__, 3, 4))) verify_ok(struct verify_context *vfy __attribute__((unused)), + bool verbose, const char *fmt, ...) { va_list ap; - if (!(flags & FL_VERBOSE)) + if (!verbose) return 0; va_start(ap, fmt); @@ -84,15 +86,15 @@ static int __attribute__ ((__format__ (__printf__, 2, 3))) return 0; } -static int verify_order(struct verify_context *vfy) +static int verify_order(struct verify_context *vfy, struct findmnt *findmnt) { struct libmnt_iter *itr = NULL; struct libmnt_fs *next; const char *tgt; tgt = mnt_fs_get_target(vfy->fs); - if (tgt && !(flags & FL_NOCACHE)) - tgt = mnt_resolve_target(tgt, cache); + if (tgt && !(findmnt->flags & FL_NOCACHE)) + tgt = mnt_resolve_target(tgt, findmnt->cache); else if (!tgt) return 0; @@ -114,8 +116,8 @@ static int verify_order(struct verify_context *vfy) size_t len; n_tgt = mnt_fs_get_target(next); - if (n_tgt && !(flags & FL_NOCACHE)) - n_tgt = mnt_resolve_target(n_tgt, cache); + if (n_tgt && !(findmnt->flags & FL_NOCACHE)) + n_tgt = mnt_resolve_target(n_tgt, findmnt->cache); else if (!n_tgt) continue; len = strlen(n_tgt); @@ -132,7 +134,7 @@ static int verify_order(struct verify_context *vfy) return 0; } -static int verify_target(struct verify_context *vfy) +static int verify_target(struct verify_context *vfy, struct findmnt *findmnt) { const char *tgt = mnt_fs_get_target(vfy->fs); struct stat sb; @@ -140,8 +142,8 @@ static int verify_target(struct verify_context *vfy) if (!tgt) return verify_err(vfy, _("undefined target (fs_file)")); - if (!(flags & FL_NOCACHE)) { - const char *cn = mnt_resolve_target(tgt, cache); + if (!(findmnt->flags & FL_NOCACHE)) { + const char *cn = mnt_resolve_target(tgt, findmnt->cache); if (!cn) return -ENOMEM; if (strcmp(cn, tgt) != 0) @@ -158,18 +160,18 @@ static int verify_target(struct verify_context *vfy) && mnt_fs_get_option(vfy->fs, "bind", NULL, NULL) == 1) { verify_err(vfy, _("target is not a directory")); } else - verify_ok(vfy, _("target exists")); + verify_ok(vfy, findmnt->flags & FL_VERBOSE, _("target exists")); return 0; } static char *verify_tag(struct verify_context *vfy, const char *name, - const char *value) + const char *value, struct findmnt *findmnt) { char *src = NULL; - if (!(flags & FL_NOCACHE)) - src = mnt_resolve_tag(name, value, cache); + if (!(findmnt->flags & FL_NOCACHE)) + src = mnt_resolve_tag(name, value, findmnt->cache); if (!src) { if (mnt_fs_get_option(vfy->fs, "noauto", NULL, NULL) == 1) @@ -177,7 +179,7 @@ static char *verify_tag(struct verify_context *vfy, const char *name, else verify_warn(vfy, _("unreachable: %s=%s"), name, value); } else - verify_ok(vfy, _("%s=%s translated to %s"), name, value, src); + verify_ok(vfy, findmnt->flags & FL_VERBOSE, _("%s=%s translated to %s"), name, value, src); return src; } @@ -186,7 +188,7 @@ static char *verify_tag(struct verify_context *vfy, const char *name, * interpret unreachable source as error. The exception is only * NAME=value, this has to be convertible to device name. */ -static int verify_source(struct verify_context *vfy) +static int verify_source(struct verify_context *vfy, struct findmnt *findmnt) { const char *src = mnt_fs_get_srcpath(vfy->fs); char *t = NULL, *v = NULL; @@ -200,7 +202,7 @@ static int verify_source(struct verify_context *vfy) if (mnt_fs_get_tag(vfy->fs, &tag, &val) != 0) return verify_err(vfy, _("undefined source (fs_spec)")); - src = verify_tag(vfy, tag, val); + src = verify_tag(vfy, tag, val, findmnt); if (!src) goto done; @@ -214,7 +216,7 @@ static int verify_source(struct verify_context *vfy) /* source is path */ if (mnt_fs_is_pseudofs(vfy->fs) || mnt_fs_is_netfs(vfy->fs)) - verify_ok(vfy, _("do not check %s source (pseudo/net)"), src); + verify_ok(vfy, findmnt->flags & FL_VERBOSE, _("do not check %s source (pseudo/net)"), src); else if (stat(src, &sb) != 0) verify_warn(vfy, _("unreachable source: %s: %m"), src); @@ -225,28 +227,28 @@ static int verify_source(struct verify_context *vfy) else if (!S_ISBLK(sb.st_mode) && !isbind) verify_warn(vfy, _("source %s is not a block device"), src); else - verify_ok(vfy, _("source %s exists"), src); + verify_ok(vfy, findmnt->flags & FL_VERBOSE, _("source %s exists"), src); done: free(t); free(v); return rc; } -static int verify_options(struct verify_context *vfy) +static int verify_options(struct verify_context *vfy, bool verbose) { const char *opts; opts = mnt_fs_get_vfs_options(vfy->fs); if (opts) - verify_ok(vfy, _("VFS options: %s"), opts); + verify_ok(vfy, verbose, _("VFS options: %s"), opts); opts = mnt_fs_get_fs_options(vfy->fs); if (opts) - verify_ok(vfy, _("FS options: %s"), opts); + verify_ok(vfy, verbose, _("FS options: %s"), opts); opts = mnt_fs_get_user_options(vfy->fs); if (opts) - verify_ok(vfy, _("userspace options: %s"), opts); + verify_ok(vfy, verbose, _("userspace options: %s"), opts); return 0; } @@ -407,9 +409,9 @@ static int read_kernel_filesystems(struct verify_context *vfy) return rc; } -static int verify_fstype(struct verify_context *vfy) +static int verify_fstype(struct verify_context *vfy, struct findmnt *findmnt) { - char *src = mnt_resolve_spec(mnt_fs_get_source(vfy->fs), cache); + char *src = mnt_resolve_spec(mnt_fs_get_source(vfy->fs), findmnt->cache); char *realtype = NULL; const char *type; int ambi = 0, isauto = 0, isswap = 0; @@ -418,7 +420,7 @@ static int verify_fstype(struct verify_context *vfy) return 0; if (mnt_fs_is_pseudofs(vfy->fs) || mnt_fs_is_netfs(vfy->fs)) { - verify_ok(vfy, _("do not check %s FS type (pseudo/net)"), src); + verify_ok(vfy, findmnt->flags & FL_VERBOSE, _("do not check %s FS type (pseudo/net)"), src); goto done; } @@ -446,7 +448,7 @@ static int verify_fstype(struct verify_context *vfy) } errno = 0; - realtype = mnt_get_fstype(src, &ambi, cache); + realtype = mnt_get_fstype(src, &ambi, findmnt->cache); if (!realtype) { const char *reason = errno ? strerror(errno) : _("reason unknown"); @@ -472,11 +474,11 @@ static int verify_fstype(struct verify_context *vfy) goto done; } - verify_ok(vfy, _("FS type is %s"), realtype); + verify_ok(vfy, findmnt->flags & FL_VERBOSE, _("FS type is %s"), realtype); } done: - if (!cache) { + if (!findmnt->cache) { free(src); free(realtype); } @@ -494,34 +496,34 @@ static int verify_passno(struct verify_context *vfy) return 0; } -static int verify_filesystem(struct verify_context *vfy) +static int verify_filesystem(struct verify_context *vfy, struct findmnt *findmnt) { int rc = 0; if (mnt_fs_is_swaparea(vfy->fs)) rc = verify_swaparea(vfy); else { - rc = verify_target(vfy); + rc = verify_target(vfy, findmnt); if (!rc) - rc = verify_options(vfy); + rc = verify_options(vfy, findmnt->flags & FL_VERBOSE); } if (!rc) - rc = verify_source(vfy); + rc = verify_source(vfy, findmnt); if (!rc) - rc = verify_fstype(vfy); + rc = verify_fstype(vfy, findmnt); if (!rc) rc = verify_passno(vfy); /* depends on verify_fstype() */ return rc; } -int verify_table(struct libmnt_table *tb) +int verify_table(struct libmnt_table *tb, struct findmnt *findmnt) { struct verify_context vfy = { .nerrors = 0 }; struct libmnt_iter *itr; int rc = 0; /* overall return code (alloc errors, etc.) */ - int check_order = is_listall_mode(); + int check_order = is_listall_mode(findmnt->flags); static int has_read_fs = 0; itr = mnt_new_iter(MNT_ITER_FORWARD); @@ -538,18 +540,18 @@ int verify_table(struct libmnt_table *tb) has_read_fs = 1; } - while (rc == 0 && (vfy.fs = get_next_fs(tb, itr))) { + while (rc == 0 && (vfy.fs = get_next_fs(tb, itr, findmnt))) { vfy.target_printed = 0; vfy.no_fsck = 0; if (check_order) - rc = verify_order(&vfy); + rc = verify_order(&vfy, findmnt); if (!rc) - rc = verify_filesystem(&vfy); + rc = verify_filesystem(&vfy, findmnt); - if (flags & FL_FIRSTONLY) + if (findmnt->flags & FL_FIRSTONLY) break; - flags |= FL_NOSWAPMATCH; + findmnt->flags |= FL_NOSWAPMATCH; } #ifdef USE_SYSTEMD @@ -569,9 +571,9 @@ int verify_table(struct libmnt_table *tb) mnt_free_iter(itr); /* summary */ - if (vfy.nerrors || parse_nerrors || vfy.nwarnings) { + if (vfy.nerrors || findmnt->parse_nerrors || vfy.nwarnings) { fputc('\n', stderr); - fprintf(stderr, P_("%d parse error", "%d parse errors", parse_nerrors), parse_nerrors); + fprintf(stderr, P_("%d parse error", "%d parse errors", findmnt->parse_nerrors), findmnt->parse_nerrors); fprintf(stderr, P_(", %d error", ", %d errors", vfy.nerrors), vfy.nerrors); fprintf(stderr, P_(", %d warning", ", %d warnings", vfy.nwarnings), vfy.nwarnings); fputc('\n', stderr); @@ -581,5 +583,5 @@ int verify_table(struct libmnt_table *tb) free_proc_filesystems(&vfy); - return rc != 0 ? rc : vfy.nerrors + parse_nerrors; + return rc != 0 ? rc : vfy.nerrors + findmnt->parse_nerrors; } diff --git a/misc-utils/findmnt.8.adoc b/misc-utils/findmnt.8.adoc index 941eb6c2c3c..f29f965421e 100644 --- a/misc-utils/findmnt.8.adoc +++ b/misc-utils/findmnt.8.adoc @@ -131,6 +131,15 @@ Print only pseudo filesystems. *--shadow*:: Print only filesystems over-mounted by another filesystem. +*-Q*, *--filter* _expr_:: +Print only the filesystems that meet the conditions specified by the expr. ++ +This feature is EXPERIMENTAL. See also *scols-filter*(5). +For example, include xfs having more than 50% free space: +____ + findmnt -Q 'INO.USED < INO.AVAIL && FSTYPE == "xfs"' +____ + *-R*, *--submounts*:: Print recursively all submounts for the selected filesystems. The restrictions defined by options *-t*, *-O*, *-S*, *-T* and *--direction* are not applied to submounts. All submounts are always printed in tree-like order. The option enables the tree-like output format by default. This option has no effect for *--mtab* or *--fstab*. @@ -243,6 +252,7 @@ mailto:kzak@redhat.com[Karel Zak] *fstab*(5), *mount*(8) +*scols-filter*(5) include::man-common/bugreports.adoc[] diff --git a/misc-utils/findmnt.c b/misc-utils/findmnt.c index f81cc433aa2..05ed951bf79 100644 --- a/misc-utils/findmnt.c +++ b/misc-utils/findmnt.c @@ -146,34 +146,32 @@ static struct colinfo infos[] = { static int columns[ARRAY_SIZE(infos) * 2]; static size_t ncolumns; -static inline size_t err_columns_index(size_t arysz, size_t idx) +static inline void add_column(int id) { - if (idx >= arysz) + if (ncolumns >= ARRAY_SIZE(columns)) errx(EXIT_FAILURE, _("too many columns specified, " "the limit is %zu columns"), - arysz - 1); - return idx; + ARRAY_SIZE(columns) - 1); + columns[ ncolumns++ ] = id; } -#define add_column(ary, n, id) \ - ((ary)[ err_columns_index(ARRAY_SIZE(ary), (n)) ] = (id)) - /* poll actions (parsed --poll= */ #define FINDMNT_NACTIONS 4 /* mount, umount, move, remount */ static int actions[FINDMNT_NACTIONS]; static int nactions; -/* global (accessed from findmnt-verify.c too) */ -unsigned int flags; -int parse_nerrors; -struct libmnt_cache *cache; - static blkid_cache blk_cache; #ifdef HAVE_LIBUDEV static struct udev *udev; #endif +/* "userdata" used by callback for libsmartcols filter */ +struct filler_data { + struct libmnt_fs *fs; + struct findmnt *findmnt; +}; + static int match_func(struct libmnt_fs *fs, void *data __attribute__ ((__unused__))); @@ -239,7 +237,7 @@ static void set_match_data(int id, void *data) * source match means COL_SOURCE *or* COL_MAJMIN, depends on * data format. */ -static void set_source_match(const char *data) +static void set_source_match(const char *data, struct findmnt *findmnt) { int maj, min; @@ -249,7 +247,7 @@ static void set_source_match(const char *data) *devno = makedev(maj, min); set_match(COL_MAJMIN, data); set_match_data(COL_MAJMIN, (void *) devno); - flags |= FL_NOSWAPMATCH; + findmnt->flags |= FL_NOSWAPMATCH; } else set_match(COL_SOURCE, data); } @@ -260,7 +258,7 @@ static void set_source_match(const char *data) * * @tb has to be from kernel (so no fstab or so)! */ -static void enable_extra_target_match(struct libmnt_table *tb) +static void enable_extra_target_match(struct libmnt_table *tb, struct findmnt *findmnt) { char *cn = NULL; const char *tgt = NULL, *mnt = NULL; @@ -270,10 +268,10 @@ static void enable_extra_target_match(struct libmnt_table *tb) * Check if match pattern is mountpoint, if not use the * real mountpoint. */ - if (flags & FL_NOCACHE) + if (findmnt->flags & FL_NOCACHE) tgt = get_match(COL_TARGET); else { - tgt = cn = mnt_resolve_path(get_match(COL_TARGET), cache); + tgt = cn = mnt_resolve_path(get_match(COL_TARGET), findmnt->cache); if (!cn) return; } @@ -284,7 +282,7 @@ static void enable_extra_target_match(struct libmnt_table *tb) if (mnt && strcmp(mnt, tgt) != 0) set_match(COL_TARGET, xstrdup(mnt)); /* replace the current setting */ - if (!cache) + if (!findmnt->cache) free(cn); } @@ -307,7 +305,7 @@ static int is_tabdiff_column(int id) /* * "findmnt" without any filter */ -int is_listall_mode(void) +int is_listall_mode(unsigned int flags) { if ((flags & FL_DF || flags & FL_REAL || flags & FL_PSEUDO) && !(flags & FL_ALL)) return 0; @@ -357,7 +355,7 @@ static int poll_action_name_to_id(const char *name, size_t namesz) * * ... it works like "mount " */ -static int is_mount_compatible_mode(void) +static int is_mount_compatible_mode(unsigned int flags) { if (!get_match(COL_SOURCE)) return 0; /* is required */ @@ -453,7 +451,7 @@ static char *get_tag(struct libmnt_fs *fs, const char *tagname, int col #ifndef HAVE_LIBUDEV __attribute__((__unused__)) #endif - ) + , struct findmnt *findmnt) { const char *t, *v; char *res = NULL; @@ -463,15 +461,15 @@ static char *get_tag(struct libmnt_fs *fs, const char *tagname, int col else { const char *dev = mnt_fs_get_source(fs); - if (dev && !(flags & FL_NOCACHE)) - dev = mnt_resolve_spec(dev, cache); + if (dev && !(findmnt->flags & FL_NOCACHE)) + dev = mnt_resolve_spec(dev, findmnt->cache); #ifdef HAVE_LIBUDEV if (dev) res = get_tag_from_udev(dev, col); #endif if (!res) { - res = mnt_cache_find_tag_value(cache, dev, tagname); - if (res && cache) + res = mnt_cache_find_tag_value(findmnt->cache, dev, tagname); + if (res && findmnt->cache) /* don't return pointer to cache */ res = xstrdup(res); } @@ -480,7 +478,7 @@ static char *get_tag(struct libmnt_fs *fs, const char *tagname, int col return res; } -static char *get_vfs_attr(struct libmnt_fs *fs, int sizetype) +static char *get_vfs_attr(struct libmnt_fs *fs, int sizetype, unsigned int flags) { struct statvfs buf; uint64_t vfs_attr = 0; @@ -616,7 +614,7 @@ static char *get_data_col_sources(struct libmnt_fs *fs, int evaluate, size_t *da /* reads FS data from libmount */ -static char *get_data(struct libmnt_fs *fs, int num, size_t *datasiz) +static char *get_data(struct libmnt_fs *fs, int num, size_t *datasiz, struct findmnt *findmnt) { char *str = NULL; int col_id = get_column_id(num); @@ -624,7 +622,7 @@ static char *get_data(struct libmnt_fs *fs, int num, size_t *datasiz) switch (col_id) { case COL_SOURCES: /* print all devices with the same tag (LABEL, UUID) */ - str = get_data_col_sources(fs, flags & FL_EVALUATE, datasiz); + str = get_data_col_sources(fs, findmnt->flags & FL_EVALUATE, datasiz); if (str) break; @@ -635,19 +633,19 @@ static char *get_data(struct libmnt_fs *fs, int num, size_t *datasiz) const char *spec = mnt_fs_get_srcpath(fs); char *cn = NULL; - if (spec && (flags & FL_CANONICALIZE)) - spec = cn = mnt_resolve_path(spec, cache); + if (spec && (findmnt->flags & FL_CANONICALIZE)) + spec = cn = mnt_resolve_path(spec, findmnt->cache); if (!spec) { spec = mnt_fs_get_source(fs); - if (spec && (flags & FL_EVALUATE)) - spec = cn = mnt_resolve_spec(spec, cache); + if (spec && (findmnt->flags & FL_EVALUATE)) + spec = cn = mnt_resolve_spec(spec, findmnt->cache); } - if (root && spec && !(flags & FL_NOFSROOT) && strcmp(root, "/") != 0) + if (root && spec && !(findmnt->flags & FL_NOFSROOT) && strcmp(root, "/") != 0) xasprintf(&str, "%s[%s]", spec, root); else if (spec) str = xstrdup(spec); - if (!cache) + if (!findmnt->cache) free(cn); break; } @@ -665,7 +663,7 @@ static char *get_data(struct libmnt_fs *fs, int num, size_t *datasiz) str = xstrdup(mnt_fs_get_options(fs)); break; case COL_VFS_OPTIONS: - if (flags & FL_VFS_ALL) + if (findmnt->flags & FL_VFS_ALL) str = mnt_fs_get_vfs_options_all(fs); else if (mnt_fs_get_vfs_options(fs)) str = xstrdup(mnt_fs_get_vfs_options(fs)); @@ -679,16 +677,16 @@ static char *get_data(struct libmnt_fs *fs, int num, size_t *datasiz) str = xstrdup(mnt_fs_get_optional_fields(fs)); break; case COL_UUID: - str = get_tag(fs, "UUID", col_id); + str = get_tag(fs, "UUID", col_id, findmnt); break; case COL_PARTUUID: - str = get_tag(fs, "PARTUUID", col_id); + str = get_tag(fs, "PARTUUID", col_id, findmnt); break; case COL_LABEL: - str = get_tag(fs, "LABEL", col_id); + str = get_tag(fs, "LABEL", col_id, findmnt); break; case COL_PARTLABEL: - str = get_tag(fs, "PARTLABEL", col_id); + str = get_tag(fs, "PARTLABEL", col_id, findmnt); break; case COL_MAJMIN: @@ -697,7 +695,7 @@ static char *get_data(struct libmnt_fs *fs, int num, size_t *datasiz) if (!devno) break; - if ((flags & FL_RAW) || (flags & FL_EXPORT) || (flags & FL_JSON)) + if ((findmnt->flags & FL_RAW) || (findmnt->flags & FL_EXPORT) || (findmnt->flags & FL_JSON)) xasprintf(&str, "%u:%u", major(devno), minor(devno)); else xasprintf(&str, "%3u:%-3u", major(devno), minor(devno)); @@ -711,7 +709,7 @@ static char *get_data(struct libmnt_fs *fs, int num, size_t *datasiz) case COL_INO_AVAIL: case COL_INO_USED: case COL_INO_USEPERC: - str = get_vfs_attr(fs, col_id); + str = get_vfs_attr(fs, col_id, findmnt->flags); break; case COL_FSROOT: if (mnt_fs_get_root(fs)) @@ -770,7 +768,8 @@ static char *get_tabdiff_data(struct libmnt_fs *old_fs, struct libmnt_fs *new_fs, int change, int num, - size_t *datasiz) + size_t *datasiz, + struct findmnt *findmnt) { char *str = NULL; @@ -809,9 +808,9 @@ static char *get_tabdiff_data(struct libmnt_fs *old_fs, break; default: if (new_fs) - str = get_data(new_fs, num, datasiz); + str = get_data(new_fs, num, datasiz, findmnt); else - str = get_data(old_fs, num, datasiz); + str = get_data(old_fs, num, datasiz, findmnt); break; } return str; @@ -833,9 +832,24 @@ static void set_line_data(struct libscols_line *ln, size_t i, char *data, size_t err(EXIT_FAILURE, _("failed to add output data")); } +static int filter_filler_cb( + struct libscols_filter *filter __attribute__((__unused__)), + struct libscols_line *line, + size_t column_index, + void *userdata) +{ + struct filler_data *fid = (struct filler_data *) userdata; + size_t datasiz = 0; + + char *data = get_data(fid->fs, column_index, &datasiz, fid->findmnt); + if (data) + set_line_data(line, column_index, data, datasiz); + return 0; +} + /* adds one line to the output @tab */ static struct libscols_line *add_line(struct libscols_table *table, struct libmnt_fs *fs, - struct libscols_line *parent) + struct libscols_line *parent, struct findmnt *findmnt, bool *filtered) { size_t i; struct libscols_line *line = scols_table_new_line(table, parent); @@ -843,9 +857,36 @@ static struct libscols_line *add_line(struct libscols_table *table, struct libmn if (!line) err(EXIT_FAILURE, _("failed to allocate output line")); + if (findmnt->filter) { + int status = 0; + struct filler_data fid = { + .fs = fs, + .findmnt = findmnt, + }; + + scols_filter_set_filler_cb(findmnt->filter, + filter_filler_cb, (void *) &fid); + + if (scols_line_apply_filter(line, findmnt->filter, &status)) + err(EXIT_FAILURE, _("failed to apply filter")); + + if (status == 0) { + if (parent) + scols_line_remove_child(parent, line); + scols_table_remove_line(table, line); + *filtered = true; + return NULL; + } + } + for (i = 0; i < ncolumns; i++) { size_t datasiz = 0; - char *data = get_data(fs, i, &datasiz); + char *data; + + if (scols_line_is_filled(line, i)) + continue; + + data = get_data(fs, i, &datasiz, findmnt); if (data) set_line_data(line, i, data, datasiz); @@ -856,7 +897,7 @@ static struct libscols_line *add_line(struct libscols_table *table, struct libmn } static struct libscols_line *add_tabdiff_line(struct libscols_table *table, struct libmnt_fs *new_fs, - struct libmnt_fs *old_fs, int change) + struct libmnt_fs *old_fs, int change, struct findmnt *findmnt) { size_t i; struct libscols_line *line = scols_table_new_line(table, NULL); @@ -866,7 +907,7 @@ static struct libscols_line *add_tabdiff_line(struct libscols_table *table, stru for (i = 0; i < ncolumns; i++) { size_t datasiz = 0; - char *data = get_tabdiff_data(old_fs, new_fs, change, i, &datasiz); + char *data = get_tabdiff_data(old_fs, new_fs, change, i, &datasiz, findmnt); if (data) set_line_data(line, i, data, datasiz); @@ -898,7 +939,7 @@ static int has_line(struct libscols_table *table, struct libmnt_fs *fs) /* reads filesystems from @tb (libmount) and fillin @table (output table) */ static int create_treenode(struct libscols_table *table, struct libmnt_table *tb, - struct libmnt_fs *fs, struct libscols_line *parent_line) + struct libmnt_fs *fs, struct libscols_line *parent_line, struct findmnt *findmnt) { struct libmnt_fs *chld = NULL; struct libmnt_iter *itr = NULL; @@ -912,16 +953,17 @@ static int create_treenode(struct libscols_table *table, struct libmnt_table *tb parent_line = NULL; first = 1; - } else if ((flags & FL_SUBMOUNTS) && has_line(table, fs)) + } else if ((findmnt->flags & FL_SUBMOUNTS) && has_line(table, fs)) return 0; itr = mnt_new_iter(MNT_ITER_FORWARD); if (!itr) goto leave; - if ((flags & FL_SUBMOUNTS) || match_func(fs, NULL)) { - line = add_line(table, fs, parent_line); - if (!line) + if ((findmnt->flags & FL_SUBMOUNTS) || match_func(fs, findmnt)) { + bool filtered = false; + line = add_line(table, fs, parent_line, findmnt, &filtered); + if (!line || filtered) goto leave; } else line = parent_line; @@ -930,7 +972,7 @@ static int create_treenode(struct libscols_table *table, struct libmnt_table *tb * add all children to the output table */ while (mnt_table_next_child_fs(tb, itr, fs, &chld) == 0) { - if (create_treenode(table, tb, chld, line)) + if (create_treenode(table, tb, chld, line, findmnt)) goto leave; } rc = 0; @@ -942,8 +984,8 @@ static int create_treenode(struct libscols_table *table, struct libmnt_table *tb fs = NULL; while (mnt_table_next_fs(tb, itr, &fs) == 0) { - if (!has_line(table, fs) && match_func(fs, NULL)) - create_treenode(table, tb, fs, NULL); + if (!has_line(table, fs) && match_func(fs, findmnt)) + create_treenode(table, tb, fs, NULL, findmnt); } } leave: @@ -952,11 +994,12 @@ static int create_treenode(struct libscols_table *table, struct libmnt_table *tb } /* error callback */ -static int parser_errcb(struct libmnt_table *tb __attribute__ ((__unused__)), +static int parser_errcb(struct libmnt_table *tb, const char *filename, int line) { + struct findmnt *findmnt = mnt_table_get_userdata(tb); warnx(_("%s: parse error at line %d -- ignored"), filename, line); - ++parse_nerrors; + findmnt->parse_nerrors++; return 1; } @@ -1085,9 +1128,10 @@ static int tab_is_kernel(struct libmnt_table *tb) /* filter function for libmount (mnt_table_find_next_fs()) */ static int match_func(struct libmnt_fs *fs, - void *data __attribute__ ((__unused__))) + void *data) { - int rc = flags & FL_INVERT ? 1 : 0; + struct findmnt *findmnt = data; + int rc = findmnt->flags & FL_INVERT ? 1 : 0; const char *m; void *md; @@ -1104,14 +1148,14 @@ static int match_func(struct libmnt_fs *fs, return rc; m = get_match(COL_TARGET); - if (m && !mnt_fs_match_target(fs, m, cache)) + if (m && !mnt_fs_match_target(fs, m, findmnt->cache)) return rc; m = get_match(COL_SOURCE); - if (m && !mnt_fs_match_source(fs, m, cache)) + if (m && !mnt_fs_match_source(fs, m, findmnt->cache)) return rc; - if ((flags & FL_DF) && !(flags & FL_ALL)) { + if ((findmnt->flags & FL_DF) && !(findmnt->flags & FL_ALL)) { const char *type = mnt_fs_get_fstype(fs); if (type && strstr(type, "tmpfs")) /* tmpfs is wanted */ @@ -1121,13 +1165,13 @@ static int match_func(struct libmnt_fs *fs, return rc; } - if ((flags & FL_REAL) && mnt_fs_is_pseudofs(fs)) + if ((findmnt->flags & FL_REAL) && mnt_fs_is_pseudofs(fs)) return rc; - if ((flags & FL_PSEUDO) && !mnt_fs_is_pseudofs(fs)) + if ((findmnt->flags & FL_PSEUDO) && !mnt_fs_is_pseudofs(fs)) return rc; - if ((flags & FL_SHADOWED)) { + if ((findmnt->flags & FL_SHADOWED)) { struct libmnt_table *tb = NULL; mnt_fs_get_table(fs, &tb); @@ -1140,18 +1184,19 @@ static int match_func(struct libmnt_fs *fs, /* iterate over filesystems in @tb */ struct libmnt_fs *get_next_fs(struct libmnt_table *tb, - struct libmnt_iter *itr) + struct libmnt_iter *itr, + struct findmnt *findmnt) { struct libmnt_fs *fs = NULL; - if (is_listall_mode()) { + if (is_listall_mode(findmnt->flags)) { /* * Print whole file */ if (mnt_table_next_fs(tb, itr, &fs) != 0) return NULL; - } else if (is_mount_compatible_mode()) { + } else if (is_mount_compatible_mode(findmnt->flags)) { /* * Look up for FS in the same way how mount(8) searches in fstab * @@ -1160,7 +1205,7 @@ struct libmnt_fs *get_next_fs(struct libmnt_table *tb, fs = mnt_table_find_source(tb, get_match(COL_SOURCE), mnt_iter_get_direction(itr)); - if (!fs && !(flags & FL_NOSWAPMATCH)) + if (!fs && !(findmnt->flags & FL_NOSWAPMATCH)) fs = mnt_table_find_target(tb, get_match(COL_SOURCE), mnt_iter_get_direction(itr)); } else { @@ -1171,11 +1216,11 @@ struct libmnt_fs *get_next_fs(struct libmnt_table *tb, * findmnt [-l] [-O ] [-t ] */ again: - if (mnt_table_find_next_fs(tb, itr, match_func, NULL, &fs) != 0) + if (mnt_table_find_next_fs(tb, itr, match_func, findmnt, &fs) != 0) fs = NULL; if (!fs && - !(flags & FL_NOSWAPMATCH) && + !(findmnt->flags & FL_NOSWAPMATCH) && !get_match(COL_TARGET) && get_match(COL_SOURCE)) { /* swap 'spec' and target. */ @@ -1195,7 +1240,8 @@ struct libmnt_fs *get_next_fs(struct libmnt_table *tb, * --submounts tree output. */ static int add_matching_lines(struct libmnt_table *tb, - struct libscols_table *table, int direction) + struct libscols_table *table, int direction, + struct findmnt *findmnt) { struct libmnt_iter *itr; struct libmnt_fs *fs; @@ -1207,17 +1253,22 @@ static int add_matching_lines(struct libmnt_table *tb, goto done; } - while((fs = get_next_fs(tb, itr))) { - if ((flags & FL_TREE) || (flags & FL_SUBMOUNTS)) - rc = create_treenode(table, tb, fs, NULL); - else - rc = !add_line(table, fs, NULL); + while((fs = get_next_fs(tb, itr, findmnt))) { + if ((findmnt->flags & FL_TREE) || (findmnt->flags & FL_SUBMOUNTS)) + rc = create_treenode(table, tb, fs, NULL, findmnt); + else { + bool filtered = false; + struct libscols_line *l = add_line(table, fs, NULL, findmnt, &filtered); + if (filtered) + continue; + rc = !l; + } if (rc) goto done; nlines++; - if (flags & FL_FIRSTONLY) + if (findmnt->flags & FL_FIRSTONLY) break; - flags |= FL_NOSWAPMATCH; + findmnt->flags |= FL_NOSWAPMATCH; } if (nlines) @@ -1227,11 +1278,11 @@ static int add_matching_lines(struct libmnt_table *tb, return rc; } -static int poll_match(struct libmnt_fs *fs) +static int poll_match(struct libmnt_fs *fs, struct findmnt *findmnt) { - int rc = match_func(fs, NULL); + int rc = match_func(fs, findmnt); - if (rc == 0 && !(flags & FL_NOSWAPMATCH) && + if (rc == 0 && !(findmnt->flags & FL_NOSWAPMATCH) && get_match(COL_SOURCE) && !get_match(COL_TARGET)) { /* * findmnt --poll /foo @@ -1242,7 +1293,7 @@ static int poll_match(struct libmnt_fs *fs) set_match(COL_TARGET, str); /* swap */ set_match(COL_SOURCE, NULL); - rc = match_func(fs, NULL); + rc = match_func(fs, findmnt); set_match(COL_TARGET, NULL); /* restore */ set_match(COL_SOURCE, str); @@ -1252,7 +1303,7 @@ static int poll_match(struct libmnt_fs *fs) } static int poll_table(struct libmnt_table *tb, const char *tabfile, - int timeout, struct libscols_table *table, int direction) + int timeout, struct libscols_table *table, int direction, struct findmnt *findmnt) { FILE *f = NULL; int rc = -1; @@ -1321,13 +1372,13 @@ static int poll_table(struct libmnt_table *tb, const char *tabfile, if (!has_poll_action(change)) continue; - if (!poll_match(new ? new : old)) + if (!poll_match(new ? new : old, findmnt)) continue; count++; - rc = !add_tabdiff_line(table, new, old, change); + rc = !add_tabdiff_line(table, new, old, change, findmnt); if (rc) goto done; - if (flags & FL_FIRSTONLY) + if (findmnt->flags & FL_FIRSTONLY) break; } @@ -1347,7 +1398,7 @@ static int poll_table(struct libmnt_table *tb, const char *tabfile, scols_table_remove_lines(table); mnt_reset_table(tb_new); - if (count && (flags & FL_FIRSTONLY)) + if (count && (findmnt->flags & FL_FIRSTONLY)) break; } @@ -1362,14 +1413,15 @@ static int poll_table(struct libmnt_table *tb, const char *tabfile, } static int uniq_fs_target_cmp( - struct libmnt_table *tb __attribute__((__unused__)), + struct libmnt_table *tb, struct libmnt_fs *a, struct libmnt_fs *b) { - return !mnt_fs_match_target(a, mnt_fs_get_target(b), cache); + struct findmnt *findmnt = mnt_table_get_userdata(tb); + return !mnt_fs_match_target(a, mnt_fs_get_target(b), findmnt->cache); } -static int get_column_json_type(int id, int scols_flags, int *multi) +static int get_column_json_type(int id, int scols_flags, int *multi, unsigned int findmnt_flags) { switch (id) { case COL_SIZE: @@ -1377,7 +1429,7 @@ static int get_column_json_type(int id, int scols_flags, int *multi) case COL_USED: if (multi) *multi = 1; - if (!(flags & FL_BYTES)) + if (!(findmnt_flags & FL_BYTES)) break; /* fallthrough */ case COL_ID: @@ -1445,6 +1497,7 @@ static void __attribute__((__noreturn__)) usage(void) fputs(_(" -P, --pairs use key=\"value\" output format\n"), out); fputs(_(" --pseudo print only pseudo-filesystems\n"), out); fputs(_(" --shadowed print only filesystems over-mounted by another filesystem\n"), out); + fputs(_(" -Q, --filter apply display filter\n"), out); fputs(_(" -R, --submounts print all submounts for the matching filesystems\n"), out); fputs(_(" -r, --raw use raw output format\n"), out); fputs(_(" --real print only real filesystems\n"), out); @@ -1473,17 +1526,18 @@ static void __attribute__((__noreturn__)) usage(void) exit(EXIT_SUCCESS); } -static void __attribute__((__noreturn__)) list_colunms(void) +static void __attribute__((__noreturn__)) list_colunms(struct findmnt *findmnt) { size_t i; struct libscols_table *tb = xcolumn_list_table_new("findmnt-columns", stdout, - flags & FL_RAW, - flags & FL_JSON); + findmnt->flags & FL_RAW, + findmnt->flags & FL_JSON); for (i = 0; i < ARRAY_SIZE(infos); i++) { const struct colinfo *ci = &infos[i]; int multi = 0; - int json = get_column_json_type(i, ci->flags, &multi); + int json = get_column_json_type(i, ci->flags, &multi, + findmnt->flags); xcolumn_list_table_append_line(tb, ci->name, multi ? -1 : json, @@ -1497,9 +1551,120 @@ static void __attribute__((__noreturn__)) list_colunms(void) exit(EXIT_SUCCESS); } +static struct libscols_table *init_scols_table(unsigned int flags, bool use_filter) +{ + struct libscols_table *table = scols_new_table(); + if (!table) { + warn(_("failed to allocate output table")); + goto leave; + } + + scols_table_enable_raw(table, !!(flags & FL_RAW)); + scols_table_enable_export(table, !!(flags & FL_EXPORT)); + scols_table_enable_shellvar(table, !!(flags & FL_SHELLVAR)); + scols_table_enable_json(table, !!(flags & FL_JSON)); + scols_table_enable_ascii(table, !!(flags & FL_ASCII)); + scols_table_enable_noheadings(table, !!(flags & FL_NOHEADINGS)); + + if (flags & FL_JSON) + scols_table_set_name(table, "filesystems"); + + for (size_t i = 0; i < ncolumns; i++) { + struct libscols_column *cl; + int fl = get_column_flags(i); + int id = get_column_id(i); + + if (!(flags & FL_TREE)) + fl &= ~SCOLS_FL_TREE; + + if (!(flags & FL_POLL) && is_tabdiff_column(id)) { + warnx(_("%s column is requested, but --poll " + "is not enabled"), get_column_name(i)); + goto leave; + } + cl = scols_table_new_column(table, get_column_name(i), + get_column_whint(i), fl); + if (!cl) { + warn(_("failed to allocate output column")); + goto leave; + } + /* multi-line cells (now used for SOURCES) */ + if (fl & SCOLS_FL_WRAP) + scols_column_set_wrapfunc(cl, + NULL, + scols_wrapzero_nextchunk, + NULL); + if ((flags & FL_JSON) || use_filter) + scols_column_set_json_type(cl, get_column_json_type(id, fl, NULL, + flags)); + } + + leave: + return table; +} + +static struct libscols_filter *new_filter(const char *query) +{ + struct libscols_filter *f; + + f = scols_new_filter(NULL); + if (!f) + err(EXIT_FAILURE, _("failed to allocate filter")); + if (query && scols_filter_parse_string(f, query) != 0) + errx(EXIT_FAILURE, _("failed to parse \"%s\": %s"), query, + scols_filter_get_errmsg(f)); + return f; +} + +static void init_scols_filter(struct libscols_table *tb, struct libscols_filter *f, unsigned int flags) +{ + struct libscols_iter *itr; + const char *name = NULL; + int nerrs = 0; + + itr = scols_new_iter(SCOLS_ITER_FORWARD); + if (!itr) + err(EXIT_FAILURE, _("failed to allocate iterator")); + + while (scols_filter_next_holder(f, itr, &name, 0) == 0) { + struct libscols_column *col = scols_table_get_column_by_name(tb, name); + int id = column_name_to_id(name, strlen(name)); + const struct colinfo *ci = id >= 0 ? &infos[id] : NULL; + + if (!ci) { + nerrs++; + continue; /* report all unknown columns */ + } + if (!col) { + int json = get_column_json_type(id, ci->flags, NULL, flags); + add_column(id); + col = scols_table_new_column(tb, ci->name, + ci->whint, SCOLS_FL_HIDDEN); + if (!col) + err(EXIT_FAILURE,_("failed to allocate output column")); + + scols_column_set_json_type(col, json); + } + + scols_filter_assign_column(f, itr, name, col); + } + + scols_free_iter(itr); + + if (!nerrs) + return; + + errx(EXIT_FAILURE, _("failed to initialize filter")); +} int main(int argc, char *argv[]) { + struct findmnt findmnt = { + .cache = NULL, + .flags = 0, + .parse_nerrors = 0, + .filter = NULL, + }; struct libmnt_table *tb = NULL; char **tabfiles = NULL; int direction = MNT_ITER_FORWARD; @@ -1547,6 +1712,7 @@ int main(int argc, char *argv[]) { "output-all", no_argument, NULL, FINDMNT_OPT_OUTPUT_ALL }, { "poll", optional_argument, NULL, 'p' }, { "pairs", no_argument, NULL, 'P' }, + { "filter", required_argument, NULL, 'Q' }, { "raw", no_argument, NULL, 'r' }, { "types", required_argument, NULL, 't' }, { "nocanonicalize", no_argument, NULL, 'C' }, @@ -1578,6 +1744,7 @@ int main(int argc, char *argv[]) { 'M', 'T' }, /* mountpoint, target */ { 'N','k','m','s' }, /* task,kernel,mtab,fstab */ { 'P','l','r','x' }, /* pairs,list,raw,verify */ + { 'Q', 'p' }, /* filter,poll */ { 'p','x' }, /* poll,verify */ { 'm','p','s' }, /* mtab,poll,fstab */ { FINDMNT_OPT_PSEUDO, FINDMNT_OPT_REAL }, @@ -1591,33 +1758,33 @@ int main(int argc, char *argv[]) close_stdout_atexit(); /* default output format */ - flags |= FL_TREE; + findmnt.flags |= FL_TREE; while ((c = getopt_long(argc, argv, - "AabCcDd:ehIiJfF:o:O:p::PklmM:nN:rst:uvRS:T:Uw:VxyH", + "AabCcDd:ehIiJfF:o:O:p::PQ:klmM:nN:rst:uvRS:T:Uw:VxyH", longopts, NULL)) != -1) { err_exclusive_options(c, longopts, excl, excl_st); switch(c) { case 'A': - flags |= FL_ALL; + findmnt.flags |= FL_ALL; break; case 'a': - flags |= FL_ASCII; + findmnt.flags |= FL_ASCII; break; case 'b': - flags |= FL_BYTES; + findmnt.flags |= FL_BYTES; break; case 'C': - flags |= FL_NOCACHE; + findmnt.flags |= FL_NOCACHE; break; case 'c': - flags |= FL_CANONICALIZE; + findmnt.flags |= FL_CANONICALIZE; break; case 'D': - flags &= ~FL_TREE; - flags |= FL_DF; + findmnt.flags &= ~FL_TREE; + findmnt.flags |= FL_DF; break; case 'd': if (!strcmp(optarg, "forward")) @@ -1629,20 +1796,20 @@ int main(int argc, char *argv[]) _("unknown direction '%s'"), optarg); break; case 'e': - flags |= FL_EVALUATE; + findmnt.flags |= FL_EVALUATE; break; case 'I': - flags &= ~FL_TREE; - flags |= (FL_DF_INODES | FL_DF); + findmnt.flags &= ~FL_TREE; + findmnt.flags |= (FL_DF_INODES | FL_DF); break; case 'i': - flags |= FL_INVERT; + findmnt.flags |= FL_INVERT; break; case 'J': - flags |= FL_JSON; + findmnt.flags |= FL_JSON; break; case 'f': - flags |= FL_FIRSTONLY; + findmnt.flags |= FL_FIRSTONLY; break; case 'F': tabfiles = append_tabfile(tabfiles, &ntabfiles, optarg); @@ -1672,20 +1839,24 @@ int main(int argc, char *argv[]) if (nactions < 0) exit(EXIT_FAILURE); } - flags |= FL_POLL; - flags &= ~FL_TREE; + findmnt.flags |= FL_POLL; + findmnt.flags &= ~FL_TREE; break; case 'P': - flags |= FL_EXPORT; - flags &= ~FL_TREE; + findmnt.flags |= FL_EXPORT; + findmnt.flags &= ~FL_TREE; + break; + case 'Q': + findmnt.filter = new_filter(optarg); + findmnt.flags &= ~FL_TREE; break; case 'm': /* mtab */ tabtype = TABTYPE_MTAB; - flags &= ~FL_TREE; + findmnt.flags &= ~FL_TREE; break; case 's': /* fstab */ tabtype = TABTYPE_FSTAB; - flags &= ~FL_TREE; + findmnt.flags &= ~FL_TREE; break; case 'k': /* kernel (mountinfo) */ tabtype = TABTYPE_KERNEL; @@ -1694,14 +1865,14 @@ int main(int argc, char *argv[]) set_match(COL_FSTYPE, optarg); break; case 'r': - flags &= ~FL_TREE; /* disable the default */ - flags |= FL_RAW; /* enable raw */ + findmnt.flags &= ~FL_TREE; /* disable the default */ + findmnt.flags |= FL_RAW; /* enable raw */ break; case 'l': - flags &= ~FL_TREE; /* disable the default */ + findmnt.flags &= ~FL_TREE; /* disable the default */ break; case 'n': - flags |= FL_NOHEADINGS; + findmnt.flags |= FL_NOHEADINGS; break; case 'N': tabtype = TABTYPE_KERNEL; @@ -1710,24 +1881,24 @@ int main(int argc, char *argv[]) _("invalid TID argument"))); break; case 'v': - flags |= FL_NOFSROOT; + findmnt.flags |= FL_NOFSROOT; break; case 'R': - flags |= FL_SUBMOUNTS; + findmnt.flags |= FL_SUBMOUNTS; break; case 'S': - set_source_match(optarg); - flags |= FL_NOSWAPMATCH; + set_source_match(optarg, &findmnt); + findmnt.flags |= FL_NOSWAPMATCH; break; case 'M': - flags |= FL_STRICTTARGET; + findmnt.flags |= FL_STRICTTARGET; /* fallthrough */ case 'T': set_match(COL_TARGET, optarg); - flags |= FL_NOSWAPMATCH; + findmnt.flags |= FL_NOSWAPMATCH; break; case 'U': - flags |= FL_UNIQ; + findmnt.flags |= FL_UNIQ; break; case 'w': timeout = strtos32_or_err(optarg, _("invalid timeout argument")); @@ -1736,25 +1907,25 @@ int main(int argc, char *argv[]) verify = 1; break; case 'y': - flags |= FL_SHELLVAR; + findmnt.flags |= FL_SHELLVAR; break; case FINDMNT_OPT_VERBOSE: - flags |= FL_VERBOSE; + findmnt.flags |= FL_VERBOSE; break; case FINDMNT_OPT_TREE: force_tree = 1; break; case FINDMNT_OPT_PSEUDO: - flags |= FL_PSEUDO; + findmnt.flags |= FL_PSEUDO; break; case FINDMNT_OPT_REAL: - flags |= FL_REAL; + findmnt.flags |= FL_REAL; break; case FINDMNT_OPT_VFS_ALL: - flags |= FL_VFS_ALL; + findmnt.flags |= FL_VFS_ALL; break; case FINDMNT_OPT_SHADOWED: - flags |= FL_SHADOWED; + findmnt.flags |= FL_SHADOWED; break; case 'H': @@ -1770,34 +1941,34 @@ int main(int argc, char *argv[]) } if (collist) - list_colunms(); /* print end exit */ - - if (!ncolumns && (flags & FL_DF)) { - add_column(columns, ncolumns++, COL_SOURCE); - add_column(columns, ncolumns++, COL_FSTYPE); - if (flags & FL_DF_INODES) { - add_column(columns, ncolumns++, COL_INO_TOTAL); - add_column(columns, ncolumns++, COL_INO_USED); - add_column(columns, ncolumns++, COL_INO_AVAIL); - add_column(columns, ncolumns++, COL_INO_USEPERC); + list_colunms(&findmnt); /* print end exit */ + + if (!ncolumns && (findmnt.flags & FL_DF)) { + add_column(COL_SOURCE); + add_column(COL_FSTYPE); + if (findmnt.flags & FL_DF_INODES) { + add_column(COL_INO_TOTAL); + add_column(COL_INO_USED); + add_column(COL_INO_AVAIL); + add_column(COL_INO_USEPERC); } else { - add_column(columns, ncolumns++, COL_SIZE); - add_column(columns, ncolumns++, COL_USED); - add_column(columns, ncolumns++, COL_AVAIL); - add_column(columns, ncolumns++, COL_USEPERC); + add_column(COL_SIZE); + add_column(COL_USED); + add_column(COL_AVAIL); + add_column(COL_USEPERC); } - add_column(columns, ncolumns++, COL_TARGET); + add_column(COL_TARGET); } /* default columns */ if (!ncolumns) { - if (flags & FL_POLL) - add_column(columns, ncolumns++, COL_ACTION); + if (findmnt.flags & FL_POLL) + add_column(COL_ACTION); - add_column(columns, ncolumns++, COL_TARGET); - add_column(columns, ncolumns++, COL_SOURCE); - add_column(columns, ncolumns++, COL_FSTYPE); - add_column(columns, ncolumns++, COL_OPTIONS); + add_column(COL_TARGET); + add_column(COL_SOURCE); + add_column(COL_FSTYPE); + add_column(COL_OPTIONS); } if (outarg && string_add_to_idarray(outarg, columns, ARRAY_SIZE(columns), @@ -1807,7 +1978,7 @@ int main(int argc, char *argv[]) if (!tabtype) tabtype = verify ? TABTYPE_FSTAB : TABTYPE_KERNEL; - if ((flags & FL_POLL) && ntabfiles > 1) + if ((findmnt.flags & FL_POLL) && ntabfiles > 1) errx(EXIT_FAILURE, _("--poll accepts only one file, but more specified by --tab-file")); if (optind < argc && (get_match(COL_SOURCE) || get_match(COL_TARGET))) @@ -1816,21 +1987,21 @@ int main(int argc, char *argv[]) "with command line element that is not an option")); if (optind < argc) - set_source_match(argv[optind++]); /* dev/tag/mountpoint/maj:min */ + set_source_match(argv[optind++], &findmnt); /* dev/tag/mountpoint/maj:min */ if (optind < argc) set_match(COL_TARGET, argv[optind++]); /* mountpoint */ - if ((flags & FL_SUBMOUNTS) && is_listall_mode()) + if ((findmnt.flags & FL_SUBMOUNTS) && is_listall_mode(findmnt.flags)) /* don't care about submounts if list all mounts */ - flags &= ~FL_SUBMOUNTS; + findmnt.flags &= ~FL_SUBMOUNTS; - if (!(flags & FL_SUBMOUNTS) && ((flags & FL_FIRSTONLY) + if (!(findmnt.flags & FL_SUBMOUNTS) && ((findmnt.flags & FL_FIRSTONLY) || get_match(COL_TARGET) || get_match(COL_SOURCE) || get_match(COL_MAJMIN))) - flags &= ~FL_TREE; + findmnt.flags &= ~FL_TREE; - if (!(flags & FL_NOSWAPMATCH) && + if (!(findmnt.flags & FL_NOSWAPMATCH) && !get_match(COL_TARGET) && get_match(COL_SOURCE)) { /* * Check if we can swap source and target, it's @@ -1840,7 +2011,7 @@ int main(int argc, char *argv[]) if (!strncmp(x, "LABEL=", 6) || !strncmp(x, "UUID=", 5) || !strncmp(x, "PARTLABEL=", 10) || !strncmp(x, "PARTUUID=", 9)) - flags |= FL_NOSWAPMATCH; + findmnt.flags |= FL_NOSWAPMATCH; } /* @@ -1851,34 +2022,35 @@ int main(int argc, char *argv[]) tb = parse_tabfiles(tabfiles, ntabfiles, tabtype); if (!tb) goto leave; + mnt_table_set_userdata(tb, &findmnt); if (tabtype == TABTYPE_MTAB && tab_is_kernel(tb)) tabtype = TABTYPE_KERNEL; istree = tab_is_tree(tb); if (istree && force_tree) - flags |= FL_TREE; + findmnt.flags |= FL_TREE; - if ((flags & FL_TREE) && (ntabfiles > 1 || !istree)) - flags &= ~FL_TREE; + if ((findmnt.flags & FL_TREE) && (ntabfiles > 1 || !istree)) + findmnt.flags &= ~FL_TREE; - if (!(flags & FL_NOCACHE)) { - cache = mnt_new_cache(); - if (!cache) { + if (!(findmnt.flags & FL_NOCACHE)) { + findmnt.cache = mnt_new_cache(); + if (!findmnt.cache) { warn(_("failed to initialize libmount cache")); goto leave; } - mnt_table_set_cache(tb, cache); + mnt_table_set_cache(tb, findmnt.cache); if (tabtype != TABTYPE_KERNEL) - cache_set_targets(cache); + cache_set_targets(findmnt.cache); } - if (flags & FL_UNIQ) + if (findmnt.flags & FL_UNIQ) mnt_table_uniq_fs(tb, MNT_UNIQ_KEEPTREE, uniq_fs_target_cmp); if (verify) { - rc = verify_table(tb); + rc = verify_table(tb, &findmnt); goto leave; } @@ -1886,89 +2058,52 @@ int main(int argc, char *argv[]) * initialize libsmartcols */ scols_init_debug(0); - table = scols_new_table(); - if (!table) { - warn(_("failed to allocate output table")); + table = init_scols_table(findmnt.flags, findmnt.filter? true: false); + if (!table) goto leave; - } - scols_table_enable_raw(table, !!(flags & FL_RAW)); - scols_table_enable_export(table, !!(flags & FL_EXPORT)); - scols_table_enable_shellvar(table, !!(flags & FL_SHELLVAR)); - scols_table_enable_json(table, !!(flags & FL_JSON)); - scols_table_enable_ascii(table, !!(flags & FL_ASCII)); - scols_table_enable_noheadings(table, !!(flags & FL_NOHEADINGS)); - - if (flags & FL_JSON) - scols_table_set_name(table, "filesystems"); - - for (i = 0; i < ncolumns; i++) { - struct libscols_column *cl; - int fl = get_column_flags(i); - int id = get_column_id(i); - - if (!(flags & FL_TREE)) - fl &= ~SCOLS_FL_TREE; - if (!(flags & FL_POLL) && is_tabdiff_column(id)) { - warnx(_("%s column is requested, but --poll " - "is not enabled"), get_column_name(i)); - goto leave; - } - cl = scols_table_new_column(table, get_column_name(i), - get_column_whint(i), fl); - if (!cl) { - warn(_("failed to allocate output column")); - goto leave; - } - /* multi-line cells (now used for SOURCES) */ - if (fl & SCOLS_FL_WRAP) - scols_column_set_wrapfunc(cl, - NULL, - scols_wrapzero_nextchunk, - NULL); - if (flags & FL_JSON) - scols_column_set_json_type(cl, get_column_json_type(id, fl, NULL)); - } + init_scols_filter(table, findmnt.filter, findmnt.flags); /* * Fill in data to the output table */ - if (flags & FL_POLL) { + if (findmnt.flags & FL_POLL) { /* poll mode (accept the first tabfile only) */ - rc = poll_table(tb, tabfiles ? *tabfiles : _PATH_PROC_MOUNTINFO, timeout, table, direction); + rc = poll_table(tb, tabfiles ? *tabfiles : _PATH_PROC_MOUNTINFO, timeout, table, direction, &findmnt); - } else if ((flags & FL_TREE) && !(flags & FL_SUBMOUNTS)) { + } else if ((findmnt.flags & FL_TREE) && !(findmnt.flags & FL_SUBMOUNTS)) { /* whole tree */ - rc = create_treenode(table, tb, NULL, NULL); + rc = create_treenode(table, tb, NULL, NULL, &findmnt); } else { /* whole list of sub-tree */ - rc = add_matching_lines(tb, table, direction); + rc = add_matching_lines(tb, table, direction, &findmnt); if (rc != 0 && tabtype == TABTYPE_KERNEL - && (flags & FL_NOSWAPMATCH) - && !(flags & FL_STRICTTARGET) + && (findmnt.flags & FL_NOSWAPMATCH) + && !(findmnt.flags & FL_STRICTTARGET) && get_match(COL_TARGET)) { /* * Found nothing, maybe the --target is regular file, * try it again with extra functionality for target * match */ - enable_extra_target_match(tb); - rc = add_matching_lines(tb, table, direction); + enable_extra_target_match(tb, &findmnt); + rc = add_matching_lines(tb, table, direction, &findmnt); } } /* * Print the output table for non-poll modes */ - if (!rc && !(flags & FL_POLL)) + if (!rc && !(findmnt.flags & FL_POLL)) scols_print_table(table); leave: scols_unref_table(table); + scols_unref_filter(findmnt.filter); mnt_unref_table(tb); - mnt_unref_cache(cache); + mnt_unref_cache(findmnt.cache); free(tabfiles); #ifdef HAVE_LIBUDEV diff --git a/misc-utils/findmnt.h b/misc-utils/findmnt.h index 85ab68da554..a8ebdea1c1d 100644 --- a/misc-utils/findmnt.h +++ b/misc-utils/findmnt.h @@ -35,12 +35,15 @@ enum { FL_JSON = (1 << 30), }; -extern struct libmnt_cache *cache; -extern unsigned int flags; -extern int parse_nerrors; +struct findmnt { + struct libmnt_cache *cache; + unsigned int flags; + int parse_nerrors; + struct libscols_filter *filter; +}; -extern int is_listall_mode(void); -extern struct libmnt_fs *get_next_fs(struct libmnt_table *tb, struct libmnt_iter *itr); -extern int verify_table(struct libmnt_table *tb); +extern int is_listall_mode(unsigned int flags); +extern struct libmnt_fs *get_next_fs(struct libmnt_table *tb, struct libmnt_iter *itr, struct findmnt *findmnt); +extern int verify_table(struct libmnt_table *tb, struct findmnt *findmnt); #endif /* UTIL_LINUX_FINDMNT_H */ diff --git a/tests/expected/findmnt/filterQ-options b/tests/expected/findmnt/filterQ-options new file mode 100644 index 00000000000..f8aae935ab9 --- /dev/null +++ b/tests/expected/findmnt/filterQ-options @@ -0,0 +1,31 @@ +TARGET SOURCE FSTYPE OPTIONS +/proc /proc proc rw,relatime +/sys /sys sysfs rw,relatime +/dev udev devtmpfs rw,relatime,size=1983516k,nr_inodes=495879,mode=755 +/dev/pts devpts devpts rw,relatime,gid=5,mode=620,ptmxmode=000 +/dev/shm tmpfs tmpfs rw,relatime +/sys/fs/cgroup tmpfs tmpfs rw,nosuid,nodev,noexec,relatime,mode=755 +/sys/fs/cgroup/systemd cgroup cgroup rw,nosuid,nodev,noexec,relatime,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd +/sys/fs/cgroup/cpuset cgroup cgroup rw,nosuid,nodev,noexec,relatime,cpuset +/sys/fs/cgroup/ns cgroup cgroup rw,nosuid,nodev,noexec,relatime,ns +/sys/fs/cgroup/cpu cgroup cgroup rw,nosuid,nodev,noexec,relatime,cpu +/sys/fs/cgroup/cpuacct cgroup cgroup rw,nosuid,nodev,noexec,relatime,cpuacct +/sys/fs/cgroup/memory cgroup cgroup rw,nosuid,nodev,noexec,relatime,memory +/sys/fs/cgroup/devices cgroup cgroup rw,nosuid,nodev,noexec,relatime,devices +/sys/fs/cgroup/freezer cgroup cgroup rw,nosuid,nodev,noexec,relatime,freezer +/sys/fs/cgroup/net_cls cgroup cgroup rw,nosuid,nodev,noexec,relatime,net_cls +/sys/fs/cgroup/blkio cgroup cgroup rw,nosuid,nodev,noexec,relatime,blkio +/sys/kernel/security systemd-1 autofs rw,relatime,fd=22,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/dev/hugepages systemd-1 autofs rw,relatime,fd=23,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/sys/kernel/debug systemd-1 autofs rw,relatime,fd=24,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/proc/sys/fs/binfmt_misc systemd-1 autofs rw,relatime,fd=25,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/dev/mqueue systemd-1 autofs rw,relatime,fd=26,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/proc/bus/usb /proc/bus/usb usbfs rw,relatime +/dev/hugepages hugetlbfs hugetlbfs rw,relatime +/dev/mqueue mqueue mqueue rw,relatime +/proc/sys/fs/binfmt_misc none binfmt_misc rw,relatime +/sys/fs/fuse/connections fusectl fusectl rw,relatime +/home/kzak/.gvfs gvfs-fuse-daemon fuse.gvfs-fuse-daemon rw,nosuid,nodev,relatime,user_id=500,group_id=500 +/var/lib/nfs/rpc_pipefs sunrpc rpc_pipefs rw,relatime +/mnt/sounds //foo.home/bar/ cifs rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344 +rc=0 diff --git a/tests/expected/findmnt/filterQ-options-name b/tests/expected/findmnt/filterQ-options-name new file mode 100644 index 00000000000..a3a0ead5887 --- /dev/null +++ b/tests/expected/findmnt/filterQ-options-name @@ -0,0 +1,7 @@ +TARGET SOURCE FSTYPE OPTIONS +/sys/kernel/security systemd-1 autofs rw,relatime,fd=22,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/dev/hugepages systemd-1 autofs rw,relatime,fd=23,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/sys/kernel/debug systemd-1 autofs rw,relatime,fd=24,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/proc/sys/fs/binfmt_misc systemd-1 autofs rw,relatime,fd=25,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/dev/mqueue systemd-1 autofs rw,relatime,fd=26,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +rc=0 diff --git a/tests/expected/findmnt/filterQ-options-nameval b/tests/expected/findmnt/filterQ-options-nameval new file mode 100644 index 00000000000..21219c52427 --- /dev/null +++ b/tests/expected/findmnt/filterQ-options-nameval @@ -0,0 +1,3 @@ +TARGET SOURCE FSTYPE OPTIONS +/sys/kernel/security systemd-1 autofs rw,relatime,fd=22,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +rc=0 diff --git a/tests/expected/findmnt/filterQ-options-nameval-multi b/tests/expected/findmnt/filterQ-options-nameval-multi new file mode 100644 index 00000000000..f2ab3ce4f0b --- /dev/null +++ b/tests/expected/findmnt/filterQ-options-nameval-multi @@ -0,0 +1,3 @@ +TARGET SOURCE FSTYPE OPTIONS +/dev/pts devpts devpts rw,relatime,gid=5,mode=620,ptmxmode=000 +rc=0 diff --git a/tests/expected/findmnt/filterQ-options-nameval-neg b/tests/expected/findmnt/filterQ-options-nameval-neg new file mode 100644 index 00000000000..bdd21952a67 --- /dev/null +++ b/tests/expected/findmnt/filterQ-options-nameval-neg @@ -0,0 +1,33 @@ +TARGET SOURCE FSTYPE OPTIONS +/proc /proc proc rw,relatime +/sys /sys sysfs rw,relatime +/dev udev devtmpfs rw,relatime,size=1983516k,nr_inodes=495879,mode=755 +/dev/pts devpts devpts rw,relatime,gid=5,mode=620,ptmxmode=000 +/dev/shm tmpfs tmpfs rw,relatime +/ /dev/sda4 ext3 rw,noatime,errors=continue,user_xattr,acl,barrier=0,data=ordered +/sys/fs/cgroup tmpfs tmpfs rw,nosuid,nodev,noexec,relatime,mode=755 +/sys/fs/cgroup/systemd cgroup cgroup rw,nosuid,nodev,noexec,relatime,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd +/sys/fs/cgroup/cpuset cgroup cgroup rw,nosuid,nodev,noexec,relatime,cpuset +/sys/fs/cgroup/ns cgroup cgroup rw,nosuid,nodev,noexec,relatime,ns +/sys/fs/cgroup/cpu cgroup cgroup rw,nosuid,nodev,noexec,relatime,cpu +/sys/fs/cgroup/cpuacct cgroup cgroup rw,nosuid,nodev,noexec,relatime,cpuacct +/sys/fs/cgroup/memory cgroup cgroup rw,nosuid,nodev,noexec,relatime,memory +/sys/fs/cgroup/devices cgroup cgroup rw,nosuid,nodev,noexec,relatime,devices +/sys/fs/cgroup/freezer cgroup cgroup rw,nosuid,nodev,noexec,relatime,freezer +/sys/fs/cgroup/net_cls cgroup cgroup rw,nosuid,nodev,noexec,relatime,net_cls +/sys/fs/cgroup/blkio cgroup cgroup rw,nosuid,nodev,noexec,relatime,blkio +/dev/hugepages systemd-1 autofs rw,relatime,fd=23,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/sys/kernel/debug systemd-1 autofs rw,relatime,fd=24,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/proc/sys/fs/binfmt_misc systemd-1 autofs rw,relatime,fd=25,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/dev/mqueue systemd-1 autofs rw,relatime,fd=26,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/proc/bus/usb /proc/bus/usb usbfs rw,relatime +/dev/hugepages hugetlbfs hugetlbfs rw,relatime +/dev/mqueue mqueue mqueue rw,relatime +/boot /dev/sda6 ext3 rw,noatime,errors=continue,barrier=0,data=ordered +/home/kzak /dev/mapper/kzak-home ext4 rw,noatime,barrier=1,data=ordered +/proc/sys/fs/binfmt_misc none binfmt_misc rw,relatime +/sys/fs/fuse/connections fusectl fusectl rw,relatime +/home/kzak/.gvfs gvfs-fuse-daemon fuse.gvfs-fuse-daemon rw,nosuid,nodev,relatime,user_id=500,group_id=500 +/var/lib/nfs/rpc_pipefs sunrpc rpc_pipefs rw,relatime +/mnt/sounds //foo.home/bar/ cifs rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344 +rc=0 diff --git a/tests/expected/findmnt/filterQ-options-neg b/tests/expected/findmnt/filterQ-options-neg new file mode 100644 index 00000000000..323d9b2a97d --- /dev/null +++ b/tests/expected/findmnt/filterQ-options-neg @@ -0,0 +1,5 @@ +TARGET SOURCE FSTYPE OPTIONS +/ /dev/sda4 ext3 rw,noatime,errors=continue,user_xattr,acl,barrier=0,data=ordered +/boot /dev/sda6 ext3 rw,noatime,errors=continue,barrier=0,data=ordered +/home/kzak /dev/mapper/kzak-home ext4 rw,noatime,barrier=1,data=ordered +rc=0 diff --git a/tests/expected/findmnt/filterQ-options-no b/tests/expected/findmnt/filterQ-options-no new file mode 100644 index 00000000000..323d9b2a97d --- /dev/null +++ b/tests/expected/findmnt/filterQ-options-no @@ -0,0 +1,5 @@ +TARGET SOURCE FSTYPE OPTIONS +/ /dev/sda4 ext3 rw,noatime,errors=continue,user_xattr,acl,barrier=0,data=ordered +/boot /dev/sda6 ext3 rw,noatime,errors=continue,barrier=0,data=ordered +/home/kzak /dev/mapper/kzak-home ext4 rw,noatime,barrier=1,data=ordered +rc=0 diff --git a/tests/expected/findmnt/filterQ-options-no-multi b/tests/expected/findmnt/filterQ-options-no-multi new file mode 100644 index 00000000000..2d714ae5cda --- /dev/null +++ b/tests/expected/findmnt/filterQ-options-no-multi @@ -0,0 +1,3 @@ +TARGET SOURCE FSTYPE OPTIONS +/sys/fs/cgroup/blkio cgroup cgroup rw,nosuid,nodev,noexec,relatime,blkio +rc=0 diff --git a/tests/expected/findmnt/filterQ-types b/tests/expected/findmnt/filterQ-types new file mode 100644 index 00000000000..6a69a66b1fd --- /dev/null +++ b/tests/expected/findmnt/filterQ-types @@ -0,0 +1,4 @@ +TARGET SOURCE FSTYPE OPTIONS +/ /dev/sda4 ext3 rw,noatime,errors=continue,user_xattr,acl,barrier=0,data=ordered +/boot /dev/sda6 ext3 rw,noatime,errors=continue,barrier=0,data=ordered +rc=0 diff --git a/tests/expected/findmnt/filterQ-types-multi b/tests/expected/findmnt/filterQ-types-multi new file mode 100644 index 00000000000..323d9b2a97d --- /dev/null +++ b/tests/expected/findmnt/filterQ-types-multi @@ -0,0 +1,5 @@ +TARGET SOURCE FSTYPE OPTIONS +/ /dev/sda4 ext3 rw,noatime,errors=continue,user_xattr,acl,barrier=0,data=ordered +/boot /dev/sda6 ext3 rw,noatime,errors=continue,barrier=0,data=ordered +/home/kzak /dev/mapper/kzak-home ext4 rw,noatime,barrier=1,data=ordered +rc=0 diff --git a/tests/expected/findmnt/filterQ-types-neg b/tests/expected/findmnt/filterQ-types-neg new file mode 100644 index 00000000000..f8aae935ab9 --- /dev/null +++ b/tests/expected/findmnt/filterQ-types-neg @@ -0,0 +1,31 @@ +TARGET SOURCE FSTYPE OPTIONS +/proc /proc proc rw,relatime +/sys /sys sysfs rw,relatime +/dev udev devtmpfs rw,relatime,size=1983516k,nr_inodes=495879,mode=755 +/dev/pts devpts devpts rw,relatime,gid=5,mode=620,ptmxmode=000 +/dev/shm tmpfs tmpfs rw,relatime +/sys/fs/cgroup tmpfs tmpfs rw,nosuid,nodev,noexec,relatime,mode=755 +/sys/fs/cgroup/systemd cgroup cgroup rw,nosuid,nodev,noexec,relatime,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd +/sys/fs/cgroup/cpuset cgroup cgroup rw,nosuid,nodev,noexec,relatime,cpuset +/sys/fs/cgroup/ns cgroup cgroup rw,nosuid,nodev,noexec,relatime,ns +/sys/fs/cgroup/cpu cgroup cgroup rw,nosuid,nodev,noexec,relatime,cpu +/sys/fs/cgroup/cpuacct cgroup cgroup rw,nosuid,nodev,noexec,relatime,cpuacct +/sys/fs/cgroup/memory cgroup cgroup rw,nosuid,nodev,noexec,relatime,memory +/sys/fs/cgroup/devices cgroup cgroup rw,nosuid,nodev,noexec,relatime,devices +/sys/fs/cgroup/freezer cgroup cgroup rw,nosuid,nodev,noexec,relatime,freezer +/sys/fs/cgroup/net_cls cgroup cgroup rw,nosuid,nodev,noexec,relatime,net_cls +/sys/fs/cgroup/blkio cgroup cgroup rw,nosuid,nodev,noexec,relatime,blkio +/sys/kernel/security systemd-1 autofs rw,relatime,fd=22,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/dev/hugepages systemd-1 autofs rw,relatime,fd=23,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/sys/kernel/debug systemd-1 autofs rw,relatime,fd=24,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/proc/sys/fs/binfmt_misc systemd-1 autofs rw,relatime,fd=25,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/dev/mqueue systemd-1 autofs rw,relatime,fd=26,pgrp=1,timeout=300,minproto=5,maxproto=5,direct +/proc/bus/usb /proc/bus/usb usbfs rw,relatime +/dev/hugepages hugetlbfs hugetlbfs rw,relatime +/dev/mqueue mqueue mqueue rw,relatime +/proc/sys/fs/binfmt_misc none binfmt_misc rw,relatime +/sys/fs/fuse/connections fusectl fusectl rw,relatime +/home/kzak/.gvfs gvfs-fuse-daemon fuse.gvfs-fuse-daemon rw,nosuid,nodev,relatime,user_id=500,group_id=500 +/var/lib/nfs/rpc_pipefs sunrpc rpc_pipefs rw,relatime +/mnt/sounds //foo.home/bar/ cifs rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344 +rc=0 diff --git a/tests/ts/findmnt/filterQ b/tests/ts/findmnt/filterQ new file mode 100755 index 00000000000..4f5f724c953 --- /dev/null +++ b/tests/ts/findmnt/filterQ @@ -0,0 +1,77 @@ +#!/bin/bash + +# This file is part of util-linux. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +TS_TOPDIR="${0%/*}/../.." +TS_DESC="filterQ" + +. "$TS_TOPDIR"/functions.sh +ts_init "$*" + +ts_check_test_command "$TS_CMD_FINDMNT" + +ts_init_subtest "types" +$TS_CMD_FINDMNT -Q 'FSTYPE == "ext3"' --kernel --tab-file "$TS_SELF/files/mountinfo" &> $TS_OUTPUT +echo rc=$? >> $TS_OUTPUT +ts_finalize_subtest + +ts_init_subtest "types-multi" +$TS_CMD_FINDMNT -Q 'FSTYPE =~ "ext[34]"' --kernel --tab-file "$TS_SELF/files/mountinfo" &> $TS_OUTPUT +echo rc=$? >> $TS_OUTPUT +ts_finalize_subtest + +ts_init_subtest "types-neg" +$TS_CMD_FINDMNT -Q 'FSTYPE !~ "ext[34]"' --kernel --tab-file "$TS_SELF/files/mountinfo" &> $TS_OUTPUT +echo rc=$? >> $TS_OUTPUT +ts_finalize_subtest + +ts_init_subtest "options" +$TS_CMD_FINDMNT -Q 'OPTIONS =~ "\"' --kernel --tab-file "$TS_SELF/files/mountinfo" &> $TS_OUTPUT +echo rc=$? >> $TS_OUTPUT +ts_finalize_subtest + +ts_init_subtest "options-name" +$TS_CMD_FINDMNT -Q 'OPTIONS =~ "\"' --kernel --tab-file "$TS_SELF/files/mountinfo" &> $TS_OUTPUT +echo rc=$? >> $TS_OUTPUT +ts_finalize_subtest + +ts_init_subtest "options-nameval" +$TS_CMD_FINDMNT -Q 'OPTIONS =~ "\"' --kernel --tab-file "$TS_SELF/files/mountinfo" &> $TS_OUTPUT +echo rc=$? >> $TS_OUTPUT +ts_finalize_subtest + +ts_init_subtest "options-nameval-neg" +$TS_CMD_FINDMNT -Q 'OPTIONS !~ "\"' --kernel --tab-file "$TS_SELF/files/mountinfo" &> $TS_OUTPUT +echo rc=$? >> $TS_OUTPUT +ts_finalize_subtest + +ts_init_subtest "options-nameval-multi" +$TS_CMD_FINDMNT -Q 'OPTIONS =~ "\" && OPTIONS =~ "\" && OPTIONS =~ "\"' --kernel --tab-file "$TS_SELF/files/mountinfo" &> $TS_OUTPUT +echo rc=$? >> $TS_OUTPUT +ts_finalize_subtest + +ts_init_subtest "options-neg" +$TS_CMD_FINDMNT -Q 'OPTIONS !~ "\"' --kernel --tab-file "$TS_SELF/files/mountinfo" &> $TS_OUTPUT +echo rc=$? >> $TS_OUTPUT +ts_finalize_subtest + +ts_init_subtest "options-no" +$TS_CMD_FINDMNT -Q 'OPTIONS =~ "\"' --kernel --tab-file "$TS_SELF/files/mountinfo" &> $TS_OUTPUT +echo rc=$? >> $TS_OUTPUT +ts_finalize_subtest + +ts_init_subtest "options-no-multi" +$TS_CMD_FINDMNT -Q 'OPTIONS =~ "\" && OPTIONS =~ "\" && OPTIONS =~ "\"' --kernel --tab-file "$TS_SELF/files/mountinfo" &> $TS_OUTPUT +echo rc=$? >> $TS_OUTPUT + +ts_finalize