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>
77 lines
1.4 KiB
Go
77 lines
1.4 KiB
Go
// +build linux
|
|
|
|
package fifo
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"sync"
|
|
"syscall"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
const O_PATH = 010000000
|
|
|
|
type handle struct {
|
|
f *os.File
|
|
dev uint64
|
|
ino uint64
|
|
closeOnce sync.Once
|
|
name string
|
|
}
|
|
|
|
func getHandle(fn string) (*handle, error) {
|
|
f, err := os.OpenFile(fn, O_PATH, 0)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed to open %v with O_PATH", fn)
|
|
}
|
|
|
|
var stat syscall.Stat_t
|
|
if err := syscall.Fstat(int(f.Fd()), &stat); err != nil {
|
|
f.Close()
|
|
return nil, errors.Wrapf(err, "failed to stat handle %v", f.Fd())
|
|
}
|
|
|
|
h := &handle{
|
|
f: f,
|
|
name: fn,
|
|
dev: uint64(stat.Dev),
|
|
ino: stat.Ino,
|
|
}
|
|
|
|
// check /proc just in case
|
|
if _, err := os.Stat(h.procPath()); err != nil {
|
|
f.Close()
|
|
return nil, errors.Wrapf(err, "couldn't stat %v", h.procPath())
|
|
}
|
|
|
|
return h, nil
|
|
}
|
|
|
|
func (h *handle) procPath() string {
|
|
return fmt.Sprintf("/proc/self/fd/%d", h.f.Fd())
|
|
}
|
|
|
|
func (h *handle) Name() string {
|
|
return h.name
|
|
}
|
|
|
|
func (h *handle) Path() (string, error) {
|
|
var stat syscall.Stat_t
|
|
if err := syscall.Stat(h.procPath(), &stat); err != nil {
|
|
return "", errors.Wrapf(err, "path %v could not be statted", h.procPath())
|
|
}
|
|
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
|
|
}
|
|
|
|
func (h *handle) Close() error {
|
|
h.closeOnce.Do(func() {
|
|
h.f.Close()
|
|
})
|
|
return nil
|
|
}
|