Commit 2f3c8420 authored by Timo Teräs's avatar Timo Teräs

io: fix skip and splice to detect unexpected end-of-file

parent 97e4d053
...@@ -108,11 +108,11 @@ struct apk_istream *apk_istream_from_file(int atfd, const char *file); ...@@ -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)
{ {
......
...@@ -21,6 +21,7 @@ ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment