Signed-off-by: Darren Stahl <darst@microsoft.com>
| ... | ... |
@@ -2,14 +2,30 @@ package system |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"os" |
| 5 |
+ "syscall" |
|
| 5 | 6 |
"time" |
| 7 |
+ "unsafe" |
|
| 6 | 8 |
) |
| 7 | 9 |
|
| 10 |
+var ( |
|
| 11 |
+ maxTime time.Time |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+func init() {
|
|
| 15 |
+ if unsafe.Sizeof(syscall.Timespec{}.Nsec) == 8 {
|
|
| 16 |
+ // This is a 64 bit timespec |
|
| 17 |
+ // os.Chtimes limits time to the following |
|
| 18 |
+ maxTime = time.Unix(0, 1<<63-1) |
|
| 19 |
+ } else {
|
|
| 20 |
+ // This is a 32 bit timespec |
|
| 21 |
+ maxTime = time.Unix(1<<31-1, 0) |
|
| 22 |
+ } |
|
| 23 |
+} |
|
| 24 |
+ |
|
| 8 | 25 |
// Chtimes changes the access time and modified time of a file at the given path |
| 9 | 26 |
func Chtimes(name string, atime time.Time, mtime time.Time) error {
|
| 10 | 27 |
unixMinTime := time.Unix(0, 0) |
| 11 |
- // The max Unix time is 33 bits set |
|
| 12 |
- unixMaxTime := unixMinTime.Add((1<<33 - 1) * time.Second) |
|
| 28 |
+ unixMaxTime := maxTime |
|
| 13 | 29 |
|
| 14 | 30 |
// If the modified time is prior to the Unix Epoch, or after the |
| 15 | 31 |
// end of Unix Time, os.Chtimes has undefined behavior |
| ... | ... |
@@ -30,9 +30,7 @@ func TestChtimes(t *testing.T) {
|
| 30 | 30 |
beforeUnixEpochTime := time.Unix(0, 0).Add(-100 * time.Second) |
| 31 | 31 |
unixEpochTime := time.Unix(0, 0) |
| 32 | 32 |
afterUnixEpochTime := time.Unix(100, 0) |
| 33 |
- // The max Unix time is 33 bits set |
|
| 34 |
- unixMaxTime := unixEpochTime.Add((1<<33 - 1) * time.Second) |
|
| 35 |
- afterUnixMaxTime := unixMaxTime.Add(100 * time.Second) |
|
| 33 |
+ unixMaxTime := maxTime |
|
| 36 | 34 |
|
| 37 | 35 |
// Test both aTime and mTime set to Unix Epoch |
| 38 | 36 |
Chtimes(file, unixEpochTime, unixEpochTime) |
| ... | ... |
@@ -90,31 +88,7 @@ func TestChtimes(t *testing.T) {
|
| 90 | 90 |
t.Fatal(err) |
| 91 | 91 |
} |
| 92 | 92 |
|
| 93 |
- if f.ModTime() != unixMaxTime {
|
|
| 94 |
- t.Fatalf("Expected: %s, got: %s", unixMaxTime, f.ModTime())
|
|
| 95 |
- } |
|
| 96 |
- |
|
| 97 |
- // Test aTime after Unix max time and mTime set to Unix max time |
|
| 98 |
- Chtimes(file, afterUnixMaxTime, unixMaxTime) |
|
| 99 |
- |
|
| 100 |
- f, err = os.Stat(file) |
|
| 101 |
- if err != nil {
|
|
| 102 |
- t.Fatal(err) |
|
| 103 |
- } |
|
| 104 |
- |
|
| 105 |
- if f.ModTime() != unixMaxTime {
|
|
| 106 |
- t.Fatalf("Expected: %s, got: %s", unixMaxTime, f.ModTime())
|
|
| 107 |
- } |
|
| 108 |
- |
|
| 109 |
- // Test aTime set to Unix Epoch and mTime before Unix Epoch |
|
| 110 |
- Chtimes(file, unixMaxTime, afterUnixMaxTime) |
|
| 111 |
- |
|
| 112 |
- f, err = os.Stat(file) |
|
| 113 |
- if err != nil {
|
|
| 114 |
- t.Fatal(err) |
|
| 115 |
- } |
|
| 116 |
- |
|
| 117 |
- if f.ModTime() != unixEpochTime {
|
|
| 118 |
- t.Fatalf("Expected: %s, got: %s", unixEpochTime, f.ModTime())
|
|
| 93 |
+ if f.ModTime().Truncate(time.Second) != unixMaxTime.Truncate(time.Second) {
|
|
| 94 |
+ t.Fatalf("Expected: %s, got: %s", unixMaxTime.Truncate(time.Second), f.ModTime().Truncate(time.Second))
|
|
| 119 | 95 |
} |
| 120 | 96 |
} |
| ... | ... |
@@ -17,9 +17,7 @@ func TestChtimesLinux(t *testing.T) {
|
| 17 | 17 |
beforeUnixEpochTime := time.Unix(0, 0).Add(-100 * time.Second) |
| 18 | 18 |
unixEpochTime := time.Unix(0, 0) |
| 19 | 19 |
afterUnixEpochTime := time.Unix(100, 0) |
| 20 |
- // The max Unix time is 33 bits set |
|
| 21 |
- unixMaxTime := unixEpochTime.Add((1<<33 - 1) * time.Second) |
|
| 22 |
- afterUnixMaxTime := unixMaxTime.Add(100 * time.Second) |
|
| 20 |
+ unixMaxTime := maxTime |
|
| 23 | 21 |
|
| 24 | 22 |
// Test both aTime and mTime set to Unix Epoch |
| 25 | 23 |
Chtimes(file, unixEpochTime, unixEpochTime) |
| ... | ... |
@@ -87,35 +85,7 @@ func TestChtimesLinux(t *testing.T) {
|
| 87 | 87 |
|
| 88 | 88 |
stat = f.Sys().(*syscall.Stat_t) |
| 89 | 89 |
aTime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)) |
| 90 |
- if aTime != unixMaxTime {
|
|
| 91 |
- t.Fatalf("Expected: %s, got: %s", unixMaxTime, aTime)
|
|
| 92 |
- } |
|
| 93 |
- |
|
| 94 |
- // Test aTime after Unix max time and mTime set to Unix max time |
|
| 95 |
- Chtimes(file, afterUnixMaxTime, unixMaxTime) |
|
| 96 |
- |
|
| 97 |
- f, err = os.Stat(file) |
|
| 98 |
- if err != nil {
|
|
| 99 |
- t.Fatal(err) |
|
| 100 |
- } |
|
| 101 |
- |
|
| 102 |
- stat = f.Sys().(*syscall.Stat_t) |
|
| 103 |
- aTime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)) |
|
| 104 |
- if aTime != unixEpochTime {
|
|
| 105 |
- t.Fatalf("Expected: %s, got: %s", unixEpochTime, aTime)
|
|
| 106 |
- } |
|
| 107 |
- |
|
| 108 |
- // Test aTime set to Unix Epoch and mTime before Unix Epoch |
|
| 109 |
- Chtimes(file, unixMaxTime, afterUnixMaxTime) |
|
| 110 |
- |
|
| 111 |
- f, err = os.Stat(file) |
|
| 112 |
- if err != nil {
|
|
| 113 |
- t.Fatal(err) |
|
| 114 |
- } |
|
| 115 |
- |
|
| 116 |
- stat = f.Sys().(*syscall.Stat_t) |
|
| 117 |
- aTime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)) |
|
| 118 |
- if aTime != unixMaxTime {
|
|
| 119 |
- t.Fatalf("Expected: %s, got: %s", unixMaxTime, aTime)
|
|
| 90 |
+ if aTime.Truncate(time.Second) != unixMaxTime.Truncate(time.Second) {
|
|
| 91 |
+ t.Fatalf("Expected: %s, got: %s", unixMaxTime.Truncate(time.Second), aTime.Truncate(time.Second))
|
|
| 120 | 92 |
} |
| 121 | 93 |
} |
| ... | ... |
@@ -17,9 +17,7 @@ func TestChtimesWindows(t *testing.T) {
|
| 17 | 17 |
beforeUnixEpochTime := time.Unix(0, 0).Add(-100 * time.Second) |
| 18 | 18 |
unixEpochTime := time.Unix(0, 0) |
| 19 | 19 |
afterUnixEpochTime := time.Unix(100, 0) |
| 20 |
- // The max Unix time is 33 bits set |
|
| 21 |
- unixMaxTime := unixEpochTime.Add((1<<33 - 1) * time.Second) |
|
| 22 |
- afterUnixMaxTime := unixMaxTime.Add(100 * time.Second) |
|
| 20 |
+ unixMaxTime := maxTime |
|
| 23 | 21 |
|
| 24 | 22 |
// Test both aTime and mTime set to Unix Epoch |
| 25 | 23 |
Chtimes(file, unixEpochTime, unixEpochTime) |
| ... | ... |
@@ -82,33 +80,7 @@ func TestChtimesWindows(t *testing.T) {
|
| 82 | 82 |
} |
| 83 | 83 |
|
| 84 | 84 |
aTime = time.Unix(0, f.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds()) |
| 85 |
- if aTime != unixMaxTime {
|
|
| 86 |
- t.Fatalf("Expected: %s, got: %s", unixMaxTime, aTime)
|
|
| 87 |
- } |
|
| 88 |
- |
|
| 89 |
- // Test aTime after Unix max time and mTime set to Unix max time |
|
| 90 |
- Chtimes(file, afterUnixMaxTime, unixMaxTime) |
|
| 91 |
- |
|
| 92 |
- f, err = os.Stat(file) |
|
| 93 |
- if err != nil {
|
|
| 94 |
- t.Fatal(err) |
|
| 95 |
- } |
|
| 96 |
- |
|
| 97 |
- aTime = time.Unix(0, f.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds()) |
|
| 98 |
- if aTime != unixEpochTime {
|
|
| 99 |
- t.Fatalf("Expected: %s, got: %s", unixEpochTime, aTime)
|
|
| 100 |
- } |
|
| 101 |
- |
|
| 102 |
- // Test aTime set to Unix Epoch and mTime before Unix Epoch |
|
| 103 |
- Chtimes(file, unixMaxTime, afterUnixMaxTime) |
|
| 104 |
- |
|
| 105 |
- f, err = os.Stat(file) |
|
| 106 |
- if err != nil {
|
|
| 107 |
- t.Fatal(err) |
|
| 108 |
- } |
|
| 109 |
- |
|
| 110 |
- aTime = time.Unix(0, f.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds()) |
|
| 111 |
- if aTime != unixMaxTime {
|
|
| 112 |
- t.Fatalf("Expected: %s, got: %s", unixMaxTime, aTime)
|
|
| 85 |
+ if aTime.Truncate(time.Second) != unixMaxTime.Truncate(time.Second) {
|
|
| 86 |
+ t.Fatalf("Expected: %s, got: %s", unixMaxTime.Truncate(time.Second), aTime.Truncate(time.Second))
|
|
| 113 | 87 |
} |
| 114 | 88 |
} |