
This mainly fixes Linux vs generic Unix differences, with some differences between Darwin and Freebsd (which are close bit not identical). Should make fixing for other Unix platforms easier. Note there are not yet `runc` equivalents for these platforms; my current use case is image manipulation for the `moby` tool. However there is interest in OCI runtime ports for both platforms. Current status is that MacOS can build and run `ctr`, `dist` and `containerd` and some operations are supported. FreeBSD 11 still needs some more fixes to continuity for extended attributes. Signed-off-by: Justin Cormack <justin.cormack@docker.com>
102 lines
2.1 KiB
Go
102 lines
2.1 KiB
Go
// +build !windows
|
|
|
|
package main
|
|
|
|
import (
|
|
gocontext "context"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"net"
|
|
"os"
|
|
"sync"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/tonistiigi/fifo"
|
|
"github.com/urfave/cli"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/grpclog"
|
|
)
|
|
|
|
func prepareStdio(stdin, stdout, stderr string, console bool) (*sync.WaitGroup, error) {
|
|
var wg sync.WaitGroup
|
|
ctx := gocontext.Background()
|
|
|
|
f, err := fifo.OpenFifo(ctx, stdin, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer func(c io.Closer) {
|
|
if err != nil {
|
|
c.Close()
|
|
}
|
|
}(f)
|
|
go func(w io.WriteCloser) {
|
|
io.Copy(w, os.Stdin)
|
|
w.Close()
|
|
}(f)
|
|
|
|
f, err = fifo.OpenFifo(ctx, stdout, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer func(c io.Closer) {
|
|
if err != nil {
|
|
c.Close()
|
|
}
|
|
}(f)
|
|
wg.Add(1)
|
|
go func(r io.ReadCloser) {
|
|
io.Copy(os.Stdout, r)
|
|
r.Close()
|
|
wg.Done()
|
|
}(f)
|
|
|
|
f, err = fifo.OpenFifo(ctx, stderr, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer func(c io.Closer) {
|
|
if err != nil {
|
|
c.Close()
|
|
}
|
|
}(f)
|
|
if !console {
|
|
wg.Add(1)
|
|
go func(r io.ReadCloser) {
|
|
io.Copy(os.Stderr, r)
|
|
r.Close()
|
|
wg.Done()
|
|
}(f)
|
|
}
|
|
|
|
return &wg, nil
|
|
}
|
|
|
|
func getGRPCConnection(context *cli.Context) (*grpc.ClientConn, error) {
|
|
if grpcConn != nil {
|
|
return grpcConn, nil
|
|
}
|
|
|
|
bindSocket := context.GlobalString("address")
|
|
// reset the logger for grpc to log to dev/null so that it does not mess with our stdio
|
|
grpclog.SetLogger(log.New(ioutil.Discard, "", log.LstdFlags))
|
|
dialOpts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithTimeout(100 * time.Second)}
|
|
dialOpts = append(dialOpts,
|
|
grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
|
|
return net.DialTimeout("unix", bindSocket, timeout)
|
|
},
|
|
))
|
|
|
|
conn, err := grpc.Dial(fmt.Sprintf("unix://%s", bindSocket), dialOpts...)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed to dial %q", bindSocket)
|
|
}
|
|
|
|
grpcConn = conn
|
|
return grpcConn, nil
|
|
}
|