else
{
bflush(f);
- f->seek(f, pos, SEEK_SET);
+ if (!f->seek || !f->seek(f, pos, SEEK_SET))
+ die("bsetpos: stream not seekable");
}
}
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);
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;
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 */
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)
{
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. */
f->bptr = f->buffer + pos;
f->bstop = f->bufend;
f->pos = len;
+ return 1;
}
void
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
}
}
-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 */
b->bptr = b->buffer + pos;
b->bstop = FB_GBUF(b)->last_written;
b->pos = len;
+ return 1;
}
static void
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;
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)
f->buffer = f->bptr = f->bufend = NULL;
f->pos = 0;
FB_MEM(f)->block = NULL;
- return;
+ return 1;
}
die("fbmem_seek to invalid offset");
}
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)
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