// An implementation of Chtimes which preserves nanosecond precision under linux // // Should go in standard library, but here for now // +build linux package main import ( "os" "syscall" "time" "unsafe" ) // COPIED from syscall // byteSliceFromString returns a NUL-terminated slice of bytes // containing the text of s. If s contains a NUL byte at any // location, it returns (nil, EINVAL). func byteSliceFromString(s string) ([]byte, error) { for i := 0; i < len(s); i++ { if s[i] == 0 { return nil, syscall.EINVAL } } a := make([]byte, len(s)+1) copy(a, s) return a, nil } // COPIED from syscall // bytePtrFromString returns a pointer to a NUL-terminated array of // bytes containing the text of s. If s contains a NUL byte at any // location, it returns (nil, EINVAL). func bytePtrFromString(s string) (*byte, error) { a, err := byteSliceFromString(s) if err != nil { return nil, err } return &a[0], nil } // COPIED from syscall auto generated code modified from utimes func utimensat(dirfd int, path string, times *[2]syscall.Timespec) (err error) { var _p0 *byte _p0, err = bytePtrFromString(path) if err != nil { return } _, _, e1 := syscall.Syscall(syscall.SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times))) if e1 != 0 { err = e1 } return } // FIXME needs defining properly! const AT_FDCWD = -100 // COPIED from syscall and modified //sys utimes(path string, times *[2]Timeval) (err error) func Utimensat(dirfd int, path string, ts []syscall.Timespec) (err error) { if len(ts) != 2 { return syscall.EINVAL } return utimensat(dirfd, path, (*[2]syscall.Timespec)(unsafe.Pointer(&ts[0]))) } // COPIED from syscall and modified func Chtimes(name string, atime time.Time, mtime time.Time) error { var utimes [2]syscall.Timespec utimes[0] = syscall.NsecToTimespec(atime.UnixNano()) utimes[1] = syscall.NsecToTimespec(mtime.UnixNano()) if e := Utimensat(AT_FDCWD, name, utimes[0:]); e != nil { return &os.PathError{Op: "chtimes", Path: name, Err: e} } return nil }