github.com/blixtra/rkt@v0.8.1-0.20160204105720-ab0d1add1a43/pkg/fileutil/fileutil_linux.go (about) 1 // Copyright 2014 Red Hat, Inc 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // +build linux 16 17 package fileutil 18 19 import ( 20 "os" 21 "syscall" 22 "unsafe" 23 ) 24 25 func hasHardLinks(fi os.FileInfo) bool { 26 // On directories, Nlink doesn't make sense when checking for hard links 27 return !fi.IsDir() && fi.Sys().(*syscall.Stat_t).Nlink > 1 28 } 29 30 func getInode(fi os.FileInfo) uint64 { 31 return fi.Sys().(*syscall.Stat_t).Ino 32 } 33 34 // These functions are from github.com/docker/docker/pkg/system 35 36 // TODO(sgotti) waiting for a utimensat functions accepting flags and a 37 // LUtimesNano using it in https://github.com/golang/sys/ 38 func LUtimesNano(path string, ts []syscall.Timespec) error { 39 // These are not currently available in syscall 40 AT_FDCWD := -100 41 AT_SYMLINK_NOFOLLOW := 0x100 42 43 var _path *byte 44 _path, err := syscall.BytePtrFromString(path) 45 if err != nil { 46 return err 47 } 48 49 if _, _, err := syscall.Syscall6(syscall.SYS_UTIMENSAT, uintptr(AT_FDCWD), uintptr(unsafe.Pointer(_path)), uintptr(unsafe.Pointer(&ts[0])), uintptr(AT_SYMLINK_NOFOLLOW), 0, 0); err != 0 && err != syscall.ENOSYS { 50 return err 51 } 52 53 return nil 54 } 55 56 // Returns a nil slice and nil error if the xattr is not set 57 func Lgetxattr(path string, attr string) ([]byte, error) { 58 pathBytes, err := syscall.BytePtrFromString(path) 59 if err != nil { 60 return nil, err 61 } 62 attrBytes, err := syscall.BytePtrFromString(attr) 63 if err != nil { 64 return nil, err 65 } 66 67 dest := make([]byte, 128) 68 destBytes := unsafe.Pointer(&dest[0]) 69 sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) 70 if errno == syscall.ENODATA { 71 return nil, nil 72 } 73 if errno == syscall.ERANGE { 74 dest = make([]byte, sz) 75 destBytes := unsafe.Pointer(&dest[0]) 76 sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) 77 } 78 if errno != 0 { 79 return nil, errno 80 } 81 82 return dest[:sz], nil 83 } 84 85 var _zero uintptr 86 87 func Lsetxattr(path string, attr string, data []byte, flags int) error { 88 pathBytes, err := syscall.BytePtrFromString(path) 89 if err != nil { 90 return err 91 } 92 attrBytes, err := syscall.BytePtrFromString(attr) 93 if err != nil { 94 return err 95 } 96 var dataBytes unsafe.Pointer 97 if len(data) > 0 { 98 dataBytes = unsafe.Pointer(&data[0]) 99 } else { 100 dataBytes = unsafe.Pointer(&_zero) 101 } 102 _, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0) 103 if errno != 0 { 104 return errno 105 } 106 return nil 107 }