Commit 34325b35 authored by Timo Teräs's avatar Timo Teräs
Browse files

uniso: process all bytes of the image

Otherwise pipelines such as 'wget http://to/foo.iso | uniso' might
report 'pipe error' as the file is not fully consumed.
parent 5368f0a5
...@@ -217,117 +217,114 @@ struct uniso_context { ...@@ -217,117 +217,114 @@ struct uniso_context {
static int do_splice(struct uniso_context *ctx, int to_fd, int bytes) static int do_splice(struct uniso_context *ctx, int to_fd, int bytes)
{ {
int r; int r, left;
do { for (left = bytes; left; ) {
r = splice(ctx->stream_fd, NULL, to_fd, NULL, bytes, r = splice(ctx->stream_fd, NULL, to_fd, NULL, left,
SPLICE_F_MOVE); SPLICE_F_MOVE);
if (r < 0) if (r < 0) return -errno;
return -errno; if (r == 0) return bytes - left;
left -= r;
bytes -= r;
ctx->pos += r; ctx->pos += r;
} while (bytes != 0); }
return 0; return bytes;
} }
static int do_read(struct uniso_context *ctx, unsigned char *buf, int bytes) static int do_read(struct uniso_context *ctx, unsigned char *buf, int bytes)
{ {
int r; int r, left;
do { for (left = bytes; left; ) {
r = read(ctx->stream_fd, buf, bytes); r = read(ctx->stream_fd, buf, left);
if (r < 0) { if (r < 0) {
perror("read"); perror("read");
return -errno; return -errno;
} }
bytes -= r; if (r == 0) return bytes - left;
left -= r;
buf += r; buf += r;
ctx->pos += r; ctx->pos += r;
} while (bytes != 0); }
return 0; return bytes;
} }
static int do_write(int tofd, const unsigned char *buf, int bytes) static int do_write(int tofd, const unsigned char *buf, int bytes)
{ {
int r; int r, left;
do { for (left = bytes; left; ) {
r = write(tofd, buf, bytes); r = write(tofd, buf, left);
if (r < 0) { if (r < 0) {
perror("write"); perror("write");
return -errno; return -errno;
} }
bytes -= r; left -= r;
buf += r; buf += r;
} while (bytes != 0); }
return 0; return bytes;
} }
static int do_skip(struct uniso_context *ctx, unsigned int bytes) static int do_skip(struct uniso_context *ctx, unsigned int bytes)
{ {
int r, now; int r, left, now;
switch (ctx->skip_method) { switch (ctx->skip_method) {
case 0: case 0:
if (lseek(ctx->stream_fd, bytes, SEEK_CUR) != (off_t) -1) { if (lseek(ctx->stream_fd, bytes, SEEK_CUR) != (off_t) -1) {
ctx->pos += bytes; ctx->pos += bytes;
break; return bytes;
} }
ctx->skip_method = 1; ctx->skip_method = 1;
case 1: case 1:
if (do_splice(ctx, ctx->null_fd, bytes) == 0) r = do_splice(ctx, ctx->null_fd, bytes);
break; if (r >= 0) return r;
ctx->skip_method = 2; ctx->skip_method = 2;
case 2: case 2:
while (bytes) { for (left = bytes; left; ) {
now = bytes; now = left;
if (now > ISOFS_TMPBUF_SIZE) if (now > ISOFS_TMPBUF_SIZE)
now = ISOFS_TMPBUF_SIZE; now = ISOFS_TMPBUF_SIZE;
r = do_read(ctx, ctx->tmpbuf, now); r = do_read(ctx, ctx->tmpbuf, now);
if (r < 0) if (r < 0) return r;
return r; if (r == 0) return bytes - left;
left -= now;
bytes -= now;
} }
break; return bytes;
} }
return 0; return 0;
} }
static int do_copy(struct uniso_context *ctx, int tofd, unsigned int bytes) static int do_copy(struct uniso_context *ctx, int tofd, int bytes)
{ {
int r, now; int r, now, left;
switch (ctx->copy_method) { switch (ctx->copy_method) {
case 0: case 0:
if (do_splice(ctx, tofd, bytes) == 0) r = do_splice(ctx, tofd, bytes);
break; if (r >= 0) return r;
ctx->skip_method = 1; ctx->skip_method = 1;
case 1: case 1:
/* FIXME: Use mmaped IO */ /* FIXME: Use mmaped IO */
ctx->skip_method = 2; ctx->skip_method = 2;
case 2: case 2:
while (bytes) { for (left = bytes; left; ) {
now = bytes; now = left;
if (now > ISOFS_TMPBUF_SIZE) if (now > ISOFS_TMPBUF_SIZE)
now = ISOFS_TMPBUF_SIZE; now = ISOFS_TMPBUF_SIZE;
r = do_read(ctx, ctx->tmpbuf, now); r = do_read(ctx, ctx->tmpbuf, now);
if (r < 0) if (r <= 0) return r < 0 ? r : -EIO;
return r;
now = r;
r = do_write(tofd, ctx->tmpbuf, now); r = do_write(tofd, ctx->tmpbuf, now);
if (r < 0) if (r != now) return r < 0 ? r : -EIO;
return r;
bytes -= now; left -= now;
} }
break; return bytes;
} }
return 0; return 0;
} }
...@@ -392,12 +389,10 @@ static int link_or_clone(const char *src, const char *dst, size_t bytes) ...@@ -392,12 +389,10 @@ static int link_or_clone(const char *src, const char *dst, size_t bytes)
if (now > sizeof(buf)) if (now > sizeof(buf))
now = sizeof(buf); now = sizeof(buf);
r = read(src_fd, buf, now); r = read(src_fd, buf, now);
if (r < 0) if (r < 0) return r;
return r;
r = write(dst_fd, buf, now); r = write(dst_fd, buf, now);
if (r < 0) if (r < 0) return r;
return r;
bytes -= now; bytes -= now;
} }
close(dst_fd); close(dst_fd);
...@@ -441,7 +436,9 @@ static int uniso_read_file(struct uniso_context *ctx, ...@@ -441,7 +436,9 @@ static int uniso_read_file(struct uniso_context *ctx,
rc = do_copy(ctx, fd, dir->size); rc = do_copy(ctx, fd, dir->size);
close(fd); close(fd);
return rc; if (rc < 0) return rc;
if (rc != dir->size) return -EIO;
return 0;
} }
static int uniso_read_directory(struct uniso_context *ctx, static int uniso_read_directory(struct uniso_context *ctx,
...@@ -581,7 +578,7 @@ int uniso(int fd) ...@@ -581,7 +578,7 @@ int uniso(int fd)
{ {
struct uniso_context context, *ctx = &context; struct uniso_context context, *ctx = &context;
struct uniso_reader *rd; struct uniso_reader *rd;
int r; int r, skipped;
memset(ctx, 0, sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx));
list_init(&ctx->parser_head); list_init(&ctx->parser_head);
...@@ -608,6 +605,15 @@ int uniso(int fd) ...@@ -608,6 +605,15 @@ int uniso(int fd)
return r; return r;
} }
if (ctx->skip_method) {
skipped = 0;
do {
r = do_skip(ctx, ISOFS_TMPBUF_SIZE);
if (r > 0) skipped += r;
} while (r == ISOFS_TMPBUF_SIZE);
if (ctx->loglevel > 1) fprintf(stderr, "Skipped %d bytes at the end\n", skipped);
}
free(ctx->tmpbuf); free(ctx->tmpbuf);
close(ctx->null_fd); close(ctx->null_fd);
} }
......
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