summaryrefslogtreecommitdiffstats
path: root/misc-utils/findmnt.c
diff options
context:
space:
mode:
authorKarel Zak2011-04-27 17:19:04 +0200
committerKarel Zak2011-04-27 17:19:04 +0200
commit32e5466aa79fedaebf6e101fbfe22c0705805af9 (patch)
tree8dfbed72092ee5b0cc6eeeb83ee9ad2aec35c62b /misc-utils/findmnt.c
parentlibmount: minor fix to mnt_tabdiff_* (diff)
downloadkernel-qcow2-util-linux-32e5466aa79fedaebf6e101fbfe22c0705805af9.tar.gz
kernel-qcow2-util-linux-32e5466aa79fedaebf6e101fbfe22c0705805af9.tar.xz
kernel-qcow2-util-linux-32e5466aa79fedaebf6e101fbfe22c0705805af9.zip
findmnt: add --poll option
The --poll functionality is based on poll(/proc/self/mountinfo) and mnt_tabdiff_* functions from libmount. $ findmnt --poll ACTION TARGET SOURCE FSTYPE OPTIONS mount /mnt/test /dev/sda1 ext3 rw,relatime,errors=continue,user_xattr,acl,barrier=0,data=ordered ... after "mount /dev/sda1 /mnt/test". Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'misc-utils/findmnt.c')
-rw-r--r--misc-utils/findmnt.c261
1 files changed, 232 insertions, 29 deletions
diff --git a/misc-utils/findmnt.c b/misc-utils/findmnt.c
index 07c0eda27..16c26a1ce 100644
--- a/misc-utils/findmnt.c
+++ b/misc-utils/findmnt.c
@@ -29,6 +29,7 @@
#include <sys/ioctl.h>
#endif
#include <assert.h>
+#include <poll.h>
#define USE_UNSTABLE_LIBMOUNT_API
#include <libmount.h>
@@ -47,6 +48,7 @@ enum {
FL_NOSWAPMATCH = (1 << 6),
FL_NOFSROOT = (1 << 7),
FL_SUBMOUNTS = (1 << 8),
+ FL_POLL = (1 << 9)
};
/* column IDs */
@@ -60,6 +62,9 @@ enum {
COL_LABEL,
COL_UUID,
COL_MAJMIN,
+ COL_ACTION,
+ COL_OLD_TARGET,
+ COL_OLD_OPTIONS,
__NCOLUMNS
};
@@ -68,21 +73,24 @@ enum {
struct colinfo {
const char *name; /* header */
double whint; /* width hint (N < 1 is in percent of termwidth) */
- int truncate; /* boolean */
+ int flags; /* tt flags */
const char *match; /* pattern for match_func() */
};
/* columns descriptions */
struct colinfo infos[__NCOLUMNS] = {
- [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_VFS_OPTIONS] = { "VFS-OPTIONS", 0.20, TRUE },
- [COL_FS_OPTIONS] = { "FS-OPTIONS", 0.10, TRUE },
- [COL_LABEL] = { "LABEL", 0.10, FALSE },
- [COL_UUID] = { "UUID", 36, FALSE },
- [COL_MAJMIN] = { "MAJ:MIN", 6, FALSE },
+ [COL_SOURCE] = { "SOURCE", 0.25 },
+ [COL_TARGET] = { "TARGET", 0.30, TT_FL_TREE },
+ [COL_FSTYPE] = { "FSTYPE", 0.10, TT_FL_TRUNC },
+ [COL_OPTIONS] = { "OPTIONS", 0.10, TT_FL_TRUNC },
+ [COL_VFS_OPTIONS] = { "VFS-OPTIONS", 0.20, TT_FL_TRUNC },
+ [COL_FS_OPTIONS] = { "FS-OPTIONS", 0.10, TT_FL_TRUNC },
+ [COL_LABEL] = { "LABEL", 0.10 },
+ [COL_UUID] = { "UUID", 36 },
+ [COL_MAJMIN] = { "MAJ:MIN", 6 },
+ [COL_ACTION] = { "ACTION", 10, TT_FL_STRICTWIDTH },
+ [COL_OLD_OPTIONS] = { "OLD-OPTIONS", 0.10, TT_FL_TRUNC },
+ [COL_OLD_TARGET] = { "OLD-TARGET", 0.30 },
};
/* global flags */
@@ -124,9 +132,9 @@ static float get_column_whint(int num)
return get_column_info(num)->whint;
}
-static int get_column_truncate(int num)
+static int get_column_flags(int num)
{
- return get_column_info(num)->truncate;
+ return get_column_info(num)->flags;
}
static const char *get_match(int id)
@@ -141,6 +149,21 @@ static void set_match(int id, const char *match)
infos[id].match = match;
}
+static int is_tabdiff_column(int id)
+{
+ assert(id < __NCOLUMNS);
+
+ switch(id) {
+ case COL_ACTION:
+ case COL_OLD_TARGET:
+ case COL_OLD_OPTIONS:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
/*
* "findmnt" without any filter
*/
@@ -169,12 +192,12 @@ static int is_mount_compatible_mode(void)
return 1; /* ok */
}
-static void set_all_columns_truncate(int set)
+static void disable_columns_truncate(void)
{
int i;
for (i = 0; i < __NCOLUMNS; i++)
- infos[i].truncate = set;
+ infos[i].flags &= ~TT_FL_TRUNC;
}
/*
@@ -285,6 +308,51 @@ static const char *get_data(struct libmnt_fs *fs, int num)
return str;
}
+static const char *get_tabdiff_data(struct libmnt_fs *old_fs,
+ struct libmnt_fs *new_fs,
+ int change,
+ int num)
+{
+ const char *str = NULL;
+
+ switch (get_column_id(num)) {
+ case COL_ACTION:
+ switch (change) {
+ case MNT_TABDIFF_MOUNT:
+ str = _("mount");
+ break;
+ case MNT_TABDIFF_UMOUNT:
+ str = _("umount");
+ break;
+ case MNT_TABDIFF_REMOUNT:
+ str = _("remount");
+ break;
+ case MNT_TABDIFF_MOVE:
+ str = _("move");
+ break;
+ default:
+ str = _("unknown");
+ break;
+ }
+ break;
+ case COL_OLD_OPTIONS:
+ if (old_fs)
+ str = mnt_fs_get_options(old_fs);
+ break;
+ case COL_OLD_TARGET:
+ if (old_fs)
+ str = mnt_fs_get_target(old_fs);
+ break;
+ default:
+ if (new_fs)
+ str = get_data(new_fs, num);
+ else
+ str = get_data(old_fs, num);
+ break;
+ }
+ return str;
+}
+
/* adds one line to the output @tab */
static struct tt_line *add_line(struct tt *tt, struct libmnt_fs *fs,
struct tt_line *parent)
@@ -303,6 +371,23 @@ static struct tt_line *add_line(struct tt *tt, struct libmnt_fs *fs,
return line;
}
+static struct tt_line *add_tabdiff_line(struct tt *tt, struct libmnt_fs *new_fs,
+ struct libmnt_fs *old_fs, int change)
+{
+ int i;
+ struct tt_line *line = tt_add_line(tt, 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_tabdiff_data(old_fs, new_fs, change, i));
+
+ return line;
+}
+
static int has_line(struct tt *tt, struct libmnt_fs *fs)
{
struct list_head *p;
@@ -368,7 +453,7 @@ static struct libmnt_table *parse_tabfile(const char *path)
struct libmnt_table *tb = mnt_new_table();
if (!tb) {
- warn(_("failed to initialize libmount tab"));
+ warn(_("failed to initialize libmount table"));
return NULL;
}
@@ -498,6 +583,101 @@ done:
return rc;
}
+static int poll_table(struct libmnt_table *tb, const char *tabfile,
+ int timeout, struct tt *tt, int direction)
+{
+ FILE *f;
+ int rc = -1;
+ struct libmnt_iter *itr = NULL;
+ struct libmnt_table *tb_new = NULL;
+ struct libmnt_tabdiff *diff = NULL;
+ struct pollfd fds[1];
+
+ tb_new = mnt_new_table();
+ if (!tb_new) {
+ warn(_("failed to initialize libmount table"));
+ goto done;
+ }
+
+ itr = mnt_new_iter(direction);
+ if (!itr) {
+ warn(_("failed to initialize libmount iterator"));
+ goto done;
+ }
+
+ diff = mnt_new_tabdiff();
+ if (!diff) {
+ warn(_("failed to initialize libmount tabdiff"));
+ goto done;
+ }
+
+ /* cache is unnecessary to detect changes */
+ mnt_table_set_cache(tb, NULL);
+ mnt_table_set_cache(tb_new, NULL);
+
+ f = fopen(tabfile, "r");
+ if (!f) {
+ warn(_("%s: open failed"), tabfile);
+ goto done;
+ }
+
+ mnt_table_set_parser_errcb(tb_new, parser_errcb);
+
+ fds[0].fd = fileno(f);
+ fds[0].events = POLLPRI;
+
+ while (1) {
+ struct libmnt_table *tmp;
+ struct libmnt_fs *old, *new;
+ int change, x;
+
+ x = poll(fds, 1, timeout);
+ if (x == 0)
+ goto done; /* timeout ? */
+ if (x < 0) {
+ warn(_("poll() failed"));
+ goto done;
+ }
+
+ rewind(f);
+ rc = mnt_table_parse_stream(tb_new, f, tabfile);
+ if (!rc)
+ rc = mnt_diff_tables(diff, tb, tb_new);
+ if (rc < 0)
+ goto done;
+
+ mnt_reset_iter(itr, direction);
+ while(mnt_tabdiff_next_change(
+ diff, itr, &old, &new, &change) == 0) {
+
+ rc = !add_tabdiff_line(tt, new, old, change);
+ if (rc)
+ goto done;
+ if (flags & FL_FIRSTONLY)
+ break;
+ }
+
+ rc = tt_print_table(tt);
+ if (rc)
+ goto done;
+
+ /* swap tables */
+ tmp = tb;
+ tb = tb_new;
+ tb_new = tmp;
+
+ tt_remove_lines(tt);
+ mnt_reset_table(tb_new);
+ }
+
+ rc = 0;
+done:
+ mnt_free_table(tb_new);
+ mnt_free_tabdiff(diff);
+ mnt_free_iter(itr);
+ return rc;
+}
+
static void __attribute__((__noreturn__)) usage(FILE *out)
{
int i;
@@ -517,6 +697,8 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
" -k, --kernel search in kernel table of mounted \n"
" filesystems (default)\n\n"
+ " -p, --poll monitor changes in table of mounted filesystems\n\n"
+
" -c, --canonicalize canonicalize printed paths\n"
" -d, --direction <word> search direction - 'forward' or 'backward'\n"
" -e, --evaluate print all TAGs (LABEL/UUID) evaluated\n"
@@ -585,6 +767,7 @@ int main(int argc, char *argv[])
{ "notruncate", 0, 0, 'u' },
{ "options", 1, 0, 'O' },
{ "output", 1, 0, 'o' },
+ { "poll", 0, 0, 'p' },
{ "raw", 0, 0, 'r' },
{ "types", 1, 0, 't' },
{ "fsroot", 0, 0, 'v' },
@@ -601,17 +784,11 @@ int main(int argc, char *argv[])
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- /* default enabled columns */
- columns[ncolumns++] = COL_TARGET;
- columns[ncolumns++] = COL_SOURCE;
- columns[ncolumns++] = COL_FSTYPE;
- columns[ncolumns++] = COL_OPTIONS;
-
/* default output format */
tt_flags |= TT_FL_TREE;
while ((c = getopt_long(argc, argv,
- "acd:ehifo:O:klmnrst:uvRS:T:", longopts, NULL)) != -1) {
+ "acd:ehifo:O:pklmnrst:uvRS:T:", longopts, NULL)) != -1) {
switch(c) {
case 'a':
tt_flags |= TT_FL_ASCII;
@@ -641,7 +818,7 @@ int main(int argc, char *argv[])
flags |= FL_FIRSTONLY;
break;
case 'u':
- set_all_columns_truncate(FALSE);
+ disable_columns_truncate();
break;
case 'o':
if (tt_parse_columns_list(optarg, columns, &ncolumns,
@@ -651,6 +828,10 @@ int main(int argc, char *argv[])
case 'O':
set_match(COL_OPTIONS, optarg);
break;
+ case 'p':
+ flags |= FL_POLL;
+ tt_flags &= ~TT_FL_TREE;
+ break;
case 'm': /* mtab */
if (tabfile)
errx_mutually_exclusive("--{fstab,mtab,kernel}");
@@ -704,6 +885,17 @@ int main(int argc, char *argv[])
}
}
+ /* default columns */
+ if (!ncolumns) {
+ if (flags & FL_POLL)
+ columns[ncolumns++] = COL_ACTION;
+
+ columns[ncolumns++] = COL_TARGET;
+ columns[ncolumns++] = COL_SOURCE;
+ columns[ncolumns++] = COL_FSTYPE;
+ columns[ncolumns++] = COL_OPTIONS;
+ }
+
if (!tabfile) {
tabfile = _PATH_PROC_MOUNTINFO;
@@ -769,10 +961,17 @@ int main(int argc, char *argv[])
}
for (i = 0; i < ncolumns; i++) {
- int fl = get_column_truncate(i) ? TT_FL_TRUNC : 0;
+ int fl = get_column_flags(i);
+ int id = get_column_id(i);
+
+ if (!(tt_flags & TT_FL_TREE))
+ fl &= ~TT_FL_TREE;
- if (get_column_id(i) == COL_TARGET && (tt_flags & TT_FL_TREE))
- fl |= TT_FL_TREE;
+ if (!(flags & FL_POLL) && is_tabdiff_column(id)) {
+ warn(_("%s column is requested, but --poll "
+ "is not enabled"), get_column_name(i));
+ goto leave;
+ }
if (!tt_define_column(tt, get_column_name(i),
get_column_whint(i), fl)) {
@@ -784,7 +983,11 @@ int main(int argc, char *argv[])
/*
* Fill in data to the output table
*/
- if ((tt_flags & TT_FL_TREE) && is_listall_mode())
+ if (flags & FL_POLL)
+ /* poll mode */
+ poll_table(tb, tabfile, -1, tt, direction);
+
+ else if ((tt_flags & TT_FL_TREE) && is_listall_mode())
/* whole tree */
rc = create_treenode(tt, tb, NULL, NULL);
else
@@ -792,9 +995,9 @@ int main(int argc, char *argv[])
rc = add_matching_lines(tb, tt, direction);
/*
- * Print the output table
+ * Print the output table for non-poll modes
*/
- if (!rc)
+ if (!rc && !(flags & FL_POLL))
tt_print_table(tt);
leave:
tt_free_table(tt);