669056f93d
lgetxattr(2) man page says: > If size is specified as zero, these calls return the current size of > the named extended attribute (and leave value unchanged). This can be > used to determine the size of the buffer that should be supplied in a > subsequent call. (But, bear in mind that there is a possibility that > the attribute value may change between the two calls, so that it is > still necessary to check the return status from the second call.) The current code does not handle the case when the size changes between the two calls, and the new size is larger. Fix the above problem, and slightly simplify the code. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
37 lines
1.1 KiB
Go
37 lines
1.1 KiB
Go
package system // import "github.com/docker/docker/pkg/system"
|
|
|
|
import "golang.org/x/sys/unix"
|
|
|
|
// Lgetxattr retrieves the value of the extended attribute identified by attr
|
|
// and associated with the given path in the file system.
|
|
// It will returns a nil slice and nil error if the xattr is not set.
|
|
func Lgetxattr(path string, attr string) ([]byte, error) {
|
|
// Start with a 128 length byte array
|
|
dest := make([]byte, 128)
|
|
sz, errno := unix.Lgetxattr(path, attr, dest)
|
|
|
|
for errno == unix.ERANGE {
|
|
// Buffer too small, use zero-sized buffer to get the actual size
|
|
sz, errno = unix.Lgetxattr(path, attr, []byte{})
|
|
if errno != nil {
|
|
return nil, errno
|
|
}
|
|
dest = make([]byte, sz)
|
|
sz, errno = unix.Lgetxattr(path, attr, dest)
|
|
}
|
|
|
|
switch {
|
|
case errno == unix.ENODATA:
|
|
return nil, nil
|
|
case errno != nil:
|
|
return nil, errno
|
|
}
|
|
|
|
return dest[:sz], nil
|
|
}
|
|
|
|
// Lsetxattr sets the value of the extended attribute identified by attr
|
|
// and associated with the given path in the file system.
|
|
func Lsetxattr(path string, attr string, data []byte, flags int) error {
|
|
return unix.Lsetxattr(path, attr, data, flags)
|
|
}
|