aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap/file_wrappers.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2012-06-05 07:24:17 +0000
committerGuy Harris <guy@alum.mit.edu>2012-06-05 07:24:17 +0000
commit7ed3d0e959c466d46c2e8328c9cfa553c09ccd56 (patch)
tree2a1c0404eaa9aa7c48da222653f4843be9508508 /wiretap/file_wrappers.c
parent9fe3d4b4f356084e8631a972e0217f02e344ff3e (diff)
From Jakub Zawadzki: when seeking backwards, if the seek will put you at
a position that's in our data buffer, just reposition within the buffer, don't do any seeks or I/O on the underlying file. This lets us do some backwards seeking on a pipe, to allow the rewind-and-try scheme we use to try to identify capture file types to work, at least for some capture file formats (those that have magic numbers at the beginning or have heuristics that don't require much data), on pipes, allowing, for example, TShark to read those formats from a pipe. svn path=/trunk/; revision=43102
Diffstat (limited to 'wiretap/file_wrappers.c')
-rw-r--r--wiretap/file_wrappers.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/wiretap/file_wrappers.c b/wiretap/file_wrappers.c
index 96ca7d603f..443bd5ce6d 100644
--- a/wiretap/file_wrappers.c
+++ b/wiretap/file_wrappers.c
@@ -920,6 +920,16 @@ file_seek(FILE_T file, gint64 offset, int whence, int *err)
offset += file->skip;
file->seek = 0;
+ if (offset < 0 && file->next) {
+ ptrdiff_t had = file->next - file->out;
+ if (-offset <= had) {
+ file->have -= offset;
+ file->next += offset;
+ file->pos += offset;
+ return file->pos;
+ }
+ }
+
/* XXX, profile */
if ((here = fast_seek_find(file, file->pos + offset)) && (offset < 0 || offset > SPAN || here->compression == UNCOMPRESSED)) {
gint64 off, off2;
@@ -1003,7 +1013,9 @@ file_seek(FILE_T file, gint64 offset, int whence, int *err)
}
/* if within raw area while reading, just go there */
- if (file->compression == UNCOMPRESSED && file->pos + offset >= file->raw) {
+ if (file->compression == UNCOMPRESSED && file->pos + offset >= file->raw
+ && (offset < 0 || offset >= file->have) /* seek only when we don't have that offset in buffer */)
+ {
if (ws_lseek64(file->fd, offset - file->have, SEEK_CUR) == -1) {
*err = errno;
return -1;