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

os: Chtimes: support nanosecond resolution on Mac OS X #22528

Closed
evanj opened this issue Nov 1, 2017 · 2 comments
Closed

os: Chtimes: support nanosecond resolution on Mac OS X #22528

evanj opened this issue Nov 1, 2017 · 2 comments

Comments

@evanj
Copy link
Contributor

@evanj evanj commented Nov 1, 2017

APFS in Mac OS X 10.13 supports nanosecond timestamps. os.Stat returns the full resolution timestamps, but os.Chtimes is unable to set them, since it doesn't call the right system call. This means it is impossible to "round trip" a file and preserve these details.

I have a change that implements this, by calling setattrlist in syscall_darwin.go. This works on at least Mac OS X 10.11.6 (it drops the resolution), and on Mac OS X 10.13 on APFS, which I will submit shortly.

What version of Go are you using (go version)?

go version go1.9.2 darwin/amd64
go version devel +018642d Wed Nov 1 14:35:30 2017 +0000 darwin/amd64

What did you do?

The following code on Mac OS X creates a temporary file, displays its ModTime, then sets it to a time in the past, and prints the new ModTime. Ideally, the full nanosecond resolution should be displayed and preserved in all cases.

package main

import (
	"fmt"
	"os"
	"runtime"
	"time"
)

func main() {
	fmt.Println("go version:", runtime.Version())

	// create a new file
	const filePath = "example"
	f, err := os.OpenFile(filePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
	if err != nil {
		panic(err)
	}
	f.Close()

	stat, err := os.Stat(filePath)
	if err != nil {
		panic(err)
	}
	fmt.Println("mtime after creation:", stat.ModTime())

	// change the time with nanosecond precision
	t := time.Unix(1509480275, 123456789)
	fmt.Println("setting mtime to:", t)
	err = os.Chtimes(filePath, t, t)
	if err != nil {
		panic(err)
	}
	stat, err = os.Stat(filePath)
	if err != nil {
		panic(err)
	}
	fmt.Println("mtime after set:", stat.ModTime())
}

Output on Mac OS X 10.13

When the file is first created, it has nanosecond precision. After the call to Chtimes, the mtime is truncated to microseconds, since Darwin calls utimes which takes a struct timeval with microsecond precision:

go version: go1.9.2
mtime after creation: 2017-11-01 12:53:21.849659583 -0400 EDT
setting mtime to: 2017-10-31 16:04:35.123456789 -0400 EDT
mtime after set: 2017-10-31 16:04:35.123457 -0400 EDT

The fixed version calls setattrlist which takes a struct timespec with nanosecond resolution:

go version: devel +018642d Wed Nov 1 14:35:30 2017 +0000
mtime after creation: 2017-11-01 12:53:27.388937366 -0400 EDT
setting mtime to: 2017-10-31 16:04:35.123456789 -0400 EDT
mtime after set: 2017-10-31 16:04:35.123456789 -0400 EDT

Output on Mac OS X 10.11

With or without the case is the same: HFS only has seconds resolution, so the timestamps are truncated.

go version: go1.9.2
mtime after creation: 2017-11-01 12:03:12 -0400 EDT
setting mtime to: 2017-10-31 16:04:35.123456789 -0400 EDT
mtime after set: 2017-10-31 16:04:35 -0400 EDT

go version: devel +018642d Wed Nov 1 14:35:30 2017 +0000
mtime after creation: 2017-11-01 12:07:38 -0400 EDT
setting mtime to: 2017-10-31 16:04:35.123456789 -0400 EDT
mtime after set: 2017-10-31 16:04:35 -0400 EDT
@gopherbot

This comment has been minimized.

Copy link

@gopherbot gopherbot commented Nov 1, 2017

Change https://golang.org/cl/74952 mentions this issue: syscall: use setattrlist for UtimesNano on Darwin for ns resolution

@ianlancetaylor ianlancetaylor changed the title os.Chtimes: Support nanosecond resolution on Mac OS X os: Chtimes: support nanosecond resolution on Mac OS X Nov 1, 2017
@gopherbot gopherbot closed this in eb2b0ed Nov 1, 2017
@gopherbot

This comment has been minimized.

Copy link

@gopherbot gopherbot commented Nov 2, 2017

Change https://golang.org/cl/75610 mentions this issue: unix: use setattrlist for UtimesNano on Darwin for ns resolution

gopherbot pushed a commit to golang/sys that referenced this issue Nov 2, 2017
Follow CL 74952 for x/sys/unix.

Update golang/go#22528

Change-Id: Id146da75b80a64cfa4eac28e9bb7b3befe944718
Reviewed-on: https://go-review.googlesource.com/75610
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
@golang golang locked and limited conversation to collaborators Nov 2, 2018
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
3 participants
You can’t perform that action at this time.