io: fix skip and splice to detect unexpected end-of-file
parent
97e4d0531f
commit
2f3c842049
|
@ -108,11 +108,11 @@ struct apk_istream *apk_istream_from_file(int atfd, const char *file);
|
||||||
struct apk_istream *apk_istream_from_file_gz(int atfd, const char *file);
|
struct apk_istream *apk_istream_from_file_gz(int atfd, const char *file);
|
||||||
struct apk_istream *apk_istream_from_fd_url_if_modified(int atfd, const char *url, time_t since);
|
struct apk_istream *apk_istream_from_fd_url_if_modified(int atfd, const char *url, time_t since);
|
||||||
struct apk_istream *apk_istream_from_url_gz(const char *url);
|
struct apk_istream *apk_istream_from_url_gz(const char *url);
|
||||||
size_t apk_istream_skip(struct apk_istream *istream, size_t size);
|
ssize_t apk_istream_skip(struct apk_istream *istream, size_t size);
|
||||||
|
|
||||||
#define APK_SPLICE_ALL 0xffffffff
|
#define APK_SPLICE_ALL 0xffffffff
|
||||||
size_t apk_istream_splice(void *stream, int fd, size_t size,
|
ssize_t apk_istream_splice(void *stream, int fd, size_t size,
|
||||||
apk_progress_cb cb, void *cb_ctx);
|
apk_progress_cb cb, void *cb_ctx);
|
||||||
|
|
||||||
static inline struct apk_istream *apk_istream_from_fd(int fd)
|
static inline struct apk_istream *apk_istream_from_fd(int fd)
|
||||||
{
|
{
|
||||||
|
|
47
src/io.c
47
src/io.c
|
@ -21,6 +21,7 @@
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/xattr.h>
|
#include <sys/xattr.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
|
||||||
|
@ -148,28 +149,23 @@ struct apk_istream *apk_istream_from_file(int atfd, const char *file)
|
||||||
return apk_istream_from_fd(fd);
|
return apk_istream_from_fd(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t apk_istream_skip(struct apk_istream *is, size_t size)
|
ssize_t apk_istream_skip(struct apk_istream *is, size_t size)
|
||||||
{
|
{
|
||||||
unsigned char buf[2048];
|
unsigned char buf[2048];
|
||||||
size_t done = 0, togo;
|
size_t done = 0, togo;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
|
|
||||||
while (done < size) {
|
while (done < size) {
|
||||||
togo = size - done;
|
togo = MIN(size - done, sizeof buf);
|
||||||
if (togo > sizeof(buf))
|
|
||||||
togo = sizeof(buf);
|
|
||||||
r = apk_istream_read(is, buf, togo);
|
r = apk_istream_read(is, buf, togo);
|
||||||
if (r < 0)
|
if (r <= 0) return r ?: -EIO;
|
||||||
return r;
|
|
||||||
done += r;
|
done += r;
|
||||||
if (r != togo)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t apk_istream_splice(void *stream, int fd, size_t size,
|
ssize_t apk_istream_splice(void *stream, int fd, size_t size,
|
||||||
apk_progress_cb cb, void *cb_ctx)
|
apk_progress_cb cb, void *cb_ctx)
|
||||||
{
|
{
|
||||||
static void *splice_buffer = NULL;
|
static void *splice_buffer = NULL;
|
||||||
struct apk_istream *is = (struct apk_istream *) stream;
|
struct apk_istream *is = (struct apk_istream *) stream;
|
||||||
|
@ -187,32 +183,29 @@ size_t apk_istream_splice(void *stream, int fd, size_t size,
|
||||||
else if (r == EBADF || r == EFBIG || r == ENOSPC || r == EIO)
|
else if (r == EBADF || r == EFBIG || r == ENOSPC || r == EIO)
|
||||||
return -r;
|
return -r;
|
||||||
}
|
}
|
||||||
if (bufsz > 2*1024*1024)
|
bufsz = MIN(bufsz, 2*1024*1024);
|
||||||
bufsz = 2*1024*1024;
|
|
||||||
buf = mmapbase;
|
buf = mmapbase;
|
||||||
}
|
}
|
||||||
if (mmapbase == MAP_FAILED) {
|
if (mmapbase == MAP_FAILED) {
|
||||||
if (splice_buffer == NULL)
|
if (!splice_buffer) splice_buffer = malloc(256*1024);
|
||||||
splice_buffer = malloc(256*1024);
|
|
||||||
buf = splice_buffer;
|
buf = splice_buffer;
|
||||||
if (buf == NULL)
|
if (!buf) return -ENOMEM;
|
||||||
return -ENOMEM;
|
bufsz = MIN(bufsz, 256*1024);
|
||||||
if (bufsz > 256*1024)
|
|
||||||
bufsz = 256*1024;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (done < size) {
|
while (done < size) {
|
||||||
if (cb != NULL)
|
if (cb != NULL) cb(cb_ctx, done);
|
||||||
cb(cb_ctx, done);
|
|
||||||
|
|
||||||
togo = size - done;
|
togo = MIN(size - done, bufsz);
|
||||||
if (togo > bufsz)
|
|
||||||
togo = bufsz;
|
|
||||||
r = apk_istream_read(is, buf, togo);
|
r = apk_istream_read(is, buf, togo);
|
||||||
if (r < 0)
|
if (r <= 0) {
|
||||||
goto err;
|
if (r) goto err;
|
||||||
if (r == 0)
|
if (size != APK_SPLICE_ALL && done != size) {
|
||||||
|
r = -EBADMSG;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (mmapbase == MAP_FAILED) {
|
if (mmapbase == MAP_FAILED) {
|
||||||
if (write(fd, buf, r) != r) {
|
if (write(fd, buf, r) != r) {
|
||||||
|
@ -224,8 +217,6 @@ size_t apk_istream_splice(void *stream, int fd, size_t size,
|
||||||
buf += r;
|
buf += r;
|
||||||
|
|
||||||
done += r;
|
done += r;
|
||||||
if (r != togo)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
r = done;
|
r = done;
|
||||||
err:
|
err:
|
||||||
|
|
Loading…
Reference in New Issue