[git commit] rpm: use "create+rename" method of replacing existing files

Denys Vlasenko vda.linux at googlemail.com
Wed Feb 20 14:58:42 UTC 2013


commit: http://git.busybox.net/busybox/commit/?id=2aec773688fd64857e9446838187170760acddd4
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

Users were reporting getting errors like
"ls: error while loading shared libraries: libc.so.6: ELF load command past end of file"
while rpm was unpacking glibc tarball.

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 archival/libarchive/data_extract_all.c |   15 ++++++++++++++-
 archival/rpm.c                         |    4 ++--
 include/bb_archive.h                   |    3 +++
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c
index 3f67b83..45776dc 100644
--- a/archival/libarchive/data_extract_all.c
+++ b/archival/libarchive/data_extract_all.c
@@ -106,15 +106,28 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
 	switch (file_header->mode & S_IFMT) {
 	case S_IFREG: {
 		/* Regular file */
+		char *dst_name;
 		int flags = O_WRONLY | O_CREAT | O_EXCL;
 		if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
 			flags = O_WRONLY | O_CREAT | O_TRUNC;
-		dst_fd = xopen3(file_header->name,
+		dst_name = file_header->name;
+#ifdef ARCHIVE_REPLACE_VIA_RENAME
+		if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME)
+			/* rpm-style temp file name */
+			dst_name = xasprintf("%s;%x", dst_name, (int)getpid());
+#endif
+		dst_fd = xopen3(dst_name,
 			flags,
 			file_header->mode
 			);
 		bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
 		close(dst_fd);
+#ifdef ARCHIVE_REPLACE_VIA_RENAME
+		if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) {
+			xrename(dst_name, file_header->name);
+			free(dst_name);
+		}
+#endif
 		break;
 	}
 	case S_IFDIR:
diff --git a/archival/rpm.c b/archival/rpm.c
index 7937016..6b227d5 100644
--- a/archival/rpm.c
+++ b/archival/rpm.c
@@ -242,8 +242,8 @@ static void extract_cpio(int fd, const char *source_rpm)
 		/* compat: overwrite existing files.
 		 * try "rpm -i foo.src.rpm" few times in a row -
 		 * standard rpm will not complain.
-		 * (TODO? real rpm creates "file;1234" and then renames it) */
-		| ARCHIVE_UNLINK_OLD;
+		 */
+		| ARCHIVE_REPLACE_VIA_RENAME;
 	archive_handle->src_fd = fd;
 	/*archive_handle->offset = 0; - init_handle() did it */
 
diff --git a/include/bb_archive.h b/include/bb_archive.h
index a7a2a11..b82cfd8 100644
--- a/include/bb_archive.h
+++ b/include/bb_archive.h
@@ -122,6 +122,9 @@ typedef struct archive_handle_t {
 #define ARCHIVE_NUMERIC_OWNER       (1 << 7)
 #define ARCHIVE_O_TRUNC             (1 << 8)
 #define ARCHIVE_REMEMBER_NAMES      (1 << 9)
+#if ENABLE_RPM
+#define ARCHIVE_REPLACE_VIA_RENAME  (1 << 10)
+#endif
 
 
 /* POSIX tar Header Block, from POSIX 1003.1-1990  */


More information about the busybox-cvs mailing list