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  }