From 80de67534169f11d389a37e7bfd81c06dc27ddcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 28 Oct 2025 21:52:25 -0400 Subject: [PATCH 1/3] incus/file/pull: Respect target name for symlinks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber Sponsored-by: https://webdock.io --- cmd/incus/file.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/incus/file.go b/cmd/incus/file.go index 35c23956ccf..7933f4d398b 100644 --- a/cmd/incus/file.go +++ b/cmd/incus/file.go @@ -652,7 +652,7 @@ func (c *cmdFilePull) Run(cmd *cobra.Command, args []string) error { } if targetIsLink { - err = os.Symlink(linkName, srcInfo.Name()) + err = os.Symlink(linkName, targetPath) if err != nil { progress.Done("") return err From 9489d7a58d237a67c5ba84f5e6d9a18193e2bcc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 28 Oct 2025 21:57:00 -0400 Subject: [PATCH 2/3] incus/file/pull: Allow reading symlink content to stdout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber Sponsored-by: https://webdock.io --- cmd/incus/file.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cmd/incus/file.go b/cmd/incus/file.go index 7933f4d398b..b33581fdd48 100644 --- a/cmd/incus/file.go +++ b/cmd/incus/file.go @@ -571,11 +571,7 @@ func (c *cmdFilePull) Run(cmd *cobra.Command, args []string) error { return err } - if srcInfo.Mode()&os.ModeSymlink == os.ModeSymlink { - targetIsLink = true - } - - // Deal with recursion + // Deal with recursion. if srcInfo.IsDir() { if c.file.flagRecursive { if !util.PathExists(target) { @@ -598,6 +594,7 @@ func (c *cmdFilePull) Run(cmd *cobra.Command, args []string) error { return errors.New(i18n.G("Can't pull a directory without --recursive")) } + // Determine the target path. var targetPath string if targetIsDir { targetPath = filepath.Join(target, filepath.Base(pathSpec[1])) @@ -605,6 +602,12 @@ func (c *cmdFilePull) Run(cmd *cobra.Command, args []string) error { targetPath = target } + // Unless we're writing to stdout, symlinks get re-created as symlinks. + if srcInfo.Mode()&os.ModeSymlink == os.ModeSymlink && targetPath != "-" { + targetIsLink = true + } + + // Prepare target. var f *os.File var linkName string From 4d75826ff8bb13feefb78e0336119fb373cc6fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 28 Oct 2025 22:13:44 -0400 Subject: [PATCH 3/3] incus/file/push: Keep remote owner/mode when present and not overriden MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber Sponsored-by: https://webdock.io --- cmd/incus/file.go | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/cmd/incus/file.go b/cmd/incus/file.go index b33581fdd48..d5ebb797b3f 100644 --- a/cmd/incus/file.go +++ b/cmd/incus/file.go @@ -885,15 +885,19 @@ func (c *cmdFilePush) Run(cmd *cobra.Command, args []string) error { } } - // Transfer the files + // Transfer the files. args := incus.InstanceFileArgs{ UID: -1, GID: -1, Mode: -1, } + // Check if the path already exists. + _, err := sftpConn.Stat(fpath) + fileExists := err == nil + if !c.noModeChange { - if c.file.flagMode == "" || c.file.flagUID == -1 || c.file.flagGID == -1 { + if !fileExists && (c.file.flagMode == "" || c.file.flagUID == -1 || c.file.flagGID == -1) { finfo, err := f.Stat() if err != nil { return err @@ -914,9 +918,17 @@ func (c *cmdFilePush) Run(cmd *cobra.Command, args []string) error { } } - args.UID = int64(uid) - args.GID = int64(gid) - args.Mode = int(mode.Perm()) + if !fileExists || c.file.flagUID != -1 { + args.UID = int64(uid) + } + + if !fileExists || c.file.flagGID != -1 { + args.GID = int64(gid) + } + + if !fileExists || c.file.flagMode != "" { + args.Mode = int(mode.Perm()) + } } args.Type = "file"