Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */ 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 : 23 0 : int namespace_flags_from_string(const char *name, unsigned long *ret) { 24 0 : unsigned long flags = 0; 25 : int r; 26 : 27 0 : assert_se(ret); 28 : 29 0 : for (;;) { 30 0 : _cleanup_free_ char *word = NULL; 31 0 : unsigned long f = 0; 32 : unsigned i; 33 : 34 0 : r = extract_first_word(&name, &word, NULL, 0); 35 0 : if (r < 0) 36 0 : return r; 37 0 : if (r == 0) 38 0 : break; 39 : 40 0 : for (i = 0; namespace_flag_map[i].name; i++) 41 0 : if (streq(word, namespace_flag_map[i].name)) { 42 0 : f = namespace_flag_map[i].flag; 43 0 : break; 44 : } 45 : 46 0 : if (f == 0) 47 0 : return -EINVAL; 48 : 49 0 : flags |= f; 50 : } 51 : 52 0 : *ret = flags; 53 0 : return 0; 54 : } 55 : 56 1 : int namespace_flags_to_string(unsigned long flags, char **ret) { 57 1 : _cleanup_free_ char *s = NULL; 58 : unsigned i; 59 : 60 8 : for (i = 0; namespace_flag_map[i].name; i++) { 61 7 : if ((flags & namespace_flag_map[i].flag) != namespace_flag_map[i].flag) 62 7 : continue; 63 : 64 0 : if (!strextend_with_separator(&s, " ", namespace_flag_map[i].name, NULL)) 65 0 : return -ENOMEM; 66 : } 67 : 68 1 : if (!s) { 69 1 : s = strdup(""); 70 1 : if (!s) 71 0 : return -ENOMEM; 72 : } 73 : 74 1 : *ret = TAKE_PTR(s); 75 : 76 1 : return 0; 77 : }