aboutsummaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/sys/unix/syscall_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/sys/unix/syscall_linux.go')
-rw-r--r--vendor/golang.org/x/sys/unix/syscall_linux.go76
1 files changed, 76 insertions, 0 deletions
diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go
index 7e429ab..c302f01 100644
--- a/vendor/golang.org/x/sys/unix/syscall_linux.go
+++ b/vendor/golang.org/x/sys/unix/syscall_linux.go
@@ -1662,6 +1662,82 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
1662 return EACCES 1662 return EACCES
1663} 1663}
1664 1664
1665//sys nameToHandleAt(dirFD int, pathname string, fh *fileHandle, mountID *_C_int, flags int) (err error) = SYS_NAME_TO_HANDLE_AT
1666//sys openByHandleAt(mountFD int, fh *fileHandle, flags int) (fd int, err error) = SYS_OPEN_BY_HANDLE_AT
1667
1668// fileHandle is the argument to nameToHandleAt and openByHandleAt. We
1669// originally tried to generate it via unix/linux/types.go with "type
1670// fileHandle C.struct_file_handle" but that generated empty structs
1671// for mips64 and mips64le. Instead, hard code it for now (it's the
1672// same everywhere else) until the mips64 generator issue is fixed.
1673type fileHandle struct {
1674 Bytes uint32
1675 Type int32
1676}
1677
1678// FileHandle represents the C struct file_handle used by
1679// name_to_handle_at (see NameToHandleAt) and open_by_handle_at (see
1680// OpenByHandleAt).
1681type FileHandle struct {
1682 *fileHandle
1683}
1684
1685// NewFileHandle constructs a FileHandle.
1686func NewFileHandle(handleType int32, handle []byte) FileHandle {
1687 const hdrSize = unsafe.Sizeof(fileHandle{})
1688 buf := make([]byte, hdrSize+uintptr(len(handle)))
1689 copy(buf[hdrSize:], handle)
1690 fh := (*fileHandle)(unsafe.Pointer(&buf[0]))
1691 fh.Type = handleType
1692 fh.Bytes = uint32(len(handle))
1693 return FileHandle{fh}
1694}
1695
1696func (fh *FileHandle) Size() int { return int(fh.fileHandle.Bytes) }
1697func (fh *FileHandle) Type() int32 { return fh.fileHandle.Type }
1698func (fh *FileHandle) Bytes() []byte {
1699 n := fh.Size()
1700 if n == 0 {
1701 return nil
1702 }
1703 return (*[1 << 30]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&fh.fileHandle.Type)) + 4))[:n:n]
1704}
1705
1706// NameToHandleAt wraps the name_to_handle_at system call; it obtains
1707// a handle for a path name.
1708func NameToHandleAt(dirfd int, path string, flags int) (handle FileHandle, mountID int, err error) {
1709 var mid _C_int
1710 // Try first with a small buffer, assuming the handle will
1711 // only be 32 bytes.
1712 size := uint32(32 + unsafe.Sizeof(fileHandle{}))
1713 didResize := false
1714 for {
1715 buf := make([]byte, size)
1716 fh := (*fileHandle)(unsafe.Pointer(&buf[0]))
1717 fh.Bytes = size - uint32(unsafe.Sizeof(fileHandle{}))
1718 err = nameToHandleAt(dirfd, path, fh, &mid, flags)
1719 if err == EOVERFLOW {
1720 if didResize {
1721 // We shouldn't need to resize more than once
1722 return
1723 }
1724 didResize = true
1725 size = fh.Bytes + uint32(unsafe.Sizeof(fileHandle{}))
1726 continue
1727 }
1728 if err != nil {
1729 return
1730 }
1731 return FileHandle{fh}, int(mid), nil
1732 }
1733}
1734
1735// OpenByHandleAt wraps the open_by_handle_at system call; it opens a
1736// file via a handle as previously returned by NameToHandleAt.
1737func OpenByHandleAt(mountFD int, handle FileHandle, flags int) (fd int, err error) {
1738 return openByHandleAt(mountFD, handle.fileHandle, flags)
1739}
1740
1665/* 1741/*
1666 * Unimplemented 1742 * Unimplemented
1667 */ 1743 */