Merge pull request #791 from justincormack/unix_build_fixes

Partial port to Darwin and FreeBSD
This commit is contained in:
Derek McGowan 2017-05-04 10:23:48 -07:00 committed by GitHub
commit ae93c236ff
22 changed files with 357 additions and 125 deletions

View File

@ -1,3 +1,5 @@
// +build !windows
package archive
import (

14
archive/time_darwin.go Normal file
View File

@ -0,0 +1,14 @@
package archive
import (
"time"
"github.com/pkg/errors"
)
// as at MacOS 10.12 there is apparently no way to set timestamps
// with nanosecond precision. We could fall back to utimes/lutimes
// and lose the precision as a temporary workaround.
func chtimes(path string, atime, mtime time.Time) error {
return errors.New("OSX missing UtimesNanoAt")
}

View File

@ -1,3 +1,5 @@
// +build linux freebsd
package archive
import (

View File

@ -0,0 +1,7 @@
// +build darwin freebsd
package main
import (
_ "github.com/containerd/containerd/snapshot/naive"
)

View File

@ -0,0 +1,16 @@
package main
func defaultConfig() *config {
return &config{
Root: "/var/lib/containerd",
State: "/run/containerd",
GRPC: grpcConfig{
Address: "/run/containerd/containerd.sock",
},
Debug: debug{
Level: "info",
Address: "/run/containerd/debug.sock",
},
Snapshotter: "overlay",
}
}

View File

@ -1,4 +1,4 @@
// +build !windows
// +build darwin freebsd
package main
@ -13,6 +13,6 @@ func defaultConfig() *config {
Level: "info",
Address: "/run/containerd/debug.sock",
},
Snapshotter: "overlay",
Snapshotter: "naive",
}
}

View File

@ -0,0 +1,59 @@
package main
import (
"os"
"golang.org/x/sys/unix"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/reaper"
"github.com/containerd/containerd/sys"
"github.com/urfave/cli"
"google.golang.org/grpc"
)
const (
defaultConfigPath = "/etc/containerd/config.toml"
)
var (
handledSignals = []os.Signal{unix.SIGTERM, unix.SIGINT, unix.SIGUSR1, unix.SIGCHLD}
)
func platformInit(context *cli.Context) error {
if conf.Subreaper {
log.G(global).Info("setting subreaper...")
if err := sys.SetSubreaper(1); err != nil {
return err
}
}
if conf.OOMScore != 0 {
log.G(global).Infof("changing OOM score to %d", conf.OOMScore)
if err := sys.SetOOMScore(os.Getpid(), conf.OOMScore); err != nil {
return err
}
}
if err := os.MkdirAll(conf.State, 0750); err != nil {
return err
}
if err := os.Chown(conf.State, conf.GRPC.Uid, conf.GRPC.Gid); err != nil {
return err
}
return nil
}
func handleSignals(signals chan os.Signal, server *grpc.Server) error {
for s := range signals {
log.G(global).WithField("signal", s).Debug("received signal")
switch s {
case unix.SIGCHLD:
if err := reaper.Reap(); err != nil {
log.G(global).WithError(err).Error("reap containerd processes")
}
default:
server.Stop()
return nil
}
}
return nil
}

View File

