mirror of https://github.com/docker/cli.git
Merge pull request #2657 from thaJeztah/bump_continuity
vendor: update containerd/continuity efbc4488d8fe1bdc16bde3b2d2990d9b3a899165
This commit is contained in:
commit
8a3788118a
|
@ -4,7 +4,7 @@ github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d05887
|
||||||
github.com/beorn7/perks 37c8de3658fcb183f997c4e13e8337516ab753e6 # v1.0.1
|
github.com/beorn7/perks 37c8de3658fcb183f997c4e13e8337516ab753e6 # v1.0.1
|
||||||
github.com/containerd/console 8375c3424e4d7b114e8a90a4a40c8e1b40d1d4e6 # v1.0.0
|
github.com/containerd/console 8375c3424e4d7b114e8a90a4a40c8e1b40d1d4e6 # v1.0.0
|
||||||
github.com/containerd/containerd c80284d4b5291a351bb471bcdabb5c1d95e7a583 # master / v1.4.0-dev
|
github.com/containerd/containerd c80284d4b5291a351bb471bcdabb5c1d95e7a583 # master / v1.4.0-dev
|
||||||
github.com/containerd/continuity 26c1120b8d4107d2471b93ad78ef7ce1fc84c4c4
|
github.com/containerd/continuity efbc4488d8fe1bdc16bde3b2d2990d9b3a899165
|
||||||
github.com/containerd/cgroups 44306b6a1d46985d916b48b4199f93a378af314f
|
github.com/containerd/cgroups 44306b6a1d46985d916b48b4199f93a378af314f
|
||||||
github.com/coreos/etcd d57e8b8d97adfc4a6c224fe116714bf1a1f3beb9 # v3.3.12
|
github.com/coreos/etcd d57e8b8d97adfc4a6c224fe116714bf1a1f3beb9 # v3.3.12
|
||||||
github.com/cpuguy83/go-md2man/v2 f79a8a8ca69da163eee19ab442bedad7a35bba5a # v2.0.0
|
github.com/cpuguy83/go-md2man/v2 f79a8a8ca69da163eee19ab442bedad7a35bba5a # v2.0.0
|
||||||
|
|
|
@ -117,15 +117,13 @@ func sameFile(f1, f2 *currentPath) (bool, error) {
|
||||||
// If the timestamp may have been truncated in both of the
|
// If the timestamp may have been truncated in both of the
|
||||||
// files, check content of file to determine difference
|
// files, check content of file to determine difference
|
||||||
if t1.Nanosecond() == 0 && t2.Nanosecond() == 0 {
|
if t1.Nanosecond() == 0 && t2.Nanosecond() == 0 {
|
||||||
var eq bool
|
|
||||||
if (f1.f.Mode() & os.ModeSymlink) == os.ModeSymlink {
|
if (f1.f.Mode() & os.ModeSymlink) == os.ModeSymlink {
|
||||||
eq, err = compareSymlinkTarget(f1.fullPath, f2.fullPath)
|
return compareSymlinkTarget(f1.fullPath, f2.fullPath)
|
||||||
} else if f1.f.Size() > 0 {
|
|
||||||
eq, err = compareFileContent(f1.fullPath, f2.fullPath)
|
|
||||||
}
|
}
|
||||||
if err != nil || !eq {
|
if f1.f.Size() == 0 { // if file sizes are zero length, the files are the same by definition
|
||||||
return eq, err
|
return true, nil
|
||||||
}
|
}
|
||||||
|
return compareFileContent(f1.fullPath, f2.fullPath)
|
||||||
} else if t1.Nanosecond() != t2.Nanosecond() {
|
} else if t1.Nanosecond() != t2.Nanosecond() {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module github.com/containerd/continuity
|
module github.com/containerd/continuity
|
||||||
|
|
||||||
go 1.11
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898
|
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package syscallx
|
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
// Readlink returns the destination of the named symbolic link.
|
|
||||||
func Readlink(path string, buf []byte) (n int, err error) {
|
|
||||||
return syscall.Readlink(path, buf)
|
|
||||||
}
|
|
|
@ -1,112 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package syscallx
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
type reparseDataBuffer struct {
|
|
||||||
ReparseTag uint32
|
|
||||||
ReparseDataLength uint16
|
|
||||||
Reserved uint16
|
|
||||||
|
|
||||||
// GenericReparseBuffer
|
|
||||||
reparseBuffer byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type mountPointReparseBuffer struct {
|
|
||||||
SubstituteNameOffset uint16
|
|
||||||
SubstituteNameLength uint16
|
|
||||||
PrintNameOffset uint16
|
|
||||||
PrintNameLength uint16
|
|
||||||
PathBuffer [1]uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
type symbolicLinkReparseBuffer struct {
|
|
||||||
SubstituteNameOffset uint16
|
|
||||||
SubstituteNameLength uint16
|
|
||||||
PrintNameOffset uint16
|
|
||||||
PrintNameLength uint16
|
|
||||||
Flags uint32
|
|
||||||
PathBuffer [1]uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
_IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003
|
|
||||||
_SYMLINK_FLAG_RELATIVE = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
// Readlink returns the destination of the named symbolic link.
|
|
||||||
func Readlink(path string, buf []byte) (n int, err error) {
|
|
||||||
fd, err := syscall.CreateFile(syscall.StringToUTF16Ptr(path), syscall.GENERIC_READ, 0, nil, syscall.OPEN_EXISTING,
|
|
||||||
syscall.FILE_FLAG_OPEN_REPARSE_POINT|syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
|
|
||||||
if err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
defer syscall.CloseHandle(fd)
|
|
||||||
|
|
||||||
rdbbuf := make([]byte, syscall.MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
|
|
||||||
var bytesReturned uint32
|
|
||||||
err = syscall.DeviceIoControl(fd, syscall.FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
|
|
||||||
if err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
|
|
||||||
rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0]))
|
|
||||||
var s string
|
|
||||||
switch rdb.ReparseTag {
|
|
||||||
case syscall.IO_REPARSE_TAG_SYMLINK:
|
|
||||||
data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
|
|
||||||
p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
|
|
||||||
s = syscall.UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
|
|
||||||
if data.Flags&_SYMLINK_FLAG_RELATIVE == 0 {
|
|
||||||
if len(s) >= 4 && s[:4] == `\??\` {
|
|
||||||
s = s[4:]
|
|
||||||
switch {
|
|
||||||
case len(s) >= 2 && s[1] == ':': // \??\C:\foo\bar
|
|
||||||
// do nothing
|
|
||||||
case len(s) >= 4 && s[:4] == `UNC\`: // \??\UNC\foo\bar
|
|
||||||
s = `\\` + s[4:]
|
|
||||||
default:
|
|
||||||
// unexpected; do nothing
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// unexpected; do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case _IO_REPARSE_TAG_MOUNT_POINT:
|
|
||||||
data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
|
|
||||||
p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
|
|
||||||
s = syscall.UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
|
|
||||||
if len(s) >= 4 && s[:4] == `\??\` { // \??\C:\foo\bar
|
|
||||||
if len(s) < 48 || s[:11] != `\??\Volume{` {
|
|
||||||
s = s[4:]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// unexpected; do nothing
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// the path is not a symlink or junction but another type of reparse
|
|
||||||
// point
|
|
||||||
return -1, syscall.ENOENT
|
|
||||||
}
|
|
||||||
n = copy(buf, []byte(s))
|
|
||||||
|
|
||||||
return n, nil
|
|
||||||
}
|
|
|
@ -1,128 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sysx
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/containerd/continuity/syscallx"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Readlink returns the destination of the named symbolic link.
|
|
||||||
// If there is an error, it will be of type *PathError.
|
|
||||||
func Readlink(name string) (string, error) {
|
|
||||||
for len := 128; ; len *= 2 {
|
|
||||||
b := make([]byte, len)
|
|
||||||
n, e := fixCount(syscallx.Readlink(fixLongPath(name), b))
|
|
||||||
if e != nil {
|
|
||||||
return "", &os.PathError{Op: "readlink", Path: name, Err: e}
|
|
||||||
}
|
|
||||||
if n < len {
|
|
||||||
return string(b[0:n]), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Many functions in package syscall return a count of -1 instead of 0.
|
|
||||||
// Using fixCount(call()) instead of call() corrects the count.
|
|
||||||
func fixCount(n int, err error) (int, error) {
|
|
||||||
if n < 0 {
|
|
||||||
n = 0
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// fixLongPath returns the extended-length (\\?\-prefixed) form of
|
|
||||||
// path when needed, in order to avoid the default 260 character file
|
|
||||||
// path limit imposed by Windows. If path is not easily converted to
|
|
||||||
// the extended-length form (for example, if path is a relative path
|
|
||||||
// or contains .. elements), or is short enough, fixLongPath returns
|
|
||||||
// path unmodified.
|
|
||||||
//
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
|
|
||||||
func fixLongPath(path string) string {
|
|
||||||
// Do nothing (and don't allocate) if the path is "short".
|
|
||||||
// Empirically (at least on the Windows Server 2013 builder),
|
|
||||||
// the kernel is arbitrarily okay with < 248 bytes. That
|
|
||||||
// matches what the docs above say:
|
|
||||||
// "When using an API to create a directory, the specified
|
|
||||||
// path cannot be so long that you cannot append an 8.3 file
|
|
||||||
// name (that is, the directory name cannot exceed MAX_PATH
|
|
||||||
// minus 12)." Since MAX_PATH is 260, 260 - 12 = 248.
|
|
||||||
//
|
|
||||||
// The MSDN docs appear to say that a normal path that is 248 bytes long
|
|
||||||
// will work; empirically the path must be less then 248 bytes long.
|
|
||||||
if len(path) < 248 {
|
|
||||||
// Don't fix. (This is how Go 1.7 and earlier worked,
|
|
||||||
// not automatically generating the \\?\ form)
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
// The extended form begins with \\?\, as in
|
|
||||||
// \\?\c:\windows\foo.txt or \\?\UNC\server\share\foo.txt.
|
|
||||||
// The extended form disables evaluation of . and .. path
|
|
||||||
// elements and disables the interpretation of / as equivalent
|
|
||||||
// to \. The conversion here rewrites / to \ and elides
|
|
||||||
// . elements as well as trailing or duplicate separators. For
|
|
||||||
// simplicity it avoids the conversion entirely for relative
|
|
||||||
// paths or paths containing .. elements. For now,
|
|
||||||
// \\server\share paths are not converted to
|
|
||||||
// \\?\UNC\server\share paths because the rules for doing so
|
|
||||||
// are less well-specified.
|
|
||||||
if len(path) >= 2 && path[:2] == `\\` {
|
|
||||||
// Don't canonicalize UNC paths.
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
if !filepath.IsAbs(path) {
|
|
||||||
// Relative path
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
const prefix = `\\?`
|
|
||||||
|
|
||||||
pathbuf := make([]byte, len(prefix)+len(path)+len(`\`))
|
|
||||||
copy(pathbuf, prefix)
|
|
||||||
n := len(path)
|
|
||||||
r, w := 0, len(prefix)
|
|
||||||
for r < n {
|
|
||||||
switch {
|
|
||||||
case os.IsPathSeparator(path[r]):
|
|
||||||
// empty block
|
|
||||||
r++
|
|
||||||
case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
|
|
||||||
// /./
|
|
||||||
r++
|
|
||||||
case r+1 < n && path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
|
|
||||||
// /../ is currently unhandled
|
|
||||||
return path
|
|
||||||
default:
|
|
||||||
pathbuf[w] = '\\'
|
|
||||||
w++
|
|
||||||
for ; r < n && !os.IsPathSeparator(path[r]); r++ {
|
|
||||||
pathbuf[w] = path[r]
|
|
||||||
w++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// A drive's root directory needs a trailing \
|
|
||||||
if w == len(`\\?\c:`) {
|
|
||||||
pathbuf[w] = '\\'
|
|
||||||
w++
|
|
||||||
}
|
|
||||||
return string(pathbuf[:w])
|
|
||||||
}
|
|
|
@ -20,7 +20,6 @@ package sysx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
@ -66,60 +65,53 @@ func LGetxattr(path, attr string) ([]byte, error) {
|
||||||
return getxattrAll(path, attr, unix.Lgetxattr)
|
return getxattrAll(path, attr, unix.Lgetxattr)
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultXattrBufferSize = 5
|
const defaultXattrBufferSize = 128
|
||||||
|
|
||||||
type listxattrFunc func(path string, dest []byte) (int, error)
|
type listxattrFunc func(path string, dest []byte) (int, error)
|
||||||
|
|
||||||
func listxattrAll(path string, listFunc listxattrFunc) ([]string, error) {
|
func listxattrAll(path string, listFunc listxattrFunc) ([]string, error) {
|
||||||
var p []byte // nil on first execution
|
buf := make([]byte, defaultXattrBufferSize)
|
||||||
|
n, err := listFunc(path, buf)
|
||||||
for {
|
for err == unix.ERANGE {
|
||||||
n, err := listFunc(path, p) // first call gets buffer size.
|
// Buffer too small, use zero-sized buffer to get the actual size
|
||||||
|
n, err = listFunc(path, []byte{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
buf = make([]byte, n)
|
||||||
if n > len(p) {
|
n, err = listFunc(path, buf)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ps := bytes.Split(bytes.TrimSuffix(buf[:n], []byte{0}), []byte{0})
|
||||||
|
var entries []string
|
||||||
|
for _, p := range ps {
|
||||||
|
if len(p) > 0 {
|
||||||
|
entries = append(entries, string(p))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type getxattrFunc func(string, string, []byte) (int, error)
|
type getxattrFunc func(string, string, []byte) (int, error)
|
||||||
|
|
||||||
func getxattrAll(path, attr string, getFunc getxattrFunc) ([]byte, error) {
|
func getxattrAll(path, attr string, getFunc getxattrFunc) ([]byte, error) {
|
||||||
p := make([]byte, defaultXattrBufferSize)
|
buf := make([]byte, defaultXattrBufferSize)
|
||||||
for {
|
n, err := getFunc(path, attr, buf)
|
||||||
n, err := getFunc(path, attr, p)
|
for err == unix.ERANGE {
|
||||||
|
// Buffer too small, use zero-sized buffer to get the actual size
|
||||||
|
n, err = getFunc(path, attr, []byte{})
|
||||||
if err != nil {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
buf = make([]byte, n)
|
||||||
// realloc to correct size and repeat
|
n, err = getFunc(path, attr, buf)
|
||||||
if n > len(p) {
|
|
||||||
p = make([]byte, n)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return p[:n], nil
|
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buf[:n], nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
var unsupported = errors.New("extended attributes unsupported on " + runtime.GOOS)
|
var errUnsupported = errors.New("extended attributes unsupported on " + runtime.GOOS)
|
||||||
|
|
||||||
// Listxattr calls syscall listxattr and reads all content
|
// Listxattr calls syscall listxattr and reads all content
|
||||||
// and returns a string array
|
// and returns a string array
|
||||||
|
@ -33,17 +33,17 @@ func Listxattr(path string) ([]string, error) {
|
||||||
|
|
||||||
// Removexattr calls syscall removexattr
|
// Removexattr calls syscall removexattr
|
||||||
func Removexattr(path string, attr string) (err error) {
|
func Removexattr(path string, attr string) (err error) {
|
||||||
return unsupported
|
return errUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setxattr calls syscall setxattr
|
// Setxattr calls syscall setxattr
|
||||||
func Setxattr(path string, attr string, data []byte, flags int) (err error) {
|
func Setxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
return unsupported
|
return errUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getxattr calls syscall getxattr
|
// Getxattr calls syscall getxattr
|
||||||
func Getxattr(path, attr string) ([]byte, error) {
|
func Getxattr(path, attr string) ([]byte, error) {
|
||||||
return []byte{}, unsupported
|
return []byte{}, errUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
// LListxattr lists xattrs, not following symlinks
|
// LListxattr lists xattrs, not following symlinks
|
||||||
|
@ -53,12 +53,12 @@ func LListxattr(path string) ([]string, error) {
|
||||||
|
|
||||||
// LRemovexattr removes an xattr, not following symlinks
|
// LRemovexattr removes an xattr, not following symlinks
|
||||||
func LRemovexattr(path string, attr string) (err error) {
|
func LRemovexattr(path string, attr string) (err error) {
|
||||||
return unsupported
|
return errUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
// LSetxattr sets an xattr, not following symlinks
|
// LSetxattr sets an xattr, not following symlinks
|
||||||
func LSetxattr(path string, attr string, data []byte, flags int) (err error) {
|
func LSetxattr(path string, attr string, data []byte, flags int) (err error) {
|
||||||
return unsupported
|
return errUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
// LGetxattr gets an xattr, not following symlinks
|
// LGetxattr gets an xattr, not following symlinks
|
||||||
|
|
Loading…
Reference in New Issue