github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/pkg/varlinkapi/transfers.go (about) 1 // +build varlink 2 3 package varlinkapi 4 5 import ( 6 "bufio" 7 "io" 8 "io/ioutil" 9 "os" 10 11 iopodman "github.com/containers/podman/v2/pkg/varlink" 12 "github.com/sirupsen/logrus" 13 ) 14 15 // SendFile allows a client to send a file to the varlink server 16 func (i *VarlinkAPI) SendFile(call iopodman.VarlinkCall, ftype string, length int64) error { 17 if !call.WantsUpgrade() { 18 return call.ReplyErrorOccurred("client must use upgraded connection to send files") 19 } 20 21 outputFile, err := ioutil.TempFile("", "varlink_send") 22 if err != nil { 23 return call.ReplyErrorOccurred(err.Error()) 24 } 25 defer outputFile.Close() 26 27 if err = call.ReplySendFile(outputFile.Name()); err != nil { 28 // If an error occurs while sending the reply, return the error 29 return err 30 } 31 32 writer := bufio.NewWriter(outputFile) 33 defer writer.Flush() 34 35 reader := call.Call.Reader 36 if _, err := io.CopyN(writer, reader, length); err != nil { 37 return err 38 } 39 40 logrus.Debugf("successfully received %s", outputFile.Name()) 41 // Send an ACK to the client 42 call.Call.Writer.WriteString(outputFile.Name() + ":") 43 call.Call.Writer.Flush() 44 return nil 45 46 } 47 48 // ReceiveFile allows the varlink server to send a file to a client 49 func (i *VarlinkAPI) ReceiveFile(call iopodman.VarlinkCall, filepath string, delete bool) error { 50 if !call.WantsUpgrade() { 51 return call.ReplyErrorOccurred("client must use upgraded connection to send files") 52 } 53 fs, err := os.Open(filepath) 54 if err != nil { 55 return call.ReplyErrorOccurred(err.Error()) 56 } 57 fileInfo, err := fs.Stat() 58 if err != nil { 59 return call.ReplyErrorOccurred(err.Error()) 60 } 61 62 // Send the file length down to client 63 // Varlink connection upgraded 64 if err = call.ReplyReceiveFile(fileInfo.Size()); err != nil { 65 // If an error occurs while sending the reply, return the error 66 return err 67 } 68 69 reader := bufio.NewReader(fs) 70 _, err = reader.WriteTo(call.Writer) 71 if err != nil { 72 return err 73 } 74 if delete { 75 if err := os.Remove(filepath); err != nil { 76 return err 77 } 78 } 79 return call.Writer.Flush() 80 }