Browse Source

This fixes Chtimes on systems with 32 bit Timespec

Signed-off-by: Darren Stahl <darst@microsoft.com>
Darren Stahl 9 years ago
parent
commit
318ad1cb43

+ 18 - 2
pkg/system/chtimes.go

@@ -2,14 +2,30 @@ package system
 
 import (
 	"os"
+	"syscall"
 	"time"
+	"unsafe"
 )
 
+var (
+	maxTime time.Time
+)
+
+func init() {
+	if unsafe.Sizeof(syscall.Timespec{}.Nsec) == 8 {
+		// This is a 64 bit timespec
+		// os.Chtimes limits time to the following
+		maxTime = time.Unix(0, 1<<63-1)
+	} else {
+		// This is a 32 bit timespec
+		maxTime = time.Unix(1<<31-1, 0)
+	}
+}
+
 // Chtimes changes the access time and modified time of a file at the given path
 func Chtimes(name string, atime time.Time, mtime time.Time) error {
 	unixMinTime := time.Unix(0, 0)
-	// The max Unix time is 33 bits set
-	unixMaxTime := unixMinTime.Add((1<<33 - 1) * time.Second)
+	unixMaxTime := maxTime
 
 	// If the modified time is prior to the Unix Epoch, or after the
 	// end of Unix Time, os.Chtimes has undefined behavior

+ 3 - 29
pkg/system/chtimes_test.go

@@ -30,9 +30,7 @@ func TestChtimes(t *testing.T) {
 	beforeUnixEpochTime := time.Unix(0, 0).Add(-100 * time.Second)
 	unixEpochTime := time.Unix(0, 0)
 	afterUnixEpochTime := time.Unix(100, 0)
-	// The max Unix time is 33 bits set
-	unixMaxTime := unixEpochTime.Add((1<<33 - 1) * time.Second)
-	afterUnixMaxTime := unixMaxTime.Add(100 * time.Second)
+	unixMaxTime := maxTime
 
 	// Test both aTime and mTime set to Unix Epoch
 	Chtimes(file, unixEpochTime, unixEpochTime)
@@ -90,31 +88,7 @@ func TestChtimes(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	if f.ModTime() != unixMaxTime {
-		t.Fatalf("Expected: %s, got: %s", unixMaxTime, f.ModTime())
-	}
-
-	// Test aTime after Unix max time and mTime set to Unix max time
-	Chtimes(file, afterUnixMaxTime, unixMaxTime)
-
-	f, err = os.Stat(file)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if f.ModTime() != unixMaxTime {
-		t.Fatalf("Expected: %s, got: %s", unixMaxTime, f.ModTime())
-	}
-
-	// Test aTime set to Unix Epoch and mTime before Unix Epoch
-	Chtimes(file, unixMaxTime, afterUnixMaxTime)
-
-	f, err = os.Stat(file)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if f.ModTime() != unixEpochTime {
-		t.Fatalf("Expected: %s, got: %s", unixEpochTime, f.ModTime())
+	if f.ModTime().Truncate(time.Second) != unixMaxTime.Truncate(time.Second) {
+		t.Fatalf("Expected: %s, got: %s", unixMaxTime.Truncate(time.Second), f.ModTime().Truncate(time.Second))
 	}
 }

+ 3 - 33
pkg/system/chtimes_unix_test.go

@@ -17,9 +17,7 @@ func TestChtimesLinux(t *testing.T) {
 	beforeUnixEpochTime := time.Unix(0, 0).Add(-100 * time.Second)
 	unixEpochTime := time.Unix(0, 0)
 	afterUnixEpochTime := time.Unix(100, 0)
-	// The max Unix time is 33 bits set
-	unixMaxTime := unixEpochTime.Add((1<<33 - 1) * time.Second)
-	afterUnixMaxTime := unixMaxTime.Add(100 * time.Second)
+	unixMaxTime := maxTime
 
 	// Test both aTime and mTime set to Unix Epoch
 	Chtimes(file, unixEpochTime, unixEpochTime)
@@ -87,35 +85,7 @@ func TestChtimesLinux(t *testing.T) {
 
 	stat = f.Sys().(*syscall.Stat_t)
 	aTime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
-	if aTime != unixMaxTime {
-		t.Fatalf("Expected: %s, got: %s", unixMaxTime, aTime)
-	}
-
-	// Test aTime after Unix max time and mTime set to Unix max time
-	Chtimes(file, afterUnixMaxTime, unixMaxTime)
-
-	f, err = os.Stat(file)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	stat = f.Sys().(*syscall.Stat_t)
-	aTime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
-	if aTime != unixEpochTime {
-		t.Fatalf("Expected: %s, got: %s", unixEpochTime, aTime)
-	}
-
-	// Test aTime set to Unix Epoch and mTime before Unix Epoch
-	Chtimes(file, unixMaxTime, afterUnixMaxTime)
-
-	f, err = os.Stat(file)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	stat = f.Sys().(*syscall.Stat_t)
-	aTime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
-	if aTime != unixMaxTime {
-		t.Fatalf("Expected: %s, got: %s", unixMaxTime, aTime)
+	if aTime.Truncate(time.Second) != unixMaxTime.Truncate(time.Second) {
+		t.Fatalf("Expected: %s, got: %s", unixMaxTime.Truncate(time.Second), aTime.Truncate(time.Second))
 	}
 }

+ 3 - 31
pkg/system/chtimes_windows_test.go

@@ -17,9 +17,7 @@ func TestChtimesWindows(t *testing.T) {
 	beforeUnixEpochTime := time.Unix(0, 0).Add(-100 * time.Second)
 	unixEpochTime := time.Unix(0, 0)
 	afterUnixEpochTime := time.Unix(100, 0)
-	// The max Unix time is 33 bits set
-	unixMaxTime := unixEpochTime.Add((1<<33 - 1) * time.Second)
-	afterUnixMaxTime := unixMaxTime.Add(100 * time.Second)
+	unixMaxTime := maxTime
 
 	// Test both aTime and mTime set to Unix Epoch
 	Chtimes(file, unixEpochTime, unixEpochTime)
@@ -82,33 +80,7 @@ func TestChtimesWindows(t *testing.T) {
 	}
 
 	aTime = time.Unix(0, f.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())
-	if aTime != unixMaxTime {
-		t.Fatalf("Expected: %s, got: %s", unixMaxTime, aTime)
-	}
-
-	// Test aTime after Unix max time and mTime set to Unix max time
-	Chtimes(file, afterUnixMaxTime, unixMaxTime)
-
-	f, err = os.Stat(file)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	aTime = time.Unix(0, f.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())
-	if aTime != unixEpochTime {
-		t.Fatalf("Expected: %s, got: %s", unixEpochTime, aTime)
-	}
-
-	// Test aTime set to Unix Epoch and mTime before Unix Epoch
-	Chtimes(file, unixMaxTime, afterUnixMaxTime)
-
-	f, err = os.Stat(file)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	aTime = time.Unix(0, f.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())
-	if aTime != unixMaxTime {
-		t.Fatalf("Expected: %s, got: %s", unixMaxTime, aTime)
+	if aTime.Truncate(time.Second) != unixMaxTime.Truncate(time.Second) {
+		t.Fatalf("Expected: %s, got: %s", unixMaxTime.Truncate(time.Second), aTime.Truncate(time.Second))
 	}
 }