rpm: use "create+rename" method of replacing existing files
authorDenys Vlasenko <vda.linux@googlemail.com>
Wed, 20 Feb 2013 14:58:42 +0000 (15:58 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Wed, 20 Feb 2013 14:58:42 +0000 (15:58 +0100)
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@googlemail.com>
archival/libarchive/data_extract_all.c
archival/rpm.c
include/bb_archive.h

index 3f67b83..45776dc 100644 (file)
@@ -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:
index 7937016..6b227d5 100644 (file)
@@ -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 */
 
index a7a2a11..b82cfd8 100644 (file)
@@ -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  */