diff --git a/tail.go b/tail.go index 36cb4b9..b3be92e 100644 --- a/tail.go +++ b/tail.go @@ -91,6 +91,21 @@ func TailFile(filename string, config Config) (*Tail, error) { return t, nil } +// Return the file's current position, like stdio's ftell(). +// But this value is not very accurate. +// it may readed one line in the chan(tail.Lines), +// so it may lost one line. +func (tail *Tail) Tell() (offset int64, err error) { + if tail.file == nil { + return + } + offset, err = tail.file.Seek(0, os.SEEK_CUR) + if err == nil { + offset -= int64(tail.reader.Buffered()) + } + return +} + // Stop stops the tailing activity. func (tail *Tail) Stop() error { tail.Kill(nil) diff --git a/tail_test.go b/tail_test.go index e3b298f..c9ec769 100644 --- a/tail_test.go +++ b/tail_test.go @@ -225,6 +225,39 @@ func TestRateLimiting(_t *testing.T) { tail.Stop() } +func TestTell(_t *testing.T) { + t := NewTailTest("tell-position", _t) + t.CreateFile("test.txt", "hello\nworld\nagain\nmore\n") + config := Config{ + Follow: false, + Location: &SeekInfo{0, os.SEEK_SET}} + tail := t.StartTail("test.txt", config) + // read noe line + <-tail.Lines + offset, err := tail.Tell() + if err != nil { + t.Errorf("Tell return error: %s", err.Error()) + } + tail.Done() + // tail.close() + + config = Config{ + Follow: false, + Location: &SeekInfo{offset, os.SEEK_SET}} + tail = t.StartTail("test.txt", config) + for l := range tail.Lines { + // it may readed one line in the chan(tail.Lines), + // so it may lost one line. + if l.Text != "world" && l.Text != "again" { + t.Fatalf("mismatch; expected world or again, but got %s", + l.Text) + } + break + } + t.RemoveFile("test.txt") + tail.Done() +} + // Test library type TailTest struct {