diff --git a/client/allocdir/alloc_dir.go b/client/allocdir/alloc_dir.go index bbdb64317..8c95d0c75 100644 --- a/client/allocdir/alloc_dir.go +++ b/client/allocdir/alloc_dir.go @@ -385,7 +385,9 @@ func getFileWatcher(path string) watch.FileWatcher { return watch.NewPollingFileWatcher(path) } -func fileCopy(src, dst string, perm os.FileMode) error { +// fileCopy from src to dst setting the permissions and owner (if uid & gid are +// both greater than 0) +func fileCopy(src, dst string, uid, gid int, perm os.FileMode) error { // Do a simple copy. srcFile, err := os.Open(src) if err != nil { @@ -400,7 +402,13 @@ func fileCopy(src, dst string, perm os.FileMode) error { defer dstFile.Close() if _, err := io.Copy(dstFile, srcFile); err != nil { - return fmt.Errorf("Couldn't copy %v to %v: %v", src, dst, err) + return fmt.Errorf("Couldn't copy %q to %q: %v", src, dst, err) + } + + if uid >= 0 && gid >= 0 { + if err := dstFile.Chown(uid, gid); err != nil { + return fmt.Errorf("Couldn't copy %q to %q: %v", src, dst, err) + } } return nil diff --git a/client/allocdir/fs_darwin.go b/client/allocdir/fs_darwin.go index fe29791c4..7cd5caf23 100644 --- a/client/allocdir/fs_darwin.go +++ b/client/allocdir/fs_darwin.go @@ -24,3 +24,8 @@ func createSecretDir(dir string) error { func removeSecretDir(dir string) error { return os.RemoveAll(dir) } + +// getOwner isn't implemented for Darwin +func getOwner(os.FileInfo) (int, int) { + return -1, -1 +} diff --git a/client/allocdir/fs_freebsd.go b/client/allocdir/fs_freebsd.go index fe29791c4..0d34925a7 100644 --- a/client/allocdir/fs_freebsd.go +++ b/client/allocdir/fs_freebsd.go @@ -24,3 +24,8 @@ func createSecretDir(dir string) error { func removeSecretDir(dir string) error { return os.RemoveAll(dir) } + +// getOwner isn't implemented for FreeBSD +func getOwner(os.FileInfo) (int, int) { + return -1, -1 +} diff --git a/client/allocdir/fs_linux.go b/client/allocdir/fs_linux.go index 7a76c5dd1..c6b079f86 100644 --- a/client/allocdir/fs_linux.go +++ b/client/allocdir/fs_linux.go @@ -88,3 +88,11 @@ func removeSecretDir(dir string) error { } return os.RemoveAll(dir) } + +func getOwner(fi os.FileInfo) (int, int) { + stat, ok := fi.Sys().(*syscall.Stat_t) + if !ok { + return -1, -1 + } + return int(stat.Uid), int(stat.Gid) +} diff --git a/client/allocdir/fs_solaris.go b/client/allocdir/fs_solaris.go index 088b58f5b..83359b1b3 100644 --- a/client/allocdir/fs_solaris.go +++ b/client/allocdir/fs_solaris.go @@ -25,3 +25,8 @@ func createSecretDir(dir string) error { func removeSecretDir(dir string) error { return os.RemoveAll(dir) } + +// getOwner isn't implemented for Solaris +func getOwner(os.FileInfo) (int, int) { + return -1, -1 +} diff --git a/client/allocdir/fs_unix.go b/client/allocdir/fs_unix.go index 648fce1ad..7e3068b3b 100644 --- a/client/allocdir/fs_unix.go +++ b/client/allocdir/fs_unix.go @@ -82,7 +82,7 @@ func getGid(u *user.User) (int, error) { // linkOrCopy attempts to hardlink dst to src and fallsback to copying if the // hardlink fails. -func linkOrCopy(src, dst string, perm os.FileMode) error { +func linkOrCopy(src, dst string, uid, gid int, perm os.FileMode) error { // Avoid link/copy if the file already exists in the chroot // TODO 0.6 clean this up. This was needed because chroot creation fails // when a process restarts. @@ -90,9 +90,9 @@ func linkOrCopy(src, dst string, perm os.FileMode) error { return nil } // Attempt to hardlink. - if err := os.Link(src, dst); err == nil { - return nil - } + //if err := os.Link(src, dst); err == nil { + // return nil + //} - return fileCopy(src, dst, perm) + return fileCopy(src, dst, uid, gid, perm) } diff --git a/client/allocdir/fs_windows.go b/client/allocdir/fs_windows.go index de0fcec89..f39f2cd72 100644 --- a/client/allocdir/fs_windows.go +++ b/client/allocdir/fs_windows.go @@ -21,8 +21,8 @@ var ( ) // linkOrCopy is always copies dst to src on Windows. -func linkOrCopy(src, dst string, perm os.FileMode) error { - return fileCopy(src, dst, perm) +func linkOrCopy(src, dst string, uid, gid int, perm os.FileMode) error { + return fileCopy(src, dst, uid, gid, perm) } // The windows version does nothing currently. @@ -70,3 +70,8 @@ func MountSpecialDirs(taskDir string) error { func unmountSpecialDirs(taskDir string) error { return nil } + +// getOwner doesn't work on Windows as Windows doesn't use int user IDs +func getOwner(os.FileInfo) (int, int) { + return -1, -1 +} diff --git a/client/allocdir/task_dir.go b/client/allocdir/task_dir.go index 4f2817e62..b43760572 100644 --- a/client/allocdir/task_dir.go +++ b/client/allocdir/task_dir.go @@ -163,7 +163,8 @@ func (t *TaskDir) embedDirs(entries map[string]string) error { // Copy the file. taskEntry := filepath.Join(t.Dir, dest) - if err := linkOrCopy(source, taskEntry, s.Mode().Perm()); err != nil { + uid, gid := getOwner(s) + if err := linkOrCopy(source, taskEntry, uid, gid, s.Mode().Perm()); err != nil { return err } @@ -217,7 +218,8 @@ func (t *TaskDir) embedDirs(entries map[string]string) error { continue } - if err := linkOrCopy(hostEntry, taskEntry, entry.Mode().Perm()); err != nil { + uid, gid := getOwner(entry) + if err := linkOrCopy(hostEntry, taskEntry, uid, gid, entry.Mode().Perm()); err != nil { return err } }