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 }