diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2013-02-20 18:58:42 +0400 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2013-02-20 18:58:42 +0400 |
commit | 2aec773688fd64857e9446838187170760acddd4 (patch) | |
tree | 4528074a1856b5656b5db6d140026a486c44714d | |
parent | 10f5f9b10d5bb18aa612e8f340d8454421015b00 (diff) |
rpm: use "create+rename" method of replacing existing files
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>
-rw-r--r-- | archival/libarchive/data_extract_all.c | 15 | ||||
-rw-r--r-- | archival/rpm.c | 4 | ||||
-rw-r--r-- | 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 3f67b835f..45776dcbe 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 793701652..6b227d537 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 a7a2a1135..b82cfd83c 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 */ |