Merge pull request #172 from Random-Liu/fix-run-as-user
Fix run as user
This commit is contained in:
commit
8fd54d2f2d
@ -19,7 +19,6 @@ set -o pipefail
|
|||||||
source $(dirname "${BASH_SOURCE[0]}")/test-utils.sh
|
source $(dirname "${BASH_SOURCE[0]}")/test-utils.sh
|
||||||
|
|
||||||
DEFAULT_SKIP="\[Flaky\]|\[Slow\]|\[Serial\]"
|
DEFAULT_SKIP="\[Flaky\]|\[Slow\]|\[Serial\]"
|
||||||
DEFAULT_SKIP+="|runAsUser"
|
|
||||||
DEFAULT_SKIP+="|scheduling\sa\sGuaranteed\sPod"
|
DEFAULT_SKIP+="|scheduling\sa\sGuaranteed\sPod"
|
||||||
DEFAULT_SKIP+="|scheduling\sa\sBurstable\sPod"
|
DEFAULT_SKIP+="|scheduling\sa\sBurstable\sPod"
|
||||||
DEFAULT_SKIP+="|scheduling\sa\sBestEffort\sPod"
|
DEFAULT_SKIP+="|scheduling\sa\sBestEffort\sPod"
|
||||||
|
@ -140,16 +140,18 @@ func (c *criContainerdService) CreateContainer(ctx context.Context, r *runtime.C
|
|||||||
containerMetadataLabel: string(metaBytes),
|
containerMetadataLabel: string(metaBytes),
|
||||||
}
|
}
|
||||||
|
|
||||||
specOpts := containerd.WithSpec(spec)
|
var specOpts []containerd.SpecOpts
|
||||||
// Set container username. This could only be done by containerd, because it needs
|
// Set container username. This could only be done by containerd, because it needs
|
||||||
// access to the container rootfs. Pass user name to containerd, and let it overwrite
|
// access to the container rootfs. Pass user name to containerd, and let it overwrite
|
||||||
// the spec for us.
|
// the spec for us.
|
||||||
if username := config.GetLinux().GetSecurityContext().GetRunAsUsername(); username != "" {
|
if uid := config.GetLinux().GetSecurityContext().GetRunAsUser(); uid != nil {
|
||||||
specOpts = containerd.WithSpec(spec, containerd.WithUsername(username))
|
specOpts = append(specOpts, containerd.WithUserID(uint32(uid.GetValue())))
|
||||||
|
}
|
||||||
|
if username := config.GetLinux().GetSecurityContext().GetRunAsUsername(); username != "" {
|
||||||
|
specOpts = append(specOpts, containerd.WithUsername(username))
|
||||||
}
|
}
|
||||||
|
|
||||||
opts = append(opts,
|
opts = append(opts,
|
||||||
specOpts,
|
containerd.WithSpec(spec, specOpts...),
|
||||||
containerd.WithRuntime(defaultRuntime),
|
containerd.WithRuntime(defaultRuntime),
|
||||||
containerd.WithContainerLabels(labels))
|
containerd.WithContainerLabels(labels))
|
||||||
var cntr containerd.Container
|
var cntr containerd.Container
|
||||||
@ -270,12 +272,6 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3
|
|||||||
// Set namespaces, share namespace with sandbox container.
|
// Set namespaces, share namespace with sandbox container.
|
||||||
setOCINamespaces(&g, securityContext.GetNamespaceOptions(), sandboxPid)
|
setOCINamespaces(&g, securityContext.GetNamespaceOptions(), sandboxPid)
|
||||||
|
|
||||||
runAsUser := securityContext.GetRunAsUser()
|
|
||||||
if runAsUser != nil {
|
|
||||||
// TODO(random-liu): We should also set gid. Use containerd#1425 instead.
|
|
||||||
g.SetProcessUID(uint32(runAsUser.GetValue()))
|
|
||||||
}
|
|
||||||
|
|
||||||
supplementalGroups := securityContext.GetSupplementalGroups()
|
supplementalGroups := securityContext.GetSupplementalGroups()
|
||||||
for _, group := range supplementalGroups {
|
for _, group := range supplementalGroups {
|
||||||
g.AddProcessAdditionalGid(uint32(group))
|
g.AddProcessAdditionalGid(uint32(group))
|
||||||
|
@ -91,7 +91,6 @@ func getCreateContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandbox
|
|||||||
},
|
},
|
||||||
SupplementalGroups: []int64{1111, 2222},
|
SupplementalGroups: []int64{1111, 2222},
|
||||||
NoNewPrivs: true,
|
NoNewPrivs: true,
|
||||||
RunAsUser: &runtime.Int64Value{Value: 255},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -144,9 +143,6 @@ func getCreateContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandbox
|
|||||||
assert.NotContains(t, spec.Process.Capabilities.Permitted, "CAP_CHOWN")
|
assert.NotContains(t, spec.Process.Capabilities.Permitted, "CAP_CHOWN")
|
||||||
assert.NotContains(t, spec.Process.Capabilities.Ambient, "CAP_CHOWN")
|
assert.NotContains(t, spec.Process.Capabilities.Ambient, "CAP_CHOWN")
|
||||||
|
|
||||||
t.Logf("Check uid")
|
|
||||||
assert.EqualValues(t, spec.Process.User.UID, 255)
|
|
||||||
|
|
||||||
t.Logf("Check supplemental groups")
|
t.Logf("Check supplemental groups")
|
||||||
assert.Contains(t, spec.Process.User.AdditionalGids, uint32(1111))
|
assert.Contains(t, spec.Process.User.AdditionalGids, uint32(1111))
|
||||||
assert.Contains(t, spec.Process.User.AdditionalGids, uint32(2222))
|
assert.Contains(t, spec.Process.User.AdditionalGids, uint32(2222))
|
||||||
|
@ -126,8 +126,12 @@ func (c *criContainerdService) RunPodSandbox(ctx context.Context, r *runtime.Run
|
|||||||
sandboxMetadataLabel: string(metaBytes),
|
sandboxMetadataLabel: string(metaBytes),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var specOpts []containerd.SpecOpts
|
||||||
|
if uid := config.GetLinux().GetSecurityContext().GetRunAsUser(); uid != nil {
|
||||||
|
specOpts = append(specOpts, containerd.WithUserID(uint32(uid.GetValue())))
|
||||||
|
}
|
||||||
opts := []containerd.NewContainerOpts{
|
opts := []containerd.NewContainerOpts{
|
||||||
containerd.WithSpec(spec),
|
containerd.WithSpec(spec, specOpts...),
|
||||||
containerd.WithContainerLabels(labels),
|
containerd.WithContainerLabels(labels),
|
||||||
containerd.WithRuntime(defaultRuntime),
|
containerd.WithRuntime(defaultRuntime),
|
||||||
containerd.WithNewSnapshotView(id, image.Image)}
|
containerd.WithNewSnapshotView(id, image.Image)}
|
||||||
@ -268,12 +272,6 @@ func (c *criContainerdService) generateSandboxContainerSpec(id string, config *r
|
|||||||
|
|
||||||
// TODO(random-liu): [P1] Apply SeLinux options.
|
// TODO(random-liu): [P1] Apply SeLinux options.
|
||||||
|
|
||||||
runAsUser := securityContext.GetRunAsUser()
|
|
||||||
if runAsUser != nil {
|
|
||||||
// TODO(random-liu): We should also set gid. Use containerd#1425 instead.
|
|
||||||
g.SetProcessUID(uint32(runAsUser.GetValue()))
|
|
||||||
}
|
|
||||||
|
|
||||||
supplementalGroups := securityContext.GetSupplementalGroups()
|
supplementalGroups := securityContext.GetSupplementalGroups()
|
||||||
for _, group := range supplementalGroups {
|
for _, group := range supplementalGroups {
|
||||||
g.AddProcessAdditionalGid(uint32(group))
|
g.AddProcessAdditionalGid(uint32(group))
|
||||||
|
@ -128,16 +128,14 @@ func TestGenerateSandboxContainerSpec(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectErr: true,
|
expectErr: true,
|
||||||
},
|
},
|
||||||
"should set user correctly": {
|
"should set supplemental groups correctly": {
|
||||||
configChange: func(c *runtime.PodSandboxConfig) {
|
configChange: func(c *runtime.PodSandboxConfig) {
|
||||||
c.Linux.SecurityContext = &runtime.LinuxSandboxSecurityContext{
|
c.Linux.SecurityContext = &runtime.LinuxSandboxSecurityContext{
|
||||||
RunAsUser: &runtime.Int64Value{Value: 255},
|
|
||||||
SupplementalGroups: []int64{1111, 2222},
|
SupplementalGroups: []int64{1111, 2222},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
||||||
require.NotNil(t, spec.Process)
|
require.NotNil(t, spec.Process)
|
||||||
assert.EqualValues(t, spec.Process.User.UID, 255)
|
|
||||||
assert.Contains(t, spec.Process.User.AdditionalGids, uint32(1111))
|
assert.Contains(t, spec.Process.User.AdditionalGids, uint32(1111))
|
||||||
assert.Contains(t, spec.Process.User.AdditionalGids, uint32(2222))
|
assert.Contains(t, spec.Process.User.AdditionalGids, uint32(2222))
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
github.com/blang/semver v3.1.0
|
github.com/blang/semver v3.1.0
|
||||||
github.com/boltdb/bolt v1.3.0-58-ge9cf4fa
|
github.com/boltdb/bolt v1.3.0-58-ge9cf4fa
|
||||||
github.com/containerd/containerd a6ce1ef2a140d79856a8647e1d1ae5ac9ab581eb
|
github.com/containerd/containerd 360e46ddda1733c8e237b8ce5a24470ffa08d306
|
||||||
|
github.com/containerd/continuity cf279e6ac893682272b4479d4c67fd3abf878b4e
|
||||||
github.com/containerd/fifo fbfb6a11ec671efbe94ad1c12c2e98773f19e1e6
|
github.com/containerd/fifo fbfb6a11ec671efbe94ad1c12c2e98773f19e1e6
|
||||||
github.com/containernetworking/cni v0.6.0
|
github.com/containernetworking/cni v0.6.0
|
||||||
github.com/containernetworking/plugins v0.6.0
|
github.com/containernetworking/plugins v0.6.0
|
||||||
|
7
vendor/github.com/containerd/containerd/client.go
generated
vendored
7
vendor/github.com/containerd/containerd/client.go
generated
vendored
@ -353,6 +353,13 @@ func (c *Client) ListImages(ctx context.Context) ([]Image, error) {
|
|||||||
return images, nil
|
return images, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Events returns an event subscription for the provided filters
|
||||||
|
func (c *Client) Events(ctx context.Context, filters ...string) (eventsapi.Events_SubscribeClient, error) {
|
||||||
|
return c.EventService().Subscribe(ctx, &eventsapi.SubscribeRequest{
|
||||||
|
Filters: filters,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Close closes the clients connection to containerd
|
// Close closes the clients connection to containerd
|
||||||
func (c *Client) Close() error {
|
func (c *Client) Close() error {
|
||||||
return c.conn.Close()
|
return c.conn.Close()
|
||||||
|
30
vendor/github.com/containerd/containerd/container.go
generated
vendored
30
vendor/github.com/containerd/containerd/container.go
generated
vendored
@ -245,19 +245,7 @@ func (c *container) loadTask(ctx context.Context, ioAttach IOAttach) (Task, erro
|
|||||||
}
|
}
|
||||||
var i IO
|
var i IO
|
||||||
if ioAttach != nil {
|
if ioAttach != nil {
|
||||||
// get the existing fifo paths from the task information stored by the daemon
|
if i, err = attachExistingIO(response, ioAttach); err != nil {
|
||||||
paths := &FIFOSet{
|
|
||||||
Dir: getFifoDir([]string{
|
|
||||||
response.Process.Stdin,
|
|
||||||
response.Process.Stdout,
|
|
||||||
response.Process.Stderr,
|
|
||||||
}),
|
|
||||||
In: response.Process.Stdin,
|
|
||||||
Out: response.Process.Stdout,
|
|
||||||
Err: response.Process.Stderr,
|
|
||||||
Terminal: response.Process.Terminal,
|
|
||||||
}
|
|
||||||
if i, err = ioAttach(paths); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,6 +258,22 @@ func (c *container) loadTask(ctx context.Context, ioAttach IOAttach) (Task, erro
|
|||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func attachExistingIO(response *tasks.GetResponse, ioAttach IOAttach) (IO, error) {
|
||||||
|
// get the existing fifo paths from the task information stored by the daemon
|
||||||
|
paths := &FIFOSet{
|
||||||
|
Dir: getFifoDir([]string{
|
||||||
|
response.Process.Stdin,
|
||||||
|
response.Process.Stdout,
|
||||||
|
response.Process.Stderr,
|
||||||
|
}),
|
||||||
|
In: response.Process.Stdin,
|
||||||
|
Out: response.Process.Stdout,
|
||||||
|
Err: response.Process.Stderr,
|
||||||
|
Terminal: response.Process.Terminal,
|
||||||
|
}
|
||||||
|
return ioAttach(paths)
|
||||||
|
}
|
||||||
|
|
||||||
// getFifoDir looks for any non-empty path for a stdio fifo
|
// getFifoDir looks for any non-empty path for a stdio fifo
|
||||||
// and returns the dir for where it is located
|
// and returns the dir for where it is located
|
||||||
func getFifoDir(paths []string) string {
|
func getFifoDir(paths []string) string {
|
||||||
|
120
vendor/github.com/containerd/containerd/fs/copy.go
generated
vendored
Normal file
120
vendor/github.com/containerd/containerd/fs/copy.go
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
bufferPool = &sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return make([]byte, 32*1024)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// CopyDir copies the directory from src to dst.
|
||||||
|
// Most efficient copy of files is attempted.
|
||||||
|
func CopyDir(dst, src string) error {
|
||||||
|
inodes := map[uint64]string{}
|
||||||
|
return copyDirectory(dst, src, inodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyDirectory(dst, src string, inodes map[uint64]string) error {
|
||||||
|
stat, err := os.Stat(src)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to stat %s", src)
|
||||||
|
}
|
||||||
|
if !stat.IsDir() {
|
||||||
|
return errors.Errorf("source is not directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
if st, err := os.Stat(dst); err != nil {
|
||||||
|
if err := os.Mkdir(dst, stat.Mode()); err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to mkdir %s", dst)
|
||||||
|
}
|
||||||
|
} else if !st.IsDir() {
|
||||||
|
return errors.Errorf("cannot copy to non-directory: %s", dst)
|
||||||
|
} else {
|
||||||
|
if err := os.Chmod(dst, stat.Mode()); err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to chmod on %s", dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fis, err := ioutil.ReadDir(src)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to read %s", src)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := copyFileInfo(stat, dst); err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to copy file info for %s", dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fi := range fis {
|
||||||
|
source := filepath.Join(src, fi.Name())
|
||||||
|
target := filepath.Join(dst, fi.Name())
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case fi.IsDir():
|
||||||
|
if err := copyDirectory(target, source, inodes); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
case (fi.Mode() & os.ModeType) == 0:
|
||||||
|
link, err := getLinkSource(target, fi, inodes)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to get hardlink")
|
||||||
|
}
|
||||||
|
if link != "" {
|
||||||
|
if err := os.Link(link, target); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to create hard link")
|
||||||
|
}
|
||||||
|
} else if err := copyFile(source, target); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to copy files")
|
||||||
|
}
|
||||||
|
case (fi.Mode() & os.ModeSymlink) == os.ModeSymlink:
|
||||||
|
link, err := os.Readlink(source)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to read link: %s", source)
|
||||||
|
}
|
||||||
|
if err := os.Symlink(link, target); err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to create symlink: %s", target)
|
||||||
|
}
|
||||||
|
case (fi.Mode() & os.ModeDevice) == os.ModeDevice:
|
||||||
|
if err := copyDevice(target, fi); err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to create device")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// TODO: Support pipes and sockets
|
||||||
|
return errors.Wrapf(err, "unsupported mode %s", fi.Mode())
|
||||||
|
}
|
||||||
|
if err := copyFileInfo(fi, target); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to copy file info")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := copyXAttrs(target, source); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to copy xattrs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyFile(source, target string) error {
|
||||||
|
src, err := os.Open(source)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to open source %s", source)
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
tgt, err := os.Create(target)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to open target %s", target)
|
||||||
|
}
|
||||||
|
defer tgt.Close()
|
||||||
|
|
||||||
|
return copyFileContent(tgt, src)
|
||||||
|
}
|
83
vendor/github.com/containerd/containerd/fs/copy_linux.go
generated
vendored
Normal file
83
vendor/github.com/containerd/containerd/fs/copy_linux.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/sys"
|
||||||
|
"github.com/containerd/continuity/sysx"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timespec := []unix.Timespec{unix.Timespec(sys.StatAtime(st)), unix.Timespec(sys.StatMtime(st))}
|
||||||
|
if err := unix.UtimesNanoAt(unix.AT_FDCWD, name, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to utime %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyFileContent(dst, src *os.File) error {
|
||||||
|
st, err := src.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "unable to stat source")
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := unix.CopyFileRange(int(src.Fd()), nil, int(dst.Fd()), nil, int(st.Size()), 0)
|
||||||
|
if err != nil {
|
||||||
|
if err != unix.ENOSYS && err != unix.EXDEV {
|
||||||
|
return errors.Wrap(err, "copy file range failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := bufferPool.Get().([]byte)
|
||||||
|
_, err = io.CopyBuffer(dst, src, buf)
|
||||||
|
bufferPool.Put(buf)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if int64(n) != st.Size() {
|
||||||
|
return errors.Wrapf(err, "short copy: %d of %d", int64(n), st.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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 unix.Mknod(dst, uint32(fi.Mode()), int(st.Rdev))
|
||||||
|
}
|
68
vendor/github.com/containerd/containerd/fs/copy_unix.go
generated
vendored
Normal file
68
vendor/github.com/containerd/containerd/fs/copy_unix.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// +build solaris darwin freebsd
|
||||||
|
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/sys"
|
||||||
|
"github.com/containerd/continuity/sysx"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timespec := []syscall.Timespec{sys.StatAtime(st), sys.StatMtime(st)}
|
||||||
|
if err := syscall.UtimesNano(name, timespec); 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 unix.Mknod(dst, uint32(fi.Mode()), int(st.Rdev))
|
||||||
|
}
|
33
vendor/github.com/containerd/containerd/fs/copy_windows.go
generated
vendored
Normal file
33
vendor/github.com/containerd/containerd/fs/copy_windows.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func copyFileInfo(fi os.FileInfo, name string) error {
|
||||||
|
if err := os.Chmod(name, fi.Mode()); err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to chmod %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: copy windows specific metadata
|
||||||
|
|
||||||
|
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 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyDevice(dst string, fi os.FileInfo) error {
|
||||||
|
return errors.New("device copy not supported")
|
||||||
|
}
|
310
vendor/github.com/containerd/containerd/fs/diff.go
generated
vendored
Normal file
310
vendor/github.com/containerd/containerd/fs/diff.go
generated
vendored
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ChangeKind is the type of modification that
|
||||||
|
// a change is making.
|
||||||
|
type ChangeKind int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ChangeKindUnmodified represents an unmodified
|
||||||
|
// file
|
||||||
|
ChangeKindUnmodified = iota
|
||||||
|
|
||||||
|
// ChangeKindAdd represents an addition of
|
||||||
|
// a file
|
||||||
|
ChangeKindAdd
|
||||||
|
|
||||||
|
// ChangeKindModify represents a change to
|
||||||
|
// an existing file
|
||||||
|
ChangeKindModify
|
||||||
|
|
||||||
|
// ChangeKindDelete represents a delete of
|
||||||
|
// a file
|
||||||
|
ChangeKindDelete
|
||||||
|
)
|
||||||
|
|
||||||
|
func (k ChangeKind) String() string {
|
||||||
|
switch k {
|
||||||
|
case ChangeKindUnmodified:
|
||||||
|
return "unmodified"
|
||||||
|
case ChangeKindAdd:
|
||||||
|
return "add"
|
||||||
|
case ChangeKindModify:
|
||||||
|
return "modify"
|
||||||
|
case ChangeKindDelete:
|
||||||
|
return "delete"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change represents single change between a diff and its parent.
|
||||||
|
type Change struct {
|
||||||
|
Kind ChangeKind
|
||||||
|
Path string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeFunc is the type of function called for each change
|
||||||
|
// computed during a directory changes calculation.
|
||||||
|
type ChangeFunc func(ChangeKind, string, os.FileInfo, error) error
|
||||||
|
|
||||||
|
// Changes computes changes between two directories calling the
|
||||||
|
// given change function for each computed change. The first
|
||||||
|
// directory is intended to the base directory and second
|
||||||
|
// directory the changed directory.
|
||||||
|
//
|
||||||
|
// The change callback is called by the order of path names and
|
||||||
|
// should be appliable in that order.
|
||||||
|
// Due to this apply ordering, the following is true
|
||||||
|
// - Removed directory trees only create a single change for the root
|
||||||
|
// directory removed. Remaining changes are implied.
|
||||||
|
// - A directory which is modified to become a file will not have
|
||||||
|
// delete entries for sub-path items, their removal is implied
|
||||||
|
// by the removal of the parent directory.
|
||||||
|
//
|
||||||
|
// Opaque directories will not be treated specially and each file
|
||||||
|
// removed from the base directory will show up as a removal.
|
||||||
|
//
|
||||||
|
// File content comparisons will be done on files which have timestamps
|
||||||
|
// which may have been truncated. If either of the files being compared
|
||||||
|
// has a zero value nanosecond value, each byte will be compared for
|
||||||
|
// differences. If 2 files have the same seconds value but different
|
||||||
|
// nanosecond values where one of those values is zero, the files will
|
||||||
|
// be considered unchanged if the content is the same. This behavior
|
||||||
|
// is to account for timestamp truncation during archiving.
|
||||||
|
func Changes(ctx context.Context, a, b string, changeFn ChangeFunc) error {
|
||||||
|
if a == "" {
|
||||||
|
logrus.Debugf("Using single walk diff for %s", b)
|
||||||
|
return addDirChanges(ctx, changeFn, b)
|
||||||
|
} else if diffOptions := detectDirDiff(b, a); diffOptions != nil {
|
||||||
|
logrus.Debugf("Using single walk diff for %s from %s", diffOptions.diffDir, a)
|
||||||
|
return diffDirChanges(ctx, changeFn, a, diffOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Debugf("Using double walk diff for %s from %s", b, a)
|
||||||
|
return doubleWalkDiff(ctx, changeFn, a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func addDirChanges(ctx context.Context, changeFn ChangeFunc, root string) error {
|
||||||
|
return filepath.Walk(root, func(path string, f os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rebase path
|
||||||
|
path, err = filepath.Rel(root, path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
path = filepath.Join(string(os.PathSeparator), path)
|
||||||
|
|
||||||
|
// Skip root
|
||||||
|
if path == string(os.PathSeparator) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return changeFn(ChangeKindAdd, path, f, nil)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// diffDirOptions is used when the diff can be directly calculated from
|
||||||
|
// a diff directory to its base, without walking both trees.
|
||||||
|
type diffDirOptions struct {
|
||||||
|
diffDir string
|
||||||
|
skipChange func(string) (bool, error)
|
||||||
|
deleteChange func(string, string, os.FileInfo) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// diffDirChanges walks the diff directory and compares changes against the base.
|
||||||
|
func diffDirChanges(ctx context.Context, changeFn ChangeFunc, base string, o *diffDirOptions) error {
|
||||||
|
changedDirs := make(map[string]struct{})
|
||||||
|
return filepath.Walk(o.diffDir, func(path string, f os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rebase path
|
||||||
|
path, err = filepath.Rel(o.diffDir, path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
path = filepath.Join(string(os.PathSeparator), path)
|
||||||
|
|
||||||
|
// Skip root
|
||||||
|
if path == string(os.PathSeparator) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle opaqueness, start new double walker at this
|
||||||
|
// location to get deletes, and skip tree in single walker
|
||||||
|
|
||||||
|
if o.skipChange != nil {
|
||||||
|
if skip, err := o.skipChange(path); skip {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var kind ChangeKind
|
||||||
|
|
||||||
|
deletedFile, err := o.deleteChange(o.diffDir, path, f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find out what kind of modification happened
|
||||||
|
if deletedFile != "" {
|
||||||
|
path = deletedFile
|
||||||
|
kind = ChangeKindDelete
|
||||||
|
f = nil
|
||||||
|
} else {
|
||||||
|
// Otherwise, the file was added
|
||||||
|
kind = ChangeKindAdd
|
||||||
|
|
||||||
|
// ...Unless it already existed in a base, in which case, it's a modification
|
||||||
|
stat, err := os.Stat(filepath.Join(base, path))
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
// The file existed in the base, so that's a modification
|
||||||
|
|
||||||
|
// However, if it's a directory, maybe it wasn't actually modified.
|
||||||
|
// If you modify /foo/bar/baz, then /foo will be part of the changed files only because it's the parent of bar
|
||||||
|
if stat.IsDir() && f.IsDir() {
|
||||||
|
if f.Size() == stat.Size() && f.Mode() == stat.Mode() && sameFsTime(f.ModTime(), stat.ModTime()) {
|
||||||
|
// Both directories are the same, don't record the change
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kind = ChangeKindModify
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If /foo/bar/file.txt is modified, then /foo/bar must be part of the changed files.
|
||||||
|
// This block is here to ensure the change is recorded even if the
|
||||||
|
// modify time, mode and size of the parent directory in the rw and ro layers are all equal.
|
||||||
|
// Check https://github.com/docker/docker/pull/13590 for details.
|
||||||
|
if f.IsDir() {
|
||||||
|
changedDirs[path] = struct{}{}
|
||||||
|
}
|
||||||
|
if kind == ChangeKindAdd || kind == ChangeKindDelete {
|
||||||
|
parent := filepath.Dir(path)
|
||||||
|
if _, ok := changedDirs[parent]; !ok && parent != "/" {
|
||||||
|
pi, err := os.Stat(filepath.Join(o.diffDir, parent))
|
||||||
|
if err := changeFn(ChangeKindModify, parent, pi, err); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
changedDirs[parent] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changeFn(kind, path, f, nil)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// doubleWalkDiff walks both directories to create a diff
|
||||||
|
func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b string) (err error) {
|
||||||
|
g, ctx := errgroup.WithContext(ctx)
|
||||||
|
|
||||||
|
var (
|
||||||
|
c1 = make(chan *currentPath)
|
||||||
|
c2 = make(chan *currentPath)
|
||||||
|
|
||||||
|
f1, f2 *currentPath
|
||||||
|
rmdir string
|
||||||
|
)
|
||||||
|
g.Go(func() error {
|
||||||
|
defer close(c1)
|
||||||
|
return pathWalk(ctx, a, c1)
|
||||||
|
})
|
||||||
|
g.Go(func() error {
|
||||||
|
defer close(c2)
|
||||||
|
return pathWalk(ctx, b, c2)
|
||||||
|
})
|
||||||
|
g.Go(func() error {
|
||||||
|
for c1 != nil || c2 != nil {
|
||||||
|
if f1 == nil && c1 != nil {
|
||||||
|
f1, err = nextPath(ctx, c1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if f1 == nil {
|
||||||
|
c1 = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if f2 == nil && c2 != nil {
|
||||||
|
f2, err = nextPath(ctx, c2)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if f2 == nil {
|
||||||
|
c2 = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if f1 == nil && f2 == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var f os.FileInfo
|
||||||
|
k, p := pathChange(f1, f2)
|
||||||
|
switch k {
|
||||||
|
case ChangeKindAdd:
|
||||||
|
if rmdir != "" {
|
||||||
|
rmdir = ""
|
||||||
|
}
|
||||||
|
f = f2.f
|
||||||
|
f2 = nil
|
||||||
|
case ChangeKindDelete:
|
||||||
|
// Check if this file is already removed by being
|
||||||
|
// under of a removed directory
|
||||||
|
if rmdir != "" && strings.HasPrefix(f1.path, rmdir) {
|
||||||
|
f1 = nil
|
||||||
|
continue
|
||||||
|
} else if rmdir == "" && f1.f.IsDir() {
|
||||||
|
rmdir = f1.path + string(os.PathSeparator)
|
||||||
|
} else if rmdir != "" {
|
||||||
|
rmdir = ""
|
||||||
|
}
|
||||||
|
f1 = nil
|
||||||
|
case ChangeKindModify:
|
||||||
|
same, err := sameFile(f1, f2)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if f1.f.IsDir() && !f2.f.IsDir() {
|
||||||
|
rmdir = f1.path + string(os.PathSeparator)
|
||||||
|
} else if rmdir != "" {
|
||||||
|
rmdir = ""
|
||||||
|
}
|
||||||
|
f = f2.f
|
||||||
|
f1 = nil
|
||||||
|
f2 = nil
|
||||||
|
if same {
|
||||||
|
if !isLinked(f) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
k = ChangeKindUnmodified
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := changeFn(k, p, f, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return g.Wait()
|
||||||
|
}
|
103
vendor/github.com/containerd/containerd/fs/diff_unix.go
generated
vendored
Normal file
103
vendor/github.com/containerd/containerd/fs/diff_unix.go
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/containerd/continuity/sysx"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// whiteouts are files with a special meaning for the layered filesystem.
|
||||||
|
// Docker uses AUFS whiteout files inside exported archives. In other
|
||||||
|
// filesystems these files are generated/handled on tar creation/extraction.
|
||||||
|
|
||||||
|
// whiteoutPrefix prefix means file is a whiteout. If this is followed by a
|
||||||
|
// filename this means that file has been removed from the base layer.
|
||||||
|
const whiteoutPrefix = ".wh."
|
||||||
|
|
||||||
|
// whiteoutMetaPrefix prefix means whiteout has a special meaning and is not
|
||||||
|
// for removing an actual file. Normally these files are excluded from exported
|
||||||
|
// archives.
|
||||||
|
const whiteoutMetaPrefix = whiteoutPrefix + whiteoutPrefix
|
||||||
|
|
||||||
|
// whiteoutLinkDir is a directory AUFS uses for storing hardlink links to other
|
||||||
|
// layers. Normally these should not go into exported archives and all changed
|
||||||
|
// hardlinks should be copied to the top layer.
|
||||||
|
const whiteoutLinkDir = whiteoutMetaPrefix + "plnk"
|
||||||
|
|
||||||
|
// whiteoutOpaqueDir file means directory has been made opaque - meaning
|
||||||
|
// readdir calls to this directory do not follow to lower layers.
|
||||||
|
const whiteoutOpaqueDir = whiteoutMetaPrefix + ".opq"
|
||||||
|
|
||||||
|
// detectDirDiff returns diff dir options if a directory could
|
||||||
|
// be found in the mount info for upper which is the direct
|
||||||
|
// diff with the provided lower directory
|
||||||
|
func detectDirDiff(upper, lower string) *diffDirOptions {
|
||||||
|
// TODO: get mount options for upper
|
||||||
|
// TODO: detect AUFS
|
||||||
|
// TODO: detect overlay
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func aufsMetadataSkip(path string) (skip bool, err error) {
|
||||||
|
skip, err = filepath.Match(string(os.PathSeparator)+whiteoutMetaPrefix+"*", path)
|
||||||
|
if err != nil {
|
||||||
|
skip = true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func aufsDeletedFile(root, path string, fi os.FileInfo) (string, error) {
|
||||||
|
f := filepath.Base(path)
|
||||||
|
|
||||||
|
// If there is a whiteout, then the file was removed
|
||||||
|
if strings.HasPrefix(f, whiteoutPrefix) {
|
||||||
|
originalFile := f[len(whiteoutPrefix):]
|
||||||
|
return filepath.Join(filepath.Dir(path), originalFile), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// compareSysStat returns whether the stats are equivalent,
|
||||||
|
// whether the files are considered the same file, and
|
||||||
|
// an error
|
||||||
|
func compareSysStat(s1, s2 interface{}) (bool, error) {
|
||||||
|
ls1, ok := s1.(*syscall.Stat_t)
|
||||||
|
if !ok {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
ls2, ok := s2.(*syscall.Stat_t)
|
||||||
|
if !ok {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return ls1.Mode == ls2.Mode && ls1.Uid == ls2.Uid && ls1.Gid == ls2.Gid && ls1.Rdev == ls2.Rdev, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func compareCapabilities(p1, p2 string) (bool, error) {
|
||||||
|
c1, err := sysx.LGetxattr(p1, "security.capability")
|
||||||
|
if err != nil && err != unix.ENODATA {
|
||||||
|
return false, errors.Wrapf(err, "failed to get xattr for %s", p1)
|
||||||
|
}
|
||||||
|
c2, err := sysx.LGetxattr(p2, "security.capability")
|
||||||
|
if err != nil && err != unix.ENODATA {
|
||||||
|
return false, errors.Wrapf(err, "failed to get xattr for %s", p2)
|
||||||
|
}
|
||||||
|
return bytes.Equal(c1, c2), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isLinked(f os.FileInfo) bool {
|
||||||
|
s, ok := f.Sys().(*syscall.Stat_t)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return !f.IsDir() && s.Nlink > 1
|
||||||
|
}
|
21
vendor/github.com/containerd/containerd/fs/diff_windows.go
generated
vendored
Normal file
21
vendor/github.com/containerd/containerd/fs/diff_windows.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
func detectDirDiff(upper, lower string) *diffDirOptions {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func compareSysStat(s1, s2 interface{}) (bool, error) {
|
||||||
|
// TODO: Use windows specific sys type
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func compareCapabilities(p1, p2 string) (bool, error) {
|
||||||
|
// TODO: Use windows equivalent
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isLinked(os.FileInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
87
vendor/github.com/containerd/containerd/fs/dtype_linux.go
generated
vendored
Normal file
87
vendor/github.com/containerd/containerd/fs/dtype_linux.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func locateDummyIfEmpty(path string) (string, error) {
|
||||||
|
children, err := ioutil.ReadDir(path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if len(children) != 0 {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
dummyFile, err := ioutil.TempFile(path, "fsutils-dummy")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
name := dummyFile.Name()
|
||||||
|
err = dummyFile.Close()
|
||||||
|
return name, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SupportsDType returns whether the filesystem mounted on path supports d_type
|
||||||
|
func SupportsDType(path string) (bool, error) {
|
||||||
|
// locate dummy so that we have at least one dirent
|
||||||
|
dummy, err := locateDummyIfEmpty(path)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if dummy != "" {
|
||||||
|
defer os.Remove(dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
visited := 0
|
||||||
|
supportsDType := true
|
||||||
|
fn := func(ent *syscall.Dirent) bool {
|
||||||
|
visited++
|
||||||
|
if ent.Type == syscall.DT_UNKNOWN {
|
||||||
|
supportsDType = false
|
||||||
|
// stop iteration
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// continue iteration
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err = iterateReadDir(path, fn); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if visited == 0 {
|
||||||
|
return false, fmt.Errorf("did not hit any dirent during iteration %s", path)
|
||||||
|
}
|
||||||
|
return supportsDType, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func iterateReadDir(path string, fn func(*syscall.Dirent) bool) error {
|
||||||
|
d, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer d.Close()
|
||||||
|
fd := int(d.Fd())
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
for {
|
||||||
|
nbytes, err := syscall.ReadDirent(fd, buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if nbytes == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for off := 0; off < nbytes; {
|
||||||
|
ent := (*syscall.Dirent)(unsafe.Pointer(&buf[off]))
|
||||||
|
if stop := fn(ent); stop {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
off += int(ent.Reclen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
12
vendor/github.com/containerd/containerd/fs/du.go
generated
vendored
Normal file
12
vendor/github.com/containerd/containerd/fs/du.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
type Usage struct {
|
||||||
|
Inodes int64
|
||||||
|
Size int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiskUsage counts the number of inodes and disk usage for the resources under
|
||||||
|
// path.
|
||||||
|
func DiskUsage(roots ...string) (Usage, error) {
|
||||||
|
return diskUsage(roots...)
|
||||||
|
}
|
47
vendor/github.com/containerd/containerd/fs/du_unix.go
generated
vendored
Normal file
47
vendor/github.com/containerd/containerd/fs/du_unix.go
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func diskUsage(roots ...string) (Usage, error) {
|
||||||
|
type inode struct {
|
||||||
|
// TODO(stevvooe): Can probably reduce memory usage by not tracking
|
||||||
|
// device, but we can leave this right for now.
|
||||||
|
dev, ino uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
size int64
|
||||||
|
inodes = map[inode]struct{}{} // expensive!
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, root := range roots {
|
||||||
|
if err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
stat := fi.Sys().(*syscall.Stat_t)
|
||||||
|
|
||||||
|
inoKey := inode{dev: uint64(stat.Dev), ino: uint64(stat.Ino)}
|
||||||
|
if _, ok := inodes[inoKey]; !ok {
|
||||||
|
inodes[inoKey] = struct{}{}
|
||||||
|
size += fi.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return Usage{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Usage{
|
||||||
|
Inodes: int64(len(inodes)),
|
||||||
|
Size: size,
|
||||||
|
}, nil
|
||||||
|
}
|
33
vendor/github.com/containerd/containerd/fs/du_windows.go
generated
vendored
Normal file
33
vendor/github.com/containerd/containerd/fs/du_windows.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func diskUsage(roots ...string) (Usage, error) {
|
||||||
|
var (
|
||||||
|
size int64
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(stevvooe): Support inodes (or equivalent) for windows.
|
||||||
|
|
||||||
|
for _, root := range roots {
|
||||||
|
if err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
size += fi.Size()
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return Usage{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Usage{
|
||||||
|
Size: size,
|
||||||
|
}, nil
|
||||||
|
}
|
27
vendor/github.com/containerd/containerd/fs/hardlink.go
generated
vendored
Normal file
27
vendor/github.com/containerd/containerd/fs/hardlink.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
// GetLinkID returns an identifier representing the node a hardlink is pointing
|
||||||
|
// to. If the file is not hard linked then 0 will be returned.
|
||||||
|
func GetLinkInfo(fi os.FileInfo) (uint64, bool) {
|
||||||
|
return getLinkInfo(fi)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getLinkSource returns a path for the given name and
|
||||||
|
// file info to its link source in the provided inode
|
||||||
|
// map. If the given file name is not in the map and
|
||||||
|
// has other links, it is added to the inode map
|
||||||
|
// to be a source for other link locations.
|
||||||
|
func getLinkSource(name string, fi os.FileInfo, inodes map[uint64]string) (string, error) {
|
||||||
|
inode, isHardlink := getLinkInfo(fi)
|
||||||
|
if !isHardlink {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
path, ok := inodes[inode]
|
||||||
|
if !ok {
|
||||||
|
inodes[inode] = name
|
||||||
|
}
|
||||||
|
return path, nil
|
||||||
|
}
|
17
vendor/github.com/containerd/containerd/fs/hardlink_unix.go
generated
vendored
Normal file
17
vendor/github.com/containerd/containerd/fs/hardlink_unix.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getLinkInfo(fi os.FileInfo) (uint64, bool) {
|
||||||
|
s, ok := fi.Sys().(*syscall.Stat_t)
|
||||||
|
if !ok {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return uint64(s.Ino), !fi.IsDir() && s.Nlink > 1
|
||||||
|
}
|
7
vendor/github.com/containerd/containerd/fs/hardlink_windows.go
generated
vendored
Normal file
7
vendor/github.com/containerd/containerd/fs/hardlink_windows.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
func getLinkInfo(fi os.FileInfo) (uint64, bool) {
|
||||||
|
return 0, false
|
||||||
|
}
|
261
vendor/github.com/containerd/containerd/fs/path.go
generated
vendored
Normal file
261
vendor/github.com/containerd/containerd/fs/path.go
generated
vendored
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errTooManyLinks = errors.New("too many links")
|
||||||
|
)
|
||||||
|
|
||||||
|
type currentPath struct {
|
||||||
|
path string
|
||||||
|
f os.FileInfo
|
||||||
|
fullPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func pathChange(lower, upper *currentPath) (ChangeKind, string) {
|
||||||
|
if lower == nil {
|
||||||
|
if upper == nil {
|
||||||
|
panic("cannot compare nil paths")
|
||||||
|
}
|
||||||
|
return ChangeKindAdd, upper.path
|
||||||
|
}
|
||||||
|
if upper == nil {
|
||||||
|
return ChangeKindDelete, lower.path
|
||||||
|
}
|
||||||
|
// TODO: compare by directory
|
||||||
|
|
||||||
|
switch i := strings.Compare(lower.path, upper.path); {
|
||||||
|
case i < 0:
|
||||||
|
// File in lower that is not in upper
|
||||||
|
return ChangeKindDelete, lower.path
|
||||||
|
case i > 0:
|
||||||
|
// File in upper that is not in lower
|
||||||
|
return ChangeKindAdd, upper.path
|
||||||
|
default:
|
||||||
|
return ChangeKindModify, upper.path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sameFile(f1, f2 *currentPath) (bool, error) {
|
||||||
|
if os.SameFile(f1.f, f2.f) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
equalStat, err := compareSysStat(f1.f.Sys(), f2.f.Sys())
|
||||||
|
if err != nil || !equalStat {
|
||||||
|
return equalStat, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if eq, err := compareCapabilities(f1.fullPath, f2.fullPath); err != nil || !eq {
|
||||||
|
return eq, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not a directory also check size, modtime, and content
|
||||||
|
if !f1.f.IsDir() {
|
||||||
|
if f1.f.Size() != f2.f.Size() {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
t1 := f1.f.ModTime()
|
||||||
|
t2 := f2.f.ModTime()
|
||||||
|
|
||||||
|
if t1.Unix() != t2.Unix() {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the timestamp may have been truncated in one of the
|
||||||
|
// files, check content of file to determine difference
|
||||||
|
if t1.Nanosecond() == 0 || t2.Nanosecond() == 0 {
|
||||||
|
if f1.f.Size() > 0 {
|
||||||
|
eq, err := compareFileContent(f1.fullPath, f2.fullPath)
|
||||||
|
if err != nil || !eq {
|
||||||
|
return eq, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if t1.Nanosecond() != t2.Nanosecond() {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const compareChuckSize = 32 * 1024
|
||||||
|
|
||||||
|
// compareFileContent compares the content of 2 same sized files
|
||||||
|
// by comparing each byte.
|
||||||
|
func compareFileContent(p1, p2 string) (bool, error) {
|
||||||
|
f1, err := os.Open(p1)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer f1.Close()
|
||||||
|
f2, err := os.Open(p2)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer f2.Close()
|
||||||
|
|
||||||
|
b1 := make([]byte, compareChuckSize)
|
||||||
|
b2 := make([]byte, compareChuckSize)
|
||||||
|
for {
|
||||||
|
n1, err1 := f1.Read(b1)
|
||||||
|
if err1 != nil && err1 != io.EOF {
|
||||||
|
return false, err1
|
||||||
|
}
|
||||||
|
n2, err2 := f2.Read(b2)
|
||||||
|
if err2 != nil && err2 != io.EOF {
|
||||||
|
return false, err2
|
||||||
|
}
|
||||||
|
if n1 != n2 || !bytes.Equal(b1[:n1], b2[:n2]) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
if err1 == io.EOF && err2 == io.EOF {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func pathWalk(ctx context.Context, root string, pathC chan<- *currentPath) error {
|
||||||
|
return filepath.Walk(root, func(path string, f os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rebase path
|
||||||
|
path, err = filepath.Rel(root, path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
path = filepath.Join(string(os.PathSeparator), path)
|
||||||
|
|
||||||
|
// Skip root
|
||||||
|
if path == string(os.PathSeparator) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
p := ¤tPath{
|
||||||
|
path: path,
|
||||||
|
f: f,
|
||||||
|
fullPath: filepath.Join(root, path),
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
case pathC <- p:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func nextPath(ctx context.Context, pathC <-chan *currentPath) (*currentPath, error) {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil, ctx.Err()
|
||||||
|
case p := <-pathC:
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RootPath joins a path with a root, evaluating and bounding any
|
||||||
|
// symlink to the root directory.
|
||||||
|
func RootPath(root, path string) (string, error) {
|
||||||
|
if path == "" {
|
||||||
|
return root, nil
|
||||||
|
}
|
||||||
|
var linksWalked int // to protect against cycles
|
||||||
|
for {
|
||||||
|
i := linksWalked
|
||||||
|
newpath, err := walkLinks(root, path, &linksWalked)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
path = newpath
|
||||||
|
if i == linksWalked {
|
||||||
|
newpath = filepath.Join("/", newpath)
|
||||||
|
if path == newpath {
|
||||||
|
return filepath.Join(root, newpath), nil
|
||||||
|
}
|
||||||
|
path = newpath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func walkLink(root, path string, linksWalked *int) (newpath string, islink bool, err error) {
|
||||||
|
if *linksWalked > 255 {
|
||||||
|
return "", false, errTooManyLinks
|
||||||
|
}
|
||||||
|
|
||||||
|
path = filepath.Join("/", path)
|
||||||
|
if path == "/" {
|
||||||
|
return path, false, nil
|
||||||
|
}
|
||||||
|
realPath := filepath.Join(root, path)
|
||||||
|
|
||||||
|
fi, err := os.Lstat(realPath)
|
||||||
|
if err != nil {
|
||||||
|
// If path does not yet exist, treat as non-symlink
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return path, false, nil
|
||||||
|
}
|
||||||
|
return "", false, err
|
||||||
|
}
|
||||||
|
if fi.Mode()&os.ModeSymlink == 0 {
|
||||||
|
return path, false, nil
|
||||||
|
}
|
||||||
|
newpath, err = os.Readlink(realPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", false, err
|
||||||
|
}
|
||||||
|
if filepath.IsAbs(newpath) && strings.HasPrefix(newpath, root) {
|
||||||
|
newpath = newpath[:len(root)]
|
||||||
|
if !strings.HasPrefix(newpath, "/") {
|
||||||
|
newpath = "/" + newpath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*linksWalked++
|
||||||
|
return newpath, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func walkLinks(root, path string, linksWalked *int) (string, error) {
|
||||||
|
switch dir, file := filepath.Split(path); {
|
||||||
|
case dir == "":
|
||||||
|
newpath, _, err := walkLink(root, file, linksWalked)
|
||||||
|
return newpath, err
|
||||||
|
case file == "":
|
||||||
|
if os.IsPathSeparator(dir[len(dir)-1]) {
|
||||||
|
if dir == "/" {
|
||||||
|
return dir, nil
|
||||||
|
}
|
||||||
|
return walkLinks(root, dir[:len(dir)-1], linksWalked)
|
||||||
|
}
|
||||||
|
newpath, _, err := walkLink(root, dir, linksWalked)
|
||||||
|
return newpath, err
|
||||||
|
default:
|
||||||
|
newdir, err := walkLinks(root, dir, linksWalked)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
newpath, islink, err := walkLink(root, filepath.Join(newdir, file), linksWalked)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if !islink {
|
||||||
|
return newpath, nil
|
||||||
|
}
|
||||||
|
if filepath.IsAbs(newpath) {
|
||||||
|
return newpath, nil
|
||||||
|
}
|
||||||
|
return filepath.Join(newdir, newpath), nil
|
||||||
|
}
|
||||||
|
}
|
13
vendor/github.com/containerd/containerd/fs/time.go
generated
vendored
Normal file
13
vendor/github.com/containerd/containerd/fs/time.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// Gnu tar and the go tar writer don't have sub-second mtime
|
||||||
|
// precision, which is problematic when we apply changes via tar
|
||||||
|
// files, we handle this by comparing for exact times, *or* same
|
||||||
|
// second count and either a or b having exactly 0 nanoseconds
|
||||||
|
func sameFsTime(a, b time.Time) bool {
|
||||||
|
return a == b ||
|
||||||
|
(a.Unix() == b.Unix() &&
|
||||||
|
(a.Nanosecond() == 0 || b.Nanosecond() == 0))
|
||||||
|
}
|
2
vendor/github.com/containerd/containerd/process.go
generated
vendored
2
vendor/github.com/containerd/containerd/process.go
generated
vendored
@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/runtime"
|
"github.com/containerd/containerd/runtime"
|
||||||
"github.com/containerd/containerd/typeurl"
|
"github.com/containerd/containerd/typeurl"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -77,7 +76,6 @@ type process struct {
|
|||||||
task *task
|
task *task
|
||||||
pid uint32
|
pid uint32
|
||||||
io IO
|
io IO
|
||||||
spec *specs.Process
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *process) ID() string {
|
func (p *process) ID() string {
|
||||||
|
80
vendor/github.com/containerd/containerd/spec_opts_unix.go
generated
vendored
80
vendor/github.com/containerd/containerd/spec_opts_unix.go
generated
vendored
@ -16,6 +16,7 @@ import (
|
|||||||
|
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/fs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
"github.com/opencontainers/image-spec/identity"
|
"github.com/opencontainers/image-spec/identity"
|
||||||
@ -94,9 +95,6 @@ func WithImageConfig(i Image) SpecOpts {
|
|||||||
return fmt.Errorf("unknown image config media type %s", ic.MediaType)
|
return fmt.Errorf("unknown image config media type %s", ic.MediaType)
|
||||||
}
|
}
|
||||||
s.Process.Env = append(s.Process.Env, config.Env...)
|
s.Process.Env = append(s.Process.Env, config.Env...)
|
||||||
var (
|
|
||||||
uid, gid uint32
|
|
||||||
)
|
|
||||||
cmd := config.Cmd
|
cmd := config.Cmd
|
||||||
s.Process.Args = append(config.Entrypoint, cmd...)
|
s.Process.Args = append(config.Entrypoint, cmd...)
|
||||||
if config.User != "" {
|
if config.User != "" {
|
||||||
@ -111,22 +109,24 @@ func WithImageConfig(i Image) SpecOpts {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
uid, gid = uint32(v), uint32(v)
|
if err := WithUserID(uint32(v))(ctx, client, c, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case 2:
|
case 2:
|
||||||
v, err := strconv.ParseUint(parts[0], 0, 10)
|
v, err := strconv.ParseUint(parts[0], 0, 10)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
uid = uint32(v)
|
uid := uint32(v)
|
||||||
if v, err = strconv.ParseUint(parts[1], 0, 10); err != nil {
|
if v, err = strconv.ParseUint(parts[1], 0, 10); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gid = uint32(v)
|
gid := uint32(v)
|
||||||
|
s.Process.User.UID, s.Process.User.GID = uid, gid
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid USER value %s", config.User)
|
return fmt.Errorf("invalid USER value %s", config.User)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.Process.User.UID, s.Process.User.GID = uid, gid
|
|
||||||
cwd := config.WorkingDir
|
cwd := config.WorkingDir
|
||||||
if cwd == "" {
|
if cwd == "" {
|
||||||
cwd = "/"
|
cwd = "/"
|
||||||
@ -287,8 +287,8 @@ func WithNamespacedCgroup() SpecOpts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithUserIDs allows the UID and GID for the Process to be set
|
// WithUidGid allows the UID and GID for the Process to be set
|
||||||
func WithUserIDs(uid, gid uint32) SpecOpts {
|
func WithUidGid(uid, gid uint32) SpecOpts {
|
||||||
return func(_ context.Context, _ *Client, _ *containers.Container, s *specs.Spec) error {
|
return func(_ context.Context, _ *Client, _ *containers.Container, s *specs.Spec) error {
|
||||||
s.Process.User.UID = uid
|
s.Process.User.UID = uid
|
||||||
s.Process.User.GID = gid
|
s.Process.User.GID = gid
|
||||||
@ -296,9 +296,61 @@ func WithUserIDs(uid, gid uint32) SpecOpts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithUserID sets the correct UID and GID for the container based
|
||||||
|
// on the image's /etc/passwd contents. If uid is not found in
|
||||||
|
// /etc/passwd, it sets uid but leaves gid 0, and not returns error.
|
||||||
|
func WithUserID(uid uint32) SpecOpts {
|
||||||
|
return func(ctx context.Context, client *Client, c *containers.Container, s *specs.Spec) error {
|
||||||
|
if c.Snapshotter == "" {
|
||||||
|
return errors.Errorf("no snapshotter set for container")
|
||||||
|
}
|
||||||
|
if c.RootFS == "" {
|
||||||
|
return errors.Errorf("rootfs not created for container")
|
||||||
|
}
|
||||||
|
snapshotter := client.SnapshotService(c.Snapshotter)
|
||||||
|
mounts, err := snapshotter.Mounts(ctx, c.RootFS)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
root, err := ioutil.TempDir("", "ctd-username")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(root)
|
||||||
|
for _, m := range mounts {
|
||||||
|
if err := m.Mount(root); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer unix.Unmount(root, 0)
|
||||||
|
ppath, err := fs.RootPath(root, "/etc/passwd")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f, err := os.Open(ppath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
users, err := user.ParsePasswdFilter(f, func(u user.User) bool {
|
||||||
|
return u.Uid == int(uid)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(users) == 0 {
|
||||||
|
s.Process.User.UID = uid
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
u := users[0]
|
||||||
|
s.Process.User.UID, s.Process.User.GID = uint32(u.Uid), uint32(u.Gid)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithUsername sets the correct UID and GID for the container
|
// WithUsername sets the correct UID and GID for the container
|
||||||
// based on the the image's /etc/passwd contents.
|
// based on the the image's /etc/passwd contents. If the username
|
||||||
// id is the snapshot id that is used
|
// is not found in /etc/passwd, it returns error.
|
||||||
func WithUsername(username string) SpecOpts {
|
func WithUsername(username string) SpecOpts {
|
||||||
return func(ctx context.Context, client *Client, c *containers.Container, s *specs.Spec) error {
|
return func(ctx context.Context, client *Client, c *containers.Container, s *specs.Spec) error {
|
||||||
if c.Snapshotter == "" {
|
if c.Snapshotter == "" {
|
||||||
@ -323,7 +375,11 @@ func WithUsername(username string) SpecOpts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
defer unix.Unmount(root, 0)
|
defer unix.Unmount(root, 0)
|
||||||
f, err := os.Open(filepath.Join(root, "/etc/passwd"))
|
ppath, err := fs.RootPath(root, "/etc/passwd")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f, err := os.Open(ppath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
20
vendor/github.com/containerd/containerd/sys/epoll.go
generated
vendored
Normal file
20
vendor/github.com/containerd/containerd/sys/epoll.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
|
package sys
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
// EpollCreate1 directly calls unix.EpollCreate1
|
||||||
|
func EpollCreate1(flag int) (int, error) {
|
||||||
|
return unix.EpollCreate1(flag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EpollCtl directly calls unix.EpollCtl
|
||||||
|
func EpollCtl(epfd int, op int, fd int, event *unix.EpollEvent) error {
|
||||||
|
return unix.EpollCtl(epfd, op, fd, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EpollWait directly calls unix.EpollWait
|
||||||
|
func EpollWait(epfd int, events []unix.EpollEvent, msec int) (int, error) {
|
||||||
|
return unix.EpollWait(epfd, events, msec)
|
||||||
|
}
|
18
vendor/github.com/containerd/containerd/sys/fds.go
generated
vendored
Normal file
18
vendor/github.com/containerd/containerd/sys/fds.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// +build !windows,!darwin
|
||||||
|
|
||||||
|
package sys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetOpenFds returns the number of open fds for the process provided by pid
|
||||||
|
func GetOpenFds(pid int) (int, error) {
|
||||||
|
dirs, err := ioutil.ReadDir(filepath.Join("/proc", strconv.Itoa(pid), "fd"))
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
return len(dirs), nil
|
||||||
|
}
|
236
vendor/github.com/containerd/containerd/sys/filesys_windows.go
generated
vendored
Normal file
236
vendor/github.com/containerd/containerd/sys/filesys_windows.go
generated
vendored
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package sys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
winio "github.com/Microsoft/go-winio"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MkdirAllWithACL is a wrapper for MkdirAll that creates a directory
|
||||||
|
// ACL'd for Builtin Administrators and Local System.
|
||||||
|
func MkdirAllWithACL(path string, perm os.FileMode) error {
|
||||||
|
return mkdirall(path, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MkdirAll implementation that is volume path aware for Windows.
|
||||||
|
func MkdirAll(path string, _ os.FileMode) error {
|
||||||
|
return mkdirall(path, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mkdirall is a custom version of os.MkdirAll modified for use on Windows
|
||||||
|
// so that it is both volume path aware, and can create a directory with
|
||||||
|
// a DACL.
|
||||||
|
func mkdirall(path string, adminAndLocalSystem bool) error {
|
||||||
|
if re := regexp.MustCompile(`^\\\\\?\\Volume{[a-z0-9-]+}$`); re.MatchString(path) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The rest of this method is largely copied from os.MkdirAll and should be kept
|
||||||
|
// as-is to ensure compatibility.
|
||||||
|
|
||||||
|
// Fast path: if we can tell whether path is a directory or file, stop with success or error.
|
||||||
|
dir, err := os.Stat(path)
|
||||||
|
if err == nil {
|
||||||
|
if dir.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &os.PathError{
|
||||||
|
Op: "mkdir",
|
||||||
|
Path: path,
|
||||||
|
Err: syscall.ENOTDIR,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slow path: make sure parent exists and then call Mkdir for path.
|
||||||
|
i := len(path)
|
||||||
|
for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator.
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
|
||||||
|
j := i
|
||||||
|
for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element.
|
||||||
|
j--
|
||||||
|
}
|
||||||
|
|
||||||
|
if j > 1 {
|
||||||
|
// Create parent
|
||||||
|
err = mkdirall(path[0:j-1], false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parent now exists; invoke os.Mkdir or mkdirWithACL and use its result.
|
||||||
|
if adminAndLocalSystem {
|
||||||
|
err = mkdirWithACL(path)
|
||||||
|
} else {
|
||||||
|
err = os.Mkdir(path, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// Handle arguments like "foo/." by
|
||||||
|
// double-checking that directory doesn't exist.
|
||||||
|
dir, err1 := os.Lstat(path)
|
||||||
|
if err1 == nil && dir.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mkdirWithACL creates a new directory. If there is an error, it will be of
|
||||||
|
// type *PathError. .
|
||||||
|
//
|
||||||
|
// This is a modified and combined version of os.Mkdir and syscall.Mkdir
|
||||||
|
// in golang to cater for creating a directory am ACL permitting full
|
||||||
|
// access, with inheritance, to any subfolder/file for Built-in Administrators
|
||||||
|
// and Local System.
|
||||||
|
func mkdirWithACL(name string) error {
|
||||||
|
sa := syscall.SecurityAttributes{Length: 0}
|
||||||
|
sddl := "D:P(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)"
|
||||||
|
sd, err := winio.SddlToSecurityDescriptor(sddl)
|
||||||
|
if err != nil {
|
||||||
|
return &os.PathError{Op: "mkdir", Path: name, Err: err}
|
||||||
|
}
|
||||||
|
sa.Length = uint32(unsafe.Sizeof(sa))
|
||||||
|
sa.InheritHandle = 1
|
||||||
|
sa.SecurityDescriptor = uintptr(unsafe.Pointer(&sd[0]))
|
||||||
|
|
||||||
|
namep, err := syscall.UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return &os.PathError{Op: "mkdir", Path: name, Err: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
e := syscall.CreateDirectory(namep, &sa)
|
||||||
|
if e != nil {
|
||||||
|
return &os.PathError{Op: "mkdir", Path: name, Err: e}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAbs is a platform-specific wrapper for filepath.IsAbs. On Windows,
|
||||||
|
// golang filepath.IsAbs does not consider a path \windows\system32 as absolute
|
||||||
|
// as it doesn't start with a drive-letter/colon combination. However, in
|
||||||
|
// docker we need to verify things such as WORKDIR /windows/system32 in
|
||||||
|
// a Dockerfile (which gets translated to \windows\system32 when being processed
|
||||||
|
// by the daemon. This SHOULD be treated as absolute from a docker processing
|
||||||
|
// perspective.
|
||||||
|
func IsAbs(path string) bool {
|
||||||
|
if !filepath.IsAbs(path) {
|
||||||
|
if !strings.HasPrefix(path, string(os.PathSeparator)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// The origin of the functions below here are the golang OS and syscall packages,
|
||||||
|
// slightly modified to only cope with files, not directories due to the
|
||||||
|
// specific use case.
|
||||||
|
//
|
||||||
|
// The alteration is to allow a file on Windows to be opened with
|
||||||
|
// FILE_FLAG_SEQUENTIAL_SCAN (particular for docker load), to avoid eating
|
||||||
|
// the standby list, particularly when accessing large files such as layer.tar.
|
||||||
|
|
||||||
|
// CreateSequential creates the named file with mode 0666 (before umask), truncating
|
||||||
|
// it if it already exists. If successful, methods on the returned
|
||||||
|
// File can be used for I/O; the associated file descriptor has mode
|
||||||
|
// O_RDWR.
|
||||||
|
// If there is an error, it will be of type *PathError.
|
||||||
|
func CreateSequential(name string) (*os.File, error) {
|
||||||
|
return OpenFileSequential(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenSequential opens the named file for reading. If successful, methods on
|
||||||
|
// the returned file can be used for reading; the associated file
|
||||||
|
// descriptor has mode O_RDONLY.
|
||||||
|
// If there is an error, it will be of type *PathError.
|
||||||
|
func OpenSequential(name string) (*os.File, error) {
|
||||||
|
return OpenFileSequential(name, os.O_RDONLY, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenFileSequential is the generalized open call; most users will use Open
|
||||||
|
// or Create instead.
|
||||||
|
// If there is an error, it will be of type *PathError.
|
||||||
|
func OpenFileSequential(name string, flag int, _ os.FileMode) (*os.File, error) {
|
||||||
|
if name == "" {
|
||||||
|
return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOENT}
|
||||||
|
}
|
||||||
|
r, errf := syscallOpenFileSequential(name, flag, 0)
|
||||||
|
if errf == nil {
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
return nil, &os.PathError{Op: "open", Path: name, Err: errf}
|
||||||
|
}
|
||||||
|
|
||||||
|
func syscallOpenFileSequential(name string, flag int, _ os.FileMode) (file *os.File, err error) {
|
||||||
|
r, e := syscallOpenSequential(name, flag|syscall.O_CLOEXEC, 0)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return os.NewFile(uintptr(r), name), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeInheritSa() *syscall.SecurityAttributes {
|
||||||
|
var sa syscall.SecurityAttributes
|
||||||
|
sa.Length = uint32(unsafe.Sizeof(sa))
|
||||||
|
sa.InheritHandle = 1
|
||||||
|
return &sa
|
||||||
|
}
|
||||||
|
|
||||||
|
func syscallOpenSequential(path string, mode int, _ uint32) (fd syscall.Handle, err error) {
|
||||||
|
if len(path) == 0 {
|
||||||
|
return syscall.InvalidHandle, syscall.ERROR_FILE_NOT_FOUND
|
||||||
|
}
|
||||||
|
pathp, err := syscall.UTF16PtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return syscall.InvalidHandle, err
|
||||||
|
}
|
||||||
|
var access uint32
|
||||||
|
switch mode & (syscall.O_RDONLY | syscall.O_WRONLY | syscall.O_RDWR) {
|
||||||
|
case syscall.O_RDONLY:
|
||||||
|
access = syscall.GENERIC_READ
|
||||||
|
case syscall.O_WRONLY:
|
||||||
|
access = syscall.GENERIC_WRITE
|
||||||
|
case syscall.O_RDWR:
|
||||||
|
access = syscall.GENERIC_READ | syscall.GENERIC_WRITE
|
||||||
|
}
|
||||||
|
if mode&syscall.O_CREAT != 0 {
|
||||||
|
access |= syscall.GENERIC_WRITE
|
||||||
|
}
|
||||||
|
if mode&syscall.O_APPEND != 0 {
|
||||||
|
access &^= syscall.GENERIC_WRITE
|
||||||
|
access |= syscall.FILE_APPEND_DATA
|
||||||
|
}
|
||||||
|
sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE)
|
||||||
|
var sa *syscall.SecurityAttributes
|
||||||
|
if mode&syscall.O_CLOEXEC == 0 {
|
||||||
|
sa = makeInheritSa()
|
||||||
|
}
|
||||||
|
var createmode uint32
|
||||||
|
switch {
|
||||||
|
case mode&(syscall.O_CREAT|syscall.O_EXCL) == (syscall.O_CREAT | syscall.O_EXCL):
|
||||||
|
createmode = syscall.CREATE_NEW
|
||||||
|
case mode&(syscall.O_CREAT|syscall.O_TRUNC) == (syscall.O_CREAT | syscall.O_TRUNC):
|
||||||
|
createmode = syscall.CREATE_ALWAYS
|
||||||
|
case mode&syscall.O_CREAT == syscall.O_CREAT:
|
||||||
|
createmode = syscall.OPEN_ALWAYS
|
||||||
|
case mode&syscall.O_TRUNC == syscall.O_TRUNC:
|
||||||
|
createmode = syscall.TRUNCATE_EXISTING
|
||||||
|
default:
|
||||||
|
createmode = syscall.OPEN_EXISTING
|
||||||
|
}
|
||||||
|
// Use FILE_FLAG_SEQUENTIAL_SCAN rather than FILE_ATTRIBUTE_NORMAL as implemented in golang.
|
||||||
|
//https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
|
||||||
|
const fileFlagSequentialScan = 0x08000000 // FILE_FLAG_SEQUENTIAL_SCAN
|
||||||
|
h, e := syscall.CreateFile(pathp, access, sharemode, sa, createmode, fileFlagSequentialScan, 0)
|
||||||
|
return h, e
|
||||||
|
}
|
31
vendor/github.com/containerd/containerd/sys/oom_unix.go
generated
vendored
Normal file
31
vendor/github.com/containerd/containerd/sys/oom_unix.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package sys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/opencontainers/runc/libcontainer/system"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OOMScoreMaxKillable is the maximum score keeping the process killable by the oom killer
|
||||||
|
const OOMScoreMaxKillable = -999
|
||||||
|
|
||||||
|
// SetOOMScore sets the oom score for the provided pid
|
||||||
|
func SetOOMScore(pid, score int) error {
|
||||||
|
path := fmt.Sprintf("/proc/%d/oom_score_adj", pid)
|
||||||
|
f, err := os.OpenFile(path, os.O_WRONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if _, err = f.WriteString(strconv.Itoa(score)); err != nil {
|
||||||
|
if os.IsPermission(err) && system.RunningInUserNS() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
5
vendor/github.com/containerd/containerd/sys/oom_windows.go
generated
vendored
Normal file
5
vendor/github.com/containerd/containerd/sys/oom_windows.go
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package sys
|
||||||
|
|
||||||
|
func SetOOMScore(pid, score int) error {
|
||||||
|
return nil
|
||||||
|
}
|
41
vendor/github.com/containerd/containerd/sys/prctl.go
generated
vendored
Normal file
41
vendor/github.com/containerd/containerd/sys/prctl.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
|
// Package sys provides access to the Get Child and Set Child prctl flags.
|
||||||
|
// See http://man7.org/linux/man-pages/man2/prctl.2.html
|
||||||
|
package sys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetSubreaper returns the subreaper setting for the calling process
|
||||||
|
func GetSubreaper() (int, error) {
|
||||||
|
var i uintptr
|
||||||
|
// PR_GET_CHILD_SUBREAPER allows retrieving the current child
|
||||||
|
// subreaper.
|
||||||
|
// Returns the "child subreaper" setting of the caller, in the
|
||||||
|
// location pointed to by (int *) arg2.
|
||||||
|
if err := unix.Prctl(unix.PR_GET_CHILD_SUBREAPER, uintptr(unsafe.Pointer(&i)), 0, 0, 0); err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
return int(i), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSubreaper sets the value i as the subreaper setting for the calling process
|
||||||
|
func SetSubreaper(i int) error {
|
||||||
|
// PR_SET_CHILD_SUBREAPER allows setting the child subreaper.
|
||||||
|
// If arg2 is nonzero, set the "child subreaper" attribute of the
|
||||||
|
// calling process; if arg2 is zero, unset the attribute. When a
|
||||||
|
// process is marked as a child subreaper, all of the children
|
||||||
|
// that it creates, and their descendants, will be marked as
|
||||||
|
// having a subreaper. In effect, a subreaper fulfills the role
|
||||||
|
// of init(1) for its descendant processes. Upon termination of
|
||||||
|
// a process that is orphaned (i.e., its immediate parent has
|
||||||
|
// already terminated) and marked as having a subreaper, the
|
||||||
|
// nearest still living ancestor subreaper will receive a SIGCHLD
|
||||||
|
// signal and be able to wait(2) on the process to discover its
|
||||||
|
// termination status.
|
||||||
|
return unix.Prctl(unix.PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0)
|
||||||
|
}
|
19
vendor/github.com/containerd/containerd/sys/prctl_solaris.go
generated
vendored
Normal file
19
vendor/github.com/containerd/containerd/sys/prctl_solaris.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// +build solaris
|
||||||
|
|
||||||
|
package sys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
//Solaris TODO
|
||||||
|
|
||||||
|
// GetSubreaper returns the subreaper setting for the calling process
|
||||||
|
func GetSubreaper() (int, error) {
|
||||||
|
return 0, errors.New("osutils GetSubreaper not implemented on Solaris")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSubreaper sets the value i as the subreaper setting for the calling process
|
||||||
|
func SetSubreaper(i int) error {
|
||||||
|
return errors.New("osutils SetSubreaper not implemented on Solaris")
|
||||||
|
}
|
64
vendor/github.com/containerd/containerd/sys/proc.go
generated
vendored
Normal file
64
vendor/github.com/containerd/containerd/sys/proc.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
|
package sys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/opencontainers/runc/libcontainer/system"
|
||||||
|
)
|
||||||
|
|
||||||
|
const nanoSecondsPerSecond = 1e9
|
||||||
|
|
||||||
|
var clockTicksPerSecond = uint64(system.GetClockTicks())
|
||||||
|
|
||||||
|
// GetSystemCPUUsage returns the host system's cpu usage in
|
||||||
|
// nanoseconds. An error is returned if the format of the underlying
|
||||||
|
// file does not match.
|
||||||
|
//
|
||||||
|
// Uses /proc/stat defined by POSIX. Looks for the cpu
|
||||||
|
// statistics line and then sums up the first seven fields
|
||||||
|
// provided. See `man 5 proc` for details on specific field
|
||||||
|
// information.
|
||||||
|
func GetSystemCPUUsage() (uint64, error) {
|
||||||
|
var line string
|
||||||
|
f, err := os.Open("/proc/stat")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
bufReader := bufio.NewReaderSize(nil, 128)
|
||||||
|
defer func() {
|
||||||
|
bufReader.Reset(nil)
|
||||||
|
f.Close()
|
||||||
|
}()
|
||||||
|
bufReader.Reset(f)
|
||||||
|
err = nil
|
||||||
|
for err == nil {
|
||||||
|
line, err = bufReader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
parts := strings.Fields(line)
|
||||||
|
switch parts[0] {
|
||||||
|
case "cpu":
|
||||||
|
if len(parts) < 8 {
|
||||||
|
return 0, fmt.Errorf("bad format of cpu stats")
|
||||||
|
}
|
||||||
|
var totalClockTicks uint64
|
||||||
|
for _, i := range parts[1:8] {
|
||||||
|
v, err := strconv.ParseUint(i, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("error parsing cpu stats")
|
||||||
|
}
|
||||||
|
totalClockTicks += v
|
||||||
|
}
|
||||||
|
return (totalClockTicks * nanoSecondsPerSecond) /
|
||||||
|
clockTicksPerSecond, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, fmt.Errorf("bad stats format")
|
||||||
|
}
|
51
vendor/github.com/containerd/containerd/sys/reaper.go
generated
vendored
Normal file
51
vendor/github.com/containerd/containerd/sys/reaper.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package sys
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
// Exit is the wait4 information from an exited process
|
||||||
|
type Exit struct {
|
||||||
|
Pid int
|
||||||
|
Status int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reap reaps all child processes for the calling process and returns their
|
||||||
|
// exit information
|
||||||
|
func Reap(wait bool) (exits []Exit, err error) {
|
||||||
|
var (
|
||||||
|
ws unix.WaitStatus
|
||||||
|
rus unix.Rusage
|
||||||
|
)
|
||||||
|
flag := unix.WNOHANG
|
||||||
|
if wait {
|
||||||
|
flag = 0
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
pid, err := unix.Wait4(-1, &ws, flag, &rus)
|
||||||
|
if err != nil {
|
||||||
|
if err == unix.ECHILD {
|
||||||
|
return exits, nil
|
||||||
|
}
|
||||||
|
return exits, err
|
||||||
|
}
|
||||||
|
if pid <= 0 {
|
||||||
|
return exits, nil
|
||||||
|
}
|
||||||
|
exits = append(exits, Exit{
|
||||||
|
Pid: pid,
|
||||||
|
Status: exitStatus(ws),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const exitSignalOffset = 128
|
||||||
|
|
||||||
|
// exitStatus returns the correct exit status for a process based on if it
|
||||||
|
// was signaled or exited cleanly
|
||||||
|
func exitStatus(status unix.WaitStatus) int {
|
||||||
|
if status.Signaled() {
|
||||||
|
return exitSignalOffset + int(status.Signal())
|
||||||
|
}
|
||||||
|
return status.ExitStatus()
|
||||||
|
}
|
59
vendor/github.com/containerd/containerd/sys/socket_unix.go
generated
vendored
Normal file
59
vendor/github.com/containerd/containerd/sys/socket_unix.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package sys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateUnixSocket creates a unix socket and returns the listener
|
||||||
|
func CreateUnixSocket(path string) (net.Listener, error) {
|
||||||
|
if err := os.MkdirAll(filepath.Dir(path), 0660); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := unix.Unlink(path); err != nil && !os.IsNotExist(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return net.Listen("unix", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLocalListener returns a listerner out of a unix socket.
|
||||||
|
func GetLocalListener(path string, uid, gid int) (net.Listener, error) {
|
||||||
|
// Ensure parent directory is created
|
||||||
|
if err := mkdirAs(filepath.Dir(path), uid, gid); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := CreateUnixSocket(path)
|
||||||
|
if err != nil {
|
||||||
|
return l, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.Chmod(path, 0660); err != nil {
|
||||||
|
l.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.Chown(path, uid, gid); err != nil {
|
||||||
|
l.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mkdirAs(path string, uid, gid int) error {
|
||||||
|
if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.Mkdir(path, 0770); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.Chown(path, uid, gid)
|
||||||
|
}
|
16
vendor/github.com/containerd/containerd/sys/socket_windows.go
generated
vendored
Normal file
16
vendor/github.com/containerd/containerd/sys/socket_windows.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package sys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetLocalListener returns a Listernet out of a named pipe.
|
||||||
|
// `path` must be of the form of `\\.\pipe\<pipename>`
|
||||||
|
// (see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150)
|
||||||
|
func GetLocalListener(path string, uid, gid int) (net.Listener, error) {
|
||||||
|
return winio.ListenPipe(path, nil)
|
||||||
|
}
|
19
vendor/github.com/containerd/containerd/sys/stat_bsd.go
generated
vendored
Normal file
19
vendor/github.com/containerd/containerd/sys/stat_bsd.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// +build darwin freebsd
|
||||||
|
|
||||||
|
package sys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StatAtime(st *syscall.Stat_t) syscall.Timespec {
|
||||||
|
return st.Atimespec
|
||||||
|
}
|
||||||
|
|
||||||
|
func StatCtime(st *syscall.Stat_t) syscall.Timespec {
|
||||||
|
return st.Ctimespec
|
||||||
|
}
|
||||||
|
|
||||||
|
func StatMtime(st *syscall.Stat_t) syscall.Timespec {
|
||||||
|
return st.Mtimespec
|
||||||
|
}
|
19
vendor/github.com/containerd/containerd/sys/stat_unix.go
generated
vendored
Normal file
19
vendor/github.com/containerd/containerd/sys/stat_unix.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// +build linux solaris
|
||||||
|
|
||||||
|
package sys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StatAtime(st *syscall.Stat_t) syscall.Timespec {
|
||||||
|
return st.Atim
|
||||||
|
}
|
||||||
|
|
||||||
|
func StatCtime(st *syscall.Stat_t) syscall.Timespec {
|
||||||
|
return st.Ctim
|
||||||
|
}
|
||||||
|
|
||||||
|
func StatMtime(st *syscall.Stat_t) syscall.Timespec {
|
||||||
|
return st.Mtim
|
||||||
|
}
|
29
vendor/github.com/containerd/containerd/task.go
generated
vendored
29
vendor/github.com/containerd/containerd/task.go
generated
vendored
@ -116,13 +116,14 @@ type Task interface {
|
|||||||
Checkpoint(context.Context, ...CheckpointTaskOpts) (v1.Descriptor, error)
|
Checkpoint(context.Context, ...CheckpointTaskOpts) (v1.Descriptor, error)
|
||||||
// Update modifies executing tasks with updated settings
|
// Update modifies executing tasks with updated settings
|
||||||
Update(context.Context, ...UpdateTaskOpts) error
|
Update(context.Context, ...UpdateTaskOpts) error
|
||||||
|
// LoadProcess loads a previously created exec'd process
|
||||||
|
LoadProcess(context.Context, string, IOAttach) (Process, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = (Task)(&task{})
|
var _ = (Task)(&task{})
|
||||||
|
|
||||||
type task struct {
|
type task struct {
|
||||||
client *Client
|
client *Client
|
||||||
container Container
|
|
||||||
|
|
||||||
io IO
|
io IO
|
||||||
id string
|
id string
|
||||||
@ -328,7 +329,6 @@ func (t *task) Exec(ctx context.Context, id string, spec *specs.Process, ioCreat
|
|||||||
id: id,
|
id: id,
|
||||||
task: t,
|
task: t,
|
||||||
io: i,
|
io: i,
|
||||||
spec: spec,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,6 +440,31 @@ func (t *task) Update(ctx context.Context, opts ...UpdateTaskOpts) error {
|
|||||||
return errdefs.FromGRPC(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *task) LoadProcess(ctx context.Context, id string, ioAttach IOAttach) (Process, error) {
|
||||||
|
response, err := t.client.TaskService().Get(ctx, &tasks.GetRequest{
|
||||||
|
ContainerID: t.id,
|
||||||
|
ExecID: id,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
err = errdefs.FromGRPC(err)
|
||||||
|
if errdefs.IsNotFound(err) {
|
||||||
|
return nil, errors.Wrapf(err, "no running process found")
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var i IO
|
||||||
|
if ioAttach != nil {
|
||||||
|
if i, err = attachExistingIO(response, ioAttach); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &process{
|
||||||
|
id: id,
|
||||||
|
task: t,
|
||||||
|
io: i,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *task) checkpointTask(ctx context.Context, index *v1.Index, request *tasks.CheckpointTaskRequest) error {
|
func (t *task) checkpointTask(ctx context.Context, index *v1.Index, request *tasks.CheckpointTaskRequest) error {
|
||||||
response, err := t.client.TaskService().Checkpoint(ctx, request)
|
response, err := t.client.TaskService().Checkpoint(ctx, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
202
vendor/github.com/containerd/continuity/LICENSE
generated
vendored
Normal file
202
vendor/github.com/containerd/continuity/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright {yyyy} {name of copyright owner}
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
74
vendor/github.com/containerd/continuity/README.md
generated
vendored
Normal file
74
vendor/github.com/containerd/continuity/README.md
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# continuity
|
||||||
|
|
||||||
|
[](https://godoc.org/github.com/containerd/continuity)
|
||||||
|
[](https://travis-ci.org/containerd/continuity)
|
||||||
|
|
||||||
|
A transport-agnostic, filesystem metadata manifest system
|
||||||
|
|
||||||
|
This project is a staging area for experiments in providing transport agnostic
|
||||||
|
metadata storage.
|
||||||
|
|
||||||
|
Please see https://github.com/opencontainers/specs/issues/11 for more details.
|
||||||
|
|
||||||
|
## Manifest Format
|
||||||
|
|
||||||
|
A continuity manifest encodes filesystem metadata in Protocol Buffers.
|
||||||
|
Please refer to [proto/manifest.proto](proto/manifest.proto).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Build:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ make
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a manifest (of this repo itself):
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ ./bin/continuity build . > /tmp/a.pb
|
||||||
|
```
|
||||||
|
|
||||||
|
Dump a manifest:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ ./bin/continuity ls /tmp/a.pb
|
||||||
|
...
|
||||||
|
-rw-rw-r-- 270 B /.gitignore
|
||||||
|
-rw-rw-r-- 88 B /.mailmap
|
||||||
|
-rw-rw-r-- 187 B /.travis.yml
|
||||||
|
-rw-rw-r-- 359 B /AUTHORS
|
||||||
|
-rw-rw-r-- 11 kB /LICENSE
|
||||||
|
-rw-rw-r-- 1.5 kB /Makefile
|
||||||
|
...
|
||||||
|
-rw-rw-r-- 986 B /testutil_test.go
|
||||||
|
drwxrwxr-x 0 B /version
|
||||||
|
-rw-rw-r-- 478 B /version/version.go
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify a manifest:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ ./bin/continuity verify . /tmp/a.pb
|
||||||
|
```
|
||||||
|
|
||||||
|
Break the directory and restore using the manifest:
|
||||||
|
```console
|
||||||
|
$ chmod 777 Makefile
|
||||||
|
$ ./bin/continuity verify . /tmp/a.pb
|
||||||
|
2017/06/23 08:00:34 error verifying manifest: resource "/Makefile" has incorrect mode: -rwxrwxrwx != -rw-rw-r--
|
||||||
|
$ ./bin/continuity apply . /tmp/a.pb
|
||||||
|
$ stat -c %a Makefile
|
||||||
|
664
|
||||||
|
$ ./bin/continuity verify . /tmp/a.pb
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Contribution Guide
|
||||||
|
### Building Proto Package
|
||||||
|
|
||||||
|
If you change the proto file you will need to rebuild the generated Go with `go generate`.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ go generate ./proto
|
||||||
|
```
|
10
vendor/github.com/containerd/continuity/sysx/asm.s
generated
vendored
Normal file
10
vendor/github.com/containerd/continuity/sysx/asm.s
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !gccgo
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
TEXT ·use(SB),NOSPLIT,$0
|
||||||
|
RET
|
18
vendor/github.com/containerd/continuity/sysx/chmod_darwin.go
generated
vendored
Normal file
18
vendor/github.com/containerd/continuity/sysx/chmod_darwin.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
const (
|
||||||
|
// AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in <sys/fcntl.h>
|
||||||
|
AtSymlinkNofollow = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
|
||||||
|
// SYS_FCHMODAT defined from golang.org/sys/unix
|
||||||
|
SYS_FCHMODAT = 467
|
||||||
|
)
|
||||||
|
|
||||||
|
// These functions will be generated by generate.sh
|
||||||
|
// $ GOOS=darwin GOARCH=386 ./generate.sh chmod
|
||||||
|
// $ GOOS=darwin GOARCH=amd64 ./generate.sh chmod
|
||||||
|
|
||||||
|
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
|
25
vendor/github.com/containerd/continuity/sysx/chmod_darwin_386.go
generated
vendored
Normal file
25
vendor/github.com/containerd/continuity/sysx/chmod_darwin_386.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// mksyscall.pl -l32 chmod_darwin.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
25
vendor/github.com/containerd/continuity/sysx/chmod_darwin_amd64.go
generated
vendored
Normal file
25
vendor/github.com/containerd/continuity/sysx/chmod_darwin_amd64.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// mksyscall.pl chmod_darwin.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
17
vendor/github.com/containerd/continuity/sysx/chmod_freebsd.go
generated
vendored
Normal file
17
vendor/github.com/containerd/continuity/sysx/chmod_freebsd.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
const (
|
||||||
|
// AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in <sys/fcntl.h>
|
||||||
|
AtSymlinkNofollow = 0x200
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
|
||||||
|
// SYS_FCHMODAT defined from golang.org/sys/unix
|
||||||
|
SYS_FCHMODAT = 490
|
||||||
|
)
|
||||||
|
|
||||||
|
// These functions will be generated by generate.sh
|
||||||
|
// $ GOOS=freebsd GOARCH=amd64 ./generate.sh chmod
|
||||||
|
|
||||||
|
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
|
25
vendor/github.com/containerd/continuity/sysx/chmod_freebsd_amd64.go
generated
vendored
Normal file
25
vendor/github.com/containerd/continuity/sysx/chmod_freebsd_amd64.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// mksyscall.pl chmod_freebsd.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
12
vendor/github.com/containerd/continuity/sysx/chmod_linux.go
generated
vendored
Normal file
12
vendor/github.com/containerd/continuity/sysx/chmod_linux.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
const (
|
||||||
|
// AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in /usr/include/linux/fcntl.h
|
||||||
|
AtSymlinkNofollow = 0x100
|
||||||
|
)
|
||||||
|
|
||||||
|
func Fchmodat(dirfd int, path string, mode uint32, flags int) error {
|
||||||
|
return syscall.Fchmodat(dirfd, path, mode, flags)
|
||||||
|
}
|
11
vendor/github.com/containerd/continuity/sysx/chmod_solaris.go
generated
vendored
Normal file
11
vendor/github.com/containerd/continuity/sysx/chmod_solaris.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
const (
|
||||||
|
AtSymlinkNofollow = unix.AT_SYMLINK_NOFOLLOW
|
||||||
|
)
|
||||||
|
|
||||||
|
func Fchmodat(dirfd int, path string, mode uint32, flags int) error {
|
||||||
|
return unix.Fchmodat(dirfd, path, mode, flags)
|
||||||
|
}
|
11
vendor/github.com/containerd/continuity/sysx/copy_linux.go
generated
vendored
Normal file
11
vendor/github.com/containerd/continuity/sysx/copy_linux.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
// These functions will be generated by generate.sh
|
||||||
|
// $ GOOS=linux GOARCH=386 ./generate.sh copy
|
||||||
|
// $ GOOS=linux GOARCH=amd64 ./generate.sh copy
|
||||||
|
// $ GOOS=linux GOARCH=arm ./generate.sh copy
|
||||||
|
// $ GOOS=linux GOARCH=arm64 ./generate.sh copy
|
||||||
|
// $ GOOS=linux GOARCH=ppc64le ./generate.sh copy
|
||||||
|
// $ GOOS=linux GOARCH=s390x ./generate.sh copy
|
||||||
|
|
||||||
|
//sys CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error)
|
20
vendor/github.com/containerd/continuity/sysx/copy_linux_386.go
generated
vendored
Normal file
20
vendor/github.com/containerd/continuity/sysx/copy_linux_386.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// mksyscall.pl -l32 copy_linux.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags))
|
||||||
|
n = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
20
vendor/github.com/containerd/continuity/sysx/copy_linux_amd64.go
generated
vendored
Normal file
20
vendor/github.com/containerd/continuity/sysx/copy_linux_amd64.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// mksyscall.pl copy_linux.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags))
|
||||||
|
n = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
20
vendor/github.com/containerd/continuity/sysx/copy_linux_arm.go
generated
vendored
Normal file
20
vendor/github.com/containerd/continuity/sysx/copy_linux_arm.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// mksyscall.pl -l32 copy_linux.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags))
|
||||||
|
n = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
20
vendor/github.com/containerd/continuity/sysx/copy_linux_arm64.go
generated
vendored
Normal file
20
vendor/github.com/containerd/continuity/sysx/copy_linux_arm64.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// mksyscall.pl copy_linux.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags))
|
||||||
|
n = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
20
vendor/github.com/containerd/continuity/sysx/copy_linux_ppc64le.go
generated
vendored
Normal file
20
vendor/github.com/containerd/continuity/sysx/copy_linux_ppc64le.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// mksyscall.pl copy_linux.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags))
|
||||||
|
n = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
20
vendor/github.com/containerd/continuity/sysx/copy_linux_s390x.go
generated
vendored
Normal file
20
vendor/github.com/containerd/continuity/sysx/copy_linux_s390x.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// mksyscall.pl copy_linux.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags))
|
||||||
|
n = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
7
vendor/github.com/containerd/continuity/sysx/nodata_linux.go
generated
vendored
Normal file
7
vendor/github.com/containerd/continuity/sysx/nodata_linux.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ENODATA = syscall.ENODATA
|
8
vendor/github.com/containerd/continuity/sysx/nodata_solaris.go
generated
vendored
Normal file
8
vendor/github.com/containerd/continuity/sysx/nodata_solaris.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This should actually be a set that contains ENOENT and EPERM
|
||||||
|
const ENODATA = syscall.ENOENT
|
9
vendor/github.com/containerd/continuity/sysx/nodata_unix.go
generated
vendored
Normal file
9
vendor/github.com/containerd/continuity/sysx/nodata_unix.go
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// +build darwin freebsd
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ENODATA = syscall.ENOATTR
|
37
vendor/github.com/containerd/continuity/sysx/sys.go
generated
vendored
Normal file
37
vendor/github.com/containerd/continuity/sysx/sys.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _zero uintptr
|
||||||
|
|
||||||
|
// use is a no-op, but the compiler cannot see that it is.
|
||||||
|
// Calling use(p) ensures that p is kept live until that point.
|
||||||
|
//go:noescape
|
||||||
|
func use(p unsafe.Pointer)
|
||||||
|
|
||||||
|
// Do the interface allocations only once for common
|
||||||
|
// Errno values.
|
||||||
|
var (
|
||||||
|
errEAGAIN error = syscall.EAGAIN
|
||||||
|
errEINVAL error = syscall.EINVAL
|
||||||
|
errENOENT error = syscall.ENOENT
|
||||||
|
)
|
||||||
|
|
||||||
|
// errnoErr returns common boxed Errno values, to prevent
|
||||||
|
// allocations at runtime.
|
||||||
|
func errnoErr(e syscall.Errno) error {
|
||||||
|
switch e {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case syscall.EAGAIN:
|
||||||
|
return errEAGAIN
|
||||||
|
case syscall.EINVAL:
|
||||||
|
return errEINVAL
|
||||||
|
case syscall.ENOENT:
|
||||||
|
return errENOENT
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}
|
7
vendor/github.com/containerd/continuity/sysx/sysnum_linux_386.go
generated
vendored
Normal file
7
vendor/github.com/containerd/continuity/sysx/sysnum_linux_386.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SYS_COPYFILERANGE defined in Kernel 4.5+
|
||||||
|
// Number defined in /usr/include/asm/unistd_32.h
|
||||||
|
SYS_COPY_FILE_RANGE = 377
|
||||||
|
)
|
7
vendor/github.com/containerd/continuity/sysx/sysnum_linux_amd64.go
generated
vendored
Normal file
7
vendor/github.com/containerd/continuity/sysx/sysnum_linux_amd64.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SYS_COPYFILERANGE defined in Kernel 4.5+
|
||||||
|
// Number defined in /usr/include/asm/unistd_64.h
|
||||||
|
SYS_COPY_FILE_RANGE = 326
|
||||||
|
)
|
7
vendor/github.com/containerd/continuity/sysx/sysnum_linux_arm.go
generated
vendored
Normal file
7
vendor/github.com/containerd/continuity/sysx/sysnum_linux_arm.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SYS_COPY_FILE_RANGE defined in Kernel 4.5+
|
||||||
|
// Number defined in /usr/include/arm-linux-gnueabihf/asm/unistd.h
|
||||||
|
SYS_COPY_FILE_RANGE = 391
|
||||||
|
)
|
7
vendor/github.com/containerd/continuity/sysx/sysnum_linux_arm64.go
generated
vendored
Normal file
7
vendor/github.com/containerd/continuity/sysx/sysnum_linux_arm64.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SYS_COPY_FILE_RANGE defined in Kernel 4.5+
|
||||||
|
// Number defined in /usr/include/asm-generic/unistd.h
|
||||||
|
SYS_COPY_FILE_RANGE = 285
|
||||||
|
)
|
7
vendor/github.com/containerd/continuity/sysx/sysnum_linux_ppc64le.go
generated
vendored
Normal file
7
vendor/github.com/containerd/continuity/sysx/sysnum_linux_ppc64le.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SYS_COPYFILERANGE defined in Kernel 4.5+
|
||||||
|
// Number defined in /usr/include/asm/unistd_64.h
|
||||||
|
SYS_COPY_FILE_RANGE = 379
|
||||||
|
)
|
7
vendor/github.com/containerd/continuity/sysx/sysnum_linux_s390x.go
generated
vendored
Normal file
7
vendor/github.com/containerd/continuity/sysx/sysnum_linux_s390x.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SYS_COPYFILERANGE defined in Kernel 4.5+
|
||||||
|
// Number defined in /usr/include/asm/unistd_64.h
|
||||||
|
SYS_COPY_FILE_RANGE = 375
|
||||||
|
)
|
67
vendor/github.com/containerd/continuity/sysx/xattr.go
generated
vendored
Normal file
67
vendor/github.com/containerd/continuity/sysx/xattr.go
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultXattrBufferSize = 5
|
||||||
|
|
||||||
|
var ErrNotSupported = fmt.Errorf("not supported")
|
||||||
|
|
||||||
|
type listxattrFunc func(path string, dest []byte) (int, error)
|
||||||
|
|
||||||
|
func listxattrAll(path string, listFunc listxattrFunc) ([]string, error) {
|
||||||
|
var p []byte // nil on first execution
|
||||||
|
|
||||||
|
for {
|
||||||
|
n, err := listFunc(path, p) // first call gets buffer size.
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if n > len(p) {
|
||||||
|
p = make([]byte, n)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p[:n]
|
||||||
|
|
||||||
|
ps := bytes.Split(bytes.TrimSuffix(p, []byte{0}), []byte{0})
|
||||||
|
var entries []string
|
||||||
|
for _, p := range ps {
|
||||||
|
s := string(p)
|
||||||
|
if s != "" {
|
||||||
|
entries = append(entries, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type getxattrFunc func(string, string, []byte) (int, error)
|
||||||
|
|
||||||
|
func getxattrAll(path, attr string, getFunc getxattrFunc) ([]byte, error) {
|
||||||
|
p := make([]byte, defaultXattrBufferSize)
|
||||||
|
for {
|
||||||
|
n, err := getFunc(path, attr, p)
|
||||||
|
if err != nil {
|
||||||
|
if errno, ok := err.(syscall.Errno); ok && errno == syscall.ERANGE {
|
||||||
|
p = make([]byte, len(p)*2) // this can't be ideal.
|
||||||
|
continue // try again!
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// realloc to correct size and repeat
|
||||||
|
if n > len(p) {
|
||||||
|
p = make([]byte, n)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return p[:n], nil
|
||||||
|
}
|
||||||
|
}
|
71
vendor/github.com/containerd/continuity/sysx/xattr_darwin.go
generated
vendored
Normal file
71
vendor/github.com/containerd/continuity/sysx/xattr_darwin.go
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
// These functions will be generated by generate.sh
|
||||||
|
// $ GOOS=darwin GOARCH=386 ./generate.sh xattr
|
||||||
|
// $ GOOS=darwin GOARCH=amd64 ./generate.sh xattr
|
||||||
|
|
||||||
|
//sys getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error)
|
||||||
|
//sys setxattr(path string, attr string, data []byte, flags int) (err error)
|
||||||
|
//sys removexattr(path string, attr string, options int) (err error)
|
||||||
|
//sys listxattr(path string, dest []byte, options int) (sz int, err error)
|
||||||
|
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
|
||||||
|
|
||||||
|
const (
|
||||||
|
xattrNoFollow = 0x01
|
||||||
|
)
|
||||||
|
|
||||||
|
func listxattrFollow(path string, dest []byte) (sz int, err error) {
|
||||||
|
return listxattr(path, dest, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listxattr calls syscall getxattr
|
||||||
|
func Listxattr(path string) ([]string, error) {
|
||||||
|
return listxattrAll(path, listxattrFollow)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removexattr calls syscall getxattr
|
||||||
|
func Removexattr(path string, attr string) (err error) {
|
||||||
|
return removexattr(path, attr, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setxattr calls syscall setxattr
|
||||||
|
func Setxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
return setxattr(path, attr, data, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getxattrFollow(path, attr string, dest []byte) (sz int, err error) {
|
||||||
|
return getxattr(path, attr, dest, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getxattr calls syscall getxattr
|
||||||
|
func Getxattr(path, attr string) ([]byte, error) {
|
||||||
|
return getxattrAll(path, attr, getxattrFollow)
|
||||||
|
}
|
||||||
|
|
||||||
|
func listxattrNoFollow(path string, dest []byte) (sz int, err error) {
|
||||||
|
return listxattr(path, dest, xattrNoFollow)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LListxattr calls syscall listxattr with XATTR_NOFOLLOW
|
||||||
|
func LListxattr(path string) ([]string, error) {
|
||||||
|
return listxattrAll(path, listxattrNoFollow)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LRemovexattr calls syscall removexattr with XATTR_NOFOLLOW
|
||||||
|
func LRemovexattr(path string, attr string) (err error) {
|
||||||
|
return removexattr(path, attr, xattrNoFollow)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setxattr calls syscall setxattr with XATTR_NOFOLLOW
|
||||||
|
func LSetxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
return setxattr(path, attr, data, flags|xattrNoFollow)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getxattrNoFollow(path, attr string, dest []byte) (sz int, err error) {
|
||||||
|
return getxattr(path, attr, dest, 0, xattrNoFollow)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LGetxattr calls syscall getxattr with XATTR_NOFOLLOW
|
||||||
|
func LGetxattr(path, attr string) ([]byte, error) {
|
||||||
|
return getxattrAll(path, attr, getxattrNoFollow)
|
||||||
|
}
|
111
vendor/github.com/containerd/continuity/sysx/xattr_darwin_386.go
generated
vendored
Normal file
111
vendor/github.com/containerd/continuity/sysx/xattr_darwin_386.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// mksyscall.pl -l32 xattr_darwin.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), uintptr(pos), uintptr(options))
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func setxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(data) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&data[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func removexattr(path string, attr string, options int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options))
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func listxattr(path string, dest []byte, options int) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall6(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(options), 0, 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
111
vendor/github.com/containerd/continuity/sysx/xattr_darwin_amd64.go
generated
vendored
Normal file
111
vendor/github.com/containerd/continuity/sysx/xattr_darwin_amd64.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// mksyscall.pl xattr_darwin.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), uintptr(pos), uintptr(options))
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func setxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(data) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&data[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func removexattr(path string, attr string, options int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options))
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func listxattr(path string, dest []byte, options int) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall6(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(options), 0, 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
12
vendor/github.com/containerd/continuity/sysx/xattr_freebsd.go
generated
vendored
Normal file
12
vendor/github.com/containerd/continuity/sysx/xattr_freebsd.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Initial stub version for FreeBSD. FreeBSD has a different
|
||||||
|
// syscall API from Darwin and Linux for extended attributes;
|
||||||
|
// it is also not widely used. It is not exposed at all by the
|
||||||
|
// Go syscall package, so we need to implement directly eventually.
|
||||||
|
|
||||||
|
var unsupported = errors.New("extended attributes unsupported on FreeBSD")
|
61
vendor/github.com/containerd/continuity/sysx/xattr_linux.go
generated
vendored
Normal file
61
vendor/github.com/containerd/continuity/sysx/xattr_linux.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
// These functions will be generated by generate.sh
|
||||||
|
// $ GOOS=linux GOARCH=386 ./generate.sh xattr
|
||||||
|
// $ GOOS=linux GOARCH=amd64 ./generate.sh xattr
|
||||||
|
// $ GOOS=linux GOARCH=arm ./generate.sh xattr
|
||||||
|
// $ GOOS=linux GOARCH=arm64 ./generate.sh xattr
|
||||||
|
// $ GOOS=linux GOARCH=ppc64 ./generate.sh xattr
|
||||||
|
// $ GOOS=linux GOARCH=ppc64le ./generate.sh xattr
|
||||||
|
// $ GOOS=linux GOARCH=s390x ./generate.sh xattr
|
||||||
|
|
||||||
|
// Listxattr calls syscall listxattr and reads all content
|
||||||
|
// and returns a string array
|
||||||
|
func Listxattr(path string) ([]string, error) {
|
||||||
|
return listxattrAll(path, syscall.Listxattr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removexattr calls syscall removexattr
|
||||||
|
func Removexattr(path string, attr string) (err error) {
|
||||||
|
return syscall.Removexattr(path, attr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setxattr calls syscall setxattr
|
||||||
|
func Setxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
return syscall.Setxattr(path, attr, data, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getxattr calls syscall getxattr
|
||||||
|
func Getxattr(path, attr string) ([]byte, error) {
|
||||||
|
return getxattrAll(path, attr, syscall.Getxattr)
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys llistxattr(path string, dest []byte) (sz int, err error)
|
||||||
|
|
||||||
|
// LListxattr lists xattrs, not following symlinks
|
||||||
|
func LListxattr(path string) ([]string, error) {
|
||||||
|
return listxattrAll(path, llistxattr)
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys lremovexattr(path string, attr string) (err error)
|
||||||
|
|
||||||
|
// LRemovexattr removes an xattr, not following symlinks
|
||||||
|
func LRemovexattr(path string, attr string) (err error) {
|
||||||
|
return lremovexattr(path, attr)
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys lsetxattr(path string, attr string, data []byte, flags int) (err error)
|
||||||
|
|
||||||
|
// LSetxattr sets an xattr, not following symlinks
|
||||||
|
func LSetxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
return lsetxattr(path, attr, data, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys lgetxattr(path string, attr string, dest []byte) (sz int, err error)
|
||||||
|
|
||||||
|
// LGetxattr gets an xattr, not following symlinks
|
||||||
|
func LGetxattr(path, attr string) ([]byte, error) {
|
||||||
|
return getxattrAll(path, attr, lgetxattr)
|
||||||
|
}
|
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_386.go
generated
vendored
Normal file
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_386.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// mksyscall.pl -l32 xattr_linux.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func llistxattr(path string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lremovexattr(path string, attr string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(data) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&data[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_amd64.go
generated
vendored
Normal file
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_amd64.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// mksyscall.pl xattr_linux.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func llistxattr(path string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lremovexattr(path string, attr string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(data) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&data[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_arm.go
generated
vendored
Normal file
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_arm.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// mksyscall.pl -l32 xattr_linux.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func llistxattr(path string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lremovexattr(path string, attr string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(data) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&data[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_arm64.go
generated
vendored
Normal file
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_arm64.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// mksyscall.pl xattr_linux.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func llistxattr(path string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lremovexattr(path string, attr string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(data) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&data[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_ppc64.go
generated
vendored
Normal file
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_ppc64.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// mksyscall.pl xattr_linux.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func llistxattr(path string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lremovexattr(path string, attr string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(data) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&data[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_ppc64le.go
generated
vendored
Normal file
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_ppc64le.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// mksyscall.pl xattr_linux.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func llistxattr(path string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lremovexattr(path string, attr string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(data) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&data[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_s390x.go
generated
vendored
Normal file
111
vendor/github.com/containerd/continuity/sysx/xattr_linux_s390x.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// mksyscall.pl xattr_linux.go
|
||||||
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func llistxattr(path string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lremovexattr(path string, attr string) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(data) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&data[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
_, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
_p0, err = syscall.BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *byte
|
||||||
|
_p1, err = syscall.BytePtrFromString(attr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 unsafe.Pointer
|
||||||
|
if len(dest) > 0 {
|
||||||
|
_p2 = unsafe.Pointer(&dest[0])
|
||||||
|
} else {
|
||||||
|
_p2 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
|
||||||
|
use(unsafe.Pointer(_p0))
|
||||||
|
use(unsafe.Pointer(_p1))
|
||||||
|
sz = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
12
vendor/github.com/containerd/continuity/sysx/xattr_solaris.go
generated
vendored
Normal file
12
vendor/github.com/containerd/continuity/sysx/xattr_solaris.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package sysx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Initial stub version for Solaris. Solaris has a different
|
||||||
|
// syscall API from Darwin and Linux for extended attributes;
|
||||||
|
// it is also not widely used. It is not exposed at all by the
|
||||||
|
// Go syscall package, so we need to implement directly eventually.
|
||||||
|
|
||||||
|
var unsupported = errors.New("extended attributes unsupported on Solaris")
|
44
vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go
generated
vendored
Normal file
44
vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// +build freebsd solaris
|
||||||
|
|
||||||
|
package sysx
|
||||||
|
|
||||||
|
// Listxattr calls syscall listxattr and reads all content
|
||||||
|
// and returns a string array
|
||||||
|
func Listxattr(path string) ([]string, error) {
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removexattr calls syscall removexattr
|
||||||
|
func Removexattr(path string, attr string) (err error) {
|
||||||
|
return unsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setxattr calls syscall setxattr
|
||||||
|
func Setxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
return unsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getxattr calls syscall getxattr
|
||||||
|
func Getxattr(path, attr string) ([]byte, error) {
|
||||||
|
return []byte{}, unsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
// LListxattr lists xattrs, not following symlinks
|
||||||
|
func LListxattr(path string) ([]string, error) {
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LRemovexattr removes an xattr, not following symlinks
|
||||||
|
func LRemovexattr(path string, attr string) (err error) {
|
||||||
|
return unsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
// LSetxattr sets an xattr, not following symlinks
|
||||||
|
func LSetxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
|
return unsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
// LGetxattr gets an xattr, not following symlinks
|
||||||
|
func LGetxattr(path, attr string) ([]byte, error) {
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
136
vendor/github.com/opencontainers/runc/libcontainer/system/linux.go
generated
vendored
Normal file
136
vendor/github.com/opencontainers/runc/libcontainer/system/linux.go
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"syscall" // only for exec
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// If arg2 is nonzero, set the "child subreaper" attribute of the
|
||||||
|
// calling process; if arg2 is zero, unset the attribute. When a
|
||||||
|
// process is marked as a child subreaper, all of the children
|
||||||
|
// that it creates, and their descendants, will be marked as
|
||||||
|
// having a subreaper. In effect, a subreaper fulfills the role
|
||||||
|
// of init(1) for its descendant processes. Upon termination of
|
||||||
|
// a process that is orphaned (i.e., its immediate parent has
|
||||||
|
// already terminated) and marked as having a subreaper, the
|
||||||
|
// nearest still living ancestor subreaper will receive a SIGCHLD
|
||||||
|
// signal and be able to wait(2) on the process to discover its
|
||||||
|
// termination status.
|
||||||
|
const PR_SET_CHILD_SUBREAPER = 36
|
||||||
|
|
||||||
|
type ParentDeathSignal int
|
||||||
|
|
||||||
|
func (p ParentDeathSignal) Restore() error {
|
||||||
|
if p == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
current, err := GetParentDeathSignal()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if p == current {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return p.Set()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ParentDeathSignal) Set() error {
|
||||||
|
return SetParentDeathSignal(uintptr(p))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Execv(cmd string, args []string, env []string) error {
|
||||||
|
name, err := exec.LookPath(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return syscall.Exec(name, args, env)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Prlimit(pid, resource int, limit unix.Rlimit) error {
|
||||||
|
_, _, err := unix.RawSyscall6(unix.SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(&limit)), uintptr(unsafe.Pointer(&limit)), 0, 0)
|
||||||
|
if err != 0 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetParentDeathSignal(sig uintptr) error {
|
||||||
|
if err := unix.Prctl(unix.PR_SET_PDEATHSIG, sig, 0, 0, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetParentDeathSignal() (ParentDeathSignal, error) {
|
||||||
|
var sig int
|
||||||
|
if err := unix.Prctl(unix.PR_GET_PDEATHSIG, uintptr(unsafe.Pointer(&sig)), 0, 0, 0); err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
return ParentDeathSignal(sig), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetKeepCaps() error {
|
||||||
|
if err := unix.Prctl(unix.PR_SET_KEEPCAPS, 1, 0, 0, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClearKeepCaps() error {
|
||||||
|
if err := unix.Prctl(unix.PR_SET_KEEPCAPS, 0, 0, 0, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Setctty() error {
|
||||||
|
if err := unix.IoctlSetInt(0, unix.TIOCSCTTY, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunningInUserNS detects whether we are currently running in a user namespace.
|
||||||
|
// Copied from github.com/lxc/lxd/shared/util.go
|
||||||
|
func RunningInUserNS() bool {
|
||||||
|
file, err := os.Open("/proc/self/uid_map")
|
||||||
|
if err != nil {
|
||||||
|
// This kernel-provided file only exists if user namespaces are supported
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
buf := bufio.NewReader(file)
|
||||||
|
l, _, err := buf.ReadLine()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
line := string(l)
|
||||||
|
var a, b, c int64
|
||||||
|
fmt.Sscanf(line, "%d %d %d", &a, &b, &c)
|
||||||
|
/*
|
||||||
|
* We assume we are in the initial user namespace if we have a full
|
||||||
|
* range - 4294967295 uids starting at uid 0.
|
||||||
|
*/
|
||||||
|
if a == 0 && b == 0 && c == 4294967295 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSubreaper sets the value i as the subreaper setting for the calling process
|
||||||
|
func SetSubreaper(i int) error {
|
||||||
|
return unix.Prctl(PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0)
|
||||||
|
}
|
113
vendor/github.com/opencontainers/runc/libcontainer/system/proc.go
generated
vendored
Normal file
113
vendor/github.com/opencontainers/runc/libcontainer/system/proc.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// State is the status of a process.
|
||||||
|
type State rune
|
||||||
|
|
||||||
|
const ( // Only values for Linux 3.14 and later are listed here
|
||||||
|
Dead State = 'X'
|
||||||
|
DiskSleep State = 'D'
|
||||||
|
Running State = 'R'
|
||||||
|
Sleeping State = 'S'
|
||||||
|
Stopped State = 'T'
|
||||||
|
TracingStop State = 't'
|
||||||
|
Zombie State = 'Z'
|
||||||
|
)
|
||||||
|
|
||||||
|
// String forms of the state from proc(5)'s documentation for
|
||||||
|
// /proc/[pid]/status' "State" field.
|
||||||
|
func (s State) String() string {
|
||||||
|
switch s {
|
||||||
|
case Dead:
|
||||||
|
return "dead"
|
||||||
|
case DiskSleep:
|
||||||
|
return "disk sleep"
|
||||||
|
case Running:
|
||||||
|
return "running"
|
||||||
|
case Sleeping:
|
||||||
|
return "sleeping"
|
||||||
|
case Stopped:
|
||||||
|
return "stopped"
|
||||||
|
case TracingStop:
|
||||||
|
return "tracing stop"
|
||||||
|
case Zombie:
|
||||||
|
return "zombie"
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown (%c)", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat_t represents the information from /proc/[pid]/stat, as
|
||||||
|
// described in proc(5) with names based on the /proc/[pid]/status
|
||||||
|
// fields.
|
||||||
|
type Stat_t struct {
|
||||||
|
// PID is the process ID.
|
||||||
|
PID uint
|
||||||
|
|
||||||
|
// Name is the command run by the process.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// State is the state of the process.
|
||||||
|
State State
|
||||||
|
|
||||||
|
// StartTime is the number of clock ticks after system boot (since
|
||||||
|
// Linux 2.6).
|
||||||
|
StartTime uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat returns a Stat_t instance for the specified process.
|
||||||
|
func Stat(pid int) (stat Stat_t, err error) {
|
||||||
|
bytes, err := ioutil.ReadFile(filepath.Join("/proc", strconv.Itoa(pid), "stat"))
|
||||||
|
if err != nil {
|
||||||
|
return stat, err
|
||||||
|
}
|
||||||
|
return parseStat(string(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetProcessStartTime is deprecated. Use Stat(pid) and
|
||||||
|
// Stat_t.StartTime instead.
|
||||||
|
func GetProcessStartTime(pid int) (string, error) {
|
||||||
|
stat, err := Stat(pid)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%d", stat.StartTime), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseStat(data string) (stat Stat_t, err error) {
|
||||||
|
// From proc(5), field 2 could contain space and is inside `(` and `)`.
|
||||||
|
// The following is an example:
|
||||||
|
// 89653 (gunicorn: maste) S 89630 89653 89653 0 -1 4194560 29689 28896 0 3 146 32 76 19 20 0 1 0 2971844 52965376 3920 18446744073709551615 1 1 0 0 0 0 0 16781312 137447943 0 0 0 17 1 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||||
|
i := strings.LastIndex(data, ")")
|
||||||
|
if i <= 2 || i >= len(data)-1 {
|
||||||
|
return stat, fmt.Errorf("invalid stat data: %q", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.SplitN(data[:i], "(", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return stat, fmt.Errorf("invalid stat data: %q", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
stat.Name = parts[1]
|
||||||
|
_, err = fmt.Sscanf(parts[0], "%d", &stat.PID)
|
||||||
|
if err != nil {
|
||||||
|
return stat, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// parts indexes should be offset by 3 from the field number given
|
||||||
|
// proc(5), because parts is zero-indexed and we've removed fields
|
||||||
|
// one (PID) and two (Name) in the paren-split.
|
||||||
|
parts = strings.Split(data[i+2:], " ")
|
||||||
|
var state int
|
||||||
|
fmt.Sscanf(parts[3-3], "%c", &state)
|
||||||
|
stat.State = State(state)
|
||||||
|
fmt.Sscanf(parts[22-3], "%d", &stat.StartTime)
|
||||||
|
return stat, nil
|
||||||
|
}
|
25
vendor/github.com/opencontainers/runc/libcontainer/system/syscall_linux_386.go
generated
vendored
Normal file
25
vendor/github.com/opencontainers/runc/libcontainer/system/syscall_linux_386.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// +build linux,386
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Setuid sets the uid of the calling thread to the specified uid.
|
||||||
|
func Setuid(uid int) (err error) {
|
||||||
|
_, _, e1 := unix.RawSyscall(unix.SYS_SETUID32, uintptr(uid), 0, 0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setgid sets the gid of the calling thread to the specified gid.
|
||||||
|
func Setgid(gid int) (err error) {
|
||||||
|
_, _, e1 := unix.RawSyscall(unix.SYS_SETGID32, uintptr(gid), 0, 0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
25
vendor/github.com/opencontainers/runc/libcontainer/system/syscall_linux_64.go
generated
vendored
Normal file
25
vendor/github.com/opencontainers/runc/libcontainer/system/syscall_linux_64.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// +build linux,arm64 linux,amd64 linux,ppc linux,ppc64 linux,ppc64le linux,s390x
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Setuid sets the uid of the calling thread to the specified uid.
|
||||||
|
func Setuid(uid int) (err error) {
|
||||||
|
_, _, e1 := unix.RawSyscall(unix.SYS_SETUID, uintptr(uid), 0, 0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setgid sets the gid of the calling thread to the specified gid.
|
||||||
|
func Setgid(gid int) (err error) {
|
||||||
|
_, _, e1 := unix.RawSyscall(unix.SYS_SETGID, uintptr(gid), 0, 0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
25
vendor/github.com/opencontainers/runc/libcontainer/system/syscall_linux_arm.go
generated
vendored
Normal file
25
vendor/github.com/opencontainers/runc/libcontainer/system/syscall_linux_arm.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// +build linux,arm
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Setuid sets the uid of the calling thread to the specified uid.
|
||||||
|
func Setuid(uid int) (err error) {
|
||||||
|
_, _, e1 := unix.RawSyscall(unix.SYS_SETUID32, uintptr(uid), 0, 0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setgid sets the gid of the calling thread to the specified gid.
|
||||||
|
func Setgid(gid int) (err error) {
|
||||||
|
_, _, e1 := unix.RawSyscall(unix.SYS_SETGID32, uintptr(gid), 0, 0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
12
vendor/github.com/opencontainers/runc/libcontainer/system/sysconfig.go
generated
vendored
Normal file
12
vendor/github.com/opencontainers/runc/libcontainer/system/sysconfig.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// +build cgo,linux cgo,freebsd
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <unistd.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func GetClockTicks() int {
|
||||||
|
return int(C.sysconf(C._SC_CLK_TCK))
|
||||||
|
}
|
15
vendor/github.com/opencontainers/runc/libcontainer/system/sysconfig_notcgo.go
generated
vendored
Normal file
15
vendor/github.com/opencontainers/runc/libcontainer/system/sysconfig_notcgo.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// +build !cgo windows
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
func GetClockTicks() int {
|
||||||
|
// TODO figure out a better alternative for platforms where we're missing cgo
|
||||||
|
//
|
||||||
|
// TODO Windows. This could be implemented using Win32 QueryPerformanceFrequency().
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx
|
||||||
|
//
|
||||||
|
// An example of its usage can be found here.
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
|
||||||
|
|
||||||
|
return 100
|
||||||
|
}
|
9
vendor/github.com/opencontainers/runc/libcontainer/system/unsupported.go
generated
vendored
Normal file
9
vendor/github.com/opencontainers/runc/libcontainer/system/unsupported.go
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
// RunningInUserNS is a stub for non-Linux systems
|
||||||
|
// Always returns false
|
||||||
|
func RunningInUserNS() bool {
|
||||||
|
return false
|
||||||
|
}
|
35
vendor/github.com/opencontainers/runc/libcontainer/system/xattrs_linux.go
generated
vendored
Normal file
35
vendor/github.com/opencontainers/runc/libcontainer/system/xattrs_linux.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package system
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
// Returns a []byte slice if the xattr is set and nil otherwise
|
||||||
|
// Requires path and its attribute as arguments
|
||||||
|
func Lgetxattr(path string, attr string) ([]byte, error) {
|
||||||
|
var sz int
|
||||||
|
// Start with a 128 length byte array
|
||||||
|
dest := make([]byte, 128)
|
||||||
|
sz, errno := unix.Lgetxattr(path, attr, dest)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case errno == unix.ENODATA:
|
||||||
|
return nil, errno
|
||||||
|
case errno == unix.ENOTSUP:
|
||||||
|
return nil, errno
|
||||||
|
case errno == unix.ERANGE:
|
||||||
|
// 128 byte array might just not be good enough,
|
||||||
|
// A dummy buffer is used to get the real size
|
||||||
|
// of the xattrs on disk
|
||||||
|
sz, errno = unix.Lgetxattr(path, attr, []byte{})
|
||||||
|
if errno != nil {
|
||||||
|
return nil, errno
|
||||||
|
}
|
||||||
|
dest = make([]byte, sz)
|
||||||
|
sz, errno = unix.Lgetxattr(path, attr, dest)
|
||||||
|
if errno != nil {
|
||||||
|
return nil, errno
|
||||||
|
}
|
||||||
|
case errno != nil:
|
||||||
|
return nil, errno
|
||||||
|
}
|
||||||
|
return dest[:sz], nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user