-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsandboxfs.go
90 lines (72 loc) · 2.16 KB
/
sandboxfs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package sandboxfs
import (
"context"
"fmt"
"io"
"os"
"os/exec"
"sync"
"syscall"
)
// Sandboxfs represents an instance of sandboxfs being prepared or run. It
// submits mapping requests to the sandboxfs instance, and keeps track of
// the number of outstanding requests to track whether the filesystem is ready.
//
// A Sandboxfs cannot be reused after calling its Run method.
type Sandboxfs struct {
// Path to the sandboxfs binary
SandboxfsPath string
// Path to use as a mount point
MountPoint string
// Writer for the sandboxfs process's stderr
Stderr io.Writer
ctx context.Context
cancel context.CancelFunc
requests chan<- []byte
outstandingRequests sync.WaitGroup
cmd *exec.Cmd
stdin io.WriteCloser
stdout io.ReadCloser
started bool
unmountHandle *os.File
}
// Run starts sandboxfs and connects to it.
//
// The sandboxfs process is detached from the process group of the current
// process. Because of this, it is imperative to use UnmountOnExit or Unmount
// to shut down the sandboxfs process cleanly.
func (sfs *Sandboxfs) Run(ctx context.Context) error {
if sfs.started {
return fmt.Errorf("instance has already been started")
}
if sfs.SandboxfsPath == "" {
return fmt.Errorf("SandboxfsPath must be specified")
}
if sfs.MountPoint == "" {
return fmt.Errorf("MountPoint must be specified")
}
sfs.ctx, sfs.cancel = context.WithCancel(ctx)
sfs.started = true
requests := make(chan []byte)
sfs.requests = requests
sfs.cmd = exec.Command(sfs.SandboxfsPath, sfs.MountPoint)
sfs.cmd.Stderr = sfs.Stderr
// prevent sandboxfs from being terminated by detaching it from our
// process group. this is necessary for UnmountOnExit to work.
sfs.cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
var err error
sfs.stdin, err = sfs.cmd.StdinPipe()
if err != nil {
return fmt.Errorf("creating stdin pipe for sandboxfs: %v", err)
}
sfs.stdout, err = sfs.cmd.StdoutPipe()
if err != nil {
return fmt.Errorf("creating stdout pipe for sandboxfs: %v", err)
}
if err := sfs.cmd.Start(); err != nil {
return fmt.Errorf("starting sandboxfs: %v", err)
}
go sfs.mapHandler(requests)
go sfs.stdoutHandler()
return nil
}