ssize_t udfread_file_read(UDFFILE *p, void *buf, size_t bytes) { uint8_t *bufpt = (uint8_t *)buf; /* sanity checks */ if (!p || !buf || p->pos < 0) { return -1; } if ((ssize_t)bytes < 0 || (int64_t)bytes < 0) { return -1; } /* limit range to file size */ if ((uint64_t)p->pos + bytes > (uint64_t)udfread_file_size(p)) { bytes = udfread_file_size(p) - p->pos; } /* small files may be stored inline in file entry */ if (p->fe->content_inline) { memcpy(buf, &p->fe->data.content + p->pos, bytes); p->pos += bytes; return bytes; } /* allocate temp storage for input block */ if (!p->block) { p->block_mem = malloc(2 * UDF_BLOCK_SIZE); p->block = ALIGN(p->block_mem, UDF_BLOCK_SIZE); } /* read chunks */ while (bytes > 0) { int64_t r = _read(p, bufpt, bytes); if (r < 0) { if (bufpt != buf) { /* got some bytes */ break; } /* got nothing */ return -1; } bufpt += r; bytes -= r; } return (intptr_t)bufpt - (intptr_t)buf; }
int64_t udfread_file_seek(UDFFILE *p, int64_t pos, int whence) { if (p) { switch (whence) { case UDF_SEEK_CUR: pos += p->pos; break; case UDF_SEEK_END: pos = udfread_file_size(p) - pos; break; case UDF_SEEK_SET: default: break; } if (pos >= 0 && pos <= udfread_file_size(p)) { p->pos = pos; p->block_valid = 0; return p->pos; } } return -1; }
static void _cat(UDFFILE *fp) { uint8_t buf[2048]; int64_t got = 0; ssize_t result; while ((result = udfread_file_read(fp, buf, sizeof(buf))) > 0) { fwrite(buf, 1, (size_t)result, stdout); got += result; } if (result < 0) { fprintf(stderr, "udfread_file_read(offset=%"PRId64") failed\n", udfread_file_tell(fp)); } fprintf(stderr, "wrote %"PRId64" bytes of %"PRId64"\n", got, udfread_file_size(fp)); }