github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fs/host/util_unsafe.go (about) 1 // Copyright 2018 The gVisor Authors. 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 package host 16 17 import ( 18 "unsafe" 19 20 "golang.org/x/sys/unix" 21 "github.com/SagerNet/gvisor/pkg/abi/linux" 22 "github.com/SagerNet/gvisor/pkg/sentry/fs" 23 ktime "github.com/SagerNet/gvisor/pkg/sentry/kernel/time" 24 ) 25 26 // NulByte is a single NUL byte. It is passed to readlinkat as an empty string. 27 var NulByte byte = '\x00' 28 29 func readLink(fd int) (string, error) { 30 // Buffer sizing copied from os.Readlink. 31 for l := 128; ; l *= 2 { 32 b := make([]byte, l) 33 n, _, errno := unix.Syscall6( 34 unix.SYS_READLINKAT, 35 uintptr(fd), 36 uintptr(unsafe.Pointer(&NulByte)), // "" 37 uintptr(unsafe.Pointer(&b[0])), 38 uintptr(l), 39 0, 0) 40 if errno != 0 { 41 return "", errno 42 } 43 if n < uintptr(l) { 44 return string(b[:n]), nil 45 } 46 } 47 } 48 49 func timespecFromTimestamp(t ktime.Time, omit, setSysTime bool) unix.Timespec { 50 if omit { 51 return unix.Timespec{0, linux.UTIME_OMIT} 52 } 53 if setSysTime { 54 return unix.Timespec{0, linux.UTIME_NOW} 55 } 56 return unix.NsecToTimespec(t.Nanoseconds()) 57 } 58 59 func setTimestamps(fd int, ts fs.TimeSpec) error { 60 if ts.ATimeOmit && ts.MTimeOmit { 61 return nil 62 } 63 var sts [2]unix.Timespec 64 sts[0] = timespecFromTimestamp(ts.ATime, ts.ATimeOmit, ts.ATimeSetSystemTime) 65 sts[1] = timespecFromTimestamp(ts.MTime, ts.MTimeOmit, ts.MTimeSetSystemTime) 66 _, _, errno := unix.Syscall6( 67 unix.SYS_UTIMENSAT, 68 uintptr(fd), 69 0, /* path */ 70 uintptr(unsafe.Pointer(&sts)), 71 0, /* flags */ 72 0, 0) 73 if errno != 0 { 74 return errno 75 } 76 return nil 77 }