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

syscall: NsecToTimeval does not handle times before 1970 #12777

Closed
rfjakob opened this issue Sep 28, 2015 · 11 comments
Closed

syscall: NsecToTimeval does not handle times before 1970 #12777

rfjakob opened this issue Sep 28, 2015 · 11 comments
Assignees
Milestone

Comments

@rfjakob
Copy link

@rfjakob rfjakob commented Sep 28, 2015

Passing a time before 1970 means that nsec is negative.

This means that the rounding will not work properly, and the returned tv.Usec will be negative.

A negative tv.Usec is invalid and rejected by the Linux kernel with EINVAL.

Source code for reference: https://github.com/golang/go/blob/master/src/syscall/syscall_linux_amd64.go#L96

@rfjakob
Copy link
Author

@rfjakob rfjakob commented Sep 28, 2015

This breaks setting of file timestamps in go-fuse, downstream bug: hanwen/go-fuse#58

@bradfitz bradfitz changed the title syscall.NsecToTimeval does not handle times before 1970 syscall: NsecToTimeval does not handle times before 1970 Sep 28, 2015
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Sep 28, 2015

What do you think should happen? It seems to me that having the kernel return EINVAL is correct.

@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Sep 28, 2015
@rfjakob
Copy link
Author

@rfjakob rfjakob commented Sep 29, 2015

tv.Sec should be negative but tv.Usec should be positive.

@rfjakob
Copy link
Author

@rfjakob rfjakob commented Sep 29, 2015

Testcase: https://gist.github.com/rfjakob/6d3359a97d22f32083bc

 t=1960-01-10 23:00:00 +0000 UTC 
 nsec=-314758800000000000 
 tv.Sec=-314758799 tv.Usec=-999999

tv.Sec and tv.Usec are both wrong. It should be:

tv.Sec=-314758800 tv.Usec=0
@hanwen
Copy link
Contributor

@hanwen hanwen commented Sep 29, 2015

nsectotimeval should do

if (tv.usec < 0) {
tv.usec += 1e6
tv.sec --
}

@hanwen
Copy link
Contributor

@hanwen hanwen commented Sep 29, 2015

the same holds for NsecToTimeSpec.

func main() {
name := "test.txt"
var utimes [2]syscall.Timespec

f:=  time.FixedZone("bla",1) 
atime := time.Date(1968, 06, 18, 0, 0, 0, 99, f)
mtime := atime
utimes[0] = syscall.NsecToTimespec(atime.UnixNano())
utimes[1] = syscall.NsecToTimespec(mtime.UnixNano())

if e := syscall.UtimesNano(name, utimes[0:]); e != nil {
    log.Fatal(e)
}

}
=>
[hanwen@pomba test]$ go run tv.go
2015/09/29 08:38:00 invalid argument
exit status 1

@hanwen
Copy link
Contributor

@hanwen hanwen commented Sep 29, 2015

I can prepare a patch if you want.

@rfjakob
Copy link
Author

@rfjakob rfjakob commented Sep 29, 2015

@hanwen I think the rounding should also be the other way round if nsec is negative

I noticed that the Linux kernel rounds DOWN while we round UP, check out http://lxr.free-electrons.com/source/kernel/time/time.c#L422 . This is unrelated, but it may be an opportunity to fix this as well.

rfjakob added a commit to rfjakob/go-fuse that referenced this issue Sep 29, 2015
syscall.NsecToTimespec does not work properly for times
before 1970, see golang/go#12777

This caused xfstests generic/258 to fail.

Fixes issue hanwen#58.
rfjakob added a commit to rfjakob/go-fuse that referenced this issue Sep 29, 2015
syscall.NsecToTimespec does not work properly for times
before 1970, see golang/go#12777

This caused xfstests generic/258 to fail.

Fixes issue hanwen#58.
rfjakob added a commit to rfjakob/go-fuse that referenced this issue Sep 29, 2015
syscall.NsecToTimespec does not work properly for times
before 1970, see golang/go#12777

This caused xfstests generic/258 to fail.

Fixes issue hanwen#58.
@rfjakob
Copy link
Author

@rfjakob rfjakob commented Aug 9, 2016

Ping? NsecToTimeval is still broken.

@bradfitz bradfitz modified the milestones: Go1.8, Unplanned Aug 9, 2016
rfjakob added a commit to rfjakob/go-fuse that referenced this issue Aug 9, 2016
For dates before 1970, syscall.NsecToTimespec() incorrectly
returns negative nanoseconds.
Ticket: golang/go#12777

Handle that case by zeroing out Nsec if it is negative,
but otherwise keep the value.

This makes nanoseconds work for the vast majority of use
cases.
@quentinmit quentinmit added the NeedsFix label Oct 10, 2016
@quentinmit quentinmit self-assigned this Oct 10, 2016
@gopherbot
Copy link

@gopherbot gopherbot commented Oct 10, 2016

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

@quentinmit
Copy link
Contributor

@quentinmit quentinmit commented Oct 12, 2016

Fixed by 6c517df

@quentinmit quentinmit closed this Oct 12, 2016
@golang golang locked and limited conversation to collaborators Oct 12, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
6 participants
You can’t perform that action at this time.