Handle partial reads and errors in package IO (RhBug:802839, RhBug:580974)
- There are no guarantees Fread() will return all of the requested size: it can return partial data eg on signals and pipe descriptors. Introduce a helper function to handle this centrally for all package read IO, effectively reintroducing timedRead() but without the caveats: timedRead() did not work on compressed streams, did not handle eg EINTR correctly and while really being an internal helper, was exported in the API.
This commit is contained in:
parent
0b9c93ed18
commit
cbd6ef58bb
32
lib/header.c
32
lib/header.c
|
@ -964,7 +964,7 @@ Header headerRead(FD_t fd, int magicp)
|
||||||
if (magicp == HEADER_MAGIC_YES) {
|
if (magicp == HEADER_MAGIC_YES) {
|
||||||
int32_t magic;
|
int32_t magic;
|
||||||
|
|
||||||
if (Fread(block, 1, 4*sizeof(*block), fd) != 4*sizeof(*block))
|
if (Freadall(fd, block, 4*sizeof(*block)) != 4*sizeof(*block))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
magic = block[0];
|
magic = block[0];
|
||||||
|
@ -975,7 +975,7 @@ Header headerRead(FD_t fd, int magicp)
|
||||||
il = ntohl(block[2]);
|
il = ntohl(block[2]);
|
||||||
dl = ntohl(block[3]);
|
dl = ntohl(block[3]);
|
||||||
} else {
|
} else {
|
||||||
if (Fread(block, 1, 2*sizeof(*block), fd) != 2*sizeof(*block))
|
if (Freadall(fd, block, 2*sizeof(*block)) != 2*sizeof(*block))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
il = ntohl(block[0]);
|
il = ntohl(block[0]);
|
||||||
|
@ -993,7 +993,7 @@ Header headerRead(FD_t fd, int magicp)
|
||||||
ei[0] = htonl(il);
|
ei[0] = htonl(il);
|
||||||
ei[1] = htonl(dl);
|
ei[1] = htonl(dl);
|
||||||
|
|
||||||
if (Fread((char *)&ei[2], 1, blen, fd) != blen)
|
if (Freadall(fd, (char *)&ei[2], blen) != blen)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
h = headerImport(ei, len, 0);
|
h = headerImport(ei, len, 0);
|
||||||
|
@ -1747,3 +1747,29 @@ void headerSetInstance(Header h, unsigned int instance)
|
||||||
h->instance = instance;
|
h->instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RETRY_ERROR(_err) \
|
||||||
|
((_err) == EINTR || (_err) == EAGAIN || (_err) == EWOULDBLOCK)
|
||||||
|
|
||||||
|
ssize_t Freadall(FD_t fd, void * buf, ssize_t size)
|
||||||
|
{
|
||||||
|
ssize_t total = 0;
|
||||||
|
ssize_t nb = 0;
|
||||||
|
char * bufp = buf;
|
||||||
|
|
||||||
|
while (total < size) {
|
||||||
|
nb = Fread(bufp, 1, size - total, fd);
|
||||||
|
|
||||||
|
if (nb == 0 || (nb < 0 && !RETRY_ERROR(errno))) {
|
||||||
|
total = nb;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nb > 0) {
|
||||||
|
bufp += nb;
|
||||||
|
total += nb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,9 @@ extern "C" {
|
||||||
RPM_GNUC_INTERNAL
|
RPM_GNUC_INTERNAL
|
||||||
void headerSetInstance(Header h, unsigned int instance);
|
void headerSetInstance(Header h, unsigned int instance);
|
||||||
|
|
||||||
|
/* Package IO helper to consolidate partial read and error handling */
|
||||||
|
RPM_GNUC_INTERNAL
|
||||||
|
ssize_t Freadall(FD_t fd, void * buf, ssize_t size);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -422,7 +422,7 @@ static rpmRC rpmpkgReadHeader(rpmKeyring keyring, rpmVSFlags vsflags,
|
||||||
*msg = NULL;
|
*msg = NULL;
|
||||||
|
|
||||||
memset(block, 0, sizeof(block));
|
memset(block, 0, sizeof(block));
|
||||||
if ((xx = Fread(block, 1, sizeof(block), fd)) != sizeof(block)) {
|
if ((xx = Freadall(fd, block, sizeof(block))) != sizeof(block)) {
|
||||||
rasprintf(&buf,
|
rasprintf(&buf,
|
||||||
_("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
|
_("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -448,7 +448,7 @@ static rpmRC rpmpkgReadHeader(rpmKeyring keyring, rpmVSFlags vsflags,
|
||||||
ei = xmalloc(uc);
|
ei = xmalloc(uc);
|
||||||
ei[0] = block[2];
|
ei[0] = block[2];
|
||||||
ei[1] = block[3];
|
ei[1] = block[3];
|
||||||
if ((xx = Fread((char *)&ei[2], 1, nb, fd)) != nb) {
|
if ((xx = Freadall(fd, (char *)&ei[2], nb)) != nb) {
|
||||||
rasprintf(&buf, _("hdr blob(%zd): BAD, read returned %d\n"), nb, xx);
|
rasprintf(&buf, _("hdr blob(%zd): BAD, read returned %d\n"), nb, xx);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <rpm/rpmstring.h>
|
#include <rpm/rpmstring.h>
|
||||||
|
|
||||||
#include "lib/signature.h"
|
#include "lib/signature.h"
|
||||||
|
#include "lib/header_internal.h" /* Freadall() */
|
||||||
#include "lib/rpmlead.h"
|
#include "lib/rpmlead.h"
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
@ -117,7 +118,7 @@ rpmRC rpmLeadRead(FD_t fd, rpmlead *lead, int *type, char **emsg)
|
||||||
char *err = NULL;
|
char *err = NULL;
|
||||||
|
|
||||||
memset(&l, 0, sizeof(l));
|
memset(&l, 0, sizeof(l));
|
||||||
if (Fread(&l, 1, sizeof(l), fd) != sizeof(l)) {
|
if (Freadall(fd, &l, sizeof(l)) != sizeof(l)) {
|
||||||
if (Ferror(fd)) {
|
if (Ferror(fd)) {
|
||||||
rasprintf(&err, _("read failed: %s (%d)\n"), Fstrerror(fd), errno);
|
rasprintf(&err, _("read failed: %s (%d)\n"), Fstrerror(fd), errno);
|
||||||
rc = RPMRC_FAIL;
|
rc = RPMRC_FAIL;
|
||||||
|
|
|
@ -86,7 +86,7 @@ rpmRC rpmReadSignature(FD_t fd, Header * sighp, sigType sig_type, char ** msg)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
memset(block, 0, sizeof(block));
|
memset(block, 0, sizeof(block));
|
||||||
if ((xx = Fread(block, 1, sizeof(block), fd)) != sizeof(block)) {
|
if ((xx = Freadall(fd, block, sizeof(block))) != sizeof(block)) {
|
||||||
rasprintf(&buf, _("sigh size(%d): BAD, read returned %d\n"),
|
rasprintf(&buf, _("sigh size(%d): BAD, read returned %d\n"),
|
||||||
(int)sizeof(block), xx);
|
(int)sizeof(block), xx);
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -118,7 +118,7 @@ rpmRC rpmReadSignature(FD_t fd, Header * sighp, sigType sig_type, char ** msg)
|
||||||
ei[1] = block[3];
|
ei[1] = block[3];
|
||||||
pe = (entryInfo) &ei[2];
|
pe = (entryInfo) &ei[2];
|
||||||
dataStart = (unsigned char *) (pe + il);
|
dataStart = (unsigned char *) (pe + il);
|
||||||
if ((xx = Fread(pe, 1, nb, fd)) != nb) {
|
if ((xx = Freadall(fd, pe, nb)) != nb) {
|
||||||
rasprintf(&buf,
|
rasprintf(&buf,
|
||||||
_("sigh blob(%d): BAD, read returned %d\n"), (int)nb, xx);
|
_("sigh blob(%d): BAD, read returned %d\n"), (int)nb, xx);
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -214,7 +214,7 @@ rpmRC rpmReadSignature(FD_t fd, Header * sighp, sigType sig_type, char ** msg)
|
||||||
rpm_loff_t archSize = 0;
|
rpm_loff_t archSize = 0;
|
||||||
|
|
||||||
/* Position at beginning of header. */
|
/* Position at beginning of header. */
|
||||||
if (pad && (trc = Fread(block, 1, pad, fd)) != pad) {
|
if (pad && (trc = Freadall(fd, block, pad)) != pad) {
|
||||||
rasprintf(&buf,
|
rasprintf(&buf,
|
||||||
_("sigh pad(%zd): BAD, read %zd bytes\n"), pad, trc);
|
_("sigh pad(%zd): BAD, read %zd bytes\n"), pad, trc);
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
Loading…
Reference in New Issue