Bug 16972

Summary: cpio: Bad magic
Product: [Retired] Red Hat Raw Hide Reporter: Dmitry V. Levin <redhat>
Component: rpmAssignee: Jeff Johnson <jbj>
Status: CLOSED WONTFIX QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: 1.0   
Target Milestone: ---   
Target Release: ---   
Hardware: i386   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2000-08-31 21:48:35 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Dmitry V. Levin 2000-08-25 21:41:31 UTC
While building packages with rpm-3.0.5, I've built a package recently which
causes rpm to abort during its installation with following diagnostics:

unpacking of archive failed: cpio: Bad magic

The package caused this bug was parted-devel-1.2.8-ipl1mdk.i686.rpm
I've rebuilt it several times with same effect, so it's repeatable bug.

Next, I've start testing with othes versions of rpm and got following
results:
3.0.3 - installs this package perfectly;
3.0.4 - buggy;
3.0.5 - buggy;
cvs snapshot - buggy;

After few hours of debugging, I know that:
cpio stream gets corrupted near the end (offset 1067992 of total length
1075016);
This bug could be repeated with rpm2cpio also; versions starting with 3.0.4
produce broken cpio archive (exactly at this offset).

Finally, I can add that
+ I've used zlib-1.1.3 in all tests;
+ I've tested all rpm versions with both glibc-2.1.3 and 2.1.92, and
noticed no difference in results.

And yes, I know, 3.0.4 differs from 3.0.3 in rpmio dramatically.

Hope this information will help. I stop hunting.

Regards,
	Dmitry

Comment 1 Jeff Johnson 2000-08-26 18:26:42 UTC
There's a bug in glibc-2.1.1 libio that has exactly this signature that was
fixed rather late
in rpm-3.0.5. What version(s) of glibc and rpm-3.0.5 are you using?

Comment 2 Jeff Johnson 2000-08-26 18:30:09 UTC
Make that what version of rpm-3.0.5 are you using? Here's the fix (in
lib/rpmio.c:2615)

                    /*
                     * XXX Red Hat 6.0 glibc-2.1.1 returns -1 and does not
                     * XXX call the close libio vector. Do that now.
                     */
                    if (rc == -1 && fd->fps[fd->nfps].fdno >= 0) {
                        fdio_close_function_t * _close = FDIOVEC(fd, close);
                        rc = _close(fd);
                    }


Comment 3 Dmitry V. Levin 2000-08-27 21:56:05 UTC
I'm using rpm-3.0.5 (release 11.6x) with glibc-2.1.92 (release 5, from rawhide)
for build (it contains those lines in rpmio.c),
and tested rpm2cpio (compiled on glibc-2.1.92, but dynamically linked) with:
+ several rpm versions (rpm-3.0.5 too)
+ both glibc-2.1.3 and glibc-2.1.92.

Comment 4 Dmitry V. Levin 2000-08-31 21:48:33 UTC
That's appeared to be a bug in interface with new libio from glibc-2.1.92
API change requires appropriate change in rpm. This already in CVS for 4.1,
same patch should be applied to other branches:
 --- rpm-3.0.5-orig/lib/rpmio.c	Thu Jul 20 05:10:31 2000
