2
0

add changes to maintain perms and owner of logfile

This commit is contained in:
Nate Finch
2014-07-25 15:42:36 -04:00
parent 8b224001f4
commit 689fc505a0
5 changed files with 149 additions and 4 deletions
+12
View File
@@ -0,0 +1,12 @@
// +build !linux
package lumberjack
import (
"os"
"syscall"
)
func chown(_ string, _ os.FileInfo) error {
return nil
}
+19
View File
@@ -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))
}
+67
View File
@@ -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
View File
@@ -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
View File
@@ -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.