[lxc-devel] [lxd/master] fix directory perms on recursive push

tych0 on Github lxc-bot at linuxcontainers.org
Fri Dec 23 16:14:55 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 589 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20161223/60f8fd72/attachment.bin>
-------------- next part --------------
From fa5e24cb02fd88aa1b18d7906b9fa3da0c245025 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Fri, 23 Dec 2016 09:13:11 -0700
Subject: [PATCH] fix directory perms on recursive push

The server side handled it, but the client side just forgot to pass them
in.

Also, this commit gets rid of lxc's getOwner in favor of
shared.GetOwnerMode, since they were exactly the same implementation.

Closes #2759

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 client.go                | 15 +++++++++++----
 lxc/file.go              | 42 +++++++++++++++++++++++++++++++++++++++---
 lxc/file_unix.go         | 21 ---------------------
 lxc/file_windows.go      | 11 -----------
 test/suites/filemanip.sh |  3 +++
 5 files changed, 53 insertions(+), 39 deletions(-)
 delete mode 100644 lxc/file_unix.go
 delete mode 100644 lxc/file_windows.go

diff --git a/client.go b/client.go
index 4faf2e6..6d4a867 100644
--- a/client.go
+++ b/client.go
@@ -1768,7 +1768,7 @@ func (c *Client) PushFile(container string, p string, gid int, uid int, mode str
 	return err
 }
 
