Skip to content

Commit 97a91cd

Browse files
authored
Merge pull request #1592 from HassanAlsamahi/change-incus-file-pull-operation-to-sftp
incus/file/pull: Port to SFTP
2 parents 42e2ebb + b81177a commit 97a91cd

File tree

16 files changed

+3723
-3873
lines changed

16 files changed

+3723
-3873
lines changed

cmd/incus/file.go

+52-61
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,9 @@ func (c *cmdFilePull) Run(cmd *cobra.Command, args []string) error {
521521
target := filepath.Clean(args[len(args)-1])
522522

523523
targetIsDir := false
524-
sb, err := os.Stat(target)
524+
targetIsLink := false
525+
526+
targetInfo, err := os.Stat(target)
525527
if err != nil && !errors.Is(err, fs.ErrNotExist) {
526528
return err
527529
}
@@ -535,7 +537,7 @@ func (c *cmdFilePull) Run(cmd *cobra.Command, args []string) error {
535537
* 3. We are dealing with recursive copy
536538
*/
537539
if err == nil {
538-
targetIsDir = sb.IsDir()
540+
targetIsDir = targetInfo.IsDir()
539541
if !targetIsDir && len(args)-1 > 1 {
540542
return fmt.Errorf(i18n.G("More than one file to download, but target is not a directory"))
541543
}
@@ -559,19 +561,46 @@ func (c *cmdFilePull) Run(cmd *cobra.Command, args []string) error {
559561
return err
560562
}
561563

564+
sftpClients := map[string]*sftp.Client{}
565+
566+
defer func() {
567+
for _, sftpClient := range sftpClients {
568+
_ = sftpClient.Close()
569+
}
570+
}()
571+
562572
for _, resource := range resources {
563573
pathSpec := strings.SplitN(resource.name, "/", 2)
564574
if len(pathSpec) != 2 {
565575
return fmt.Errorf(i18n.G("Invalid source %s"), resource.name)
566576
}
567577

568-
buf, resp, err := fileGetWrapper(resource.server, pathSpec[0], pathSpec[1])
578+
sftpConn, ok := sftpClients[pathSpec[0]]
579+
if !ok {
580+
sftpConn, err = resource.server.GetInstanceFileSFTP(pathSpec[0])
581+
if err != nil {
582+
return err
583+
}
584+
585+
sftpClients[pathSpec[0]] = sftpConn
586+
}
587+
588+
src, err := sftpConn.Open(pathSpec[1])
569589
if err != nil {
570590
return err
571591
}
572592

593+
srcInfo, err := sftpConn.Lstat(pathSpec[1])
594+
if err != nil {
595+
return err
596+
}
597+
598+
if srcInfo.Mode()&os.ModeSymlink == os.ModeSymlink {
599+
targetIsLink = true
600+
}
601+
573602
// Deal with recursion
574-
if resp.Type == "directory" {
603+
if srcInfo.IsDir() {
575604
if c.file.flagRecursive {
576605
if !util.PathExists(target) {
577606
err := os.MkdirAll(target, DirMode)
@@ -600,56 +629,16 @@ func (c *cmdFilePull) Run(cmd *cobra.Command, args []string) error {
600629
targetPath = target
601630
}
602631

603-
logger.Infof("Pulling %s from %s (%s)", targetPath, pathSpec[1], resp.Type)
632+
var f *os.File
633+
var linkName string
604634

605-
if resp.Type == "symlink" {
606-
linkTarget, err := io.ReadAll(buf)
635+
if targetPath == "-" {
636+
f = os.Stdout
637+
} else if targetIsLink {
638+
linkName, err = sftpConn.ReadLink(pathSpec[1])
607639
if err != nil {
608640
return err
609641
}
610-
611-
// Follow the symlink
612-
if targetPath == "-" || c.file.flagRecursive {
613-
i := 0
614-
for {
615-
newPath := strings.TrimSuffix(string(linkTarget), "\n")
616-
if !strings.HasPrefix(newPath, "/") {
617-
newPath = filepath.Clean(filepath.Join(filepath.Dir(pathSpec[1]), newPath))
618-
}
619-
620-
buf, resp, err = resource.server.GetInstanceFile(pathSpec[0], newPath)
621-
if err != nil {
622-
return err
623-
}
624-
625-
if resp.Type != "symlink" {
626-
break
627-
}
628-
629-
i++
630-
if i > 255 {
631-
return fmt.Errorf(i18n.G("Too many links"))
632-
}
633-
634-
// Update link target for next iteration.
635-
linkTarget, err = io.ReadAll(buf)
636-
if err != nil {
637-
return err
638-
}
639-
}
640-
} else {
641-
err = os.Symlink(strings.TrimSpace(string(linkTarget)), targetPath)
642-
if err != nil {
643-
return err
644-
}
645-
646-
continue
647-
}
648-
}
649-
650-
var f *os.File
651-
if targetPath == "-" {
652-
f = os.Stdout
653642
} else {
654643
f, err = os.Create(targetPath)
655644
if err != nil {
@@ -658,7 +647,7 @@ func (c *cmdFilePull) Run(cmd *cobra.Command, args []string) error {
658647

659648
defer func() { _ = f.Close() }()
660649

661-
err = os.Chmod(targetPath, os.FileMode(resp.Mode))
650+
err = os.Chmod(targetPath, os.FileMode(srcInfo.Mode()))
662651
if err != nil {
663652
return err
664653
}
@@ -685,16 +674,18 @@ func (c *cmdFilePull) Run(cmd *cobra.Command, args []string) error {
685674
},
686675
}
687676

688-
_, err = io.Copy(writer, buf)
689-
if err != nil {
690-
progress.Done("")
691-
return err
692-
}
693-
694-
err = f.Close()
695-
if err != nil {
696-
progress.Done("")
697-
return err
677+
if targetIsLink {
678+
err = os.Symlink(linkName, srcInfo.Name())
679+
if err != nil {
680+
progress.Done("")
681+
return err
682+
}
683+
} else {
684+
_, err = io.Copy(writer, src)
685+
if err != nil {
686+
progress.Done("")
687+
return err
688+
}
698689
}
699690

700691
progress.Done("")

0 commit comments

Comments
 (0)