]> Cypherpunks repositories - gostls13.git/commitdiff
os: treat "nul" as DevNull file on windows
authorAlex Brainman <alex.brainman@gmail.com>
Sun, 25 Mar 2018 00:08:12 +0000 (11:08 +1100)
committerAlex Brainman <alex.brainman@gmail.com>
Sun, 25 Mar 2018 08:33:21 +0000 (08:33 +0000)
Also add more tests to test both nul and NUL on windows.

Fixes #24482

Change-Id: I3dfe68ec8de7f90ca869c1096dde0054df3c5cf6
Reviewed-on: https://go-review.googlesource.com/102457
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/os/os_test.go
src/os/os_windows_test.go
src/os/stat_windows.go

index 65a2d7e23a8eb59c949569d06fe167e69c9c59c8..38cbfca272c8c5d0b783c6cfda47a68f2f203f1c 100644 (file)
@@ -1791,23 +1791,60 @@ func TestSameFile(t *testing.T) {
        }
 }
 
-func TestDevNullFile(t *testing.T) {
-       f, err := Open(DevNull)
+func testDevNullFileInfo(t *testing.T, statname, devNullName string, fi FileInfo, ignoreCase bool) {
+       pre := fmt.Sprintf("%s(%q): ", statname, devNullName)
+       name := filepath.Base(devNullName)
+       if ignoreCase {
+               if strings.ToUpper(fi.Name()) != strings.ToUpper(name) {
+                       t.Errorf(pre+"wrong file name have %v want %v", fi.Name(), name)
+               }
+       } else {
+               if fi.Name() != name {
+                       t.Errorf(pre+"wrong file name have %v want %v", fi.Name(), name)
+               }
+       }
+       if fi.Size() != 0 {
+               t.Errorf(pre+"wrong file size have %d want 0", fi.Size())
+       }
+       if fi.Mode()&ModeDevice == 0 {
+               t.Errorf(pre+"wrong file mode %q: ModeDevice is not set", fi.Mode())
+       }
+       if fi.Mode()&ModeCharDevice == 0 {
+               t.Errorf(pre+"wrong file mode %q: ModeCharDevice is not set", fi.Mode())
+       }
+       if fi.Mode().IsRegular() {
+               t.Errorf(pre+"wrong file mode %q: IsRegular returns true", fi.Mode())
+       }
+}
+
+func testDevNullFile(t *testing.T, devNullName string, ignoreCase bool) {
+       f, err := Open(devNullName)
        if err != nil {
-               t.Fatalf("Open(%s): %v", DevNull, err)
+               t.Fatalf("Open(%s): %v", devNullName, err)
        }
        defer f.Close()
+
        fi, err := f.Stat()
        if err != nil {
-               t.Fatalf("Stat(%s): %v", DevNull, err)
+               t.Fatalf("Stat(%s): %v", devNullName, err)
        }
-       name := filepath.Base(DevNull)
-       if fi.Name() != name {
-               t.Fatalf("wrong file name have %v want %v", fi.Name(), name)
+       testDevNullFileInfo(t, "f.Stat", devNullName, fi, ignoreCase)
+
+       fi, err = Stat(devNullName)
+       if err != nil {
+               t.Fatalf("Stat(%s): %v", devNullName, err)
        }
-       if fi.Size() != 0 {
-               t.Fatalf("wrong file size have %d want 0", fi.Size())
+       testDevNullFileInfo(t, "Stat", devNullName, fi, ignoreCase)
+
+       fi, err = Lstat(devNullName)
+       if err != nil {
+               t.Fatalf("Lstat(%s): %v", devNullName, err)
        }
+       testDevNullFileInfo(t, "Lstat", devNullName, fi, ignoreCase)
+}
+
+func TestDevNullFile(t *testing.T) {
+       testDevNullFile(t, DevNull, false)
 }
 
 var testLargeWrite = flag.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output")
index 12cd9c1f2e205b72b024905c843badbeb87854aa..25f93cf131808ae74696d01cd50e0f5f156b9b1f 100644 (file)
@@ -979,3 +979,35 @@ func TestOneDrive(t *testing.T) {
        }
        testIsDir(t, dir, fi)
 }
+
+func TestWindowsDevNullFile(t *testing.T) {
+       testDevNullFile(t, "NUL", true)
+       testDevNullFile(t, "nul", true)
+       testDevNullFile(t, "Nul", true)
+
+       f1, err := os.Open("NUL")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer f1.Close()
+
+       fi1, err := f1.Stat()
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       f2, err := os.Open("nul")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer f2.Close()
+
+       fi2, err := f2.Stat()
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       if !os.SameFile(fi1, fi2) {
+               t.Errorf(`"NUL" and "nul" are not the same file`)
+       }
+}
index 0b54a154474151c625fab6a3f84642ce1aece181..19cc0cf6b773c08200bbac31a304ec20d43e0d1b 100644 (file)
@@ -8,6 +8,24 @@ import (
        "syscall"
 )
 
+// isNulName returns true if name is NUL file name.
+// For example, it returns true for both "NUL" and "nul".
+func isNulName(name string) bool {
+       if len(name) != 3 {
+               return false
+       }
+       if name[0] != 'n' && name[0] != 'N' {
+               return false
+       }
+       if name[1] != 'u' && name[1] != 'U' {
+               return false
+       }
+       if name[2] != 'l' && name[2] != 'L' {
+               return false
+       }
+       return true
+}
+
 // Stat returns the FileInfo structure describing file.
 // If there is an error, it will be of type *PathError.
 func (file *File) Stat() (FileInfo, error) {
@@ -19,7 +37,7 @@ func (file *File) Stat() (FileInfo, error) {
                // I don't know any better way to do that for directory
                return Stat(file.dirinfo.path)
        }
-       if file.name == DevNull {
+       if isNulName(file.name) {
                return &devNullStat, nil
        }
 
@@ -45,7 +63,7 @@ func statNolog(name string) (FileInfo, error) {
        if len(name) == 0 {
                return nil, &PathError{"Stat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
        }
-       if name == DevNull {
+       if isNulName(name) {
                return &devNullStat, nil
        }
        namep, err := syscall.UTF16PtrFromString(fixLongPath(name))
@@ -80,7 +98,7 @@ func lstatNolog(name string) (FileInfo, error) {
        if len(name) == 0 {
                return nil, &PathError{"Lstat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
        }
-       if name == DevNull {
+       if isNulName(name) {
                return &devNullStat, nil
        }
        namep, err := syscall.UTF16PtrFromString(fixLongPath(name))