[libvirt PATCHv2 7/9] util: add virGetSubUIDs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



A function for parsing /etc/sub[ug]id

Signed-off-by: Ján Tomko <jtomko@xxxxxxxxxx>
---
 src/libvirt_private.syms     |  2 ++
 src/util/virutil.c           | 70 ++++++++++++++++++++++++++++++++++++
 src/util/virutil.h           | 12 +++++++
 tests/utiltest.c             | 33 +++++++++++++++++
 tests/virutiltestdata/subuid |  4 +++
 5 files changed, 121 insertions(+)
 create mode 100644 tests/virutiltestdata/subuid

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 553b01b8c0..20f34d72b5 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3640,6 +3640,7 @@ virGetHostname;
 virGetHostnameQuiet;
 virGetPassword;
 virGetSelfLastChanged;
+virGetSubIDs;
 virGetSystemPageSize;
 virGetSystemPageSizeKB;
 virGetUserCacheDirectory;
@@ -3670,6 +3671,7 @@ virSetNonBlock;
 virSetSockReuseAddr;
 virSetUIDGID;
 virSetUIDGIDWithCaps;
+virSubIDsFree;
 virUpdateSelfLastChanged;
 virValidateWWN;
 virWaitForDevices;
diff --git a/src/util/virutil.c b/src/util/virutil.c
index 17d65ad834..369e0bc4dc 100644
--- a/src/util/virutil.c
+++ b/src/util/virutil.c
@@ -738,6 +738,76 @@ virGetUserIDByName(const char *name, uid_t *uid, bool missing_ok)
     return ret;
 }
 
+void
+virSubIDsFree(virSubID **uids, size_t n)
+{
+    size_t i;
+
+    for (i = 0; i < n; i++) {
+        if ((*uids)[i].idstr)
+            g_free((*uids)[i].idstr);
+    }
+    g_clear_pointer(uids, g_free);
+}
+
+int
+virGetSubIDs(virSubID **retval, const char *file)
+{
+    g_autofree char *buf = NULL;
+    g_auto(GStrv) lines = NULL;
+    virSubID *entries = NULL;
+    size_t i = 0;
+    size_t len;
+    int ret = -1;
+
+    *retval = NULL;
+
+    if (virFileReadAll(file, BUFSIZ, &buf) < 0)
+        return -1;
+
+    lines = g_strsplit(buf, "\n", 0);
+    if (!lines)
+        return -1;
+
+    len = g_strv_length(lines);
+    entries = g_new0(virSubID, len);
+
+    for (i = 0; i < len; i++) {
+        g_auto(GStrv) fields = NULL;
+        unsigned long ulong_id;
+
+        fields = g_strsplit(lines[i], ":", 0);
+        if (!fields)
+            goto cleanup;
+
+        if (g_strv_length(fields) != 3)
+            break;
+
+        if (g_ascii_isdigit(fields[0][0])) {
+            if (virStrToLong_ul(fields[0], NULL, 10, &ulong_id) < 0)
+                goto cleanup;
+            entries[i].id = ulong_id;
+        } else {
+            entries[i].idstr = g_strdup(fields[0]);
+        }
+
+        if (virStrToLong_ul(fields[1], NULL, 10, &ulong_id) < 0)
+            goto cleanup;
+        entries[i].start = ulong_id;
+
+        if (virStrToLong_ul(fields[2], NULL, 10, &ulong_id) < 0)
+            goto cleanup;
+        entries[i].range = ulong_id;
+    }
+
+    *retval = g_steal_pointer(&entries);
+    ret = i;
+ cleanup:
+    if (entries)
+        virSubIDsFree(&entries, len);
+    return ret;
+}
+
 /* Try to match a user id based on `user`. The default behavior is to parse
  * `user` first as a user name and then as a user id. However if `user`
  * contains a leading '+', the rest of the string is always parsed as a uid.
diff --git a/src/util/virutil.h b/src/util/virutil.h
index ab8511bf8d..3bac15d02b 100644
--- a/src/util/virutil.h
+++ b/src/util/virutil.h
@@ -102,6 +102,18 @@ char *virGetUserName(uid_t uid) G_NO_INLINE;
 char *virGetGroupName(gid_t gid) G_NO_INLINE;
 int virGetGroupList(uid_t uid, gid_t group, gid_t **groups)
     ATTRIBUTE_NONNULL(3);
+
+typedef struct _virSubID {
+    uid_t id;
+    char *idstr;
+    uid_t start;
+    uid_t range;
+} virSubID;
+
+int virGetSubIDs(virSubID **ret, const char *file);
+void virSubIDsFree(virSubID **uids, size_t n);
+
+
 int virGetUserID(const char *name,
                  uid_t *uid) G_GNUC_WARN_UNUSED_RESULT;
 int virGetGroupID(const char *name,
diff --git a/tests/utiltest.c b/tests/utiltest.c
index 5930557c08..b30bfbed70 100644
--- a/tests/utiltest.c
+++ b/tests/utiltest.c
@@ -377,6 +377,38 @@ testKernelCmdlineMatchParam(const void *data G_GNUC_UNUSED)
 }
 
 
+static int
+testGetSubIDs(const void *data G_GNUC_UNUSED)
+{
+    g_autofree char *subuid_file = g_strdup_printf("%s/virutiltestdata/subuid", abs_srcdir);
+    virSubID *subids = NULL;
+    int len = 0;
+    int ret = -1;
+
+    if ((len = virGetSubIDs(&subids, subuid_file)) < 0) {
+        VIR_TEST_DEBUG("virGetSubIDs failed");
+        goto cleanup;
+    }
+
+    if (len != 4) {
+        VIR_TEST_DEBUG("virGetSubIDs returned %d (expected 4)", len);
+        goto cleanup;
+    }
+
+    if (STRNEQ(subids[0].idstr, "joe")) {
+        VIR_TEST_DEBUG("virGetSubIDs returned wrong name for entry 0: '%s'", NULLSTR(subids[0].idstr));
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    if (len >= 0)
+        virSubIDsFree(&subids, len);
+    return ret;
+}
+
+
 static int
 mymain(void)
 {
@@ -400,6 +432,7 @@ mymain(void)
     DO_TEST(OverflowCheckMacro);
     DO_TEST(KernelCmdlineNextParam);
     DO_TEST(KernelCmdlineMatchParam);
+    DO_TEST(GetSubIDs);
 
     return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
diff --git a/tests/virutiltestdata/subuid b/tests/virutiltestdata/subuid
new file mode 100644
index 0000000000..c873c0e3bf
--- /dev/null
+++ b/tests/virutiltestdata/subuid
@@ -0,0 +1,4 @@
+joe:100000:65535
+bob:300000:65535
+1024:400000:65535
+alice:200000:65535
-- 
2.42.0
_______________________________________________
Devel mailing list -- devel@xxxxxxxxxxxxxxxxx
To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxx




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux