Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/sys/unix: No clean way to call utimes(path, NULL) or friends #11830

Closed
tv42 opened this issue Jul 23, 2015 · 6 comments
Closed

x/sys/unix: No clean way to call utimes(path, NULL) or friends #11830

tv42 opened this issue Jul 23, 2015 · 6 comments

Comments

@tv42
Copy link

tv42 commented Jul 23, 2015

The kernel differentiates between setting time to now vs setting it to some timestamp (that may be very very recent past). For example, FUSE sets a separate flag that signals this:

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=17637cbaba592076c221dc045ca78422b4af6290

This is normally achieved by passing NULL as times to utimes(2) and friends.

The Go syscall wrappers all explicitly prevent this:

func Utimes(path string, tv []Timeval) (err error) {
    if len(tv) != 2 {
        return EINVAL
    }
    return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
}

My use case: I wanted to write a FUSE unit test that behaves like touch, and actually causes that flag to be set. Measuring current time and passing it as argument is not good enough.

@ianlancetaylor ianlancetaylor added this to the Unreleased milestone Jul 23, 2015
@bradfitz
Copy link
Contributor

Seems like an easy enough fix. Want to send a CL?

// Utimes blah blah. If tv is nil, blah. Otherwise tv must contain exactly 2 items and blah.
func Utimes(path string, tv []Timeval) (err error) {
    if tv == nil {
        return utimes(path, nil)
    }
    switch len(tv) != 2 {
        return EINVAL
    }
    return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
}

@tv42
Copy link
Author

tv42 commented Jul 23, 2015

Sorry, I'm not very thrilled about CLAs, and have not signed the Google CLA.

@ebfe
Copy link
Contributor

ebfe commented Jul 23, 2015

As a workaround

const UTIME_NOW = (1<<30)-1
UtimesNano(path, []Timespec{{0, UTIME_NOW}, {0, UTIME_NOW}})

might work.

@gopherbot
Copy link

CL https://golang.org/cl/12648 mentions this issue.

@tv42
Copy link
Author

tv42 commented Jul 24, 2015

This leaves a bunch of the sister calls, and platforms other than linux, still enforcing that logic.

$ git grep -B 1 'len\(.*\) != 2'|grep func|grep -v Pipe
unix/syscall_bsd.go-func Utimes(path string, tv []Timeval) (err error) {
unix/syscall_bsd.go-func Futimes(fd int, tv []Timeval) (err error) {
unix/syscall_linux.go-func UtimesNano(path string, ts []Timespec) (err error) {
unix/syscall_linux.go-func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) (err error) {
unix/syscall_linux.go-func Futimesat(dirfd int, path string, tv []Timeval) (err error) {
unix/syscall_solaris.go-func UtimesNano(path string, ts []Timespec) (err error) {
windows/syscall_windows.go-func Utimes(path string, tv []Timeval) (err error) {
windows/syscall_windows.go-func UtimesNano(path string, ts []Timespec) (err error) {

@mdempsky mdempsky reopened this Jul 24, 2015
@gopherbot
Copy link

CL https://golang.org/cl/12690 mentions this issue.

@golang golang locked and limited conversation to collaborators Aug 5, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants