]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsns: fix compilation on old systems without linux/nsfs.h
authorKarel Zak <kzak@redhat.com>
Tue, 30 Nov 2021 14:02:10 +0000 (15:02 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 30 Nov 2021 14:02:10 +0000 (15:02 +0100)
Addresses: https://github.com/util-linux/util-linux/pull/1521
Reported-by: Anatoly Pugachev <matorola@gmail.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/lsns.c

index ba2a58ef59382da0ed76ef932ff75374344c6dfa..1a7e9f333482f0737792ca397c425b4337a1adbc 100644 (file)
 #include <libmount.h>
 
 #ifdef HAVE_LINUX_NET_NAMESPACE_H
-#include <stdbool.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/net_namespace.h>
+# include <stdbool.h>
+# include <sys/socket.h>
+# include <linux/netlink.h>
+# include <linux/rtnetlink.h>
+# include <linux/net_namespace.h>
 #endif
 
 #ifdef HAVE_LINUX_NSFS_H
-#include <linux/nsfs.h>
+# include <linux/nsfs.h>
+# define USE_NS_GET_API        1
 #endif
 
 #include "pathnames.h"
@@ -296,7 +297,7 @@ static int get_ns_ino(int dir, const char *nsname, ino_t *ino, ino_t *pino, ino_
        *pino = 0;
        *oino = 0;
 
-#ifdef HAVE_LINUX_NSFS_H
+#ifdef USE_NS_GET_API
        int fd, pfd, ofd;
        fd = openat(dir, path, 0);
        if (fd < 0)
@@ -684,6 +685,7 @@ static int netnsid_xasputs(char **str, int netnsid)
        return 0;
 }
 
+#ifdef USE_NS_GET_API
 static int clone_type_to_lsns_type(int clone_type)
 {
        switch (clone_type) {
@@ -799,12 +801,67 @@ static void interpolate_missing_namespaces(struct lsns *ls, struct lsns_namespac
        close(fd_missing);
 }
 
-static int read_namespaces(struct lsns *ls)
+static void read_related_namespaces(struct lsns *ls)
 {
        struct list_head *p;
        struct lsns_namespace *orphan[2] = {NULL, NULL};
        int rela;
 
+       list_for_each(p, &ls->namespaces) {
+               struct lsns_namespace *ns = list_entry(p, struct lsns_namespace, namespaces);
+               struct list_head *pp;
+               list_for_each(pp, &ls->namespaces) {
+                       struct lsns_namespace *pns = list_entry(pp, struct lsns_namespace, namespaces);
+                       if (ns->type == LSNS_ID_USER
+                           || ns->type == LSNS_ID_PID) {
+                               if (ns->related_id[RELA_PARENT] == pns->id)
+                                       ns->related_ns[RELA_PARENT] = pns;
+                               if (ns->related_id[RELA_OWNER] == pns->id)
+                                       ns->related_ns[RELA_OWNER] = pns;
+                               if (ns->related_ns[RELA_PARENT] && ns->related_ns[RELA_OWNER])
+                                       break;
+                       } else {
+                               if (ns->related_id[RELA_OWNER] == pns->id) {
+                                       ns->related_ns[RELA_OWNER] = pns;
+                                       break;
+                               }
+                       }
+               }
+
+               /* lsns scans /proc/[0-9]+ for finding namespaces.
+                * So if a namespace has no process, lsns cannot
+                * find it. Here we call it a missing namespace.
+                *
+                * If the id for a related namesspce is known but
+                * namespace for the id is not found, there must
+                * be orphan namespaces. A missing namespace is an
+                * owner or a parent of the orphan namespace.
+                */
+               for (rela = 0; rela < MAX_RELA; rela++) {
+                       if (ns->related_id[rela] != 0
+                           && ns->related_ns[rela] == NULL) {
+                               ns->related_ns[rela] = orphan[rela];
+                               orphan[rela] = ns;
+                       }
+               }
+       }
+
+       for (rela = 0; rela < MAX_RELA; rela++) {
+               while (orphan[rela]) {
+                       struct lsns_namespace *current = orphan[rela];
+                       orphan[rela] = orphan[rela]->related_ns[rela];
+                       current->related_ns[rela] = NULL;
+                       interpolate_missing_namespaces(ls, current, rela);
+               }
+       }
+}
+
+#endif /* USE_NS_GET_API */
+
+static int read_namespaces(struct lsns *ls)
+{
+       struct list_head *p;
+
        DBG(NS, ul_debug("reading namespace"));
 
        list_for_each(p, &ls->processes) {
@@ -825,56 +882,10 @@ static int read_namespaces(struct lsns *ls)
                }
        }
 
-       if (ls->tree == LSNS_TREE_OWNER || ls->tree == LSNS_TREE_PARENT) {
-               list_for_each(p, &ls->namespaces) {
-                       struct lsns_namespace *ns = list_entry(p, struct lsns_namespace, namespaces);
-                       struct list_head *pp;
-                       list_for_each(pp, &ls->namespaces) {
-                               struct lsns_namespace *pns = list_entry(pp, struct lsns_namespace, namespaces);
-                               if (ns->type == LSNS_ID_USER
-                                   || ns->type == LSNS_ID_PID) {
-                                       if (ns->related_id[RELA_PARENT] == pns->id)
-                                               ns->related_ns[RELA_PARENT] = pns;
-                                       if (ns->related_id[RELA_OWNER] == pns->id)
-                                               ns->related_ns[RELA_OWNER] = pns;
-                                       if (ns->related_ns[RELA_PARENT] && ns->related_ns[RELA_OWNER])
-                                               break;
-                               } else {
-                                       if (ns->related_id[RELA_OWNER] == pns->id) {
-                                               ns->related_ns[RELA_OWNER] = pns;
-                                               break;
-                                       }
-                               }
-                       }
-
-                       /* lsns scans /proc/[0-9]+ for finding namespaces.
-                        * So if a namespace has no process, lsns cannot
-                        * find it. Here we call it a missing namespace.
-                        *
-                        * If the id for a related namesspce is known but
-                        * namespace for the id is not found, there must
-                        * be orphan namespaces. A missing namespace is an
-                        * owner or a parent of the orphan namespace.
-                        */
-                       for (rela = 0; rela < MAX_RELA; rela++) {
-                               if (ns->related_id[rela] != 0
-                                   && ns->related_ns[rela] == NULL) {
-                                       ns->related_ns[rela] = orphan[rela];
-                                       orphan[rela] = ns;
-                               }
-                       }
-               }
-       }
-
-       for (rela = 0; rela < MAX_RELA; rela++) {
-               while (orphan[rela]) {
-                       struct lsns_namespace *current = orphan[rela];
-                       orphan[rela] = orphan[rela]->related_ns[rela];
-                       current->related_ns[rela] = NULL;
-                       interpolate_missing_namespaces(ls, current, rela);
-               }
-       }
-
+#ifdef USE_NS_GET_API
+       if (ls->tree == LSNS_TREE_OWNER || ls->tree == LSNS_TREE_PARENT)
+               read_related_namespaces(ls);
+#endif
        list_sort(&ls->namespaces, cmp_namespaces, NULL);
 
        return 0;
@@ -1377,6 +1388,10 @@ int main(int argc, char *argv[])
                        ls.tree = LSNS_TREE_PROCESS;
        }
 
+#ifndef USE_NS_GET_API
+       if (ls.tree && ls.tree != LSNS_TREE_PROCESS)
+               errx(EXIT_FAILURE, _("--tree={parent|owner} is unsupported for your system"));
+#endif
        if (outarg && string_add_to_idarray(outarg, columns, ARRAY_SIZE(columns),
                                  &ncolumns, column_name_to_id) < 0)
                return EXIT_FAILURE;