From 52b042971a6f9bb72db18b5ef88445e9ebc6d220 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Sun, 25 Jun 2017 09:05:24 +0200 Subject: [PATCH] keep file permissions and try to keep user/group on supported systems (fixes #1467) --- fs/config.go | 13 ++++++++++++- fs/config_other.go | 10 ++++++++++ fs/config_unix.go | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 fs/config_other.go create mode 100644 fs/config_unix.go diff --git a/fs/config.go b/fs/config.go index 44b4689e8..8c5d2ac5d 100644 --- a/fs/config.go +++ b/fs/config.go @@ -652,7 +652,18 @@ func SaveConfig() { log.Fatalf("Failed to close config file: %v", err) } - err = os.Chmod(f.Name(), 0600) + var fileMode os.FileMode = 0600 + info, err := os.Stat(ConfigPath) + if err != nil { + Debugf(nil, "Using default permissions for config file: %v", fileMode) + } else if info.Mode() != fileMode { + Debugf(nil, "Keeping previous permissions for config file: %v", info.Mode()) + fileMode = info.Mode() + } + + attemptCopyGroup(ConfigPath, f.Name()) + + err = os.Chmod(f.Name(), fileMode) if err != nil { Errorf(nil, "Failed to set permissions on config file: %v", err) } diff --git a/fs/config_other.go b/fs/config_other.go new file mode 100644 index 000000000..7c0834318 --- /dev/null +++ b/fs/config_other.go @@ -0,0 +1,10 @@ +// Read, write and edit the config file +// Non-unix specific functions. + +// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris + +package fs + +// attemptCopyGroups tries to keep the group the same, which only makes sense +// for system with user-group-world permission model. +func attemptCopyGroup(fromPath, toPath string) {} diff --git a/fs/config_unix.go b/fs/config_unix.go new file mode 100644 index 000000000..f0fe9daa0 --- /dev/null +++ b/fs/config_unix.go @@ -0,0 +1,35 @@ +// Read, write and edit the config file +// Unix specific functions. + +// +build darwin dragonfly freebsd linux netbsd openbsd solaris + +package fs + +import ( + "os" + "os/user" + "strconv" + "syscall" +) + +// attemptCopyGroups tries to keep the group the same. User will be the one +// who is currently running this process. +func attemptCopyGroup(fromPath, toPath string) { + info, err := os.Stat(fromPath) + if err != nil || info.Sys() == nil { + return + } + if stat, ok := info.Sys().(*syscall.Stat_t); ok { + uid := int(stat.Uid) + // prefer self over previous owner of file, because it has a higher chance + // of success + if user, err := user.Current(); err == nil { + if tmpUID, err := strconv.Atoi(user.Uid); err == nil { + uid = tmpUID + } + } + if err = os.Chown(toPath, uid, int(stat.Gid)); err != nil { + Debugf(nil, "Failed to keep previous owner of config file: %v", err) + } + } +}