summaryrefslogtreecommitdiffstats
path: root/debfilecontents.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 19:12:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 19:12:14 +0000
commit4b8a0f3f3dcf60dac2ce308ea08d413a535af29f (patch)
tree0f09c0ad2a4d0f535d89040a63dc3a866a6606e6 /debfilecontents.c
parentInitial commit. (diff)
downloadreprepro-upstream/5.4.4.tar.xz
reprepro-upstream/5.4.4.zip
Adding upstream version 5.4.4.upstream/5.4.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--debfilecontents.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/debfilecontents.c b/debfilecontents.c
new file mode 100644
index 0000000..611a93f
--- /dev/null
+++ b/debfilecontents.c
@@ -0,0 +1,221 @@
+/* This file is part of "reprepro"
+ * Copyright (C) 2006,2007 Bernhard R. Link
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+#include <config.h>
+
+#include <errno.h>
+#include <assert.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <archive.h>
+#include <archive_entry.h>
+#include "error.h"
+#include "uncompression.h"
+#include "ar.h"
+#include "filelist.h"
+#include "debfile.h"
+
+#ifndef HAVE_LIBARCHIVE
+#error Why did this file got compiled?
+#endif
+#if ARCHIVE_VERSION_NUMBER < 3000000
+#define archive_read_free archive_read_finish
+#endif
+
+static retvalue read_data_tar(/*@out@*/char **list, /*@out@*/size_t *size, const char *debfile, struct ar_archive *ar, struct archive *tar) {
+ struct archive_entry *entry;
+ struct filelistcompressor c;
+ retvalue r;
+ int a, e;
+
+ r = filelistcompressor_setup(&c);
+ if (RET_WAS_ERROR(r))
+ return r;
+
+ archive_read_support_format_tar(tar);
+ archive_read_support_format_gnutar(tar);
+ a = archive_read_open(tar, ar,
+ ar_archivemember_open,
+ ar_archivemember_read,
+ ar_archivemember_close);
+ if (a != ARCHIVE_OK) {
+ filelistcompressor_cancel(&c);
+ e = archive_errno(tar);
+ if (e == -EINVAL) /* special code to say there is none */
+ fprintf(stderr,
+"open data.tar within '%s' failed: %s\n",
+ debfile, archive_error_string(tar));
+ else
+ fprintf(stderr,
+"open data.tar within '%s' failed: %d:%d:%s\n", debfile, a, e,
+ archive_error_string(tar));
+ return RET_ERROR;
+ }
+ while ((a=archive_read_next_header(tar, &entry)) == ARCHIVE_OK) {
+ const char *name = archive_entry_pathname(entry);
+ mode_t mode;
+
+ if (name[0] == '.')
+ name++;
+ if (name[0] == '/')
+ name++;
+ if (name[0] == '\0')
+ continue;
+ mode = archive_entry_mode(entry);
+ if (!S_ISDIR(mode)) {
+ r = filelistcompressor_add(&c, name, strlen(name));
+ if (RET_WAS_ERROR(r)) {
+ filelistcompressor_cancel(&c);
+ return r;
+ }
+ }
+ if (interrupted()) {
+ filelistcompressor_cancel(&c);
+ return RET_ERROR_INTERRUPTED;
+ }
+ a = archive_read_data_skip(tar);
+ if (a != ARCHIVE_OK) {
+ e = archive_errno(tar);
+ if (e == -EINVAL) {
+ r = RET_ERROR;
+ fprintf(stderr,
+"Error skipping %s within data.tar from %s: %s\n",
+ archive_entry_pathname(entry),
+ debfile, archive_error_string(tar));
+ } else {
+ fprintf(stderr,
+"Error %d skipping %s within data.tar from %s: %s\n",
+ e, archive_entry_pathname(entry),
+ debfile, archive_error_string(tar));
+ if (e != 0)
+ r = RET_ERRNO(e);
+ else
+ r = RET_ERROR;
+ }
+ filelistcompressor_cancel(&c);
+ return r;
+ }
+ }
+ if (a != ARCHIVE_EOF) {
+ e = archive_errno(tar);
+ if (e == -EINVAL) {
+ r = RET_ERROR;
+ fprintf(stderr,
+"Error reading data.tar from %s: %s\n", debfile, archive_error_string(tar));
+ } else {
+ fprintf(stderr,
+"Error %d reading data.tar from %s: %s\n",
+ e, debfile, archive_error_string(tar));
+ if (e != 0)
+ r = RET_ERRNO(e);
+ else
+ r = RET_ERROR;
+ }
+ filelistcompressor_cancel(&c);
+ return r;
+ }
+ return filelistcompressor_finish(&c, list, size);
+}
+
+
+retvalue getfilelist(/*@out@*/char **filelist, size_t *size, const char *debfile) {
+ struct ar_archive *ar;
+ retvalue r;
+ bool hadcandidate;
+ bool uncompressedretry = false;
+ retrylabel:
+ hadcandidate = false;
+ r = ar_open(&ar, debfile);
+ if (RET_WAS_ERROR(r))
+ return r;
+ assert (r != RET_NOTHING);
+ do {
+ char *filename;
+ enum compression c;
+
+ r = ar_nextmember(ar, &filename);
+ if (RET_IS_OK(r)) {
+ if (strncmp(filename, "data.tar", 8) != 0) {
+ free(filename);
+ continue;
+ }
+ hadcandidate = true;
+ for (c = 0 ; c < c_COUNT ; c++) {
+ if (strcmp(filename + 8,
+ uncompression_suffix[c]) == 0)
+ break;
+ }
+ if (c >= c_COUNT) {
+ free(filename);
+ continue;
+ }
+ if (uncompressedretry) c = c_none;
+ ar_archivemember_setcompression(ar, c);
+ if (uncompression_supported(c)) {
+ struct archive *tar;
+ int a;
+
+ tar = archive_read_new();
+ r = read_data_tar(filelist, size,
+ debfile, ar, tar);
+ a = archive_read_close(tar);
+ if (a != ARCHIVE_OK && !RET_WAS_ERROR(r)) {
+ int e = archive_errno(tar);
+ if (e == -EINVAL)
+ fprintf(stderr,
+"reading data.tar within '%s' failed: %s\n",
+ debfile,
+ archive_error_string(
+ tar));
+ else
+ fprintf(stderr,
+"reading data.tar within '%s' failed: %d:%d:%s\n", debfile, a, e,
+ archive_error_string(
+ tar));
+ r = RET_ERROR;
+ }
+ a = archive_read_free(tar);
+ if (a != ARCHIVE_OK && !RET_WAS_ERROR(r)) {
+ r = RET_ERROR;
+ }
+ if (r != RET_NOTHING) {
+ ar_close(ar);
+ free(filename);
+ if ((r == RET_ERROR) && (!uncompressedretry)) {
+ uncompressedretry = true;
+ fprintf(stderr,"retrying uncompressed\n");
+ goto retrylabel;
+ } else {
+ return r;
+ }
+ }
+
+ }
+ free(filename);
+ }
+ } while (RET_IS_OK(r));
+ ar_close(ar);
+ if (hadcandidate)
+ fprintf(stderr,
+"Could not find a suitable data.tar file within '%s'!\n", debfile);
+ else
+ fprintf(stderr,
+"Could not find a data.tar file within '%s'!\n", debfile);
+ return RET_ERROR_MISSING;
+}