+++ rpm-3.0.5/lib/rpmio.c	Thu Aug 31 15:48:47 2000
@@ -429,7 +429,11 @@
 	return fd;
 }
 
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int fdSeekNot(void * cookie,  /*@unused@*/ _IO_off64_t *pos, 
/*@unused@*/ int whence) {
+#else
 static inline int fdSeekNot(void * cookie,  /*@unused@*/ off_t pos, 
/*@unused@*/ int whence) {
+#endif
     FD_t fd = c2f(cookie);
     FDSANE(fd);		/* XXX keep gcc quiet */
     return -2;
@@ -577,16 +581,21 @@
     return rc;
 }
 
-static inline int fdSeek(void * cookie, off_t pos, int whence) {
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int fdSeek(void * cookie, _IO_off64_t *pos, int whence) {
+    _IO_off64_t p = *pos;
+#else
+static inline int fdSeek(void * cookie, off_t p, int whence) {
+#endif
     FD_t fd = c2f(cookie);
     off_t rc;
 
     assert(fd->bytesRemain == -1);	/* XXX FIXME fadio only for now */
     fdstat_enter(fd, FDSTAT_SEEK);
-    rc = lseek(fdFileno(fd), pos, whence);
+    rc = lseek(fdFileno(fd), p, whence);
     fdstat_exit(fd, FDSTAT_SEEK, rc);
 
-DBGIO(fd, (stderr, "==>\tfdSeek(%p,%ld,%d) rc %lx %s\n", cookie, pos, whence,
(long)rc, fdbg(fd)));
+DBGIO(fd, (stderr, "==>\tfdSeek(%p,%ld,%d) rc %lx %s\n", cookie, (long)p,
whence, (long)rc, fdbg(fd)));
 
     return rc;
 }
@@ -1840,8 +1849,11 @@
     return count;
 }
 
-static int ufdSeek(void * cookie, off_t pos, int whence)
-{
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int ufdSeek(void * cookie, _IO_off64_t *pos, int whence) {
+#else
+static inline int ufdSeek(void * cookie, off_t pos, int whence) {
+#endif
     FD_t fd = c2f(cookie);
 
     switch (fd->urlType) {
@@ -2266,7 +2278,12 @@
 }
 
 /* XXX zlib-1.0.4 has not */
-static int gzdSeek(void * cookie, off_t pos, int whence) {
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int gzdSeek(void * cookie, _IO_off64_t *pos, int whence) {
+    _IO_off64_t p = *pos;
+#else
+static inline int gzdSeek(void * cookie, off_t p, int whence) {
+#endif
     int rc;
 #if HAVE_GZSEEK
     FD_t fd = c2f(cookie);
@@ -2275,8 +2292,8 @@
     assert(fd->bytesRemain == -1);	/* XXX FIXME */
     gzfile = gzdFileno(fd);
     fdstat_enter(fd, FDSTAT_SEEK);
-    rc = gzseek(gzfile, pos, whence);
-DBGIO(fd, (stderr, "==>\tgzdSeek(%p,%ld,%d) rc %lx %s\n", cookie, pos, whence,
(long)rc, fdbg(fd)));
+    rc = gzseek(gzfile, p, whence);
+DBGIO(fd, (stderr, "==>\tgzdSeek(%p,%ld,%d) rc %lx %s\n", cookie, (long)p,
whence, (long)rc, fdbg(fd)));
     if (rc < 0) {
 	int zerror = 0;
 	fd->errcookie = gzerror(gzfile, &zerror);
@@ -2436,7 +2453,11 @@
     return rc;
 }
 
-static int bzdSeek(void * cookie, /*@unused@*/ off_t pos, /*@unused@*/ int
whence) {
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int bzdSeek(void * cookie, _IO_off64_t *pos, int whence) {
+#else
+static inline int bzdSeek(void * cookie, off_t p, int whence) {
+#endif
     FD_t fd = c2f(cookie);
 
     BZDONLY(fd);
@@ -2556,21 +2577,32 @@
     return rc;
 }
 
-int Fseek(FD_t fd, long int offset, int whence) {
+#ifdef USE_COOKIE_SEEK_POINTER
+int Fseek(FD_t fd, _IO_off64_t offset, int whence) {
+#else 
+int Fseek(FD_t fd, off_t offset, int whence) {
+#endif
     fdio_seek_function_t *_seek;
     long int rc;
 
     FDSANE(fd);
-DBGIO(fd, (stderr, "==> Fseek(%p,%ld,%d) %s\n", fd, offset, whence, fdbg(fd)));
+DBGIO(fd, (stderr, "==> Fseek(%p,%ld,%d) %s\n", fd, (long)offset, whence,
fdbg(fd)));
 
     if (fdGetIo(fd) == fpio) {
-	rc = fseek(fdGetFILE(fd), offset, whence);
+	FILE *fp;
+
+	fp = fdGetFILE(fd);
+	rc = fseek(fp, offset, whence);
 	return rc;
     }
 
     _seek = FDIOVEC(fd, seek);
 
+#ifdef USE_COOKIE_SEEK_POINTER
+    rc = (_seek ? _seek(fd, &offset, whence) : -2);
+#else
     rc = (_seek ? _seek(fd, offset, whence) : -2);
+#endif
     return rc;
 }
 
@@ -2705,6 +2737,13 @@
 	*f = flags;
 }
 
+#if _USE_LIBIO
+#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0
+/* XXX retrofit glibc-2.1.x typedef on glibc-2.0.x systems */
+typedef _IO_cookie_io_functions_t cookie_io_functions_t;
+#endif
+#endif
+
 FD_t Fdopen(FD_t ofd, const char *fmode)
 {
     char stdio[20], other[20], zstdio[20];
@@ -2774,7 +2813,7 @@
 	FILE * fp = NULL;
 
 #if _USE_LIBIO
-	{   _IO_cookie_io_functions_t ciof;
+	{   cookie_io_functions_t ciof;
 	    ciof.read = iof->read;
 	    ciof.write = iof->write;
 	    ciof.seek = iof->seek;
@@ -2929,13 +2968,21 @@
  */
 
 /* XXX falloc.c: analogues to pread(3)/pwrite(3). */
+#ifdef USE_COOKIE_SEEK_POINTER
+ssize_t Pread(FD_t fd, void * buf, size_t count, _IO_off64_t offset) {
+#else
 ssize_t Pread(FD_t fd, void * buf, size_t count, off_t offset) {
+#endif
     if (Fseek(fd, offset, SEEK_SET) < 0)
 	return -1;
     return Fread(buf, sizeof(char), count, fd);
 }
 
+#ifdef USE_COOKIE_SEEK_POINTER
+ssize_t Pwrite(FD_t fd, const void * buf, size_t count, _IO_off64_t offset) {
+#else
 ssize_t Pwrite(FD_t fd, const void * buf, size_t count, off_t offset) {
+#endif
     if (Fseek(fd, offset, SEEK_SET) < 0)
 	return -1;
     return Fwrite(buf, sizeof(char), count, fd);
--- rpm-3.0.5-orig/lib/rpmio.h	Tue Jun 20 20:27:25 2000
+++ rpm-3.0.5/lib/rpmio.h	Thu Aug 31 15:48:47 2000
@@ -9,6 +9,10 @@
 #include <stdlib.h>
 #include <unistd.h>
 
+#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 2
+#define USE_COOKIE_SEEK_POINTER 1
+#endif
+
 typedef	/*@abstract@*/ /*@refcounted@*/ struct _FD_s * FD_t;
 typedef /*@observer@*/ struct FDIO_s * FDIO_t;
 
@@ -18,7 +22,11 @@
 
 typedef ssize_t fdio_read_function_t (void *cookie, char *buf, size_t nbytes);
 typedef ssize_t fdio_write_function_t (void *cookie, const char *buf, size_t
nbytes);
+#ifdef USE_COOKIE_SEEK_POINTER
+typedef int fdio_seek_function_t (void *cookie, _IO_off64_t * offset, int
whence);
+#else
 typedef int fdio_seek_function_t (void *cookie, off_t offset, int whence);
+#endif
 typedef int fdio_close_function_t (void *cookie);
 
 typedef /*@null@*/ FD_t fdio_ref_function_t ( /*@only@*/ void * cookie,
@@ -73,7 +81,12 @@
 
 size_t	Fread	(/*@out@*/ void * buf, size_t size, size_t nmemb, FD_t fd);
 size_t	Fwrite	(const void *buf, size_t size, size_t nmemb, FD_t fd);
-int	Fseek	(FD_t fd, long int offset, int whence);
+
+#ifdef USE_COOKIE_SEEK_POINTER
+int	Fseek	(FD_t fd, _IO_off64_t offset, int whence);
+#else
+int	Fseek	(FD_t fd, off_t offset, int whence);
+#endif
 int	Fclose	( /*@killref@*/ FD_t fd);
 FD_t	Fdopen	(FD_t fd, const char * fmode);
 FD_t	Fopen	(const char * path, const char * fmode);
@@ -83,8 +96,16 @@
 int	Fileno	(FD_t fd);
 
 int	Fcntl	(FD_t, int op, void *lip);
-ssize_t Pread	(FD_t fd, /*@out@*/ void * buf, size_t count, off_t offset);
-ssize_t Pwrite	(FD_t fd, const void * buf, size_t count, off_t offset);
+#ifdef USE_COOKIE_SEEK_POINTER
+ssize_t Pread(FD_t fd, void * buf, size_t count, _IO_off64_t offset);
+#else
+ssize_t Pread(FD_t fd, void * buf, size_t count, off_t offset);
+#endif
+#ifdef USE_COOKIE_SEEK_POINTER
+ssize_t Pwrite(FD_t fd, const void * buf, size_t count, _IO_off64_t offset);
+#else
+ssize_t Pwrite(FD_t fd, const void * buf, size_t count, off_t offset);
+#endif
 int	Mkdir	(const char * path, mode_t mode);
 int	Chdir	(const char * path);
 int	Rmdir	(const char * path);


Comment 5 Jeff Johnson 2000-09-14 16:57:47 UTC
While the patch (basically a backport from rpm-4.0) to rpm-3.0.5 is correct,
I've chosen to
"fix" this problem by putting
	Conflicts: glibc > 2.1.3
into rpm-3.0.6

Apply the patch if you need rpm-3.0.6 with glibc > 2.1.3