rpmio: fixed Fwrite() truncated return value

This is the reason why files >= 2G could not be added to cpio, even on
64-bit architectures.  Fwrite was called with a buffer >= 2G, but the
return value was truncated to int (this narrowing conversion is probably
undefined behavior already; what happens next, though, is that after
casting to size_t it assumes a very big numeric value of >= 2^64-2^32).
So rpmbuild was failing with an unrelated errno, "cpio: write failed -
Bad file descriptor".

There are other reasons why this still won't work on 32-bit architectures.
For one, rpmbuild mmaps a file before feeding it to cpio, and 32-bit
architectures have a very limited ability, if any, to mmap 2G+ files.
This commit is contained in:
Alexey Tourbin 2018-01-28 23:52:21 +03:00
parent c58b3a24d0
commit a1a075caa2

View File

@ -3104,7 +3104,7 @@ static ssize_t lzdWrite(void * cookie, const char * buf, size_t count)
fdstat_enter(fd, FDSTAT_WRITE);
rc = lzwrite(lzfile, (void *)buf, count);
if (rc < 0) {
if (rc == -1) {
fd->errcookie = "Lzma: encoding error";
} else if (rc > 0) {
fdstat_exit(fd, FDSTAT_WRITE, rc);
@ -3244,9 +3244,6 @@ DBGIO(fd, (stderr, "==> Fread(%p,%u,%u,%p) %s\n", buf, (unsigned)size, (unsigned
size_t Fwrite(const void *buf, size_t size, size_t nmemb, FD_t fd)
{
fdio_write_function_t _write;
int rc;
FDSANE(fd);
/*@-modfilesys@*/
DBGIO(fd, (stderr, "==> Fwrite(%p,%u,%u,%p) %s\n", buf, (unsigned)size, (unsigned)nmemb, (fd ? fd : NULL), fdbg(fd)));
@ -3254,17 +3251,28 @@ DBGIO(fd, (stderr, "==> Fwrite(%p,%u,%u,%p) %s\n", buf, (unsigned)size, (unsigne
if (fdGetIo(fd) == fpio) {
/*@+voidabstract -nullpass@*/
rc = fwrite(buf, size, nmemb, fdGetFILE(fd));
size_t ret = fwrite(buf, size, nmemb, fdGetFILE(fd));
/*@=voidabstract =nullpass@*/
return rc;
return ret * size;
}
/*@-nullderef@*/
_write = FDIOVEC(fd, write);
fdio_write_function_t _write = FDIOVEC(fd, write);
/*@=nullderef@*/
assert(_write);
rc = (_write ? _write(fd, buf, size * nmemb) : -2);
return rc;
// XXX check for overflow instead of assuming that size=1.
size_t n = size * nmemb;
// XXX sloppy mixing of size_t and ssize_t is going on here.
ssize_t ret = _write(fd, buf, n);
if (ret == -1)
return 0;
if (ret == n)
return n;
if (ret < 0)
return 0;
return ret;
}
int Fseek(FD_t fd, _libio_off_t offset, int whence) {