diff options
Diffstat (limited to 'sys-utils/lsns.c')
-rw-r--r-- | sys-utils/lsns.c | 108 |
1 files changed, 104 insertions, 4 deletions
diff --git a/sys-utils/lsns.c b/sys-utils/lsns.c index bb7d3956d..c4d806e24 100644 --- a/sys-utils/lsns.c +++ b/sys-utils/lsns.c @@ -28,6 +28,7 @@ #include <sys/types.h> #include <wchar.h> #include <libsmartcols.h> +#include <libmount.h> #ifdef HAVE_LINUX_NET_NAMESPACE_H #include <stdbool.h> @@ -78,7 +79,8 @@ enum { COL_COMMAND, COL_UID, COL_USER, - COL_NETNSID + COL_NETNSID, + COL_NSFS, }; /* column names */ @@ -100,7 +102,8 @@ static const struct colinfo infos[] = { [COL_COMMAND] = { "COMMAND", 0, SCOLS_FL_TRUNC, N_("command line of the PID")}, [COL_UID] = { "UID", 0, SCOLS_FL_RIGHT, N_("UID of the PID")}, [COL_USER] = { "USER", 0, 0, N_("username of the PID")}, - [COL_NETNSID] = { "NETNSID", 0, SCOLS_FL_RIGHT, N_("Net namespace ID")} + [COL_NETNSID] = { "NETNSID", 0, SCOLS_FL_RIGHT, N_("Net namespace ID")}, + [COL_NSFS] = { "NSFS", 0, SCOLS_FL_WRAP, N_("Logical name established by nsfs")} }; static int columns[ARRAY_SIZE(infos) * 2]; @@ -171,6 +174,8 @@ struct lsns { list : 1, notrunc : 1, no_headings: 1; + + struct libmnt_table *tab; }; struct netnsid_cache { @@ -612,6 +617,80 @@ static int read_namespaces(struct lsns *ls) return 0; } +static int find_nsfs_in_tab(struct libmnt_fs *fs, void *data) +{ + return (mnt_fs_match_fstype(fs, "nsfs") && + (strcmp(mnt_fs_get_root(fs), (char *)data) == 0)); +} + +static bool str_includes_path(const char *path_set, const char *elt, + const char sep) +{ + size_t elt_len; + size_t path_set_len; + char *tmp; + + + tmp = strstr(path_set, elt); + if (!tmp) + return false; + + elt_len = strlen(elt); + path_set_len = strlen(path_set); + + /* path_set includes only elt or + * path_set includes elt as the first element. + */ + if (tmp == path_set + && ((path_set_len == elt_len) + || (path_set[elt_len] == sep))) + return true; + /* path_set includes elt at the middle + * or as the last element. + */ + if ((*(tmp - 1) == sep) + && ((*(tmp + elt_len) == sep) + || (*(tmp + elt_len) == '\0'))) + return true; + + return false; +} + +static int nsfs_xasputs(char **str, + struct lsns_namespace *ns, + struct libmnt_table *tab, + char sep) +{ + struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_FORWARD); + char *expected_root; + char *tmp; + + xasprintf(&expected_root, "%s:[%lu]", ns_names[ns->type], ns->id); + + tmp = NULL; + while (1) { + struct libmnt_fs *fs = NULL; + + if (mnt_table_find_next_fs(tab, itr, find_nsfs_in_tab, + expected_root, &fs) != 0) + break; + if (tmp == NULL) { + xasprintf(str, "%s", mnt_fs_get_target(fs)); + tmp = *str; + } else if (!str_includes_path(*str, mnt_fs_get_target(fs), + sep)) { + *str = NULL; + xasprintf(str, "%s%c%s", + tmp, sep, mnt_fs_get_target(fs)); + free(tmp); + tmp = *str; + } + } + free(expected_root); + mnt_free_iter(itr); + + return 1; +} static void add_scols_line(struct lsns *ls, struct libscols_table *table, struct lsns_namespace *ns, struct lsns_process *proc) { @@ -665,6 +744,10 @@ static void add_scols_line(struct lsns *ls, struct libscols_table *table, if (ns->type == LSNS_ID_NET) netnsid_xasputs(&str, proc->netnsid); break; + case COL_NSFS: + nsfs_xasputs(&str, ns, ls->tab, + ls->raw ? ',' : '\n'); + break; default: break; } @@ -697,16 +780,25 @@ static struct libscols_table *init_scols_table(struct lsns *ls) for (i = 0; i < ncolumns; i++) { const struct colinfo *col = get_column_info(i); int flags = col->flags; + struct libscols_column *cl; if (ls->notrunc) flags &= ~SCOLS_FL_TRUNC; if (ls->tree && get_column_id(i) == COL_COMMAND) flags |= SCOLS_FL_TREE; - if (!scols_table_new_column(tab, col->name, col->whint, flags)) { + cl = scols_table_new_column(tab, col->name, col->whint, flags); + if (cl == NULL) { warnx(_("failed to initialize output column")); goto err; } + if (get_column_id(i) == COL_NSFS) { + scols_column_set_wrapfunc(cl, + scols_wrapnl_chunksize, + scols_wrapnl_nextchunk, + NULL); + scols_column_set_safechars(cl, "\n"); + } } return tab; @@ -928,8 +1020,10 @@ int main(int argc, char *argv[]) columns[ncolumns++] = COL_NPROCS; columns[ncolumns++] = COL_PID; columns[ncolumns++] = COL_USER; - if (enabling_netnsid) + if (enabling_netnsid) { columns[ncolumns++] = COL_NETNSID; + columns[ncolumns++] = COL_NSFS; + } columns[ncolumns++] = COL_COMMAND; } @@ -956,6 +1050,11 @@ int main(int argc, char *argv[]) if (enabling_netnsid) netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); #endif + + ls.tab = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO); + if (!ls.tab) + err(MNT_EX_FAIL, _("failed to parse %s"), _PATH_PROC_MOUNTINFO); + r = read_processes(&ls); if (!r) r = read_namespaces(&ls); @@ -970,6 +1069,7 @@ int main(int argc, char *argv[]) r = show_namespaces(&ls); } + mnt_free_table(ls.tab); if (netlink_fd >= 0) close(netlink_fd); free_idcache(uid_cache); |