| 
									
										
										
										
											2013-11-06 16:42:50 +08:00
										 |  |  | package sftp_test | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2018-01-12 10:24:04 +08:00
										 |  |  | 	"bufio" | 
					
						
							| 
									
										
										
										
											2014-09-30 06:43:45 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2018-01-12 10:24:04 +08:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2013-11-06 16:42:50 +08:00
										 |  |  | 	"log" | 
					
						
							| 
									
										
										
										
											2014-09-30 06:43:45 +08:00
										 |  |  | 	"os" | 
					
						
							|  |  |  | 	"os/exec" | 
					
						
							| 
									
										
										
										
											2017-06-19 09:46:58 +08:00
										 |  |  | 	"path" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2013-11-06 16:42:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-07 12:54:42 +08:00
										 |  |  | 	"github.com/pkg/sftp" | 
					
						
							|  |  |  | 	"golang.org/x/crypto/ssh" | 
					
						
							| 
									
										
										
										
											2013-11-06 16:42:50 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-23 07:37:25 +08:00
										 |  |  | func Example() { | 
					
						
							|  |  |  | 	var conn *ssh.Client | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-30 06:39:25 +08:00
										 |  |  | 	// open an SFTP session over an existing ssh connection.
 | 
					
						
							| 
									
										
										
										
											2020-05-28 20:42:41 +08:00
										 |  |  | 	client, err := sftp.NewClient(conn) | 
					
						
							| 
									
										
										
										
											2013-11-06 16:42:50 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-30 11:01:49 +08:00
										 |  |  | 	defer client.Close() | 
					
						
							| 
									
										
										
										
											2013-11-06 16:42:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// walk a directory
 | 
					
						
							| 
									
										
										
										
											2020-05-28 20:42:41 +08:00
										 |  |  | 	w := client.Walk("/home/user") | 
					
						
							| 
									
										
										
										
											2013-11-06 16:42:50 +08:00
										 |  |  | 	for w.Step() { | 
					
						
							|  |  |  | 		if w.Err() != nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		log.Println(w.Path()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// leave your mark
 | 
					
						
							| 
									
										
										
										
											2020-05-28 20:42:41 +08:00
										 |  |  | 	f, err := client.Create("hello.txt") | 
					
						
							| 
									
										
										
										
											2013-11-06 16:42:50 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if _, err := f.Write([]byte("Hello world!")); err != nil { | 
					
						
							|  |  |  | 		log.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-05 17:48:26 +08:00
										 |  |  | 	f.Close() | 
					
						
							| 
									
										
										
										
											2013-11-06 16:42:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-06 16:48:37 +08:00
										 |  |  | 	// check it's there
 | 
					
						
							| 
									
										
										
										
											2020-05-28 20:42:41 +08:00
										 |  |  | 	fi, err := client.Lstat("hello.txt") | 
					
						
							| 
									
										
										
										
											2013-11-06 16:42:50 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	log.Println(fi) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-09-30 06:43:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func ExampleNewClientPipe() { | 
					
						
							|  |  |  | 	// Connect to a remote host and request the sftp subsystem via the 'ssh'
 | 
					
						
							|  |  |  | 	// command.  This assumes that passwordless login is correctly configured.
 | 
					
						
							|  |  |  | 	cmd := exec.Command("ssh", "example.com", "-s", "sftp") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// send errors from ssh to stderr
 | 
					
						
							|  |  |  | 	cmd.Stderr = os.Stderr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// get stdin and stdout
 | 
					
						
							|  |  |  | 	wr, err := cmd.StdinPipe() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	rd, err := cmd.StdoutPipe() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// start the process
 | 
					
						
							|  |  |  | 	if err := cmd.Start(); err != nil { | 
					
						
							|  |  |  | 		log.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer cmd.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// open the SFTP session
 | 
					
						
							|  |  |  | 	client, err := sftp.NewClientPipe(rd, wr) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// read a directory
 | 
					
						
							|  |  |  | 	list, err := client.ReadDir("/") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// print contents
 | 
					
						
							|  |  |  | 	for _, item := range list { | 
					
						
							|  |  |  | 		fmt.Println(item.Name()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// close the connection
 | 
					
						
							|  |  |  | 	client.Close() | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-06-19 09:46:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func ExampleClient_Mkdir_parents() { | 
					
						
							|  |  |  | 	// Example of mimicing 'mkdir --parents'; I.E. recursively create
 | 
					
						
							|  |  |  | 	// directoryies and don't error if any directories already exists.
 | 
					
						
							|  |  |  | 	var conn *ssh.Client | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	client, err := sftp.NewClient(conn) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer client.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-18 09:04:12 +08:00
										 |  |  | 	sshFxFailure := uint32(4) | 
					
						
							| 
									
										
										
										
											2017-06-19 09:46:58 +08:00
										 |  |  | 	mkdirParents := func(client *sftp.Client, dir string) (err error) { | 
					
						
							|  |  |  | 		var parents string | 
					
						
							| 
									
										
										
										
											2018-01-12 10:24:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-18 09:04:12 +08:00
										 |  |  | 		if path.IsAbs(dir) { | 
					
						
							|  |  |  | 			// Otherwise, an absolute path given below would be turned in to a relative one
 | 
					
						
							|  |  |  | 			// by splitting on "/"
 | 
					
						
							|  |  |  | 			parents = "/" | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-01-12 10:24:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-19 09:46:58 +08:00
										 |  |  | 		for _, name := range strings.Split(dir, "/") { | 
					
						
							| 
									
										
										
										
											2017-08-18 09:04:12 +08:00
										 |  |  | 			if name == "" { | 
					
						
							|  |  |  | 				// Paths with double-/ in them should just move along
 | 
					
						
							|  |  |  | 				// this will also catch the case of the first character being a "/", i.e. an absolute path
 | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-06-19 09:46:58 +08:00
										 |  |  | 			parents = path.Join(parents, name) | 
					
						
							|  |  |  | 			err = client.Mkdir(parents) | 
					
						
							|  |  |  | 			if status, ok := err.(*sftp.StatusError); ok { | 
					
						
							| 
									
										
										
										
											2017-08-18 09:04:12 +08:00
										 |  |  | 				if status.Code == sshFxFailure { | 
					
						
							| 
									
										
										
										
											2017-06-19 09:46:58 +08:00
										 |  |  | 					var fi os.FileInfo | 
					
						
							|  |  |  | 					fi, err = client.Stat(parents) | 
					
						
							|  |  |  | 					if err == nil { | 
					
						
							|  |  |  | 						if !fi.IsDir() { | 
					
						
							| 
									
										
										
										
											2021-03-17 19:03:24 +08:00
										 |  |  | 							return fmt.Errorf("file exists: %s", parents) | 
					
						
							| 
									
										
										
										
											2017-06-19 09:46:58 +08:00
										 |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = mkdirParents(client, "/tmp/foo/bar") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-01-12 10:24:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func ExampleFile_ReadFrom_bufio() { | 
					
						
							|  |  |  | 	// Using Bufio to buffer writes going to an sftp.File won't buffer as it
 | 
					
						
							|  |  |  | 	// skips buffering if the underlying writer support ReadFrom. The
 | 
					
						
							|  |  |  | 	// workaround is to wrap your writer in a struct that only implements
 | 
					
						
							|  |  |  | 	// io.Writer.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// For background see github.com/pkg/sftp/issues/125
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var data_source io.Reader | 
					
						
							|  |  |  | 	var f *sftp.File | 
					
						
							|  |  |  | 	type writerOnly struct{ io.Writer } | 
					
						
							|  |  |  | 	bw := bufio.NewWriter(writerOnly{f}) // no ReadFrom()
 | 
					
						
							|  |  |  | 	bw.ReadFrom(data_source) | 
					
						
							|  |  |  | } |