From d894fe2e0d3bc2d3d9d3a2b84d372fb2ea2b5ca0 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sat, 10 Mar 2007 20:15:06 +0100 Subject: [PATCH] Fastbufs now work better on unseekable files. The seek callback returns success, bseek() and bsetpos() dies if seek fails, bfilesize() returns -1 if the file is unseekable. --- lib/fastbuf.c | 10 +++++++--- lib/fastbuf.h | 4 ++-- lib/fb-buffer.c | 3 ++- lib/fb-file.c | 7 ++++--- lib/fb-grow.c | 3 ++- lib/fb-mem.c | 6 +++--- lib/fb-mmap.c | 3 ++- 7 files changed, 22 insertions(+), 14 deletions(-) diff --git a/lib/fastbuf.c b/lib/fastbuf.c index 980d53aa..79229d4e 100644 --- a/lib/fastbuf.c +++ b/lib/fastbuf.c @@ -38,7 +38,8 @@ inline void bsetpos(struct fastbuf *f, sh_off_t pos) else { bflush(f); - f->seek(f, pos, SEEK_SET); + if (!f->seek || !f->seek(f, pos, SEEK_SET)) + die("bsetpos: stream not seekable"); } } @@ -52,7 +53,8 @@ void bseek(struct fastbuf *f, sh_off_t pos, int whence) return bsetpos(f, btell(f) + pos); case SEEK_END: bflush(f); - f->seek(f, pos, SEEK_END); + if (!f->seek || !f->seek(f, pos, SEEK_END)) + die("bseek: stream not seekable"); break; default: die("bseek: invalid whence=%d", whence); @@ -192,7 +194,9 @@ bfilesize(struct fastbuf *f) if (!f) return 0; sh_off_t pos = btell(f); - bseek(f, 0, SEEK_END); + bflush(f); + if (!f->seek(f, pos, SEEK_END)) + return -1; sh_off_t len = btell(f); bsetpos(f, pos); return len; diff --git a/lib/fastbuf.h b/lib/fastbuf.h index 598a21d9..12bb5da2 100644 --- a/lib/fastbuf.h +++ b/lib/fastbuf.h @@ -73,7 +73,7 @@ struct fastbuf { sh_off_t pos; /* Position of bstop in the file */ int (*refill)(struct fastbuf *); /* Get a buffer with new data */ void (*spout)(struct fastbuf *); /* Write buffer data to the file */ - void (*seek)(struct fastbuf *, sh_off_t, int); /* Slow path for bseek(), buffer already flushed */ + int (*seek)(struct fastbuf *, sh_off_t, int); /* Slow path for bseek(), buffer already flushed; returns success */ void (*close)(struct fastbuf *); /* Close the stream */ int (*config)(struct fastbuf *, uns, int); /* Configure the stream */ int can_overwrite_buffer; /* Can the buffer be altered? (see discussion above) 0=never, 1=temporarily, 2=permanently */ @@ -153,7 +153,7 @@ void bflush(struct fastbuf *f); void bseek(struct fastbuf *f, sh_off_t pos, int whence); void bsetpos(struct fastbuf *f, sh_off_t pos); void brewind(struct fastbuf *f); -sh_off_t bfilesize(struct fastbuf *f); +sh_off_t bfilesize(struct fastbuf *f); // -1 if not seekable static inline sh_off_t btell(struct fastbuf *f) { diff --git a/lib/fb-buffer.c b/lib/fb-buffer.c index 09c74293..9ad248a2 100644 --- a/lib/fb-buffer.c +++ b/lib/fb-buffer.c @@ -18,7 +18,7 @@ fbbuf_refill(struct fastbuf *f UNUSED) return 0; } -static void +static int fbbuf_seek(struct fastbuf *f, sh_off_t pos, int whence) { /* Somebody might want to seek to the end of buffer, try to be nice to him. */ @@ -29,6 +29,7 @@ fbbuf_seek(struct fastbuf *f, sh_off_t pos, int whence) f->bptr = f->buffer + pos; f->bstop = f->bufend; f->pos = len; + return 1; } void diff --git a/lib/fb-file.c b/lib/fb-file.c index 0dcf22a9..c4543277 100644 --- a/lib/fb-file.c +++ b/lib/fb-file.c @@ -53,16 +53,17 @@ bfd_spout(struct fastbuf *f) f->bptr = f->buffer = FB_BUFFER(f); } -static void +static int bfd_seek(struct fastbuf *f, sh_off_t pos, int whence) { if (whence == SEEK_SET && pos == f->pos) - return; + return 1; sh_off_t l = sh_seek(FB_FILE(f)->fd, pos, whence); if (l < 0) - die("lseek on %s: %m", f->name); + return 0; f->pos = l; + return 1; } static void diff --git a/lib/fb-grow.c b/lib/fb-grow.c index 0b04817f..1a10a501 100644 --- a/lib/fb-grow.c +++ b/lib/fb-grow.c @@ -45,7 +45,7 @@ fbgrow_spout(struct fastbuf *b) } } -static void +static int fbgrow_seek(struct fastbuf *b, sh_off_t pos, int whence) { ASSERT(FB_GBUF(b)->last_written); /* Seeks allowed only in read mode */ @@ -56,6 +56,7 @@ fbgrow_seek(struct fastbuf *b, sh_off_t pos, int whence) b->bptr = b->buffer + pos; b->bstop = FB_GBUF(b)->last_written; b->pos = len; + return 1; } static void diff --git a/lib/fb-mem.c b/lib/fb-mem.c index 0de590e0..c3f104f1 100644 --- a/lib/fb-mem.c +++ b/lib/fb-mem.c @@ -93,7 +93,7 @@ fbmem_spout(struct fastbuf *f) FB_MEM(f)->block = bb; } -static void +static int fbmem_seek(struct fastbuf *f, sh_off_t pos, int whence) { struct memstream *m = FB_MEM(f)->stream; @@ -115,7 +115,7 @@ fbmem_seek(struct fastbuf *f, sh_off_t pos, int whence) f->bufend = f->bstop = b->data + b->size; f->pos = b->pos + b->size; FB_MEM(f)->block = b; - return; + return 1; } } if (!m->first && !pos) @@ -124,7 +124,7 @@ fbmem_seek(struct fastbuf *f, sh_off_t pos, int whence) f->buffer = f->bptr = f->bufend = NULL; f->pos = 0; FB_MEM(f)->block = NULL; - return; + return 1; } die("fbmem_seek to invalid offset"); } diff --git a/lib/fb-mmap.c b/lib/fb-mmap.c index 85dc27ee..41e65832 100644 --- a/lib/fb-mmap.c +++ b/lib/fb-mmap.c @@ -117,7 +117,7 @@ bfmm_spout(struct fastbuf *f) DBG(" -> %p %p %p(%x) %p", f->buffer, f->bptr, f->bstop, (int)f->pos, f->bufend); } -static void +static int bfmm_seek(struct fastbuf *f, sh_off_t pos, int whence) { if (whence == SEEK_END) @@ -128,6 +128,7 @@ bfmm_seek(struct fastbuf *f, sh_off_t pos, int whence) f->pos = pos; f->bptr = f->bstop = f->bufend; /* force refill/spout call */ DBG("Seek -> %p %p %p(%x) %p", f->buffer, f->bptr, f->bstop, (int)f->pos, f->bufend); + return 1; } static void -- 2.39.2