github.com/hanwen/go-fuse@v1.0.0/fuse/pathfs/syscall_linux.go (about) 1 // Copyright 2016 the Go-FUSE Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package pathfs 6 7 import ( 8 "bytes" 9 "syscall" 10 "unsafe" 11 ) 12 13 var _zero uintptr 14 15 func getXAttr(path string, attr string, dest []byte) (value []byte, err error) { 16 sz, err := sysGetxattr(path, attr, dest) 17 for sz > cap(dest) && err == nil { 18 dest = make([]byte, sz) 19 sz, err = sysGetxattr(path, attr, dest) 20 } 21 22 if err != nil { 23 return nil, err 24 } 25 26 return dest[:sz], err 27 } 28 29 func listXAttr(path string) (attributes []string, err error) { 30 dest := make([]byte, 0) 31 sz, err := sysListxattr(path, dest) 32 if err != nil { 33 return nil, err 34 } 35 36 for sz > cap(dest) && err == nil { 37 dest = make([]byte, sz) 38 sz, err = sysListxattr(path, dest) 39 } 40 41 if sz == 0 { 42 return nil, err 43 } 44 45 // -1 to drop the final empty slice. 46 dest = dest[:sz-1] 47 attributesBytes := bytes.Split(dest, []byte{0}) 48 attributes = make([]string, len(attributesBytes)) 49 for i, v := range attributesBytes { 50 attributes[i] = string(v) 51 } 52 return attributes, err 53 } 54 55 // Below is cut & paste from std lib syscall, so gccgo 4.8.1 can 56 // compile this too. 57 func sysGetxattr(path string, attr string, dest []byte) (sz int, err error) { 58 var _p0 *byte 59 _p0, err = syscall.BytePtrFromString(path) 60 if err != nil { 61 return 62 } 63 var _p1 *byte 64 _p1, err = syscall.BytePtrFromString(attr) 65 if err != nil { 66 return 67 } 68 var _p2 unsafe.Pointer 69 if len(dest) > 0 { 70 _p2 = unsafe.Pointer(&dest[0]) 71 } else { 72 _p2 = unsafe.Pointer(&_zero) 73 } 74 r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) 75 sz = int(r0) 76 if e1 != 0 { 77 err = e1 78 } 79 return 80 } 81 82 func sysRemovexattr(path string, attr string) (err error) { 83 var _p0 *byte 84 _p0, err = syscall.BytePtrFromString(path) 85 if err != nil { 86 return 87 } 88 var _p1 *byte 89 _p1, err = syscall.BytePtrFromString(attr) 90 if err != nil { 91 return 92 } 93 _, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) 94 if e1 != 0 { 95 err = e1 96 } 97 return 98 } 99 100 func sysListxattr(path string, dest []byte) (sz int, err error) { 101 var _p0 *byte 102 _p0, err = syscall.BytePtrFromString(path) 103 if err != nil { 104 return 105 } 106 var _p1 unsafe.Pointer 107 if len(dest) > 0 { 108 _p1 = unsafe.Pointer(&dest[0]) 109 } else { 110 _p1 = unsafe.Pointer(&_zero) 111 } 112 r0, _, e1 := syscall.Syscall(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) 113 sz = int(r0) 114 if e1 != 0 { 115 err = e1 116 } 117 return 118 } 119 120 func sysSetxattr(path string, attr string, val []byte, flag int) error { 121 return syscall.Setxattr(path, attr, val, flag) 122 } 123 124 const _AT_SYMLINK_NOFOLLOW = 0x100 125 126 // Linux kernel syscall utimensat(2) 127 // 128 // Needed to implement SetAttr on symlinks correctly as only utimensat provides 129 // AT_SYMLINK_NOFOLLOW. 130 func sysUtimensat(dirfd int, pathname string, times *[2]syscall.Timespec, flags int) (err error) { 131 132 // Null-terminated version of pathname 133 p0, err := syscall.BytePtrFromString(pathname) 134 if err != nil { 135 return err 136 } 137 138 _, _, e1 := syscall.Syscall6(syscall.SYS_UTIMENSAT, 139 uintptr(dirfd), uintptr(unsafe.Pointer(p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) 140 if e1 != 0 { 141 err = syscall.Errno(e1) 142 } 143 return 144 }