-func (c *Client) Mkdir(container string, p string, mode os.FileMode) error {
+func (c *Client) Mkdir(container string, p string, mode os.FileMode, uid int, gid int) error {
 	if c.Remote.Public {
 		return fmt.Errorf("This function isn't supported by public remotes.")
 	}
@@ -1784,6 +1784,12 @@ func (c *Client) Mkdir(container string, p string, mode os.FileMode) error {
 	req.Header.Set("User-Agent", version.UserAgent)
 	req.Header.Set("X-LXD-type", "directory")
 	req.Header.Set("X-LXD-mode", fmt.Sprintf("%04o", mode.Perm()))
+	if uid != -1 {
+		req.Header.Set("X-LXD-uid", strconv.FormatUint(uint64(uid), 10))
+	}
+	if gid != -1 {
+		req.Header.Set("X-LXD-gid", strconv.FormatUint(uint64(gid), 10))
+	}
 
 	raw, err := c.Http.Do(req)
 	if err != nil {
@@ -1794,7 +1800,7 @@ func (c *Client) Mkdir(container string, p string, mode os.FileMode) error {
 	return err
 }
 
-func (c *Client) MkdirP(container string, p string, mode os.FileMode) error {
+func (c *Client) MkdirP(container string, p string, mode os.FileMode, uid int, gid int) error {
 	if c.Remote.Public {
 		return fmt.Errorf("This function isn't supported by public remotes.")
 	}
@@ -1824,7 +1830,7 @@ func (c *Client) MkdirP(container string, p string, mode os.FileMode) error {
 
 	for ; i <= len(parts); i++ {
 		cur := filepath.Join(parts[:i]...)
-		if err := c.Mkdir(container, cur, mode); err != nil {
+		if err := c.Mkdir(container, cur, mode, uid, gid); err != nil {
 			return err
 		}
 	}
@@ -1851,7 +1857,8 @@ func (c *Client) RecursivePushFile(container string, source string, target strin
 
 		targetPath := path.Join(target, p[appendLen:])
 		if fInfo.IsDir() {
-			return c.Mkdir(container, targetPath, fInfo.Mode())
+			mode, uid, gid := shared.GetOwnerMode(fInfo)
+			return c.Mkdir(container, targetPath, mode, uid, gid)
 		}
 
 		f, err := os.Open(p)
diff --git a/lxc/file.go b/lxc/file.go
index a5167c6..1fbb65c 100644
--- a/lxc/file.go
+++ b/lxc/file.go
@@ -120,7 +120,18 @@ func (c *fileCmd) push(config *lxd.Config, send_file_perms bool, args []string)
 		}
 
 		if c.mkdirs {
-			if err := d.MkdirP(container, targetPath, mode); err != nil {
+			f, err := os.Open(args[0])
+			if err != nil {
+				return err
+			}
+			finfo, err := f.Stat()
+			f.Close()
+			if err != nil {
+				return err
+			}
+
+			mode, uid, gid := shared.GetOwnerMode(finfo)
+			if err := d.MkdirP(container, targetPath, mode, uid, gid); err != nil {
 				return err
 			}
 		}
@@ -173,14 +184,39 @@ func (c *fileCmd) push(config *lxd.Config, send_file_perms bool, args []string)
 		}
 
 		if c.mkdirs {
-			if err := d.MkdirP(container, path.Dir(fpath), mode); err != nil {
+			finfo, err := f.Stat()
+			if err != nil {
+				return err
+			}
+
+			if c.mode == "" || c.uid == -1 || c.gid == -1 {
+				dMode, dUid, dGid := shared.GetOwnerMode(finfo)
+				if c.mode == "" {
+					mode = dMode
+				}
+
+				if c.uid == -1 {
+					uid = dUid
+				}
+
+				if c.gid == -1 {
+					gid = dGid
+				}
+			}
+
+			if err := d.MkdirP(container, path.Dir(fpath), mode, uid, gid); err != nil {
 				return err
 			}
 		}
 
 		if send_file_perms {
 			if c.mode == "" || c.uid == -1 || c.gid == -1 {
-				fMode, fUid, fGid, err := c.getOwner(f)
+				finfo, err := f.Stat()
+				if err != nil {
+					return err
+				}
+
+				fMode, fUid, fGid := shared.GetOwnerMode(finfo)
 				if err != nil {
 					return err
 				}
diff --git a/lxc/file_unix.go b/lxc/file_unix.go
deleted file mode 100644
index 1cc6aba..0000000
--- a/lxc/file_unix.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// +build !windows
-
-package main
-
-import (
-	"os"
-	"syscall"
-)
-
-func (c *fileCmd) getOwner(f *os.File) (os.FileMode, int, int, error) {
-	fInfo, err := f.Stat()
-	if err != nil {
-		return os.FileMode(0), -1, -1, err
-	}
-
-	mode := fInfo.Mode()
-	uid := int(fInfo.Sys().(*syscall.Stat_t).Uid)
-	gid := int(fInfo.Sys().(*syscall.Stat_t).Gid)
-
-	return mode, uid, gid, nil
-}
diff --git a/lxc/file_windows.go b/lxc/file_windows.go
deleted file mode 100644
index c3bf927..0000000
--- a/lxc/file_windows.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// +build windows
-
-package main
-
-import (
-	"os"
-)
-
-func (c *fileCmd) getOwner(f *os.File) (os.FileMode, int, int, error) {
-	return os.FileMode(0), -1, -1, nil
-}
diff --git a/test/suites/filemanip.sh b/test/suites/filemanip.sh
index ab7ade6..afb27bf 100644
--- a/test/suites/filemanip.sh
+++ b/test/suites/filemanip.sh
@@ -22,6 +22,7 @@ test_filemanip() {
   # lxc {push|pull} -r
   mkdir "${TEST_DIR}"/source
   mkdir "${TEST_DIR}"/source/another_level
+  chown 1000:1000 "${TEST_DIR}"/source/another_level
   echo "foo" > "${TEST_DIR}"/source/foo
   echo "bar" > "${TEST_DIR}"/source/bar
 
@@ -29,6 +30,8 @@ test_filemanip() {
 
   [ "$(lxc exec filemanip -- stat -c "%u" /tmp/ptest/source)" = "$(id -u)" ]
   [ "$(lxc exec filemanip -- stat -c "%g" /tmp/ptest/source)" = "$(id -g)" ]
+  [ "$(lxc exec filemanip -- stat -c "%u" /tmp/ptest/source/another_level)" = "1000" ]
+  [ "$(lxc exec filemanip -- stat -c "%g" /tmp/ptest/source/another_level)" = "1000" ]
   [ "$(lxc exec filemanip -- stat -c "%a" /tmp/ptest/source)" = "755" ]
 
   lxc exec filemanip -- rm -rf /tmp/ptest/source


More information about the lxc-devel mailing list