add changes to maintain perms and owner of logfile
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
// +build !linux
|
||||
|
||||
package lumberjack
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func chown(_ string, _ os.FileInfo) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package lumberjack
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// os_Chown is a var so we can mock it out during tests.
|
||||
var os_Chown = os.Chown
|
||||
|
||||
func chown(name string, info os.FileInfo) error {
|
||||
f, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.Close()
|
||||
stat := info.Sys().(*syscall.Stat_t)
|
||||
return os_Chown(name, int(stat.Uid), int(stat.Gid))
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// +build linux
|
||||
|
||||
package lumberjack
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMaintainOwner(t *testing.T) {
|
||||
fakeC := fakeChown{}
|
||||
os_Chown = fakeC.Set
|
||||
os_Stat = fakeStat
|
||||
defer func() {
|
||||
os_Chown = os.Chown
|
||||
os_Stat = os.Stat
|
||||
}()
|
||||
currentTime = fakeTime
|
||||
dir := makeTempDir("TestMaintainOwner", t)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
filename := logFile(dir)
|
||||
|
||||
l := &Logger{
|
||||
Filename: filename,
|
||||
MaxBackups: 1,
|
||||
MaxSize: 100, // megabytes
|
||||
}
|
||||
defer l.Close()
|
||||
b := []byte("boo!")
|
||||
n, err := l.Write(b)
|
||||
isNil(err, t)
|
||||
equals(len(b), n, t)
|
||||
|
||||
newFakeTime()
|
||||
|
||||
err = l.Rotate()
|
||||
isNil(err, t)
|
||||
|
||||
equals(555, fakeC.uid, t)
|
||||
equals(666, fakeC.gid, t)
|
||||
}
|
||||
|
||||
type fakeChown struct {
|
||||
name string
|
||||
uid int
|
||||
gid int
|
||||
}
|
||||
|
||||
func (f *fakeChown) Set(name string, uid, gid int) error {
|
||||
f.name = name
|
||||
f.uid = uid
|
||||
f.gid = gid
|
||||
return nil
|
||||
}
|
||||
|
||||
func fakeStat(name string) (os.FileInfo, error) {
|
||||
info, err := os.Stat(name)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
stat := info.Sys().(*syscall.Stat_t)
|
||||
stat.Uid = 555
|
||||
stat.Gid = 666
|
||||
return info, nil
|
||||
}
|
||||
+14
-3
@@ -101,6 +101,9 @@ var (
|
||||
// currentTime exists so it can be mocked out by tests.
|
||||
currentTime = time.Now
|
||||
|
||||
// os_Stat exists so it can be mocked out by tests.
|
||||
os_Stat = os.Stat
|
||||
|
||||
// megabyte is the conversion factor between MaxSize and bytes. It is a
|
||||
// variable so tests can mock it out and not need to write megabytes of data
|
||||
// to disk.
|
||||
@@ -191,19 +194,27 @@ func (l *Logger) openNew() error {
|
||||
}
|
||||
|
||||
name := l.filename()
|
||||
_, err = os.Stat(name)
|
||||
mode := os.FileMode(0644)
|
||||
info, err := os_Stat(name)
|
||||
if err == nil {
|
||||
// Copy the mode off the old logfile.
|
||||
mode = info.Mode()
|
||||
// move the existing file
|
||||
newname := backupName(name, l.LocalTime)
|
||||
if err := os.Rename(name, newname); err != nil {
|
||||
return fmt.Errorf("can't rename log file: %s", err)
|
||||
}
|
||||
|
||||
// this is a no-op anywhere but linux
|
||||
if err := chown(name, info); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// we use truncate here because this should only get called when we've moved
|
||||
// the file ourselves. if someone else creates the file in the meantime,
|
||||
// just wipe out the contents.
|
||||
f, err := os.OpenFile(l.filename(), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||
f, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't open new logfile: %s", err)
|
||||
}
|
||||
@@ -234,7 +245,7 @@ func backupName(name string, local bool) string {
|
||||
// put it over the MaxSize, a new file is created.
|
||||
func (l *Logger) openExistingOrNew(writeLen int) error {
|
||||
filename := l.filename()
|
||||
info, err := os.Stat(filename)
|
||||
info, err := os_Stat(filename)
|
||||
if os.IsNotExist(err) {
|
||||
return l.openNew()
|
||||
}
|
||||
|
||||
+37
-1
@@ -493,7 +493,6 @@ func TestRotate(t *testing.T) {
|
||||
existsWithLen(filename2, n, t)
|
||||
existsWithLen(filename, 0, t)
|
||||
fileCount(dir, 2, t)
|
||||
|
||||
newFakeTime()
|
||||
|
||||
err = l.Rotate()
|
||||
@@ -574,6 +573,43 @@ localtime = true`[1:]
|
||||
equals(0, len(md.Undecoded()), t)
|
||||
}
|
||||
|
||||
func TestMaintainMode(t *testing.T) {
|
||||
currentTime = fakeTime
|
||||
dir := makeTempDir("TestMaintainMode", t)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
filename := logFile(dir)
|
||||
|
||||
mode := os.FileMode(0770)
|
||||
f, err := os.OpenFile(filename, os.O_CREATE|os.O_RDWR, mode)
|
||||
isNil(err, t)
|
||||
f.Close()
|
||||
|
||||
l := &Logger{
|
||||
Filename: filename,
|
||||
MaxBackups: 1,
|
||||
MaxSize: 100, // megabytes
|
||||
}
|
||||
defer l.Close()
|
||||
b := []byte("boo!")
|
||||
n, err := l.Write(b)
|
||||
isNil(err, t)
|
||||
equals(len(b), n, t)
|
||||
|
||||
newFakeTime()
|
||||
|
||||
err = l.Rotate()
|
||||
isNil(err, t)
|
||||
|
||||
filename2 := backupFile(dir)
|
||||
info, err := os.Stat(filename)
|
||||
isNil(err, t)
|
||||
info2, err := os.Stat(filename2)
|
||||
isNil(err, t)
|
||||
equals(mode, info.Mode(), t)
|
||||
equals(mode, info2.Mode(), t)
|
||||
}
|
||||
|
||||
// makeTempDir creates a file with a semi-unique name in the OS temp directory.
|
||||
// It should be based on the name of the test, to keep parallel tests from
|
||||
// colliding, and must be cleaned up after the test is finished.
|
||||
|
||||
Reference in New Issue
Block a user