From 4e6c7e6df022075ae0eb5197395318641bca2243 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 23 May 2005 09:27:31 +0200 Subject: fixed seek/tell bug in openbuffer files --- Jamfile | 14 ++- apps/unix/x11pdf.c | 2 +- stream/filt_buffer.c | 93 -------------- stream/filt_filec.c | 349 --------------------------------------------------- stream/filt_filer.c | 252 ------------------------------------- stream/filt_filew.c | 260 -------------------------------------- stream/stm_buffer.c | 93 ++++++++++++++ stream/stm_filec.c | 349 +++++++++++++++++++++++++++++++++++++++++++++++++++ stream/stm_filer.c | 252 +++++++++++++++++++++++++++++++++++++ stream/stm_filew.c | 260 ++++++++++++++++++++++++++++++++++++++ 10 files changed, 963 insertions(+), 961 deletions(-) delete mode 100644 stream/filt_buffer.c delete mode 100644 stream/filt_filec.c delete mode 100644 stream/filt_filer.c delete mode 100644 stream/filt_filew.c create mode 100644 stream/stm_buffer.c create mode 100644 stream/stm_filec.c create mode 100644 stream/stm_filer.c create mode 100644 stream/stm_filew.c diff --git a/Jamfile b/Jamfile index c2243b94..5ee8a604 100644 --- a/Jamfile +++ b/Jamfile @@ -134,28 +134,30 @@ Library libstream : obj_print.c obj_simple.c + stm_buffer.c + stm_filec.c + stm_filer.c + stm_filew.c + + filt_process.c + filt_pipeline.c + filt_a85d.c filt_a85e.c filt_ahxd.c filt_ahxe.c filt_arc4.c - filt_buffer.c filt_dctd.c filt_dcte.c filt_faxd.c filt_faxdtab.c filt_faxe.c filt_faxetab.c - filt_filec.c - filt_filer.c - filt_filew.c filt_flate.c filt_lzwd.c filt_lzwe.c filt_null.c - filt_pipeline.c filt_predict.c - filt_process.c filt_rld.c filt_rle.c diff --git a/apps/unix/x11pdf.c b/apps/unix/x11pdf.c index f12d27f1..eecb70dd 100644 --- a/apps/unix/x11pdf.c +++ b/apps/unix/x11pdf.c @@ -408,7 +408,7 @@ int main(int argc, char **argv) double zoom = 1.0; int pageno = 1; - while ((c = getopt(argc, argv, "dzp:")) != -1) + while ((c = getopt(argc, argv, "d:z:p:")) != -1) { switch (c) { diff --git a/stream/filt_buffer.c b/stream/filt_buffer.c deleted file mode 100644 index 206137a6..00000000 --- a/stream/filt_buffer.c +++ /dev/null @@ -1,93 +0,0 @@ -#include - -fz_error * -fz_newbuffer(fz_buffer **bp, int size) -{ - fz_buffer *b; - - b = *bp = fz_malloc(sizeof(fz_buffer)); - if (!b) return fz_outofmem; - - b->refs = 1; - b->ownsdata = 1; - b->bp = fz_malloc(size); - if (!b->bp) { fz_free(b); return fz_outofmem; } - - b->rp = b->bp; - b->wp = b->bp; - b->ep = b->bp + size; - b->eof = 0; - - return nil; -} - -fz_error * -fz_newbufferwithdata(fz_buffer **bp, unsigned char *data, int size) -{ - fz_buffer *b; - - b = *bp = fz_malloc(sizeof(fz_buffer)); - if (!b) return fz_outofmem; - - b->refs = 1; - b->ownsdata = 0; - b->bp = data; - - b->rp = b->bp; - b->wp = b->bp + size; - b->ep = b->bp + size; - b->eof = 0; - - return nil; -} - -fz_buffer * -fz_keepbuffer(fz_buffer *buf) -{ - buf->refs ++; - return buf; -} - -void -fz_dropbuffer(fz_buffer *buf) -{ - if (--buf->refs == 0) - { - if (buf->ownsdata) - fz_free(buf->bp); - fz_free(buf); - } -} - -fz_error * -fz_growbuffer(fz_buffer *buf) -{ - unsigned char *newbp; - - int rp = buf->rp - buf->bp; - int wp = buf->wp - buf->bp; - int ep = buf->ep - buf->bp; - - assert(buf->ownsdata); - - newbp = fz_realloc(buf->bp, ep * 2); - if (!newbp) return fz_outofmem; - - buf->bp = newbp; - buf->rp = buf->bp + rp; - buf->wp = buf->bp + wp; - buf->ep = buf->bp + ep * 2; - - return nil; -} - -fz_error * -fz_rewindbuffer(fz_buffer *buf) -{ - assert(buf->ownsdata); - memmove(buf->bp, buf->rp, buf->wp - buf->rp); - buf->wp = buf->bp + (buf->wp - buf->rp); - buf->rp = buf->bp; - return nil; -} - diff --git a/stream/filt_filec.c b/stream/filt_filec.c deleted file mode 100644 index 05813185..00000000 --- a/stream/filt_filec.c +++ /dev/null @@ -1,349 +0,0 @@ -#include - -fz_error * -fz_ferror(fz_file *f) -{ - fz_error *e = f->error; - f->error = nil; - return e; -} - -fz_error * -fz_openfile(fz_file **filep, char *path, int mode) -{ - fz_error *error; - fz_file *file; - int realmode; - int fd; - int n; - - assert(mode == FZ_READ || mode == FZ_WRITE || mode == FZ_APPEND); - - realmode = 0; - if (mode == FZ_READ) - realmode = O_BINARY | O_RDONLY; - if (mode == FZ_WRITE) - realmode = O_BINARY | O_WRONLY | O_CREAT | O_TRUNC; - if (mode == FZ_APPEND) - realmode = O_BINARY | O_WRONLY; - - fd = open(path, realmode, 0644); - if (fd == -1) - return fz_throw("ioerror: open '%s': %s", path, strerror(errno)); - - if (mode == FZ_APPEND) - { - mode = FZ_WRITE; - n = lseek(fd, 0, 2); - if (n == -1) { - error = fz_throw("ioerror: lseek: %s", strerror(errno)); - close(fd); - return error; - } - } - - file = *filep = fz_malloc(sizeof(fz_file)); - if (!file) - return fz_outofmem; - - file->mode = mode; - file->fd = fd; - file->depth = 0; - file->error = nil; - file->filter = nil; - file->in = nil; - file->out = nil; - - error = fz_newbuffer(&file->in, FZ_BUFSIZE); - if (error) - goto cleanup; - - error = fz_newbuffer(&file->out, FZ_BUFSIZE); - if (error) - goto cleanup; - - return nil; - -cleanup: - *filep = nil; - close(fd); - fz_dropbuffer(file->out); - fz_dropbuffer(file->in); - fz_free(file); - return error; -} - -fz_error * -fz_openbuffer(fz_file **filep, fz_buffer *buf, int mode) -{ - fz_error *error; - fz_file *file; - - assert(mode == FZ_READ || mode == FZ_WRITE); - - file = *filep = fz_malloc(sizeof(fz_file)); - if (!file) - return fz_outofmem; - - file->mode = mode; - file->fd = -1; - file->depth = 0; - file->error = nil; - file->filter = nil; - - if (mode == FZ_READ) - { - file->out = fz_keepbuffer(buf); - error = fz_newbuffer(&file->in, FZ_BUFSIZE); - if (error) - goto cleanup; - } - - else - { - error = fz_newbuffer(&file->out, FZ_BUFSIZE); - if (error) - goto cleanup; - file->in = fz_keepbuffer(buf); - } - - return nil; - -cleanup: - *filep = nil; - fz_free(file); - return error; -} - -void -fz_closefile(fz_file *file) -{ - assert(file->depth == 0); - - if (file->mode == FZ_WRITE) - fz_flush(file); - - if (file->error) - { - fz_warn("%s", file->error->msg); - fz_droperror(file->error); - file->error = nil; - } - - if (file->fd != -1) /* open to real file */ - close(file->fd); - - fz_dropbuffer(file->in); - fz_dropbuffer(file->out); - - if (file->filter) - fz_dropfilter(file->filter); - - fz_free(file); -} - -fz_error * -fz_pushfilter(fz_file *file, fz_filter *filter) -{ - fz_error *error; - - /* without a filter, one buffer is ignored: unignore. */ - if (file->depth == 0) - { - fz_buffer *buf; - - buf = file->out; - file->out = file->in; - file->in = buf; - - if (file->mode == FZ_READ) - { - file->out->rp = file->out->bp; - file->out->wp = file->out->bp; - file->out->eof = 0; - } - else - { - file->out->eof = 0; - file->in->rp = file->in->bp; - file->in->wp = file->in->bp; - file->in->eof = 0; - } - - file->filter = fz_keepfilter(filter); - } - - else - { - if (file->mode == FZ_READ) - { - error = fz_chainpipeline(&file->filter, file->filter, filter, file->out); - if (error) - return error; - - error = fz_newbuffer(&file->out, FZ_BUFSIZE); - if (error) - { - fz_unchainpipeline(file->filter, &file->filter, &file->out); - return error; - } - } - - else - { - error = fz_chainpipeline(&file->filter, filter, file->filter, file->in); - if (error) - return error; - - error = fz_newbuffer(&file->in, FZ_BUFSIZE); - if (error) - { - fz_unchainpipeline(file->filter, &file->filter, &file->in); - return error; - } - } - } - - file->depth ++; - - return nil; -} - -void -fz_popfilter(fz_file *file) -{ - fz_buffer *buf; - - assert(file->depth > 0); - - if (file->mode == FZ_WRITE) - fz_flush(file); - - if (file->error) - { - fz_warn("%s", file->error->msg); - fz_droperror(file->error); - file->error = nil; - } - - if (file->depth == 1) - { - fz_dropfilter(file->filter); - file->filter = nil; - - buf = file->out; - file->out = file->in; - file->in = buf; - } - else - { - if (file->mode == FZ_READ) - { - fz_dropbuffer(file->out); - fz_unchainpipeline(file->filter, &file->filter, &file->out); - } - else - { - fz_dropbuffer(file->in); - fz_unchainpipeline(file->filter, &file->filter, &file->in); - } - } - - file->depth --; -} - -int -fz_seek(fz_file *f, int ofs, int whence) -{ - int t; - int c; - - if (f->filter) - { - assert(f->mode == FZ_READ && whence == 0); - - if (ofs < fz_tell(f)) - { - f->error = fz_throw("ioerror: cannot seek backwards in filter"); - return -1; - } - while (fz_tell(f) < ofs) - { - c = fz_readbyte(f); - if (c == EOF) - return -1; - } - return ofs; - } - - if (whence == 1) - { - ofs = fz_tell(f) + ofs; - whence = 0; - } - - if (f->fd == -1) - { - if (whence == 0) - { - if (f->mode == FZ_READ) - f->out->rp = CLAMP(f->out->bp + ofs, f->out->bp, f->in->ep); - else - f->in->wp = CLAMP(f->in->bp + ofs, f->in->bp, f->in->ep); - } - else - { - if (f->mode == FZ_READ) - f->out->rp = CLAMP(f->out->ep + ofs, f->out->bp, f->in->ep); - else - f->in->wp = CLAMP(f->in->ep + ofs, f->in->bp, f->in->ep); - } - return fz_tell(f); - } - - t = lseek(f->fd, ofs, whence); - if (t == -1) - { - f->error = fz_throw("ioerror: lseek: %s", strerror(errno)); - return -1; - } - - f->out->rp = f->out->bp; - f->out->wp = f->out->bp; - f->out->eof = 0; - - return t; -} - -int -fz_tell(fz_file *f) -{ - int t; - - if (f->filter) - { - assert(f->mode == FZ_READ); - return f->filter->count - (f->out->wp - f->out->rp); - } - - if (f->fd == -1) - { - if (f->mode == FZ_READ) - return f->out->rp - f->out->bp; - else - return f->in->wp - f->in->bp; - } - - t = lseek(f->fd, 0, 1); - if (t == -1) - { - f->error = fz_throw("ioerror: lseek: %s", strerror(errno)); - return -1; - } - - if (f->mode == FZ_READ) - return t - (f->out->wp - f->out->rp); - else - return t + (f->in->wp - f->in->rp); -} - diff --git a/stream/filt_filer.c b/stream/filt_filer.c deleted file mode 100644 index a63a7dd2..00000000 --- a/stream/filt_filer.c +++ /dev/null @@ -1,252 +0,0 @@ -#include - -static int doread(fz_buffer *b, int fd) -{ - int n = read(fd, b->wp, b->ep - b->wp); - if (n == -1) - return -1; - if (n == 0) - b->eof = 1; - b->wp += n; - return n; -} - -int fz_producedata(fz_file *f) -{ - fz_error *reason; - int produced; - int n; - - assert(f->mode == FZ_READ); - assert(f->error == nil); - - if (!f->filter) - { - fz_rewindbuffer(f->out); - n = doread(f->out, f->fd); - if (n < 0) { - f->error = fz_throw("ioerror in read: %s", strerror(errno)); - return -1; - } - return 0; - } - - produced = 0; - - while (1) - { - reason = fz_process(f->filter, f->in, f->out); - - if (f->filter->produced) - produced = 1; - - if (reason == fz_ioneedin) - { - if (f->in->eof) { - f->error = fz_throw("ioerror: premature eof in filter"); - return -1; - } - - /* no space to produce, rewind or grow */ - if (f->in->wp == f->in->ep) - { - if (f->in->rp > f->in->bp) - f->error = fz_rewindbuffer(f->in); - else - f->error = fz_growbuffer(f->in); - if (f->error) - return -1; - } - - /* then fill with more input */ - n = doread(f->in, f->fd); - if (n < 0) { - f->error = fz_throw("ioerror in read: %s", strerror(errno)); - return -1; - } - - if (produced) - return 0; - } - - else if (reason == fz_ioneedout) - { - if (produced) - return 0; - - /* need more outspace, and produced no data */ - if (f->out->rp > f->out->bp) - f->error = fz_rewindbuffer(f->out); - else - f->error = fz_growbuffer(f->out); - if (f->error) - return -1; - } - - else if (reason == fz_iodone) - return 0; - - else { - f->error = reason; - return -1; - } - } -} - -int -fz_peekbyte(fz_file *f) -{ - if (f->out->rp == f->out->wp) - { - if (f->out->eof) return EOF; - if (fz_producedata(f)) return EOF; - } - - if (f->out->rp < f->out->wp) - return *f->out->rp; - - return EOF; -} - -int -fz_readbyte(fz_file *f) -{ - if (f->out->rp == f->out->wp) - { - if (f->out->eof) return EOF; - if (fz_producedata(f)) return EOF; - } - - if (f->out->rp < f->out->wp) - return *f->out->rp++; - - return EOF; -} - -int -fz_read(fz_file *f, unsigned char *buf, int n) -{ - int i = 0; - - while (i < n) - { - while (f->out->rp < f->out->wp && i < n) - buf[i++] = *f->out->rp ++; - - if (f->out->rp == f->out->wp) - { - if (f->out->eof) return i; - if (fz_producedata(f) < 0) return -1; - } - } - - return i; -} - -int -fz_readline(fz_file *f, char *buf, int n) -{ - int c = EOF; - char *s = buf; - - while (n > 1) - { - c = fz_readbyte(f); - if (c == EOF) - break; - if (c == '\r') { - c = fz_peekbyte(f); - if (c == '\n') - c = fz_readbyte(f); - break; - } - if (c == '\n') - break; - *s++ = c; - n--; - } - if (n) - *s = '\0'; - return s - buf; -} - -/* - * Utility function to consume contents of file stream into - * a freshly allocated buffer; realloced and trimmed to size. - */ - -enum { CHUNKSIZE = 1024 * 32 }; - -fz_error * -fz_readfile(fz_buffer **bufp, fz_file *file) -{ - fz_buffer *real; - unsigned char *newbuf; - unsigned char *buf; - int len; - int pos; - int n; - - *bufp = nil; - - len = 0; - pos = 0; - buf = nil; - - while (1) - { - if (len - pos == 0) - { - len += CHUNKSIZE; - newbuf = fz_realloc(buf, len); - if (!newbuf) - { - fz_free(buf); - return fz_outofmem; - } - buf = newbuf; - } - - n = fz_read(file, buf + pos, len - pos); - - if (n < 0) - { - fz_free(buf); - return fz_ferror(file); - } - - pos += n; - - if (n < CHUNKSIZE) - { - if (pos > 0) - { - newbuf = fz_realloc(buf, pos); - if (!newbuf) - { - fz_free(buf); - return fz_outofmem; - } - } - else newbuf = buf; - - real = *bufp = fz_malloc(sizeof(fz_buffer)); - if (!real) - { - fz_free(newbuf); - return fz_outofmem; - } - - real->refs = 1; - real->ownsdata = 1; - real->bp = buf; - real->rp = buf; - real->wp = buf + pos; - real->ep = buf + pos; - real->eof = 1; - - return nil; - } - } -} - diff --git a/stream/filt_filew.c b/stream/filt_filew.c deleted file mode 100644 index f83399a2..00000000 --- a/stream/filt_filew.c +++ /dev/null @@ -1,260 +0,0 @@ -#include - -int -fz_printstring(fz_file *f, char *s) -{ - return fz_write(f, s, strlen(s)); -} - -int -fz_printobj(fz_file *file, fz_obj *obj, int tight) -{ - char buf[1024]; - char *ptr; - int n; - - n = fz_sprintobj(nil, 0, obj, tight); - if (n < sizeof buf) - { - fz_sprintobj(buf, sizeof buf, obj, tight); - return fz_write(file, buf, n); - } - else - { - ptr = fz_malloc(n); - if (!ptr) { - file->error = fz_outofmem; - return -1; - } - fz_sprintobj(ptr, n, obj, tight); - n = fz_write(file, ptr, n); - fz_free(ptr); - return n; - } -} - -int -fz_print(fz_file *f, char *fmt, ...) -{ - va_list ap; - char buf[1024]; - char *p; - int n; - - va_start(ap, fmt); - n = vsnprintf(buf, sizeof buf, fmt, ap); - va_end(ap); - - if (n < sizeof buf) - return fz_write(f, buf, n); - - p = fz_malloc(n); - if (!p) { - f->error = fz_outofmem; - return -1; - } - - va_start(ap, fmt); - vsnprintf(p, n, fmt, ap); - va_end(ap); - - n = fz_write(f, p, n); - - fz_free(p); - - return n; -} - -static int dowrite(fz_buffer *b, int fd) -{ - int n = write(fd, b->rp, b->wp - b->rp); - if (n == -1) - return -1; - b->rp += n; - return n; -} - -int -fz_write(fz_file *f, unsigned char *buf, int n) -{ - fz_error *reason; - int i = 0; - int x; - - assert(f->mode == FZ_WRITE); - assert(f->error == nil); - - if (!f->filter) - { - while (i < n) - { - while (f->in->wp < f->in->ep && i < n) - *f->in->wp++ = buf[i++]; - - if (f->in->wp == f->in->ep) - { - if (f->fd != -1) - { - x = dowrite(f->in, f->fd); - if (x < 0) { - f->error = fz_throw("ioerror in write: %s", strerror(errno)); - return -1; - } - } - - if (f->in->rp > f->in->bp) - f->error = fz_rewindbuffer(f->in); - else - f->error = fz_growbuffer(f->in); - if (f->error) - return -1; - } - } - - return 0; - } - - while (i < n) - { - while (f->in->wp < f->in->ep && i < n) - *f->in->wp++ = buf[i++]; - - if (f->in->wp == f->in->ep) - { - reason = fz_process(f->filter, f->in, f->out); - - if (reason == fz_ioneedin) - { - if (f->in->wp == f->in->ep) { - if (f->in->rp > f->in->bp) - f->error = fz_rewindbuffer(f->in); - else - f->error = fz_growbuffer(f->in); - if (f->error) - return -1; - } - } - - else if (reason == fz_ioneedout) - { - if (f->fd != -1) - { - x = dowrite(f->out, f->fd); - if (x < 0) { - f->error = fz_throw("ioerror in write: %s", strerror(errno)); - return -1; - } - } - - if (f->out->rp > f->out->bp) - f->error = fz_rewindbuffer(f->out); - else - f->error = fz_growbuffer(f->out); - if (f->error) - return -1; - } - - else if (reason == fz_iodone) - { - if (f->fd != -1) - { - while (f->out->rp < f->out->wp) - { - x = dowrite(f->out, f->fd); - if (x < 0) { - f->error = fz_throw("ioerror in write: %s", strerror(errno)); - return -1; - } - } - } - break; - } - - else { - f->error = reason; - return -1; - } - } - } - - return i; -} - -int -fz_flush(fz_file *f) -{ - fz_error *reason; - int n; - - assert(f->mode == FZ_WRITE); - assert(f->error == nil); - - f->in->eof = 1; - - if (!f->filter) - { - if (f->fd != -1) - { - while (f->in->rp < f->in->wp) - { - n = dowrite(f->in, f->fd); - if (n < 0) { - f->error = fz_throw("ioerror in write: %s", strerror(errno)); - return -1; - } - } - } - return 0; - } - - while (!f->out->eof) - { - reason = fz_process(f->filter, f->in, f->out); - - if (reason == fz_ioneedin) { - f->error = fz_throw("ioerror: premature eof in filter"); - return -1; - } - - else if (reason == fz_ioneedout) - { - if (f->fd != -1) - { - n = dowrite(f->out, f->fd); - if (n < 0) { - f->error = fz_throw("ioerror in write: %s", strerror(errno)); - return -1; - } - } - - if (f->out->rp > f->out->bp) - f->error = fz_rewindbuffer(f->out); - else - f->error = fz_growbuffer(f->out); - if (f->error) - return -1; - } - - else if (reason == fz_iodone) - { - if (f->fd != -1) - { - n = dowrite(f->out, f->fd); - if (n < 0) { - f->error = fz_throw("ioerror in write: %s", strerror(errno)); - return -1; - } - } - break; - } - - else - { - f->error = reason; - return -1; - } - } - - return 0; -} - diff --git a/stream/stm_buffer.c b/stream/stm_buffer.c new file mode 100644 index 00000000..206137a6 --- /dev/null +++ b/stream/stm_buffer.c @@ -0,0 +1,93 @@ +#include + +fz_error * +fz_newbuffer(fz_buffer **bp, int size) +{ + fz_buffer *b; + + b = *bp = fz_malloc(sizeof(fz_buffer)); + if (!b) return fz_outofmem; + + b->refs = 1; + b->ownsdata = 1; + b->bp = fz_malloc(size); + if (!b->bp) { fz_free(b); return fz_outofmem; } + + b->rp = b->bp; + b->wp = b->bp; + b->ep = b->bp + size; + b->eof = 0; + + return nil; +} + +fz_error * +fz_newbufferwithdata(fz_buffer **bp, unsigned char *data, int size) +{ + fz_buffer *b; + + b = *bp = fz_malloc(sizeof(fz_buffer)); + if (!b) return fz_outofmem; + + b->refs = 1; + b->ownsdata = 0; + b->bp = data; + + b->rp = b->bp; + b->wp = b->bp + size; + b->ep = b->bp + size; + b->eof = 0; + + return nil; +} + +fz_buffer * +fz_keepbuffer(fz_buffer *buf) +{ + buf->refs ++; + return buf; +} + +void +fz_dropbuffer(fz_buffer *buf) +{ + if (--buf->refs == 0) + { + if (buf->ownsdata) + fz_free(buf->bp); + fz_free(buf); + } +} + +fz_error * +fz_growbuffer(fz_buffer *buf) +{ + unsigned char *newbp; + + int rp = buf->rp - buf->bp; + int wp = buf->wp - buf->bp; + int ep = buf->ep - buf->bp; + + assert(buf->ownsdata); + + newbp = fz_realloc(buf->bp, ep * 2); + if (!newbp) return fz_outofmem; + + buf->bp = newbp; + buf->rp = buf->bp + rp; + buf->wp = buf->bp + wp; + buf->ep = buf->bp + ep * 2; + + return nil; +} + +fz_error * +fz_rewindbuffer(fz_buffer *buf) +{ + assert(buf->ownsdata); + memmove(buf->bp, buf->rp, buf->wp - buf->rp); + buf->wp = buf->bp + (buf->wp - buf->rp); + buf->rp = buf->bp; + return nil; +} + diff --git a/stream/stm_filec.c b/stream/stm_filec.c new file mode 100644 index 00000000..93f9ce5a --- /dev/null +++ b/stream/stm_filec.c @@ -0,0 +1,349 @@ +#include + +fz_error * +fz_ferror(fz_file *f) +{ + fz_error *e = f->error; + f->error = nil; + return e; +} + +fz_error * +fz_openfile(fz_file **filep, char *path, int mode) +{ + fz_error *error; + fz_file *file; + int realmode; + int fd; + int n; + + assert(mode == FZ_READ || mode == FZ_WRITE || mode == FZ_APPEND); + + realmode = 0; + if (mode == FZ_READ) + realmode = O_BINARY | O_RDONLY; + if (mode == FZ_WRITE) + realmode = O_BINARY | O_WRONLY | O_CREAT | O_TRUNC; + if (mode == FZ_APPEND) + realmode = O_BINARY | O_WRONLY; + + fd = open(path, realmode, 0644); + if (fd == -1) + return fz_throw("ioerror: open '%s': %s", path, strerror(errno)); + + if (mode == FZ_APPEND) + { + mode = FZ_WRITE; + n = lseek(fd, 0, 2); + if (n == -1) { + error = fz_throw("ioerror: lseek: %s", strerror(errno)); + close(fd); + return error; + } + } + + file = *filep = fz_malloc(sizeof(fz_file)); + if (!file) + return fz_outofmem; + + file->mode = mode; + file->fd = fd; + file->depth = 0; + file->error = nil; + file->filter = nil; + file->in = nil; + file->out = nil; + + error = fz_newbuffer(&file->in, FZ_BUFSIZE); + if (error) + goto cleanup; + + error = fz_newbuffer(&file->out, FZ_BUFSIZE); + if (error) + goto cleanup; + + return nil; + +cleanup: + *filep = nil; + close(fd); + fz_dropbuffer(file->out); + fz_dropbuffer(file->in); + fz_free(file); + return error; +} + +fz_error * +fz_openbuffer(fz_file **filep, fz_buffer *buf, int mode) +{ + fz_error *error; + fz_file *file; + + assert(mode == FZ_READ || mode == FZ_WRITE); + + file = *filep = fz_malloc(sizeof(fz_file)); + if (!file) + return fz_outofmem; + + file->mode = mode; + file->fd = -1; + file->depth = 0; + file->error = nil; + file->filter = nil; + + if (mode == FZ_READ) + { + file->out = fz_keepbuffer(buf); + error = fz_newbuffer(&file->in, FZ_BUFSIZE); + if (error) + goto cleanup; + } + + else + { + error = fz_newbuffer(&file->out, FZ_BUFSIZE); + if (error) + goto cleanup; + file->in = fz_keepbuffer(buf); + } + + return nil; + +cleanup: + *filep = nil; + fz_free(file); + return error; +} + +void +fz_closefile(fz_file *file) +{ + assert(file->depth == 0); + + if (file->mode == FZ_WRITE) + fz_flush(file); + + if (file->error) + { + fz_warn("%s", file->error->msg); + fz_droperror(file->error); + file->error = nil; + } + + if (file->fd != -1) /* open to real file */ + close(file->fd); + + fz_dropbuffer(file->in); + fz_dropbuffer(file->out); + + if (file->filter) + fz_dropfilter(file->filter); + + fz_free(file); +} + +fz_error * +fz_pushfilter(fz_file *file, fz_filter *filter) +{ + fz_error *error; + + /* without a filter, one buffer is ignored: unignore. */ + if (file->depth == 0) + { + fz_buffer *buf; + + buf = file->out; + file->out = file->in; + file->in = buf; + + if (file->mode == FZ_READ) + { + file->out->rp = file->out->bp; + file->out->wp = file->out->bp; + file->out->eof = 0; + } + else + { + file->out->eof = 0; + file->in->rp = file->in->bp; + file->in->wp = file->in->bp; + file->in->eof = 0; + } + + file->filter = fz_keepfilter(filter); + } + + else + { + if (file->mode == FZ_READ) + { + error = fz_chainpipeline(&file->filter, file->filter, filter, file->out); + if (error) + return error; + + error = fz_newbuffer(&file->out, FZ_BUFSIZE); + if (error) + { + fz_unchainpipeline(file->filter, &file->filter, &file->out); + return error; + } + } + + else + { + error = fz_chainpipeline(&file->filter, filter, file->filter, file->in); + if (error) + return error; + + error = fz_newbuffer(&file->in, FZ_BUFSIZE); + if (error) + { + fz_unchainpipeline(file->filter, &file->filter, &file->in); + return error; + } + } + } + + file->depth ++; + + return nil; +} + +void +fz_popfilter(fz_file *file) +{ + fz_buffer *buf; + + assert(file->depth > 0); + + if (file->mode == FZ_WRITE) + fz_flush(file); + + if (file->error) + { + fz_warn("%s", file->error->msg); + fz_droperror(file->error); + file->error = nil; + } + + if (file->depth == 1) + { + fz_dropfilter(file->filter); + file->filter = nil; + + buf = file->out; + file->out = file->in; + file->in = buf; + } + else + { + if (file->mode == FZ_READ) + { + fz_dropbuffer(file->out); + fz_unchainpipeline(file->filter, &file->filter, &file->out); + } + else + { + fz_dropbuffer(file->in); + fz_unchainpipeline(file->filter, &file->filter, &file->in); + } + } + + file->depth --; +} + +int +fz_seek(fz_file *f, int ofs, int whence) +{ + int t; + int c; + + if (f->filter) + { + assert(f->mode == FZ_READ && whence == 0); + + if (ofs < fz_tell(f)) + { + f->error = fz_throw("ioerror: cannot seek backwards in filter"); + return -1; + } + while (fz_tell(f) < ofs) + { + c = fz_readbyte(f); + if (c == EOF) + return -1; + } + return ofs; + } + + if (whence == 1) + { + ofs = fz_tell(f) + ofs; + whence = 0; + } + + if (f->fd == -1) + { + if (whence == 0) + { + if (f->mode == FZ_READ) + f->out->rp = CLAMP(f->out->bp + ofs, f->out->bp, f->out->ep); + else + f->in->wp = CLAMP(f->in->bp + ofs, f->in->bp, f->in->ep); + } + else + { + if (f->mode == FZ_READ) + f->out->rp = CLAMP(f->out->ep + ofs, f->out->bp, f->out->ep); + else + f->in->wp = CLAMP(f->in->ep + ofs, f->in->bp, f->in->ep); + } + return fz_tell(f); + } + + t = lseek(f->fd, ofs, whence); + if (t == -1) + { + f->error = fz_throw("ioerror: lseek: %s", strerror(errno)); + return -1; + } + + f->out->rp = f->out->bp; + f->out->wp = f->out->bp; + f->out->eof = 0; + + return t; +} + +int +fz_tell(fz_file *f) +{ + int t; + + if (f->filter) + { + assert(f->mode == FZ_READ); + return f->filter->count - (f->out->wp - f->out->rp); + } + + if (f->fd == -1) + { + if (f->mode == FZ_READ) + return f->out->rp - f->out->bp; + else + return f->in->wp - f->in->bp; + } + + t = lseek(f->fd, 0, 1); + if (t == -1) + { + f->error = fz_throw("ioerror: lseek: %s", strerror(errno)); + return -1; + } + + if (f->mode == FZ_READ) + return t - (f->out->wp - f->out->rp); + else + return t + (f->in->wp - f->in->rp); +} + diff --git a/stream/stm_filer.c b/stream/stm_filer.c new file mode 100644 index 00000000..a63a7dd2 --- /dev/null +++ b/stream/stm_filer.c @@ -0,0 +1,252 @@ +#include + +static int doread(fz_buffer *b, int fd) +{ + int n = read(fd, b->wp, b->ep - b->wp); + if (n == -1) + return -1; + if (n == 0) + b->eof = 1; + b->wp += n; + return n; +} + +int fz_producedata(fz_file *f) +{ + fz_error *reason; + int produced; + int n; + + assert(f->mode == FZ_READ); + assert(f->error == nil); + + if (!f->filter) + { + fz_rewindbuffer(f->out); + n = doread(f->out, f->fd); + if (n < 0) { + f->error = fz_throw("ioerror in read: %s", strerror(errno)); + return -1; + } + return 0; + } + + produced = 0; + + while (1) + { + reason = fz_process(f->filter, f->in, f->out); + + if (f->filter->produced) + produced = 1; + + if (reason == fz_ioneedin) + { + if (f->in->eof) { + f->error = fz_throw("ioerror: premature eof in filter"); + return -1; + } + + /* no space to produce, rewind or grow */ + if (f->in->wp == f->in->ep) + { + if (f->in->rp > f->in->bp) + f->error = fz_rewindbuffer(f->in); + else + f->error = fz_growbuffer(f->in); + if (f->error) + return -1; + } + + /* then fill with more input */ + n = doread(f->in, f->fd); + if (n < 0) { + f->error = fz_throw("ioerror in read: %s", strerror(errno)); + return -1; + } + + if (produced) + return 0; + } + + else if (reason == fz_ioneedout) + { + if (produced) + return 0; + + /* need more outspace, and produced no data */ + if (f->out->rp > f->out->bp) + f->error = fz_rewindbuffer(f->out); + else + f->error = fz_growbuffer(f->out); + if (f->error) + return -1; + } + + else if (reason == fz_iodone) + return 0; + + else { + f->error = reason; + return -1; + } + } +} + +int +fz_peekbyte(fz_file *f) +{ + if (f->out->rp == f->out->wp) + { + if (f->out->eof) return EOF; + if (fz_producedata(f)) return EOF; + } + + if (f->out->rp < f->out->wp) + return *f->out->rp; + + return EOF; +} + +int +fz_readbyte(fz_file *f) +{ + if (f->out->rp == f->out->wp) + { + if (f->out->eof) return EOF; + if (fz_producedata(f)) return EOF; + } + + if (f->out->rp < f->out->wp) + return *f->out->rp++; + + return EOF; +} + +int +fz_read(fz_file *f, unsigned char *buf, int n) +{ + int i = 0; + + while (i < n) + { + while (f->out->rp < f->out->wp && i < n) + buf[i++] = *f->out->rp ++; + + if (f->out->rp == f->out->wp) + { + if (f->out->eof) return i; + if (fz_producedata(f) < 0) return -1; + } + } + + return i; +} + +int +fz_readline(fz_file *f, char *buf, int n) +{ + int c = EOF; + char *s = buf; + + while (n > 1) + { + c = fz_readbyte(f); + if (c == EOF) + break; + if (c == '\r') { + c = fz_peekbyte(f); + if (c == '\n') + c = fz_readbyte(f); + break; + } + if (c == '\n') + break; + *s++ = c; + n--; + } + if (n) + *s = '\0'; + return s - buf; +} + +/* + * Utility function to consume contents of file stream into + * a freshly allocated buffer; realloced and trimmed to size. + */ + +enum { CHUNKSIZE = 1024 * 32 }; + +fz_error * +fz_readfile(fz_buffer **bufp, fz_file *file) +{ + fz_buffer *real; + unsigned char *newbuf; + unsigned char *buf; + int len; + int pos; + int n; + + *bufp = nil; + + len = 0; + pos = 0; + buf = nil; + + while (1) + { + if (len - pos == 0) + { + len += CHUNKSIZE; + newbuf = fz_realloc(buf, len); + if (!newbuf) + { + fz_free(buf); + return fz_outofmem; + } + buf = newbuf; + } + + n = fz_read(file, buf + pos, len - pos); + + if (n < 0) + { + fz_free(buf); + return fz_ferror(file); + } + + pos += n; + + if (n < CHUNKSIZE) + { + if (pos > 0) + { + newbuf = fz_realloc(buf, pos); + if (!newbuf) + { + fz_free(buf); + return fz_outofmem; + } + } + else newbuf = buf; + + real = *bufp = fz_malloc(sizeof(fz_buffer)); + if (!real) + { + fz_free(newbuf); + return fz_outofmem; + } + + real->refs = 1; + real->ownsdata = 1; + real->bp = buf; + real->rp = buf; + real->wp = buf + pos; + real->ep = buf + pos; + real->eof = 1; + + return nil; + } + } +} + diff --git a/stream/stm_filew.c b/stream/stm_filew.c new file mode 100644 index 00000000..f83399a2 --- /dev/null +++ b/stream/stm_filew.c @@ -0,0 +1,260 @@ +#include + +int +fz_printstring(fz_file *f, char *s) +{ + return fz_write(f, s, strlen(s)); +} + +int +fz_printobj(fz_file *file, fz_obj *obj, int tight) +{ + char buf[1024]; + char *ptr; + int n; + + n = fz_sprintobj(nil, 0, obj, tight); + if (n < sizeof buf) + { + fz_sprintobj(buf, sizeof buf, obj, tight); + return fz_write(file, buf, n); + } + else + { + ptr = fz_malloc(n); + if (!ptr) { + file->error = fz_outofmem; + return -1; + } + fz_sprintobj(ptr, n, obj, tight); + n = fz_write(file, ptr, n); + fz_free(ptr); + return n; + } +} + +int +fz_print(fz_file *f, char *fmt, ...) +{ + va_list ap; + char buf[1024]; + char *p; + int n; + + va_start(ap, fmt); + n = vsnprintf(buf, sizeof buf, fmt, ap); + va_end(ap); + + if (n < sizeof buf) + return fz_write(f, buf, n); + + p = fz_malloc(n); + if (!p) { + f->error = fz_outofmem; + return -1; + } + + va_start(ap, fmt); + vsnprintf(p, n, fmt, ap); + va_end(ap); + + n = fz_write(f, p, n); + + fz_free(p); + + return n; +} + +static int dowrite(fz_buffer *b, int fd) +{ + int n = write(fd, b->rp, b->wp - b->rp); + if (n == -1) + return -1; + b->rp += n; + return n; +} + +int +fz_write(fz_file *f, unsigned char *buf, int n) +{ + fz_error *reason; + int i = 0; + int x; + + assert(f->mode == FZ_WRITE); + assert(f->error == nil); + + if (!f->filter) + { + while (i < n) + { + while (f->in->wp < f->in->ep && i < n) + *f->in->wp++ = buf[i++]; + + if (f->in->wp == f->in->ep) + { + if (f->fd != -1) + { + x = dowrite(f->in, f->fd); + if (x < 0) { + f->error = fz_throw("ioerror in write: %s", strerror(errno)); + return -1; + } + } + + if (f->in->rp > f->in->bp) + f->error = fz_rewindbuffer(f->in); + else + f->error = fz_growbuffer(f->in); + if (f->error) + return -1; + } + } + + return 0; + } + + while (i < n) + { + while (f->in->wp < f->in->ep && i < n) + *f->in->wp++ = buf[i++]; + + if (f->in->wp == f->in->ep) + { + reason = fz_process(f->filter, f->in, f->out); + + if (reason == fz_ioneedin) + { + if (f->in->wp == f->in->ep) { + if (f->in->rp > f->in->bp) + f->error = fz_rewindbuffer(f->in); + else + f->error = fz_growbuffer(f->in); + if (f->error) + return -1; + } + } + + else if (reason == fz_ioneedout) + { + if (f->fd != -1) + { + x = dowrite(f->out, f->fd); + if (x < 0) { + f->error = fz_throw("ioerror in write: %s", strerror(errno)); + return -1; + } + } + + if (f->out->rp > f->out->bp) + f->error = fz_rewindbuffer(f->out); + else + f->error = fz_growbuffer(f->out); + if (f->error) + return -1; + } + + else if (reason == fz_iodone) + { + if (f->fd != -1) + { + while (f->out->rp < f->out->wp) + { + x = dowrite(f->out, f->fd); + if (x < 0) { + f->error = fz_throw("ioerror in write: %s", strerror(errno)); + return -1; + } + } + } + break; + } + + else { + f->error = reason; + return -1; + } + } + } + + return i; +} + +int +fz_flush(fz_file *f) +{ + fz_error *reason; + int n; + + assert(f->mode == FZ_WRITE); + assert(f->error == nil); + + f->in->eof = 1; + + if (!f->filter) + { + if (f->fd != -1) + { + while (f->in->rp < f->in->wp) + { + n = dowrite(f->in, f->fd); + if (n < 0) { + f->error = fz_throw("ioerror in write: %s", strerror(errno)); + return -1; + } + } + } + return 0; + } + + while (!f->out->eof) + { + reason = fz_process(f->filter, f->in, f->out); + + if (reason == fz_ioneedin) { + f->error = fz_throw("ioerror: premature eof in filter"); + return -1; + } + + else if (reason == fz_ioneedout) + { + if (f->fd != -1) + { + n = dowrite(f->out, f->fd); + if (n < 0) { + f->error = fz_throw("ioerror in write: %s", strerror(errno)); + return -1; + } + } + + if (f->out->rp > f->out->bp) + f->error = fz_rewindbuffer(f->out); + else + f->error = fz_growbuffer(f->out); + if (f->error) + return -1; + } + + else if (reason == fz_iodone) + { + if (f->fd != -1) + { + n = dowrite(f->out, f->fd); + if (n < 0) { + f->error = fz_throw("ioerror in write: %s", strerror(errno)); + return -1; + } + } + break; + } + + else + { + f->error = reason; + return -1; + } + } + + return 0; +} + -- cgit v1.2.3