github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/varlinkapi/transfers.go (about)

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