Accepting request 1245646 from Base:System
- make the rpm package not depend on libarchive OBS-URL: https://build.opensuse.org/request/show/1245646 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/rpm?expand=0&rev=319
This commit is contained in:
commit
70c5694e7e
@ -1,122 +0,0 @@
|
||||
From fc04a1bde1941d2c61a9e33e55c5c492327674ba Mon Sep 17 00:00:00 2001
|
||||
From: Jan Zerebecki <jan.suse@zerebecki.de>
|
||||
Date: Thu, 15 Feb 2024 09:57:35 +0100
|
||||
Subject: [PATCH 1/3] Add option to set mtime of files in rpms
|
||||
|
||||
to SOURCE_DATE_EPOCH.
|
||||
|
||||
For backwards compatibility the option clamp / limit the maximum mtime
|
||||
is retained.
|
||||
|
||||
Setting it ouright avoids problems with an incorrectly older clock. It
|
||||
also avoids problems with build scrips that incorrectly change file
|
||||
mtimes when SOURCE_DATE_EPOCH_MTIME is in use.
|
||||
|
||||
mtimes are required to increase with new versions and releases
|
||||
of an rpm with the same name, as rsync without --checksum and similar
|
||||
tools would get confused if the content changes without newer mtime.
|
||||
|
||||
If SOURCE_DATE_EPOCH_MTIME is set use it instead for file modification time
|
||||
stamps. It is supposed to be newer. This can be used if we might want to
|
||||
compare if the file content remains the same when a build dependency
|
||||
changes while a build script embeds SOURCE_DATE_EPOCH in the file
|
||||
content.
|
||||
|
||||
This can be used to support automatic rebuilds. Normally automatic
|
||||
rebuilds work, but together with reproducible builds an undesirable
|
||||
situation may occur. If a build e.g. embeds SOURCE_DATE_EPOCH in the
|
||||
output, then the output changes every time such a rebuild happens, which
|
||||
can be very often. This is to be avoided as updating packages without
|
||||
necessity is too expensive.
|
||||
---
|
||||
build/files.c | 33 ++++++++++++++++++++++++++++-----
|
||||
docs/manual/buildprocess.md | 5 +++--
|
||||
2 files changed, 31 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/build/files.c b/build/files.c
|
||||
index c403c806e..cec7999ca 100644
|
||||
--- a/build/files.c
|
||||
+++ b/build/files.c
|
||||
@@ -1033,14 +1033,34 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
|
||||
rpm_loff_t totalFileSize = 0;
|
||||
Header h = pkg->header; /* just a shortcut */
|
||||
int override_date = 0;
|
||||
+ int set_mtime = 0;
|
||||
time_t source_date_epoch = 0;
|
||||
char *srcdate = getenv("SOURCE_DATE_EPOCH");
|
||||
+ char *msrcdate = getenv("SOURCE_DATE_EPOCH_MTIME");
|
||||
|
||||
- /* Limit the maximum date to SOURCE_DATE_EPOCH if defined
|
||||
- * similar to the tar --clamp-mtime option
|
||||
+ /* If SOURCE_DATE_EPOCH_MTIME is set use it for file modification time
|
||||
+ * stamps, it is supposed to be newer. This can be used if we might want to
|
||||
+ * compare if the file content remains the same when a build dependency
|
||||
+ * changes while a build script embeds SOURCE_DATE_EPOCH in the file
|
||||
+ * content. mtimes are required to increase with new versions and releases
|
||||
+ * of an rpm with the same name, as rsync without --checksum and similar
|
||||
+ * tools would get confused if the content changes without newer mtime. */
|
||||
+ if (msrcdate != NULL) {
|
||||
+ srcdate = msrcdate;
|
||||
+ }
|
||||
+
|
||||
+ /* Set the file mtime to SOURCE_DATE_EPOCH it if requested to make the
|
||||
+ * resulting rpm reproducible.
|
||||
* https://reproducible-builds.org/specs/source-date-epoch/
|
||||
+ *
|
||||
+ * For backwards compatibility clamp / limit the maximum mtime if requested
|
||||
+ * similar the tar --clamp-mtime option. Setting it ouright avoids problems
|
||||
+ * with an incorrectly older clock. It also avoids problems with build
|
||||
+ * scrips that incorrectly change file mtimes when SOURCE_DATE_EPOCH_MTIME
|
||||
+ * is in use.
|
||||
*/
|
||||
- if (srcdate && rpmExpandNumeric("%{?clamp_mtime_to_source_date_epoch}")) {
|
||||
+ if (srcdate && (rpmExpandNumeric("%{?clamp_mtime_to_source_date_epoch}")
|
||||
+ || rpmExpandNumeric("%{?set_mtime_to_source_date_epoch}"))) {
|
||||
char *endptr;
|
||||
errno = 0;
|
||||
source_date_epoch = strtol(srcdate, &endptr, 10);
|
||||
@@ -1049,6 +1069,9 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
|
||||
fl->processingFailed = 1;
|
||||
}
|
||||
override_date = 1;
|
||||
+ if (rpmExpandNumeric("%{?set_mtime_to_source_date_epoch}")) {
|
||||
+ set_mtime = 1;
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1191,8 +1214,8 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
|
||||
totalFileSize += flp->fl_size;
|
||||
}
|
||||
}
|
||||
-
|
||||
- if (override_date && flp->fl_mtime > source_date_epoch) {
|
||||
+
|
||||
+ if (override_date && (flp->fl_mtime > source_date_epoch || set_mtime)) {
|
||||
flp->fl_mtime = source_date_epoch;
|
||||
}
|
||||
/*
|
||||
diff --git a/docs/manual/buildprocess.md b/docs/manual/buildprocess.md
|
||||
index 1ceb47a7e..64cd35626 100644
|
||||
--- a/docs/manual/buildprocess.md
|
||||
+++ b/docs/manual/buildprocess.md
|
||||
@@ -94,13 +94,14 @@ Macro name | Description
|
||||
`%_build_pkgcheck` | Progam to run on each generated binary package
|
||||
`%_build_pkcheck_set` | Program to run on the generated binary package set
|
||||
|
||||
-### Reproducability
|
||||
+### Reproducibility
|
||||
|
||||
Macro name | Description
|
||||
--------------------------------------|-----------
|
||||
`%source_date_epoch_from_changelog` | Set `SOURCE_DATE_EPOCH` from latest `%changelog` entry
|
||||
`%use_source_date_epoch_as_buildtime` | Set package BuildTime to `SOURCE_DATE_EPOCH`
|
||||
-`%clamp_mtime_to_source_date_epoch` | Ensure file timestamps are not newer than `SOURCE_DATE_EPOCH`
|
||||
+`%set_mtime_to_source_date_epoch` | Set file modification timestamps to `SOURCE_DATE_EPOCH_MTIME` or as fallback to `SOURCE_DATE_EPOCH`
|
||||
+`%clamp_mtime_to_source_date_epoch` | You should use the above instead, it is for backwards compatibility only. Ensure file timestamps are not newer than `SOURCE_DATE_EPOCH`
|
||||
|
||||
### Vendor defaults
|
||||
|
||||
--
|
||||
2.30.2
|
||||
|
12
buildsys.diff
Normal file
12
buildsys.diff
Normal file
@ -0,0 +1,12 @@
|
||||
--- build/parseSpec.c.orig 2025-02-13 13:20:21.075462279 +0000
|
||||
+++ build/parseSpec.c 2025-02-13 13:15:42.447942795 +0000
|
||||
@@ -1429,7 +1429,8 @@ static rpmRC parseSpecParts(rpmSpec spec
|
||||
/* rpmGlob returns files sorted */
|
||||
if (rpmGlob(pattern, &argc, &argv) == 0) {
|
||||
for (int i = 0; i < argc; i++) {
|
||||
- rpmlog(RPMLOG_NOTICE, "Reading %s\n", argv[i]);
|
||||
+ if (stage != PARSE_BUILDSYS)
|
||||
+ rpmlog(RPMLOG_NOTICE, "Reading %s\n", argv[i]);
|
||||
pushOFI(spec, argv[i]);
|
||||
snprintf(spec->fileStack->readBuf, spec->fileStack->readBufLen,
|
||||
"# Spec part read from %s\n\n", argv[i]);
|
@ -1,16 +1,6 @@
|
||||
--- macros.in.orig 2024-12-16 12:48:44.110837972 +0000
|
||||
+++ macros.in 2024-12-16 12:52:32.014378635 +0000
|
||||
@@ -118,6 +118,9 @@
|
||||
# The directory where sources/patches will be unpacked and built.
|
||||
%_builddir %{_topdir}/BUILD
|
||||
|
||||
+# The build root where built files will be installed into
|
||||
+%buildroot %{_builddir}/%{NAME}-%{VERSION}-build/BUILDROOT
|
||||
+
|
||||
# The interpreter used for build scriptlets.
|
||||
%_buildshell /bin/sh
|
||||
|
||||
@@ -163,6 +166,7 @@
|
||||
--- macros.in.orig 2025-02-12 13:23:21.868124201 +0000
|
||||
+++ macros.in 2025-02-12 13:23:58.436059109 +0000
|
||||
@@ -163,6 +163,7 @@
|
||||
%{?_unique_debug_names:--unique-debug-suffix "-%{VERSION}-%{RELEASE}.%{_arch}"} \\\
|
||||
%{?_unique_debug_srcs:--unique-debug-src-base "%{name}-%{VERSION}-%{RELEASE}.%{_arch}"} \\\
|
||||
%{?_find_debuginfo_dwz_opts} \\\
|
||||
@ -18,7 +8,7 @@
|
||||
%{?_find_debuginfo_opts} \\\
|
||||
%{?_debugsource_packages:-S debugsourcefiles.list} \\\
|
||||
"%{builddir}/%{?buildsubdir}"\
|
||||
@@ -216,7 +220,8 @@ Supplements: (%{name} = %{version}-%{r
|
||||
@@ -216,7 +217,8 @@ Supplements: (%{name} = %{version}-%{r
|
||||
%files langpack-%{1}\
|
||||
%{nil}
|
||||
|
||||
@ -28,7 +18,7 @@
|
||||
%_defaultlicensedir %{_datadir}/licenses
|
||||
|
||||
# Following macros for filtering auto deps must not be used in spec files.
|
||||
@@ -275,7 +280,8 @@ Supplements: (%{name} = %{version}-%{r
|
||||
@@ -275,7 +277,8 @@ Supplements: (%{name} = %{version}-%{r
|
||||
%_tmppath %{_var}/tmp
|
||||
|
||||
# Path to top of build area.
|
||||
@ -38,7 +28,7 @@
|
||||
|
||||
#==============================================================================
|
||||
# ---- Optional rpmrc macros.
|
||||
@@ -366,7 +372,7 @@ Supplements: (%{name} = %{version}-%{r
|
||||
@@ -366,7 +369,7 @@ Supplements: (%{name} = %{version}-%{r
|
||||
# "w.ufdio" uncompressed
|
||||
#
|
||||
#%_source_payload w9.gzdio
|
||||
@ -47,7 +37,7 @@
|
||||
|
||||
# Algorithm to use for generating file checksum digests on build.
|
||||
# If not specified or 0, MD5 is used.
|
||||
@@ -476,6 +482,19 @@ Supplements: (%{name} = %{version}-%{r
|
||||
@@ -476,6 +479,19 @@ Supplements: (%{name} = %{version}-%{r
|
||||
#
|
||||
#%_include_minidebuginfo 1
|
||||
|
||||
@ -67,7 +57,7 @@
|
||||
#
|
||||
# Include a .gdb_index section in the .debug files.
|
||||
# Requires _enable_debug_packages and gdb-add-index installed.
|
||||
@@ -508,39 +527,39 @@ Supplements: (%{name} = %{version}-%{r
|
||||
@@ -508,39 +524,39 @@ Supplements: (%{name} = %{version}-%{r
|
||||
# Same as for "separate" but if the __debug_package global is set then
|
||||
# the -debuginfo package will have a compatibility link for the main
|
||||
# ELF /usr/lib/debug/.build-id/xx/yyy -> /usr/lib/.build-id/xx/yyy
|
||||
@ -114,7 +104,7 @@
|
||||
|
||||
#
|
||||
# Use internal dependency generator rather than external helpers?
|
||||
@@ -559,6 +578,7 @@ Supplements: (%{name} = %{version}-%{r
|
||||
@@ -559,6 +575,7 @@ Supplements: (%{name} = %{version}-%{r
|
||||
%__find_requires %{_rpmconfigdir}/find-requires
|
||||
#%__find_conflicts ???
|
||||
#%__find_obsoletes ???
|
||||
@ -122,7 +112,7 @@
|
||||
|
||||
#
|
||||
# Path to file attribute classifications for automatic dependency
|
||||
@@ -980,7 +1000,7 @@ Supplements: (%{name} = %{version}-%{r
|
||||
@@ -980,7 +997,7 @@ Supplements: (%{name} = %{version}-%{r
|
||||
%_build_vendor %{_host_vendor}
|
||||
%_build_os %{_host_os}
|
||||
%_host @host@
|
||||
@ -131,7 +121,7 @@
|
||||
%_host_cpu @host_cpu@
|
||||
%_host_vendor @host_vendor@
|
||||
%_host_os @host_os@
|
||||
@@ -1105,11 +1125,13 @@ Supplements: (%{name} = %{version}-%{r
|
||||
@@ -1105,11 +1122,13 @@ Supplements: (%{name} = %{version}-%{r
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# arch macro for all supported 32-bit ARM processors
|
||||
|
34
mtime_policy_set.diff
Normal file
34
mtime_policy_set.diff
Normal file
@ -0,0 +1,34 @@
|
||||
--- build/files.c.orig 2025-02-12 13:27:08.131721537 +0000
|
||||
+++ build/files.c 2025-02-12 13:32:28.371151422 +0000
|
||||
@@ -1049,10 +1049,10 @@ static void genCpioListAndHeader(FileLis
|
||||
}
|
||||
}
|
||||
|
||||
- if (!strcmp(mtime_policy_str, "clamp_to_buildtime")) {
|
||||
+ if (!strcmp(mtime_policy_str, "clamp_to_buildtime") || !strcmp(mtime_policy_str, "set_to_buildtime")) {
|
||||
mtime_clamp = spec->buildTime;
|
||||
- override_date = 1;
|
||||
- } else if (!strcmp(mtime_policy_str, "clamp_to_source_date_epoch")) {
|
||||
+ override_date = mtime_policy_str[0] == 's' ? 2 : 1;
|
||||
+ } else if (!strcmp(mtime_policy_str, "clamp_to_source_date_epoch") || !strcmp(mtime_policy_str, "set_to_source_date_epoch")) {
|
||||
/* Limit the maximum date to SOURCE_DATE_EPOCH if defined
|
||||
* similar to the tar --clamp-mtime option
|
||||
* https://reproducible-builds.org/specs/source-date-epoch/
|
||||
@@ -1065,7 +1065,7 @@ static void genCpioListAndHeader(FileLis
|
||||
rpmlog(RPMLOG_ERR, _("unable to parse %s=%s\n"), "SOURCE_DATE_EPOCH", srcdate);
|
||||
fl->processingFailed = 1;
|
||||
}
|
||||
- override_date = 1;
|
||||
+ override_date = mtime_policy_str[0] == 's' ? 2 : 1;
|
||||
}
|
||||
} else if (*mtime_policy_str) {
|
||||
rpmlog(RPMLOG_WARNING,
|
||||
@@ -1214,7 +1214,7 @@ static void genCpioListAndHeader(FileLis
|
||||
}
|
||||
}
|
||||
|
||||
- if (override_date && flp->fl_mtime > mtime_clamp) {
|
||||
+ if (override_date && (flp->fl_mtime > mtime_clamp || override_date == 2)) {
|
||||
flp->fl_mtime = mtime_clamp;
|
||||
}
|
||||
/*
|
17
rpm.changes
17
rpm.changes
@ -1,3 +1,20 @@
|
||||
-------------------------------------------------------------------
|
||||
Wed Feb 12 13:36:45 CET 2025 - mls@suse.de
|
||||
|
||||
- make the rpm package not depend on libarchive
|
||||
* move the rpmuncompress tool to rpm-build
|
||||
* rewrite rpm2archive to not use libarchive for cpio/tar writing
|
||||
* new patch: rpm2archive.diff
|
||||
- revert buildroot macro setting that did more harm than good
|
||||
- add set_to_buildtime and set_to_source_date_epoch mtime policy
|
||||
support
|
||||
* new patch: mtime_policy_set.diff
|
||||
- drop unused 0001-Add-option-to-set-mtime-of-files-in-rpms.patch
|
||||
patch
|
||||
- do not output debug messages in rpmspec -q if a buildsystem is
|
||||
used
|
||||
* new patch: buildsys.diff
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Feb 3 13:13:27 CET 2025 - mls@suse.de
|
||||
|
||||
|
11
rpm.spec
11
rpm.spec
@ -116,7 +116,6 @@ Patch135: selinux_transactional_update.patch
|
||||
Patch136: rpmsort_reverse.diff
|
||||
Patch138: canongnu.diff
|
||||
Patch139: cmake_python_version.diff
|
||||
Patch140: 0001-Add-option-to-set-mtime-of-files-in-rpms.patch
|
||||
Patch141: 0002-log-build-time-if-it-is-set-from-SOURCE_DATE_EPOCH.patch
|
||||
Patch142: 0003-Error-out-on-a-missing-changelog-date.patch
|
||||
Patch150: unshare.diff
|
||||
@ -124,6 +123,9 @@ Patch151: buildroot-symlink.diff
|
||||
Patch152: debugpackage.diff
|
||||
Patch153: nextfiles.diff
|
||||
Patch154: undefbuildroot.diff
|
||||
Patch155: rpm2archive.diff
|
||||
Patch156: mtime_policy_set.diff
|
||||
Patch157: buildsys.diff
|
||||
Patch6464: auto-config-update-aarch64-ppc64le.diff
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
#
|
||||
@ -241,11 +243,8 @@ rm -rf sqlite
|
||||
%patch -P 122 -P 123
|
||||
%patch -P 131 -P 133 -P 134 -P 135 -P 136 -P 138
|
||||
%patch -P 139
|
||||
%if 0
|
||||
%patch -P 140
|
||||
%endif
|
||||
%patch -P 141 -P 142
|
||||
%patch -P 150 -P 151 -P 152 -P 153 -P 154
|
||||
%patch -P 150 -P 151 -P 152 -P 153 -P 154 -P 155 -P 156 -P 157
|
||||
|
||||
%ifarch aarch64 ppc64le riscv64 loongarch64
|
||||
%patch -P 6464
|
||||
@ -450,7 +449,6 @@ fi
|
||||
/usr/lib/rpm/rpmpopt-*
|
||||
/usr/lib/rpm/rpmrc
|
||||
/usr/lib/rpm/rpmsort
|
||||
/usr/lib/rpm/rpmuncompress
|
||||
/usr/lib/rpm/rpmdump
|
||||
/usr/lib/rpm/suse
|
||||
/usr/lib/rpm/tgpg
|
||||
@ -483,6 +481,7 @@ fi
|
||||
/usr/lib/rpm/rpm_macros_provides.sh
|
||||
/usr/lib/rpm/elfdeps
|
||||
/usr/lib/rpm/rpmdeps
|
||||
/usr/lib/rpm/rpmuncompress
|
||||
/usr/bin/rpmspec
|
||||
/usr/lib/rpm/brp-*
|
||||
/usr/lib/rpm/check-*
|
||||
|
612
rpm2archive.diff
Normal file
612
rpm2archive.diff
Normal file
@ -0,0 +1,612 @@
|
||||
--- tools/CMakeLists.txt.orig 2025-02-13 09:56:00.257085875 +0000
|
||||
+++ tools/CMakeLists.txt 2025-02-13 09:56:11.433064235 +0000
|
||||
@@ -40,11 +40,8 @@ if (READLINE_FOUND)
|
||||
target_link_libraries(rpmlua PRIVATE PkgConfig::READLINE)
|
||||
endif()
|
||||
|
||||
-if (WITH_ARCHIVE)
|
||||
- add_executable(rpm2archive rpm2archive.c)
|
||||
- target_link_libraries(rpm2archive PRIVATE PkgConfig::LIBARCHIVE)
|
||||
- install(TARGETS rpm2archive)
|
||||
-endif()
|
||||
+add_executable(rpm2archive rpm2archive.c)
|
||||
+install(TARGETS rpm2archive)
|
||||
|
||||
# Everything links to these
|
||||
get_property(executables DIRECTORY PROPERTY BUILDSYSTEM_TARGETS)
|
||||
@@ -60,12 +57,10 @@ foreach(cmd rpmverify rpmquery)
|
||||
)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${cmd} TYPE BIN)
|
||||
endforeach()
|
||||
-if (WITH_ARCHIVE)
|
||||
- add_custom_target(rpm2cpio ALL COMMAND
|
||||
- ${CMAKE_COMMAND} -E create_symlink rpm2archive rpm2cpio
|
||||
- )
|
||||
- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/rpm2cpio TYPE BIN)
|
||||
-endif()
|
||||
+add_custom_target(rpm2cpio ALL COMMAND
|
||||
+ ${CMAKE_COMMAND} -E create_symlink rpm2archive rpm2cpio
|
||||
+ )
|
||||
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/rpm2cpio TYPE BIN)
|
||||
|
||||
if (WITH_CXX)
|
||||
set (cxx_sources
|
||||
--- tools/rpm2archive.c.orig 2024-10-07 09:35:46.000000000 +0000
|
||||
+++ tools/rpm2archive.c 2025-02-13 11:50:46.533098005 +0000
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
#include "system.h"
|
||||
|
||||
+#if defined(MAJOR_IN_MKDEV)
|
||||
+#include <sys/mkdev.h>
|
||||
+#elif defined(MAJOR_IN_SYSMACROS)
|
||||
+#include <sys/sysmacros.h>
|
||||
+#else
|
||||
+#include <sys/types.h> /* already included from system.h */
|
||||
+#endif
|
||||
+
|
||||
#include <rpm/rpmlib.h> /* rpmReadPackageFile .. */
|
||||
#include <rpm/rpmfi.h>
|
||||
#include <rpm/rpmstring.h>
|
||||
@@ -12,8 +20,11 @@
|
||||
|
||||
#include <popt.h>
|
||||
|
||||
+#if 0
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
+#endif
|
||||
+
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
@@ -36,6 +47,8 @@ static struct poptOption optionsTable[]
|
||||
POPT_TABLEEND
|
||||
};
|
||||
|
||||
+#if 0
|
||||
+
|
||||
static void fill_archive_entry(struct archive_entry * entry, rpmfi fi,
|
||||
char **hardlink)
|
||||
{
|
||||
@@ -282,6 +295,540 @@ static int process_package(rpmts ts, con
|
||||
return rc;
|
||||
}
|
||||
|
||||
+#else
|
||||
+
|
||||
+static int do_fwrite(FD_t fdo, const void *p, size_t l)
|
||||
+{
|
||||
+ if (Fwrite(p, l, 1, fdo) != l) {
|
||||
+ fprintf(stderr, "Error writing archive: %s\n", Fstrerror(fdo));
|
||||
+ return RPMRC_FAIL;
|
||||
+ }
|
||||
+ return RPMRC_OK;
|
||||
+}
|
||||
+
|
||||
+static int do_fwrite_content(FD_t fdo, char * buf, rpmfi fi)
|
||||
+{
|
||||
+ rpm_loff_t left = rpmfiFSize(fi);
|
||||
+ size_t len, read;
|
||||
+
|
||||
+ while (left) {
|
||||
+ len = (left > BUFSIZE ? BUFSIZE : left);
|
||||
+ read = rpmfiArchiveRead(fi, buf, len);
|
||||
+ if (read != len) {
|
||||
+ fprintf(stderr, "Error reading file from rpm payload\n");
|
||||
+ break;
|
||||
+ }
|
||||
+ if (do_fwrite(fdo, buf, len)) {
|
||||
+ fprintf(stderr, "Error writing archive: %s\n", Fstrerror(fdo));
|
||||
+ break;
|
||||
+ }
|
||||
+ left -= len;
|
||||
+ }
|
||||
+ return (left > 0);
|
||||
+}
|
||||
+
|
||||
+/* cpio support */
|
||||
+
|
||||
+static inline void write_cpio_entry_num(unsigned char *p, unsigned long val)
|
||||
+{
|
||||
+ char space[64];
|
||||
+ sprintf(space, "%8.8lx", val);
|
||||
+ memcpy(p, space, 8);
|
||||
+}
|
||||
+
|
||||
+static int write_cpio_entry(FD_t fdo, rpmfi fi, const char *filename, struct stat *st, const char *flink, const char *hlink, char *buf)
|
||||
+{
|
||||
+ unsigned char cpioh[110];
|
||||
+ memcpy(cpioh, "070701", 6);
|
||||
+ if (!fi) {
|
||||
+ memset(cpioh + 6, '0', sizeof(cpioh) - 6);
|
||||
+ write_cpio_entry_num(cpioh + 38, 1);
|
||||
+ write_cpio_entry_num(cpioh + 94, 11);
|
||||
+ if (do_fwrite(fdo, cpioh, sizeof(cpioh)))
|
||||
+ return RPMRC_FAIL;
|
||||
+ if (do_fwrite(fdo, "TRAILER!!!\0\0\0", 11 + 3))
|
||||
+ return RPMRC_FAIL;
|
||||
+ return RPMRC_OK;
|
||||
+ }
|
||||
+ if (st->st_size > UINT32_MAX) {
|
||||
+ fprintf(stderr, "Warning: file too large for format, skipping: %s\n", filename);
|
||||
+ return RPMRC_OK;
|
||||
+ }
|
||||
+ size_t fnl = strlen(filename);
|
||||
+ write_cpio_entry_num(cpioh + 6, st->st_ino);
|
||||
+ write_cpio_entry_num(cpioh + 14, st->st_mode);
|
||||
+ write_cpio_entry_num(cpioh + 22, st->st_uid);
|
||||
+ write_cpio_entry_num(cpioh + 30, st->st_gid);
|
||||
+ write_cpio_entry_num(cpioh + 38, st->st_nlink);
|
||||
+ write_cpio_entry_num(cpioh + 46, st->st_mtime);
|
||||
+ write_cpio_entry_num(cpioh + 54, st->st_size);
|
||||
+ write_cpio_entry_num(cpioh + 62, major(st->st_dev));
|
||||
+ write_cpio_entry_num(cpioh + 70, minor(st->st_dev));
|
||||
+ write_cpio_entry_num(cpioh + 78, major(st->st_rdev));
|
||||
+ write_cpio_entry_num(cpioh + 86, minor(st->st_rdev));
|
||||
+ write_cpio_entry_num(cpioh + 94, fnl + 1);
|
||||
+ write_cpio_entry_num(cpioh + 102, 0);
|
||||
+ if (do_fwrite(fdo, cpioh, sizeof(cpioh)))
|
||||
+ return RPMRC_FAIL;
|
||||
+ if (do_fwrite(fdo, filename, fnl + 1))
|
||||
+ return RPMRC_FAIL;
|
||||
+ fnl = (110 + fnl + 1) & 3;
|
||||
+ if (fnl && do_fwrite(fdo, "\0\0\0", 4 - fnl))
|
||||
+ return RPMRC_FAIL;
|
||||
+ if (S_ISLNK(st->st_mode)) {
|
||||
+ if (st->st_size != strlen(flink))
|
||||
+ return RPMRC_FAIL;
|
||||
+ if (do_fwrite(fdo, flink, st->st_size))
|
||||
+ return RPMRC_FAIL;
|
||||
+ } else if (S_ISREG(st->st_mode)) {
|
||||
+ if (st->st_size && do_fwrite_content(fdo, buf, fi))
|
||||
+ return RPMRC_FAIL;
|
||||
+ } else {
|
||||
+ return RPMRC_OK;
|
||||
+ }
|
||||
+ fnl = (st->st_size) & 3;
|
||||
+ if (fnl && do_fwrite(fdo, "\0\0\0", 4 - fnl))
|
||||
+ return RPMRC_FAIL;
|
||||
+ return RPMRC_OK;
|
||||
+}
|
||||
+
|
||||
+/* pax support */
|
||||
+
|
||||
+static void add_pax_attrib(char **paxbuf, const char *pax, const char *val)
|
||||
+{
|
||||
+ size_t ten, len = 1 + strlen(pax) + 1 + strlen(val) + 1;
|
||||
+ for (ten = 1; ten <= len; ten *= 10)
|
||||
+ len++;
|
||||
+ if (*paxbuf)
|
||||
+ *paxbuf = realloc(*paxbuf, strlen(*paxbuf) + len + 1);
|
||||
+ else {
|
||||
+ *paxbuf = xmalloc(len + 1);
|
||||
+ **paxbuf = 0;
|
||||
+ }
|
||||
+ sprintf(*paxbuf + strlen(*paxbuf), "%llu %s=%s\n", (unsigned long long)len, pax, val);
|
||||
+}
|
||||
+
|
||||
+static void set_pax_entry_num_base256(unsigned char *p, unsigned long long val, int size)
|
||||
+{
|
||||
+ /* use base-256 encoding */
|
||||
+ unsigned char *pe = p + size;
|
||||
+ for (; pe > p; val >>= 8)
|
||||
+ *pe-- = (unsigned char)(val & 255);
|
||||
+ *p |= 0x80;
|
||||
+}
|
||||
+
|
||||
+static inline void set_pax_entry_num(unsigned char *p, unsigned long long val, int size, char *pax, char **paxbuf)
|
||||
+{
|
||||
+ char space[64];
|
||||
+ int sz = size == 12 ? size - 1 : size - 2;
|
||||
+ if (paxbuf && val >= (unsigned long long)1 << (sz * 3)) {
|
||||
+ /* add pax header */
|
||||
+ sprintf(space, "%llu", val);
|
||||
+ add_pax_attrib(paxbuf, pax, space);
|
||||
+ }
|
||||
+ if (val >= (unsigned long long)1 << (size * 3)) {
|
||||
+ set_pax_entry_num_base256(p, val, size);
|
||||
+ return;
|
||||
+ }
|
||||
+ sprintf(space, "%0*llo ", sz, val);
|
||||
+ memcpy(p, space, size);
|
||||
+}
|
||||
+
|
||||
+static int pax_is_ascii(const char *val)
|
||||
+{
|
||||
+ for (; *val; val++)
|
||||
+ if (*(const unsigned char *)val >= 0x80)
|
||||
+ return 0;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static inline void set_pax_entry_str(unsigned char *p, const char *val, int size, char *pax, char **paxbuf)
|
||||
+{
|
||||
+ size_t l = strlen(val);
|
||||
+ if (paxbuf && (l > size || !pax_is_ascii(val)))
|
||||
+ add_pax_attrib(paxbuf, pax, val);
|
||||
+ memcpy(p, val, l < size ? l : size);
|
||||
+}
|
||||
+
|
||||
+static void set_pax_path_mangle(unsigned char *paxh, const char *filename, const char *insert)
|
||||
+{
|
||||
+ size_t l = strlen(filename);
|
||||
+ size_t ilen = insert ? strlen(insert) + 1 : 0;
|
||||
+ const char *p, *p2, *bn;
|
||||
+ int isdir = 0;
|
||||
+ /* strip trailing '/' and '/.' components */
|
||||
+ while (l && (filename[l - 1] == '/' || (filename[l - 1] == '.' && l > 1 && filename[l - 2] == '/'))) {
|
||||
+ l--;
|
||||
+ isdir = 1;
|
||||
+ }
|
||||
+ if (ilen) {
|
||||
+ isdir = 0; /* no trailing slash for a PaxHeader */
|
||||
+ if (l == 0) {
|
||||
+ filename = "/rootdir";
|
||||
+ l = 8;
|
||||
+ } else if (l == 1 && filename[0] == '.') {
|
||||
+ filename = "currentdir";
|
||||
+ l = 10;
|
||||
+ } else if (l == 2 && filename[0] == '.' && filename[1] == '.') {
|
||||
+ filename = "parrentdir";
|
||||
+ l = 10;
|
||||
+ }
|
||||
+ }
|
||||
+ /* find the basename */
|
||||
+ bn = filename + l;
|
||||
+ while (bn > filename && bn[-1] != '/')
|
||||
+ bn--;
|
||||
+ /* truncate basename (we use 99 like libarchive so we can add a '/' if the prefix is empty) */
|
||||
+ l -= bn - filename;
|
||||
+ if (l > 99 - (ilen + isdir))
|
||||
+ l = 99 - (ilen + isdir);
|
||||
+ /* calculate prefix */
|
||||
+ if (bn - filename <= 100 - (l + ilen + isdir)) {
|
||||
+ p = filename; /* no need for a prefix */
|
||||
+ } else {
|
||||
+ p = bn - filename > 155 ? filename + 155 : bn;
|
||||
+ while (p > filename && *p != '/')
|
||||
+ p--;
|
||||
+ /* move as much of the prefix into name as possible */
|
||||
+ if (p > filename && bn - p < 99 - (l + ilen + isdir)) {
|
||||
+ p2 = strchr(bn - (99 - (l + ilen + isdir)), '/');
|
||||
+ if (p2 && p2 < p)
|
||||
+ p = p2;
|
||||
+ }
|
||||
+ }
|
||||
+ /* copy the prefix */
|
||||
+ if (p != filename) {
|
||||
+ memcpy(paxh + 345, filename, p - filename);
|
||||
+ p++; /* skip the '/' */
|
||||
+ }
|
||||
+ /* copy rest of the dir */
|
||||
+ p2 = p + (99 - (l + ilen + isdir)) > bn ? bn : p + (99 - (l + ilen + isdir));
|
||||
+ while (p2 > p && *p2 != '/')
|
||||
+ p2--;
|
||||
+ if (p2 < bn && *p2 == '/')
|
||||
+ p2++; /* always fits as we used 99 as size limit above */
|
||||
+ memcpy(paxh, p, p2 - p);
|
||||
+ /* copy the insert */
|
||||
+ if (ilen) {
|
||||
+ memcpy(paxh + (p2 - p), insert, ilen);
|
||||
+ paxh[p2 - p + ilen - 1] = '/';
|
||||
+ }
|
||||
+ /* copy the basename */
|
||||
+ memcpy(paxh + (p2 - p) + ilen, bn, l);
|
||||
+ if (isdir)
|
||||
+ paxh[p2 - p + ilen + l] = '/';
|
||||
+}
|
||||
+
|
||||
+static int set_pax_path(unsigned char *paxh, const char *filename)
|
||||
+{
|
||||
+ size_t l = strlen(filename);
|
||||
+ if (l <= 100) {
|
||||
+ memcpy(paxh, filename, l);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ const char *p = strchr(filename + l - 100 - 1, '/');
|
||||
+ if (p == filename)
|
||||
+ p = strchr(filename + 1, '/');
|
||||
+ if (p && p[1] && p - filename <= 155) {
|
||||
+ memcpy(paxh, p + 1, l - (p + 1 - filename));
|
||||
+ memcpy(paxh + 345, filename, p - filename);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ set_pax_path_mangle(paxh, filename, NULL);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static int write_pax_entry_pax(FD_t fdo, rpmfi fi, const char *filename, struct stat *st, char *paxbuf);
|
||||
+
|
||||
+static int write_pax_entry(FD_t fdo, rpmfi fi, const char *filename, struct stat *st, const char *flink, const char *hlink, char *buf)
|
||||
+{
|
||||
+ unsigned char paxh[512];
|
||||
+ int tartype = -1;
|
||||
+ rpm_loff_t size = 0;
|
||||
+
|
||||
+ memset(paxh, 0, sizeof(paxh));
|
||||
+ if (!fi) {
|
||||
+ if (do_fwrite(fdo, paxh, sizeof(paxh)))
|
||||
+ return RPMRC_FAIL;
|
||||
+ if (do_fwrite(fdo, paxh, sizeof(paxh)))
|
||||
+ return RPMRC_FAIL;
|
||||
+ return RPMRC_OK;
|
||||
+ }
|
||||
+ if (filename == NULL && flink)
|
||||
+ tartype = 'x';
|
||||
+ else if (S_ISREG(st->st_mode))
|
||||
+ tartype = st->st_nlink > 1 && !rpmfiArchiveHasContent(fi) ? '1' : '0';
|
||||
+ else if (S_ISLNK(st->st_mode))
|
||||
+ tartype = '2';
|
||||
+ else if (S_ISCHR(st->st_mode))
|
||||
+ tartype = '3';
|
||||
+ else if (S_ISBLK(st->st_mode))
|
||||
+ tartype = '4';
|
||||
+ else if (S_ISDIR(st->st_mode))
|
||||
+ tartype = '5';
|
||||
+ else if (S_ISFIFO(st->st_mode))
|
||||
+ tartype = '6';
|
||||
+ if (tartype == -1) {
|
||||
+ fprintf(stderr, "Warning: unsupported file type, skipping: %s\n", filename);
|
||||
+ return RPMRC_OK;
|
||||
+ }
|
||||
+ if (tartype == '5') {
|
||||
+ size_t l = strlen(filename);
|
||||
+ if (!l || filename[l - 1] != '/') {
|
||||
+ char *dirfilename = rstrscat(NULL, filename, "/", NULL);
|
||||
+ int r = write_pax_entry(fdo, fi, dirfilename, st, flink, hlink, buf);
|
||||
+ _free(dirfilename);
|
||||
+ return r;
|
||||
+ }
|
||||
+ }
|
||||
+ if (tartype == '0' || tartype == '1')
|
||||
+ size = rpmfiFSize(fi);
|
||||
+ else if (tartype == 'x')
|
||||
+ size = (rpm_loff_t)strlen(buf);
|
||||
+
|
||||
+ /* fill entry header */
|
||||
+ char *paxbuf = NULL;
|
||||
+ char **paxbufp = tartype == 'x' ? NULL : &paxbuf;
|
||||
+ if (tartype == 'x') {
|
||||
+ set_pax_path_mangle(paxh, flink, "PaxHeader");
|
||||
+ } else {
|
||||
+ if (set_pax_path(paxh, filename) || !pax_is_ascii(filename))
|
||||
+ add_pax_attrib(paxbufp, "path", filename);
|
||||
+ }
|
||||
+ set_pax_entry_num(paxh + 100, st->st_mode & 07777, 8, NULL, NULL);
|
||||
+ set_pax_entry_num(paxh + 108, st->st_uid, 8, "uid", paxbufp);
|
||||
+ set_pax_entry_num(paxh + 116, st->st_gid, 8, "gid", paxbufp);
|
||||
+ set_pax_entry_num(paxh + 124, size, 12, "size", paxbufp);
|
||||
+ set_pax_entry_num(paxh + 136, st->st_mtime, 12, "mtime", paxbufp);
|
||||
+ memset(paxh + 148, ' ', 8);
|
||||
+ paxh[156] = tartype;
|
||||
+ if (tartype == '1' || tartype == '2')
|
||||
+ set_pax_entry_str(paxh + 157, tartype == '1' ? hlink : flink, 100, "linkpath", paxbufp);
|
||||
+ memcpy(paxh + 257, "ustar\00000", 8);
|
||||
+ set_pax_entry_str(paxh + 265, rpmfiFUser(fi), 32, "user", paxbufp);
|
||||
+ set_pax_entry_str(paxh + 297, rpmfiFGroup(fi), 32, "group", paxbufp);
|
||||
+ set_pax_entry_num(paxh + 329, major(st->st_rdev), 8, "SCHILY.devmajor", paxbufp);
|
||||
+ set_pax_entry_num(paxh + 337, minor(st->st_rdev), 8, "SCHILY.devminor", paxbufp);
|
||||
+ int i, checksum = 0;
|
||||
+ for (i = 0; i < 512; i++)
|
||||
+ checksum += paxh[i];
|
||||
+ set_pax_entry_num(paxh + 148, checksum, 8, NULL, NULL);
|
||||
+ paxh[148 + 6] = 0;
|
||||
+ paxh[148 + 7] = ' ';
|
||||
+ /* write pax header if we need it */
|
||||
+ if (paxbuf) {
|
||||
+ int r = write_pax_entry_pax(fdo, fi, filename, st, paxbuf);
|
||||
+ free(paxbuf);
|
||||
+ if (r)
|
||||
+ return RPMRC_FAIL;
|
||||
+ }
|
||||
+ /* write entry header */
|
||||
+ if (do_fwrite(fdo, paxh, 512))
|
||||
+ return RPMRC_FAIL;
|
||||
+ if (tartype != '0' && tartype != 'x')
|
||||
+ return RPMRC_OK; /* no content for those types */
|
||||
+ /* write content */
|
||||
+ if (tartype == '0' && size && do_fwrite_content(fdo, buf, fi))
|
||||
+ return RPMRC_FAIL;
|
||||
+ if (tartype == 'x' && size && do_fwrite(fdo, buf, size))
|
||||
+ return RPMRC_FAIL;
|
||||
+ /* write padding */
|
||||
+ size &= 511;
|
||||
+ if (size) {
|
||||
+ memset(paxh, 0, sizeof(paxh));
|
||||
+ if (do_fwrite(fdo, paxh, 512 - size))
|
||||
+ return RPMRC_FAIL;
|
||||
+ }
|
||||
+ return RPMRC_OK;
|
||||
+}
|
||||
+
|
||||
+static int write_pax_entry_pax(FD_t fdo, rpmfi fi, const char *filename, struct stat *st, char *paxbuf)
|
||||
+{
|
||||
+ /* tweak stat data and filename */
|
||||
+ struct stat paxst = *st;
|
||||
+ paxst.st_size = strlen(paxbuf);
|
||||
+ paxst.st_mode = paxst.st_mode & 0777;
|
||||
+ if (paxst.st_uid >= (1 << 18))
|
||||
+ paxst.st_uid = (1 << 18) - 1;
|
||||
+ if (paxst.st_gid >= (1 << 18))
|
||||
+ paxst.st_gid = (1 << 18) - 1;
|
||||
+ if (paxst.st_mtime < 0)
|
||||
+ paxst.st_mtime = 0;
|
||||
+ if ((unsigned long long)paxst.st_mtime >= 1ULL << 33)
|
||||
+ paxst.st_mtime = (time_t)((1ULL << 33) - 1);
|
||||
+ return write_pax_entry(fdo, fi, NULL, &paxst, filename, NULL, paxbuf);
|
||||
+}
|
||||
+
|
||||
+static int process_package(rpmts ts, const char * filename)
|
||||
+{
|
||||
+ FD_t fdi;
|
||||
+ FD_t gzdi;
|
||||
+ FD_t fdo;
|
||||
+ Header h;
|
||||
+ int rc = 0;
|
||||
+ char * rpmio_flags = NULL;
|
||||
+ int iscpio = 0;
|
||||
+
|
||||
+ if (!strcmp(filename, "-")) {
|
||||
+ if(isatty(STDIN_FILENO)) {
|
||||
+ fprintf(stderr, "Error: missing input RPM package\n");
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ }
|
||||
+ fdi = fdDup(STDIN_FILENO);
|
||||
+ } else {
|
||||
+ fdi = Fopen(filename, "r.ufdio");
|
||||
+ }
|
||||
+
|
||||
+ if (Ferror(fdi)) {
|
||||
+ fprintf(stderr, "rpm2archive: %s: %s\n",
|
||||
+ filename, Fstrerror(fdi));
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ }
|
||||
+
|
||||
+ rc = rpmReadPackageFile(ts, fdi, "rpm2cpio", &h);
|
||||
+
|
||||
+ switch (rc) {
|
||||
+ case RPMRC_OK:
|
||||
+ case RPMRC_NOKEY:
|
||||
+ case RPMRC_NOTTRUSTED:
|
||||
+ break;
|
||||
+ case RPMRC_NOTFOUND:
|
||||
+ fprintf(stderr, _("argument is not an RPM package\n"));
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ break;
|
||||
+ case RPMRC_FAIL:
|
||||
+ default:
|
||||
+ fprintf(stderr, _("error reading header from package\n"));
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /* Retrieve payload size and compression type. */
|
||||
+ { const char *compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
|
||||
+ rpmio_flags = rstrscat(NULL, "r.", compr ? compr : "gzip", NULL);
|
||||
+ }
|
||||
+
|
||||
+ gzdi = Fdopen(fdi, rpmio_flags); /* XXX gzdi == fdi */
|
||||
+ free(rpmio_flags);
|
||||
+
|
||||
+ if (gzdi == NULL) {
|
||||
+ fprintf(stderr, _("cannot re-open payload: %s\n"), Fstrerror(gzdi));
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ }
|
||||
+
|
||||
+ if (rstreq(format, "pax")) {
|
||||
+ iscpio = 0;
|
||||
+ } else if (rstreq(format, "cpio")) {
|
||||
+ iscpio = 1;
|
||||
+ } else {
|
||||
+ fprintf(stderr, "Error: Format %s is not supported\n", format);
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ }
|
||||
+
|
||||
+ if (!isatty(STDOUT_FILENO)) {
|
||||
+ fdo = fdDup(STDOUT_FILENO);
|
||||
+ } else {
|
||||
+ if (!strcmp(filename, "-")) {
|
||||
+ fprintf(stderr, "Error: refusing to output archive data to a terminal.\n");
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ }
|
||||
+ char * outname;
|
||||
+ if (urlIsURL(filename)) {
|
||||
+ const char * fname = strrchr(filename, '/');
|
||||
+ if (fname != NULL) {
|
||||
+ fname++;
|
||||
+ } else {
|
||||
+ fname = filename;
|
||||
+ }
|
||||
+ outname = rstrscat(NULL, fname, NULL);
|
||||
+ } else {
|
||||
+ outname = rstrscat(NULL, filename, NULL);
|
||||
+ }
|
||||
+ if (compress) {
|
||||
+ outname = rstrscat(&outname, ".tgz", NULL);
|
||||
+ } else {
|
||||
+ outname = rstrscat(&outname, ".tar", NULL);
|
||||
+ }
|
||||
+ fdo = Fopen(outname, "w.ufdio");
|
||||
+ if (!fdo) {
|
||||
+ fprintf(stderr, "Error: Can't open output file: %s\n", outname);
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ }
|
||||
+ _free(outname);
|
||||
+ }
|
||||
+ if (compress && fdo)
|
||||
+ fdo = Fdopen(fdo, "w.gzdio");
|
||||
+ if (!fdo) {
|
||||
+ fprintf(stderr, "Error: Can't setup output file\n");
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ }
|
||||
+
|
||||
+ char * buf = (char *)xmalloc(BUFSIZE);
|
||||
+ char * hardlink = NULL;
|
||||
+
|
||||
+ rpmfiles files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
|
||||
+ rpmfi fi = rpmfiNewArchiveReader(gzdi, files, iscpio ? RPMFI_ITER_READ_ARCHIVE : RPMFI_ITER_READ_ARCHIVE_CONTENT_FIRST);
|
||||
+
|
||||
+ while ((rc = rpmfiNext(fi)) >= 0) {
|
||||
+ struct stat st;
|
||||
+ const char *dn, *flink;
|
||||
+ char *filename;
|
||||
+ if (rpmfiStat(fi, 0, &st)) {
|
||||
+ break;
|
||||
+ }
|
||||
+ dn = rpmfiDN(fi);
|
||||
+ if (!strcmp(dn, "")) dn = "/";
|
||||
+ filename = rstrscat(NULL, ".", dn, rpmfiBN(fi), NULL);
|
||||
+ flink = S_ISLNK(st.st_mode) ? rpmfiFLink(fi) : NULL;
|
||||
+ if (st.st_nlink > 1 && !iscpio) {
|
||||
+ if (rpmfiArchiveHasContent(fi)) {
|
||||
+ /* hardlink sizes are special, see rpmfiStat() */
|
||||
+ _free(hardlink);
|
||||
+ hardlink = xstrdup(filename);
|
||||
+ }
|
||||
+ }
|
||||
+ if (iscpio)
|
||||
+ rc = write_cpio_entry(fdo, fi, filename, &st, flink, st.st_nlink > 1 ? hardlink : NULL, buf);
|
||||
+ else
|
||||
+ rc = write_pax_entry(fdo, fi, filename, &st, flink, st.st_nlink > 1 ? hardlink : NULL, buf);
|
||||
+ _free(filename);
|
||||
+ if (rc == RPMRC_FAIL)
|
||||
+ break;
|
||||
+ }
|
||||
+ /* End of iteration is not an error, everything else is */
|
||||
+ if (rc == RPMERR_ITER_END) {
|
||||
+ rc = 0;
|
||||
+ } else {
|
||||
+ rc = 1;
|
||||
+ }
|
||||
+
|
||||
+ /* write trailer */
|
||||
+ if (!rc) {
|
||||
+ if (iscpio)
|
||||
+ rc = write_cpio_entry(fdo, NULL, NULL, NULL, NULL, NULL, buf);
|
||||
+ else
|
||||
+ rc = write_pax_entry(fdo, NULL, NULL, NULL, NULL, NULL, buf);
|
||||
+ rc = rc == RPMRC_FAIL ? 1 : 0;
|
||||
+ }
|
||||
+
|
||||
+ if (Fclose(fdo) && !rc) {
|
||||
+ fprintf(stderr, "Error writing archive\n");
|
||||
+ rc = 1;
|
||||
+ }
|
||||
+
|
||||
+ _free(hardlink);
|
||||
+
|
||||
+ Fclose(gzdi); /* XXX gzdi == fdi */
|
||||
+ buf = _free(buf);
|
||||
+ rpmfilesFree(files);
|
||||
+ rpmfiFree(fi);
|
||||
+ headerFree(h);
|
||||
+ return rc;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rc = 0;
|
Loading…
x
Reference in New Issue
Block a user