github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/daemon/graphdriver/lcow/remotefs.go (about)

     1  //go:build windows
     2  // +build windows
     3  
     4  package lcow // import "github.com/docker/docker/daemon/graphdriver/lcow"
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"io"
    10  	"runtime"
    11  	"strings"
    12  	"sync"
    13  
    14  	"github.com/Microsoft/hcsshim"
    15  	"github.com/Microsoft/opengcs/service/gcsutils/remotefs"
    16  	"github.com/docker/docker/pkg/archive"
    17  	"github.com/docker/docker/pkg/containerfs"
    18  	"github.com/sirupsen/logrus"
    19  )
    20  
    21  type lcowfs struct {
    22  	root        string
    23  	d           *Driver
    24  	mappedDisks []hcsshim.MappedVirtualDisk
    25  	vmID        string
    26  	currentSVM  *serviceVM
    27  	sync.Mutex
    28  }
    29  
    30  var _ containerfs.ContainerFS = &lcowfs{}
    31  
    32  // ErrNotSupported is an error for unsupported operations in the remotefs
    33  var ErrNotSupported = fmt.Errorf("not supported")
    34  
    35  // Functions to implement the ContainerFS interface
    36  func (l *lcowfs) Path() string {
    37  	return l.root
    38  }
    39  
    40  func (l *lcowfs) ResolveScopedPath(path string, rawPath bool) (string, error) {
    41  	logrus.Debugf("remotefs.resolvescopedpath inputs: %s %s ", path, l.root)
    42  
    43  	arg1 := l.Join(l.root, path)
    44  	if !rawPath {
    45  		// The l.Join("/", path) will make path an absolute path and then clean it
    46  		// so if path = ../../X, it will become /X.
    47  		arg1 = l.Join(l.root, l.Join("/", path))
    48  	}
    49  	arg2 := l.root
    50  
    51  	output := &bytes.Buffer{}
    52  	if err := l.runRemoteFSProcess(nil, output, remotefs.ResolvePathCmd, arg1, arg2); err != nil {
    53  		return "", err
    54  	}
    55  
    56  	logrus.Debugf("remotefs.resolvescopedpath success. Output: %s\n", output.String())
    57  	return output.String(), nil
    58  }
    59  
    60  func (l *lcowfs) OS() string {
    61  	return "linux"
    62  }
    63  
    64  func (l *lcowfs) Architecture() string {
    65  	return runtime.GOARCH
    66  }
    67  
    68  // Other functions that are used by docker like the daemon Archiver/Extractor
    69  func (l *lcowfs) ExtractArchive(src io.Reader, dst string, opts *archive.TarOptions) error {
    70  	logrus.Debugf("remotefs.ExtractArchve inputs: %s %+v", dst, opts)
    71  
    72  	tarBuf := &bytes.Buffer{}
    73  	if err := remotefs.WriteTarOptions(tarBuf, opts); err != nil {
    74  		return fmt.Errorf("failed to marshall tar opts: %s", err)
    75  	}
    76  
    77  	input := io.MultiReader(tarBuf, src)
    78  	if err := l.runRemoteFSProcess(input, nil, remotefs.ExtractArchiveCmd, dst); err != nil {
    79  		return fmt.Errorf("failed to extract archive to %s: %s", dst, err)
    80  	}
    81  	return nil
    82  }
    83  
    84  func (l *lcowfs) ArchivePath(src string, opts *archive.TarOptions) (io.ReadCloser, error) {
    85  	logrus.Debugf("remotefs.ArchivePath: %s %+v", src, opts)
    86  
    87  	tarBuf := &bytes.Buffer{}
    88  	if err := remotefs.WriteTarOptions(tarBuf, opts); err != nil {
    89  		return nil, fmt.Errorf("failed to marshall tar opts: %s", err)
    90  	}
    91  
    92  	r, w := io.Pipe()
    93  	go func() {
    94  		defer w.Close()
    95  		if err := l.runRemoteFSProcess(tarBuf, w, remotefs.ArchivePathCmd, src); err != nil {
    96  			logrus.Debugf("REMOTEFS: Failed to extract archive: %s %+v %s", src, opts, err)
    97  		}
    98  	}()
    99  	return r, nil
   100  }
   101  
   102  // Helper functions
   103  func (l *lcowfs) startVM() error {
   104  	l.Lock()
   105  	defer l.Unlock()
   106  	if l.currentSVM != nil {
   107  		return nil
   108  	}
   109  
   110  	svm, err := l.d.startServiceVMIfNotRunning(l.vmID, l.mappedDisks, fmt.Sprintf("lcowfs.startVM"))
   111  	if err != nil {
   112  		return err
   113  	}
   114  
   115  	if err = svm.createUnionMount(l.root, l.mappedDisks...); err != nil {
   116  		return err
   117  	}
   118  	l.currentSVM = svm
   119  	return nil
   120  }
   121  
   122  func (l *lcowfs) runRemoteFSProcess(stdin io.Reader, stdout io.Writer, args ...string) error {
   123  	if err := l.startVM(); err != nil {
   124  		return err
   125  	}
   126  
   127  	// Append remotefs prefix and setup as a command line string
   128  	cmd := fmt.Sprintf("%s %s", remotefs.RemotefsCmd, strings.Join(args, " "))
   129  	stderr := &bytes.Buffer{}
   130  	if err := l.currentSVM.runProcess(cmd, stdin, stdout, stderr); err != nil {
   131  		return err
   132  	}
   133  
   134  	eerr, err := remotefs.ReadError(stderr)
   135  	if eerr != nil {
   136  		// Process returned an error so return that.
   137  		return remotefs.ExportedToError(eerr)
   138  	}
   139  	return err
   140  }