1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <errno.h>
4 
5 #include "alloc-util.h"
6 #include "extract-word.h"
7 #include "nsflags.h"
8 #include "string-util.h"
9 
10 const struct namespace_flag_map namespace_flag_map[] = {
11         { CLONE_NEWCGROUP, "cgroup" },
12         { CLONE_NEWIPC,    "ipc"    },
13         { CLONE_NEWNET,    "net"    },
14         /* So, the mount namespace flag is called CLONE_NEWNS for historical reasons. Let's expose it here under a more
15          * explanatory name: "mnt". This is in-line with how the kernel exposes namespaces in /proc/$PID/ns. */
16         { CLONE_NEWNS,     "mnt"    },
17         { CLONE_NEWPID,    "pid"    },
18         { CLONE_NEWUSER,   "user"   },
19         { CLONE_NEWUTS,    "uts"    },
20         {}
21 };
22 
namespace_flags_from_string(const char * name,unsigned long * ret)23 int namespace_flags_from_string(const char *name, unsigned long *ret) {
24         unsigned long flags = 0;
25         int r;
26 
27         assert_se(ret);
28 
29         for (;;) {
30                 _cleanup_free_ char *word = NULL;
31                 unsigned long f = 0;
32                 unsigned i;
33 
34                 r = extract_first_word(&name, &word, NULL, 0);
35                 if (r < 0)
36                         return r;
37                 if (r == 0)
38                         break;
39 
40                 for (i = 0; namespace_flag_map[i].name; i++)
41                         if (streq(word, namespace_flag_map[i].name)) {
42                                  f = namespace_flag_map[i].flag;
43                                  break;
44                         }
45 
46                 if (f == 0)
47                         return -EINVAL;
48 
49                 flags |= f;
50         }
51 
52         *ret = flags;
53         return 0;
54 }
55 
namespace_flags_to_string(unsigned long flags,char ** ret)56 int namespace_flags_to_string(unsigned long flags, char **ret) {
57         _cleanup_free_ char *s = NULL;
58         unsigned i;
59 
60         for (i = 0; namespace_flag_map[i].name; i++) {
61                 if ((flags & namespace_flag_map[i].flag) != namespace_flag_map[i].flag)
62                         continue;
63 
64                 if (!strextend_with_separator(&s, " ", namespace_flag_map[i].name))
65                         return -ENOMEM;
66         }
67 
68         *ret = TAKE_PTR(s);
69 
70         return 0;
71 }
72 
namespace_single_flag_to_string(unsigned long flag)73 const char *namespace_single_flag_to_string(unsigned long flag) {
74         for (unsigned i = 0; namespace_flag_map[i].name; i++)
75                 if (namespace_flag_map[i].flag == flag)
76                         return namespace_flag_map[i].name;
77 
78         return NULL;
79 }
80