commit: ffe362f97546bbabe6b5f869ed60070a6cdf8ec1
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sat Jan 3 15:34:32 2026 +0000
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sat Jan 3 15:34:32 2026 +0000
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=ffe362f9
qpkg: properly store directories and symlinks in gpkg files
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
qpkg.c | 117 +++++++++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 81 insertions(+), 36 deletions(-)
diff --git a/qpkg.c b/qpkg.c
index 409f18f..a765339 100644
--- a/qpkg.c
+++ b/qpkg.c
@@ -18,7 +18,7 @@
#include <sys/types.h>
#include <sys/stat.h>
-#ifdef HAVE_LIBARCHIVE
+#ifdef ENABLE_GPKG
# include <archive.h>
# include <archive_entry.h>
#endif
@@ -267,7 +267,7 @@ qgpkg_make(tree_pkg_ctx *pkg, qpkg_cb_args *args)
int mfd;
mode_t mask;
depend_atom *atom = tree_get_atom(pkg, false);
- size_t len;
+ ssize_t len;
if (pretend) {
printf(" %s-%s %s:\n",
@@ -315,7 +315,7 @@ qgpkg_make(tree_pkg_ctx *pkg, qpkg_cb_args *args)
/* contractually we don't have to put anything in here, but we drop
* our signature so it can be traced back to us */
len = snprintf(ename, sizeof(ename), "portage-utils-%s", VERSION);
- if (write(fd, ename, len) != len)
+ if (write(fd, ename, (size_t)len) != len)
warnp("could not write self-identifier");
close(fd);
write_hashes(buf, "DATA", mfd);
@@ -352,7 +352,7 @@ qgpkg_make(tree_pkg_ctx *pkg, qpkg_cb_args *args)
archive_entry_set_perm(entry, 0644);
archive_write_header(a, entry);
while ((len = read(fd, buf, sizeof(buf))) > 0)
- archive_write_data(a, buf, len);
+ archive_write_data(a, buf, (size_t)len);
close(fd);
archive_entry_free(entry);
}
@@ -372,38 +372,83 @@ qgpkg_make(tree_pkg_ctx *pkg, qpkg_cb_args *args)
for (; (line = strtok_r(line, "\n", &savep)) != NULL; line = NULL) {
contents_entry *e;
e = contents_parse_line(line);
- if (!e || e->type == CONTENTS_DIR)
+ if (!e)
continue;
if (check_pkg_install_mask(e->name) != 0)
continue;
- if (e->type == CONTENTS_OBJ && verbose) {
- char *hash = hash_file(e->name, HASH_MD5);
- if (hash != NULL) {
- if (strcmp(e->digest, hash) != 0)
- warn("MD5: mismatch expected %s got %s
for %s",
- e->digest, hash,
e->name);
- }
- }
-
- if ((fd = open(e->name, O_RDONLY)) < 0)
- continue;
- if (fstat(fd, &st) < 0) {
- close(fd);
- continue;
+ switch (e->type) {
+ case CONTENTS_OBJ:
+ if (verbose) {
+ char *hash = hash_file(e->name,
HASH_MD5);
+ if (hash != NULL) {
+ if (strcmp(e->digest, hash) !=
0)
+ warn("MD5 mismatch:
expected %s got %s for %s",
+
e->digest, hash, e->name);
+ }
+ }
+
+ if ((fd = open(e->name, O_RDONLY)) < 0)
+ continue;
+ if (fstat(fd, &st) < 0) {
+ close(fd);
+ continue;
+ }
+
+ entry = archive_entry_new();
+ snprintf(ename, sizeof(ename), "image/%s",
e->name + 1);
+ archive_entry_set_pathname(entry, ename);
+ archive_entry_copy_stat(entry, &st);
+ archive_write_header(a, entry);
+ while ((len = read(fd, buf, sizeof(buf))) > 0)
+ archive_write_data(a, buf, (size_t)len);
+ close(fd);
+ archive_entry_free(entry);
+ break;
+ case CONTENTS_SYM:
+ /* like for files, we take whatever is in the
filesystem */
+ if ((len = readlink(e->name, ename,
sizeof(ename) - 1)) < 0)
+ snprintf(ename, sizeof(ename), "%s",
e->sym_target);
+ else
+ ename[len] = '\0';
+
+ if (verbose) {
+ if (strcmp(e->sym_target, ename) != 0)
+ warn("symlink target mismatch: "
+ "expected %s got %s
for %s",
+ e->sym_target, ename,
e->name);
+ }
+
+ entry = archive_entry_new();
+ archive_entry_set_symlink(entry, ename);
+ snprintf(ename, sizeof(ename), "image/%s",
e->name + 1);
+ archive_entry_set_pathname(entry, ename);
+ if (lstat(e->name, &st) < 0) {
+ archive_entry_set_mtime(entry,
e->mtime, 0);
+ archive_entry_set_filetype(entry,
AE_IFLNK);
+ archive_entry_set_mode(entry, 0777);
+ } else {
+ archive_entry_copy_stat(entry, &st);
+ }
+ archive_write_header(a, entry);
+ archive_entry_free(entry);
+ break;
+ case CONTENTS_DIR:
+ if ((fd = open(e->name, O_RDONLY)) < 0)
+ continue;
+ if (fstat(fd, &st) < 0) {
+ close(fd);
+ continue;
+ }
+ close(fd);
+
+ entry = archive_entry_new();
+ snprintf(ename, sizeof(ename), "image/%s",
e->name + 1);
+ archive_entry_set_pathname(entry, ename);
+ archive_entry_copy_stat(entry, &st);
+ archive_write_header(a, entry);
+ archive_entry_free(entry);
+ break;
}
-
- entry = archive_entry_new();
- snprintf(ename, sizeof(ename), "image/%s", e->name + 1);
- archive_entry_set_pathname(entry, ename);
- archive_entry_set_size(entry, st.st_size);
- archive_entry_set_mtime(entry, st.st_mtime, 0);
- archive_entry_set_filetype(entry, st.st_mode & S_IFMT);
- archive_entry_set_perm(entry, st.st_mode & ~S_IFMT);
- archive_write_header(a, entry);
- while ((len = read(fd, buf, sizeof(buf))) > 0)
- archive_write_data(a, buf, len);
- close(fd);
- archive_entry_free(entry);
}
archive_write_close(a);
archive_write_free(a);
@@ -429,7 +474,7 @@ qgpkg_make(tree_pkg_ctx *pkg, qpkg_cb_args *args)
archive_entry_set_perm(entry, 0644);
archive_write_header(a, entry);
while ((len = read(fd, buf, sizeof(buf))) > 0)
- archive_write_data(a, buf, len);
+ archive_write_data(a, buf, (size_t)len);
close(fd);
archive_entry_free(entry);
}
@@ -448,7 +493,7 @@ qgpkg_make(tree_pkg_ctx *pkg, qpkg_cb_args *args)
archive_entry_set_perm(entry, 0644);
archive_write_header(a, entry);
while ((len = read(fd, buf, sizeof(buf))) > 0)
- archive_write_data(a, buf, len);
+ archive_write_data(a, buf, (size_t)len);
close(fd);
archive_entry_free(entry);
}
@@ -468,7 +513,7 @@ qgpkg_make(tree_pkg_ctx *pkg, qpkg_cb_args *args)
archive_entry_set_perm(entry, 0644);
archive_write_header(a, entry);
while ((len = read(fd, buf, sizeof(buf))) > 0)
- archive_write_data(a, buf, len);
+ archive_write_data(a, buf, (size_t)len);
close(fd);
archive_entry_free(entry);
}
@@ -489,7 +534,7 @@ qgpkg_make(tree_pkg_ctx *pkg, qpkg_cb_args *args)
archive_entry_set_perm(entry, 0644);
archive_write_header(a, entry);
while ((len = read(fd, buf, sizeof(buf))) > 0)
- archive_write_data(a, buf, len);
+ archive_write_data(a, buf, (size_t)len);
close(fd);
archive_entry_free(entry);
}