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,23 @@ 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+ // min of 0 and ret - tail.Location.Offset
298+ // if ret - tail.Location.Offset is negative, then 0 is returned
299+ // otherwise ret - tail.Location.Offset is returned
300+
301+ offset = int64 (math .Min (0 , float64 (ret )- math .Abs (float64 (offset ))))
302+ }
303+
304+ if _ , err := tail .file .Seek (offset , tail .Location .Whence ); err != nil {
305+ _ = tail .Killf ("Seek error on %s: %s" , tail .Filename , err )
290306 return
291307 }
292308 }
@@ -312,7 +328,7 @@ func (tail *Tail) tailFileSync() {
312328 if cooloff {
313329 // Wait a second before seeking till the end of
314330 // file when rate limit is reached.
315- msg := ( "Too much log activity; waiting a second before resuming tailing")
331+ msg := "too much log activity; waiting a second before resuming tailing"
316332 offset , _ := tail .Tell ()
317333 tail .Lines <- & Line {msg , tail .lineNum , SeekInfo {Offset : offset }, time .Now (), errors .New (msg )}
318334 select {
@@ -346,7 +362,7 @@ func (tail *Tail) tailFileSync() {
346362 // implementation (inotify or polling).
347363 err := tail .waitForChanges ()
348364 if err != nil {
349- if err != ErrStop {
365+ if ! errors . Is ( err , ErrStop ) {
350366 tail .Kill (err )
351367 }
352368 return
@@ -359,7 +375,7 @@ func (tail *Tail) tailFileSync() {
359375
360376 select {
361377 case <- tail .Dying ():
362- if tail .Err () == errStopAtEOF {
378+ if errors . Is ( tail .Err (), errStopAtEOF ) {
363379 continue
364380 }
365381 return
0 commit comments