@ -1,4 +1,4 @@
// +build !windows
// +build darwin freebsd
package main
@ -9,7 +9,6 @@ import (
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/reaper"
"github.com/containerd/containerd/sys"
"github.com/urfave/cli"
"google.golang.org/grpc"
)
@ -23,18 +22,6 @@ var (
)
func platformInit(context *cli.Context) error {
if conf.Subreaper {
log.G(global).Info("setting subreaper...")
if err := sys.SetSubreaper(1); err != nil {
return err
}
}
if conf.OOMScore != 0 {
log.G(global).Infof("changing OOM score to %d", conf.OOMScore)
if err := sys.SetOOMScore(os.Getpid(), conf.OOMScore); err != nil {
return err
}
}
if err := os.MkdirAll(conf.State, 0750); err != nil {
return err
}

View File

@ -1,4 +1,4 @@
// +build linux
// +build !windows
package main

45
cmd/ctr/signals_linux.go Normal file
View File

@ -0,0 +1,45 @@
package main
import (
"syscall"
"golang.org/x/sys/unix"
)
var signalMap = map[string]syscall.Signal{
"ABRT": unix.SIGABRT,
"ALRM": unix.SIGALRM,
"BUS": unix.SIGBUS,
"CHLD": unix.SIGCHLD,
"CLD": unix.SIGCLD,
"CONT": unix.SIGCONT,
"FPE": unix.SIGFPE,
"HUP": unix.SIGHUP,
"ILL": unix.SIGILL,
"INT": unix.SIGINT,
"IO": unix.SIGIO,
"IOT": unix.SIGIOT,
"KILL": unix.SIGKILL,
"PIPE": unix.SIGPIPE,
"POLL": unix.SIGPOLL,
"PROF": unix.SIGPROF,
"PWR": unix.SIGPWR,
"QUIT": unix.SIGQUIT,
"SEGV": unix.SIGSEGV,
"STKFLT": unix.SIGSTKFLT,
"STOP": unix.SIGSTOP,
"SYS": unix.SIGSYS,
"TERM": unix.SIGTERM,
"TRAP": unix.SIGTRAP,
"TSTP": unix.SIGTSTP,
"TTIN": unix.SIGTTIN,
"TTOU": unix.SIGTTOU,
"UNUSED": unix.SIGUNUSED,
"URG": unix.SIGURG,
"USR1": unix.SIGUSR1,
"USR2": unix.SIGUSR2,
"VTALRM": unix.SIGVTALRM,
"WINCH": unix.SIGWINCH,
"XCPU": unix.SIGXCPU,
"XFSZ": unix.SIGXFSZ,
}

42
cmd/ctr/signals_unix.go Normal file
View File

@ -0,0 +1,42 @@
// +build darwin freebsd
package main
import (
"syscall"
"golang.org/x/sys/unix"
)
var signalMap = map[string]syscall.Signal{
"ABRT": unix.SIGABRT,
"ALRM": unix.SIGALRM,
"BUS": unix.SIGBUS,
"CHLD": unix.SIGCHLD,
"CONT": unix.SIGCONT,
"FPE": unix.SIGFPE,
"HUP": unix.SIGHUP,
"ILL": unix.SIGILL,
"INT": unix.SIGINT,
"IO": unix.SIGIO,
"IOT": unix.SIGIOT,
"KILL": unix.SIGKILL,
"PIPE": unix.SIGPIPE,
"PROF": unix.SIGPROF,
"QUIT": unix.SIGQUIT,
"SEGV": unix.SIGSEGV,
"STOP": unix.SIGSTOP,
"SYS": unix.SIGSYS,
"TERM": unix.SIGTERM,
"TRAP": unix.SIGTRAP,
"TSTP": unix.SIGTSTP,
"TTIN": unix.SIGTTIN,
"TTOU": unix.SIGTTOU,
"URG": unix.SIGURG,
"USR1": unix.SIGUSR1,
"USR2": unix.SIGUSR2,
"VTALRM": unix.SIGVTALRM,
"WINCH": unix.SIGWINCH,
"XCPU": unix.SIGXCPU,
"XFSZ": unix.SIGXFSZ,
}

View File

@ -17,7 +17,6 @@ import (
"github.com/pkg/errors"
"github.com/tonistiigi/fifo"
"github.com/urfave/cli"
"golang.org/x/sys/unix"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
)
@ -100,41 +99,3 @@ func getGRPCConnection(context *cli.Context) (*grpc.ClientConn, error) {
grpcConn = conn
return grpcConn, nil
}
var signalMap = map[string]syscall.Signal{
"ABRT": unix.SIGABRT,
"ALRM": unix.SIGALRM,
"BUS": unix.SIGBUS,
"CHLD": unix.SIGCHLD,
"CLD": unix.SIGCLD,
"CONT": unix.SIGCONT,
"FPE": unix.SIGFPE,
"HUP": unix.SIGHUP,
"ILL": unix.SIGILL,
"INT": unix.SIGINT,
"IO": unix.SIGIO,
"IOT": unix.SIGIOT,
"KILL": unix.SIGKILL,
"PIPE": unix.SIGPIPE,
"POLL": unix.SIGPOLL,
"PROF": unix.SIGPROF,
"PWR": unix.SIGPWR,
"QUIT": unix.SIGQUIT,
"SEGV": unix.SIGSEGV,
"STKFLT": unix.SIGSTKFLT,
"STOP": unix.SIGSTOP,
"SYS": unix.SIGSYS,
"TERM": unix.SIGTERM,
"TRAP": unix.SIGTRAP,
"TSTP": unix.SIGTSTP,
"TTIN": unix.SIGTTIN,
"TTOU": unix.SIGTTOU,
"UNUSED": unix.SIGUNUSED,
"URG": unix.SIGURG,
"USR1": unix.SIGUSR1,
"USR2": unix.SIGUSR2,
"VTALRM": unix.SIGVTALRM,
"WINCH": unix.SIGWINCH,
"XCPU": unix.SIGXCPU,
"XFSZ": unix.SIGXFSZ,
}

15
content/store_linux.go Normal file
View File

@ -0,0 +1,15 @@
package content
import (
"os"
"syscall"
"time"
)
func getStartTime(fi os.FileInfo) time.Time {
if st, ok := fi.Sys().(*syscall.Stat_t); ok {
return time.Unix(int64(st.Ctim.Sec), int64(st.Ctim.Nsec))
}
return fi.ModTime()
}

View File

@ -1,4 +1,4 @@
// +build linux
// +build darwin freebsd
package content
@ -10,7 +10,7 @@ import (
func getStartTime(fi os.FileInfo) time.Time {
if st, ok := fi.Sys().(*syscall.Stat_t); ok {
return time.Unix(int64(st.Ctim.Sec), int64(st.Ctim.Nsec))
return time.Unix(int64(st.Ctimespec.Sec), int64(st.Ctimespec.Nsec))
}
return fi.ModTime()

65
fs/copy_unix.go Normal file
View File

@ -0,0 +1,65 @@
// +build darwin freebsd
package fs
import (
"io"
"os"
"syscall"
"github.com/containerd/continuity/sysx"
"github.com/pkg/errors"
)
func copyFileInfo(fi os.FileInfo, name string) error {
st := fi.Sys().(*syscall.Stat_t)
if err := os.Lchown(name, int(st.Uid), int(st.Gid)); err != nil {
return errors.Wrapf(err, "failed to chown %s", name)
}
if (fi.Mode() & os.ModeSymlink) != os.ModeSymlink {
if err := os.Chmod(name, fi.Mode()); err != nil {
return errors.Wrapf(err, "failed to chmod %s", name)
}
}
if err := syscall.UtimesNano(name, []syscall.Timespec{st.Atimespec, st.Mtimespec}); err != nil {
return errors.Wrapf(err, "failed to utime %s", name)
}
return nil
}
func copyFileContent(dst, src *os.File) error {
buf := bufferPool.Get().([]byte)
_, err := io.CopyBuffer(dst, src, buf)
bufferPool.Put(buf)
return err
}
func copyXAttrs(dst, src string) error {
xattrKeys, err := sysx.LListxattr(src)
if err != nil {
return errors.Wrapf(err, "failed to list xattrs on %s", src)
}
for _, xattr := range xattrKeys {
data, err := sysx.LGetxattr(src, xattr)
if err != nil {
return errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src)
}
if err := sysx.LSetxattr(dst, xattr, data, 0); err != nil {
return errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst)
}
}
return nil
}
func copyDevice(dst string, fi os.FileInfo) error {
st, ok := fi.Sys().(*syscall.Stat_t)
if !ok {
return errors.New("unsupported stat type")
}
return syscall.Mknod(dst, uint32(fi.Mode()), int(st.Rdev))
}

View File

@ -1,3 +1,5 @@
// +build !windows
package fs
import (

View File

@ -27,7 +27,7 @@ func diskUsage(roots ...string) (Usage, error) {
}
stat := fi.Sys().(*syscall.Stat_t)
inodes[inode{dev: stat.Dev, ino: stat.Ino}] = struct{}{}
inodes[inode{dev: uint64(stat.Dev), ino: stat.Ino}] = struct{}{}
size += fi.Size()
return nil
}); err != nil {

70
mount_linux.go Normal file
View File

@ -0,0 +1,70 @@
package containerd
import (
"strings"
"golang.org/x/sys/unix"
)
func (m *Mount) Mount(target string) error {
flags, data := parseMountOptions(m.Options)
return unix.Mount(m.Source, target, m.Type, uintptr(flags), data)
}
func Unmount(mount string, flags int) error {
return unix.Unmount(mount, flags)
}
// parseMountOptions takes fstab style mount options and parses them for
// use with a standard mount() syscall
func parseMountOptions(options []string) (int, string) {
var (
flag int
data []string
)
flags := map[string]struct {
clear bool
flag int
}{
"async": {true, unix.MS_SYNCHRONOUS},
"atime": {true, unix.MS_NOATIME},
"bind": {false, unix.MS_BIND},
"defaults": {false, 0},
"dev": {true, unix.MS_NODEV},
"diratime": {true, unix.MS_NODIRATIME},
"dirsync": {false, unix.MS_DIRSYNC},
"exec": {true, unix.MS_NOEXEC},
"mand": {false, unix.MS_MANDLOCK},
"noatime": {false, unix.MS_NOATIME},
"nodev": {false, unix.MS_NODEV},
"nodiratime": {false, unix.MS_NODIRATIME},
"noexec": {false, unix.MS_NOEXEC},
"nomand": {true, unix.MS_MANDLOCK},
"norelatime": {true, unix.MS_RELATIME},
"nostrictatime": {true, unix.MS_STRICTATIME},
"nosuid": {false, unix.MS_NOSUID},
"rbind": {false, unix.MS_BIND | unix.MS_REC},
"relatime": {false, unix.MS_RELATIME},
"remount": {false, unix.MS_REMOUNT},
"ro": {false, unix.MS_RDONLY},
"rw": {true, unix.MS_RDONLY},
"strictatime": {false, unix.MS_STRICTATIME},
"suid": {true, unix.MS_NOSUID},
"sync": {false, unix.MS_SYNCHRONOUS},
}
for _, o := range options {
// If the option does not exist in the flags table or the flag
// is not supported on the platform,
// then it is a data value for a specific fs type
if f, exists := flags[o]; exists && f.flag != 0 {
if f.clear {
flag &^= f.flag
} else {
flag |= f.flag
}
} else {
data = append(data, o)
}
}
return flag, strings.Join(data, ",")
}

View File

@ -1,72 +1,17 @@
// +build linux
// +build darwin freebsd
package containerd
import (
"strings"
import "github.com/pkg/errors"
"golang.org/x/sys/unix"
var (
ErrNotImplementOnUnix = errors.New("not implemented under unix")
)
func (m *Mount) Mount(target string) error {
flags, data := parseMountOptions(m.Options)
return unix.Mount(m.Source, target, m.Type, uintptr(flags), data)
return ErrNotImplementOnUnix
}
func Unmount(mount string, flags int) error {
return unix.Unmount(mount, flags)
}
// parseMountOptions takes fstab style mount options and parses them for
// use with a standard mount() syscall
func parseMountOptions(options []string) (int, string) {
var (
flag int
data []string
)
flags := map[string]struct {
clear bool
flag int
}{
"async": {true, unix.MS_SYNCHRONOUS},
"atime": {true, unix.MS_NOATIME},
"bind": {false, unix.MS_BIND},
"defaults": {false, 0},
"dev": {true, unix.MS_NODEV},
"diratime": {true, unix.MS_NODIRATIME},
"dirsync": {false, unix.MS_DIRSYNC},
"exec": {true, unix.MS_NOEXEC},
"mand": {false, unix.MS_MANDLOCK},
"noatime": {false, unix.MS_NOATIME},
"nodev": {false, unix.MS_NODEV},
"nodiratime": {false, unix.MS_NODIRATIME},
"noexec": {false, unix.MS_NOEXEC},
"nomand": {true, unix.MS_MANDLOCK},
"norelatime": {true, unix.MS_RELATIME},
"nostrictatime": {true, unix.MS_STRICTATIME},
"nosuid": {false, unix.MS_NOSUID},
"rbind": {false, unix.MS_BIND | unix.MS_REC},
"relatime": {false, unix.MS_RELATIME},
"remount": {false, unix.MS_REMOUNT},
"ro": {false, unix.MS_RDONLY},
"rw": {true, unix.MS_RDONLY},
"strictatime": {false, unix.MS_STRICTATIME},
"suid": {true, unix.MS_NOSUID},
"sync": {false, unix.MS_SYNCHRONOUS},
}
for _, o := range options {
// If the option does not exist in the flags table or the flag
// is not supported on the platform,
// then it is a data value for a specific fs type
if f, exists := flags[o]; exists && f.flag != 0 {
if f.clear {
flag &^= f.flag
} else {
flag |= f.flag
}
} else {
data = append(data, o)
}
}
return flag, strings.Join(data, ",")
return ErrNotImplementOnUnix
}

View File

@ -20,7 +20,7 @@ github.com/containerd/btrfs e9c546f46bccffefe71a6bc137e4c21b5503cc18
github.com/stretchr/testify v1.1.4
github.com/davecgh/go-spew v1.1.0
github.com/pmezard/go-difflib v1.0.0
github.com/tonistiigi/fifo fe870ccf293940774c2b44e23f6c71fff8f7547d
github.com/tonistiigi/fifo f071cd4a2739654fec4e768a14efd9332b3e8af1
github.com/urfave/cli 8ba6f23b6e36d03666a14bd9421f5e3efcb59aca
golang.org/x/net 8b4af36cd21a1f85a7484b49feb7c79363106d8e
google.golang.org/grpc v1.0.5

View File

@ -36,7 +36,7 @@ func getHandle(fn string) (*handle, error) {
h := &handle{
f: f,
name: fn,
dev: stat.Dev,
dev: uint64(stat.Dev),
ino: stat.Ino,
}
@ -62,7 +62,7 @@ func (h *handle) Path() (string, error) {
if err := syscall.Stat(h.procPath(), &stat); err != nil {
return "", errors.Wrapf(err, "path %v could not be statted", h.procPath())
}
if stat.Dev != h.dev || stat.Ino != h.ino {
if uint64(stat.Dev) != h.dev || stat.Ino != h.ino {
return "", errors.Errorf("failed to verify handle %v/%v %v/%v", stat.Dev, h.dev, stat.Ino, h.ino)
}
return h.procPath(), nil

View File

@ -23,7 +23,7 @@ func getHandle(fn string) (*handle, error) {
h := &handle{
fn: fn,
dev: uint64(stat.Dev),
ino: stat.Ino,
ino: uint64(stat.Ino),
}
return h, nil
@ -34,7 +34,7 @@ func (h *handle) Path() (string, error) {
if err := syscall.Stat(h.fn, &stat); err != nil {
return "", errors.Wrapf(err, "path %v could not be statted", h.fn)
}
if uint64(stat.Dev) != h.dev || stat.Ino != h.ino {
if uint64(stat.Dev) != h.dev || uint64(stat.Ino) != h.ino {
return "", errors.Errorf("failed to verify handle %v/%v %v/%v for %v", stat.Dev, h.dev, stat.Ino, h.ino, h.fn)
}
return h.fn, nil