]> git.ipfire.org Git - pakfire.git/commitdiff
archive: extract: Set groups correctly
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 8 Mar 2021 11:44:43 +0000 (11:44 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 8 Mar 2021 11:44:43 +0000 (11:44 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/archive.c
src/libpakfire/include/pakfire/pwd.h
src/libpakfire/pwd.c

index 3d694b44e95b0fc0cbb78b1cf3b2c3acc399baeb..bfc126ecd90d9395d4908aa617bacf00c46b303e 100644 (file)
@@ -719,6 +719,25 @@ static la_int64_t archive_user_lookup(void* data, const char* name, la_int64_t u
        return entry->pw_uid;
 }
 
+static la_int64_t archive_group_lookup(void* data, const char* name, la_int64_t uid) {
+       Pakfire pakfire = (Pakfire)data;
+
+       // Fast path for "root"
+       if (strcmp(name, "root") == 0)
+               return 0;
+
+       // Find a matching entry in /etc/group
+       struct group* entry = pakfire_getgrnam(pakfire, name);
+       if (!entry) {
+               ERROR(pakfire, "Could not retrieve GID for '%s': %s\n", name, strerror(errno));
+               return 0;
+       }
+
+       DEBUG(pakfire, "Mapping %s to GID %d\n", name, entry->gr_gid);
+
+       return entry->gr_gid;
+}
+
 static int archive_extract(PakfireArchive archive, struct archive* a, const char* prefix) {
        struct archive_entry* entry;
        int r;
@@ -741,10 +760,10 @@ static int archive_extract(PakfireArchive archive, struct archive* a, const char
        flags |= ARCHIVE_EXTRACT_XATTR;
 
        archive_write_disk_set_options(ext, flags);
-       archive_write_disk_set_standard_lookup(ext);
 
-       // Install our own routine for user lookups
+       // Install our own routine for user/group lookups
        archive_write_disk_set_user_lookup(ext, archive->pakfire, archive_user_lookup, NULL);
+       archive_write_disk_set_group_lookup(ext, archive->pakfire, archive_group_lookup, NULL);
 
        for (;;) {
                r = archive_read_next_header(a, &entry);
index 118629e678b4a0a56217809b6006373c87441986..372cf1a9fafe5382fc3b09fbe3e0977120929bd0 100644 (file)
@@ -23,6 +23,7 @@
 
 #ifdef PAKFIRE_PRIVATE
 
+#include <grp.h>
 #include <pwd.h>
 
 #include <pakfire/types.h>
@@ -30,6 +31,9 @@
 struct passwd* pakfire_getpwnam(Pakfire pakfire, const char* name);
 struct passwd* pakfire_getpwuid(Pakfire pakfire, uid_t uid);
 
+struct group* pakfire_getgrnam(Pakfire pakfire, const char* name);
+struct group* pakfire_getgruid(Pakfire pakfire, gid_t gid);
+
 #endif
 
 #endif /* PAKFIRE_PWD_H */
index 47143fab0a8a738a89cf63a690fb8e5eafd86653..819e31a3389cfdcc26b0bb12e781d4472371b617 100644 (file)
@@ -18,6 +18,7 @@
 #                                                                             #
 #############################################################################*/
 
+#include <grp.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -85,3 +86,64 @@ static int __pakfire_getpwuid(struct passwd* entry, const void* value) {
 struct passwd* pakfire_getpwuid(Pakfire pakfire, uid_t uid) {
        return pakfire_getpwent(pakfire, __pakfire_getpwuid, &uid);
 }
+
+static struct group* pakfire_getgrent(Pakfire pakfire,
+               int(*cmp)(struct group* entry, const void* value), const void* value) {
+       struct group* entry = NULL;
+
+       // Get path to /etc/group
+       char* path = pakfire_make_path(pakfire, "/etc/group");
+       if (!path)
+               return NULL;
+
+       FILE* f = fopen(path, "r");
+       if (!f)
+               goto END;
+
+       for (;;) {
+               // Parse entry
+               entry = fgetgrent(f);
+               if (!entry)
+                       goto END;
+
+               // Check if this is what we are looking for
+               if (cmp(entry, value))
+                       break;
+               else
+                       entry = NULL;
+       }
+
+END:
+       free(path);
+
+       if (f)
+               fclose(f);
+
+       return entry;
+}
+
+static int __pakfire_getgrnam(struct group* entry, const void* value) {
+       const char* name = (const char*)value;
+
+       if (strcmp(entry->gr_name, name) == 0)
+               return 1;
+
+       return 0;
+}
+
+struct group* pakfire_getgrnam(Pakfire pakfire, const char* name) {
+       return pakfire_getgrent(pakfire, __pakfire_getgrnam, name);
+}
+
+static int __pakfire_getgrgid(struct group* entry, const void* value) {
+       gid_t* gid = (gid_t*)value;
+
+       if (entry->gr_gid == *gid)
+               return 1;
+
+       return 0;
+}
+
+struct group* pakfire_getgruid(Pakfire pakfire, gid_t gid) {
+       return pakfire_getgrent(pakfire, __pakfire_getgrgid, &gid);
+}