22// Copyright (c) 2015 HPE Software Inc. All rights reserved.
33// Copyright (c) 2013 ActiveState Software Inc. All rights reserved.
44
5- //nxadm/tail provides a Go library that emulates the features of the BSD `tail`
6- //program. The library comes with full support for truncation/move detection as
7- //it is designed to work with log rotation tools. The library works on all
8- //operating systems supported by Go, including POSIX systems like Linux and
9- //*BSD, and MS Windows. Go 1.9 is the oldest compiler release supported.
5+ // nxadm/tail provides a Go library that emulates the features of the BSD `tail`
6+ // program. The library comes with full support for truncation/move detection as
7+ // it is designed to work with log rotation tools. The library works on all
8+ // operating systems supported by Go, including POSIX systems like Linux and
9+ // *BSD, and MS Windows. Go 1.9 is the oldest compiler release supported.
1010package tail
1111
1212import (
@@ -16,15 +16,17 @@ import (
1616 "io"
1717 "io/ioutil"
1818 "log"
19+ "math"
1920 "os"
2021 "strings"
2122 "sync"
2223 "time"
2324
25+ "gopkg.in/tomb.v1"
26+
2427 "github.com/nxadm/tail/ratelimiter"
2528 "github.com/nxadm/tail/util"
2629 "github.com/nxadm/tail/watch"
27- "gopkg.in/tomb.v1"
2830)
2931
3032var (
@@ -221,14 +223,14 @@ func (tail *Tail) reopen() error {
221223 if os .IsNotExist (err ) {
222224 tail .Logger .Printf ("Waiting for %s to appear..." , tail .Filename )
223225 if err := tail .watcher .BlockUntilExists (& tail .Tomb ); err != nil {
224- if err == tomb .ErrDying {
226+ if errors . Is ( err , tomb .ErrDying ) {
225227 return err
226228 }
227- return fmt .Errorf ("Failed to detect creation of %s: %s" , tail .Filename , err )
229+ return fmt .Errorf ("failed to detect creation of %s: %s" , tail .Filename , err )
228230 }
229231 continue
230232 }
231- return fmt .Errorf ("Unable to open file %s: %s" , tail .Filename , err )
233+ return fmt .Errorf ("unable to open file %s: %s" , tail .Filename , err )
232234 }
233235 break
234236 }
@@ -275,7 +277,7 @@ func (tail *Tail) tailFileSync() {
275277 // deferred first open.
276278 err := tail .reopen ()
277279 if err != nil {
278- if err != tomb .ErrDying {
280+ if ! errors . Is ( err , tomb .ErrDying ) {
279281 tail .Kill (err )
280282 }
281283 return
@@ -284,9 +286,24 @@ func (tail *Tail) tailFileSync() {
284286
285287 // Seek to requested location on first open of the file.
286288 if tail .Location != nil {
287- _ , err := tail .file .Seek (tail .Location .Offset , tail .Location .Whence )
288- if err != nil {
289- tail .Killf ("Seek error on %s: %s" , tail .Filename , err )
289+ offset := tail .Location .Offset
290+ if tail .Location .Whence == io .SeekEnd && offset < 0 {
291+ ret , err := tail .file .Seek (0 , io .SeekEnd )
292+ if err != nil {
293+ _ = tail .Killf ("Seek error on %s: %s" , tail .Filename , err )
294+ return
295+ }
296+
297+ // if ret > abs(offset), use offset
298+ // otherwise, use ret
299+
300+ if ret < int64 (math .Abs (float64 (offset ))) {
301+ offset = ret
302+ }
303+ }
304+
305+ if _ , err := tail .file .Seek (offset , tail .Location .Whence ); err != nil {
306+ _ = tail .Killf ("Seek error on %s: %s" , tail .Filename , err )
290307 return
291308 }
292309 }
@@ -312,7 +329,7 @@ func (tail *Tail) tailFileSync() {
312329 if cooloff {
313330 // Wait a second before seeking till the end of
314331 // file when rate limit is reached.
315- msg := ( "Too much log activity; waiting a second before resuming tailing")
332+ msg := "too much log activity; waiting a second before resuming tailing"
316333 offset , _ := tail .Tell ()
317334 tail .Lines <- & Line {msg , tail .lineNum , SeekInfo {Offset : offset }, time .Now (), errors .New (msg )}
318335 select {
@@ -346,7 +363,7 @@ func (tail *Tail) tailFileSync() {
346363 // implementation (inotify or polling).
347364 err := tail .waitForChanges ()
348365 if err != nil {
349- if err != ErrStop {
366+ if ! errors . Is ( err , ErrStop ) {
350367 tail .Kill (err )
351368 }
352369 return
@@ -359,7 +376,7 @@ func (tail *Tail) tailFileSync() {
359376
360377 select {
361378 case <- tail .Dying ():
362- if tail .Err () == errStopAtEOF {
379+ if errors . Is ( tail .Err (), errStopAtEOF ) {
363380 continue
364381 }
365382 return
0 commit comments