[lxc-devel] [lxd/master] file: Implement retrieving symlinks

stgraber on Github lxc-bot at linuxcontainers.org
Thu Feb 8 23:35:20 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 371 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180208/2cc326a8/attachment.bin>
-------------- next part --------------
From cba0580e4733814478a41b4fdb67bcc0539dca1b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 8 Feb 2018 18:24:04 -0500
Subject: [PATCH] file: Implement retrieving symlinks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes: #4227

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 doc/api-extensions.md |  3 +++
 lxc/file.go           | 24 ++++++++++++++++++++++++
 lxd/container_file.go |  2 +-
 lxd/main_nsexec.go    | 19 +++++++++++++++++--
 shared/version/api.go |  1 +
 5 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 1ba3db34d..2091cc7f3 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -395,3 +395,6 @@ getting a stream of events over websocket.
 ## proxy
 This adds a new `proxy` device type to containers, allowing forwarding
 of connections between the host and container.
+
+## file\_get\_symlink
+This makes it possible to retrieve symlinks using the file API.
diff --git a/lxc/file.go b/lxc/file.go
index d0b5cb127..600a8ada7 100644
--- a/lxc/file.go
+++ b/lxc/file.go
@@ -110,6 +110,16 @@ func (c *fileCmd) recursivePullFile(d lxd.ContainerServer, container string, p s
 		if err != nil {
 			return err
 		}
+	} else if resp.Type == "symlink" {
+		linkTarget, err := ioutil.ReadAll(buf)
+		if err != nil {
+			return err
+		}
+
+		err = os.Symlink(strings.TrimSpace(string(linkTarget)), target)
+		if err != nil {
+			return err
+		}
 	} else {
 		return fmt.Errorf(i18n.G("Unknown file type '%s'"), resp.Type)
 	}
@@ -504,6 +514,20 @@ func (c *fileCmd) pull(conf *config.Config, args []string) error {
 		if targetPath == "-" {
 			f = os.Stdout
 		} else {
+			if resp.Type == "symlink" {
+				linkTarget, err := ioutil.ReadAll(buf)
+				if err != nil {
+					return err
+				}
+
+				err = os.Symlink(strings.TrimSpace(string(linkTarget)), targetPath)
+				if err != nil {
+					return err
+				}
+
+				continue
+			}
+
 			f, err = os.Create(targetPath)
 			if err != nil {
 				return err
diff --git a/lxd/container_file.go b/lxd/container_file.go
index a7f6974a8..0ac112449 100644
--- a/lxd/container_file.go
+++ b/lxd/container_file.go
@@ -65,7 +65,7 @@ func containerFileGet(c container, path string, r *http.Request) Response {
 		"X-LXD-type": type_,
 	}
 
-	if type_ == "file" {
+	if type_ == "file" || type_ == "symlink" {
 		// Make a file response struct
 		files := make([]fileResponseEntry, 1)
 		files[0].identifier = filepath.Base(path)
diff --git a/lxd/main_nsexec.go b/lxd/main_nsexec.go
index 65dcfd7b3..1af0a37c8 100644
--- a/lxd/main_nsexec.go
+++ b/lxd/main_nsexec.go
@@ -188,6 +188,7 @@ int manip_file_in_ns(char *rootfs, int pid, char *host, char *container, bool is
 	int exists = 1;
 	bool is_dir_manip = type != NULL && !strcmp(type, "directory");
 	bool is_symlink_manip = type != NULL && !strcmp(type, "symlink");
+	char link_target[PATH_MAX];
 
 	if (!is_dir_manip && !is_symlink_manip) {
 		host_fd = open(host, O_RDWR);
@@ -268,7 +269,7 @@ int manip_file_in_ns(char *rootfs, int pid, char *host, char *container, bool is
 		return 0;
 	}
 
-	if (stat(container, &st) < 0)
+	if (fstatat(AT_FDCWD, container, &st, AT_SYMLINK_NOFOLLOW) < 0)
 		exists = 0;
 
 	container_open_flags = O_RDWR;
@@ -283,6 +284,21 @@ int manip_file_in_ns(char *rootfs, int pid, char *host, char *container, bool is
 	if (exists && S_ISDIR(st.st_mode))
 		container_open_flags = O_DIRECTORY;
 
+	if (!is_put && exists && S_ISLNK(st.st_mode)) {
+		fprintf(stderr, "uid: %ld\n", (long)st.st_uid);
+		fprintf(stderr, "gid: %ld\n", (long)st.st_gid);
+		fprintf(stderr, "mode: %ld\n", (unsigned long)st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
+		fprintf(stderr, "type: symlink\n");
+
+		if (readlink(container, link_target, PATH_MAX) < 0) {
+			error("error: readlink");
+			goto close_host;
+		}
+
+		dprintf(host_fd, "%s\n", link_target);
+		goto close_container;
+	}
+
 	umask(0);
 	container_fd = open(container, container_open_flags, 0);
 	if (container_fd < 0) {
@@ -321,7 +337,6 @@ int manip_file_in_ns(char *rootfs, int pid, char *host, char *container, bool is
 		}
 		ret = 0;
 	} else {
-
 		if (fstat(container_fd, &st) < 0) {
 			error("error: stat");
 			goto close_container;
diff --git a/shared/version/api.go b/shared/version/api.go
index feb31aab8..f31b714fc 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -87,4 +87,5 @@ var APIExtensions = []string{
 	"maas_network",
 	"devlxd_events",
 	"proxy",
+	"file_get_symlink",
 }


More information about the lxc-devel mailing list