Skip to content

Commit 48c4eee

Browse files
committed
os: treat "nul" as DevNull file on windows
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 <[email protected]> Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 5ce92d0 commit 48c4eee

File tree

3 files changed

+99
-12
lines changed

3 files changed

+99
-12
lines changed

src/os/os_test.go

+46-9
Original file line numberDiff line numberDiff line change
@@ -1791,23 +1791,60 @@ func TestSameFile(t *testing.T) {
17911791
}
17921792
}
17931793

1794-
func TestDevNullFile(t *testing.T) {
1795-
f, err := Open(DevNull)
1794+
func testDevNullFileInfo(t *testing.T, statname, devNullName string, fi FileInfo, ignoreCase bool) {
1795+
pre := fmt.Sprintf("%s(%q): ", statname, devNullName)
1796+
name := filepath.Base(devNullName)
1797+
if ignoreCase {
1798+
if strings.ToUpper(fi.Name()) != strings.ToUpper(name) {
1799+
t.Errorf(pre+"wrong file name have %v want %v", fi.Name(), name)
1800+
}
1801+
} else {
1802+
if fi.Name() != name {
1803+
t.Errorf(pre+"wrong file name have %v want %v", fi.Name(), name)
1804+
}
1805+
}
1806+
if fi.Size() != 0 {
1807+
t.Errorf(pre+"wrong file size have %d want 0", fi.Size())
1808+
}
1809+
if fi.Mode()&ModeDevice == 0 {
1810+
t.Errorf(pre+"wrong file mode %q: ModeDevice is not set", fi.Mode())
1811+
}
1812+
if fi.Mode()&ModeCharDevice == 0 {
1813+
t.Errorf(pre+"wrong file mode %q: ModeCharDevice is not set", fi.Mode())
1814+
}
1815+
if fi.Mode().IsRegular() {
1816+
t.Errorf(pre+"wrong file mode %q: IsRegular returns true", fi.Mode())
1817+
}
1818+
}
1819+
1820+
func testDevNullFile(t *testing.T, devNullName string, ignoreCase bool) {
1821+
f, err := Open(devNullName)
17961822
if err != nil {
1797-
t.Fatalf("Open(%s): %v", DevNull, err)
1823+
t.Fatalf("Open(%s): %v", devNullName, err)
17981824
}
17991825
defer f.Close()
1826+
18001827
fi, err := f.Stat()
18011828
if err != nil {
1802-
t.Fatalf("Stat(%s): %v", DevNull, err)
1829+
t.Fatalf("Stat(%s): %v", devNullName, err)
18031830
}
1804-
name := filepath.Base(DevNull)
1805-
if fi.Name() != name {
1806-
t.Fatalf("wrong file name have %v want %v", fi.Name(), name)
1831+
testDevNullFileInfo(t, "f.Stat", devNullName, fi, ignoreCase)
1832+
1833+
fi, err = Stat(devNullName)
1834+
if err != nil {
1835+
t.Fatalf("Stat(%s): %v", devNullName, err)
18071836
}
1808-
if fi.Size() != 0 {
1809-
t.Fatalf("wrong file size have %d want 0", fi.Size())
1837+
testDevNullFileInfo(t, "Stat", devNullName, fi, ignoreCase)
1838+
1839+
fi, err = Lstat(devNullName)
1840+
if err != nil {
1841+
t.Fatalf("Lstat(%s): %v", devNullName, err)
18101842
}
1843+
testDevNullFileInfo(t, "Lstat", devNullName, fi, ignoreCase)
1844+
}
1845+
1846+
func TestDevNullFile(t *testing.T) {
1847+
testDevNullFile(t, DevNull, false)
18111848
}
18121849

18131850
var testLargeWrite = flag.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output")

src/os/os_windows_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -979,3 +979,35 @@ func TestOneDrive(t *testing.T) {
979979
}
980980
testIsDir(t, dir, fi)
981981
}
982+
983+
func TestWindowsDevNullFile(t *testing.T) {
984+
testDevNullFile(t, "NUL", true)
985+
testDevNullFile(t, "nul", true)
986+
testDevNullFile(t, "Nul", true)
987+
988+
f1, err := os.Open("NUL")
989+
if err != nil {
990+
t.Fatal(err)
991+
}
992+
defer f1.Close()
993+
994+
fi1, err := f1.Stat()
995+
if err != nil {
996+
t.Fatal(err)
997+
}
998+
999+
f2, err := os.Open("nul")
1000+
if err != nil {
1001+
t.Fatal(err)
1002+
}
1003+
defer f2.Close()
1004+
1005+
fi2, err := f2.Stat()
1006+
if err != nil {
1007+
t.Fatal(err)
1008+
}
1009+
1010+
if !os.SameFile(fi1, fi2) {
1011+
t.Errorf(`"NUL" and "nul" are not the same file`)
1012+
}
1013+
}

src/os/stat_windows.go

+21-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,24 @@ import (
88
"syscall"
99
)
1010

11+
// isNulName returns true if name is NUL file name.
12+
// For example, it returns true for both "NUL" and "nul".
13+
func isNulName(name string) bool {
14+
if len(name) != 3 {
15+
return false
16+
}
17+
if name[0] != 'n' && name[0] != 'N' {
18+
return false
19+
}
20+
if name[1] != 'u' && name[1] != 'U' {
21+
return false
22+
}
23+
if name[2] != 'l' && name[2] != 'L' {
24+
return false
25+
}
26+
return true
27+
}
28+
1129
// Stat returns the FileInfo structure describing file.
1230
// If there is an error, it will be of type *PathError.
1331
func (file *File) Stat() (FileInfo, error) {
@@ -19,7 +37,7 @@ func (file *File) Stat() (FileInfo, error) {
1937
// I don't know any better way to do that for directory
2038
return Stat(file.dirinfo.path)
2139
}
22-
if file.name == DevNull {
40+
if isNulName(file.name) {
2341
return &devNullStat, nil
2442
}
2543

@@ -45,7 +63,7 @@ func statNolog(name string) (FileInfo, error) {
4563
if len(name) == 0 {
4664
return nil, &PathError{"Stat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
4765
}
48-
if name == DevNull {
66+
if isNulName(name) {
4967
return &devNullStat, nil
5068
}
5169
namep, err := syscall.UTF16PtrFromString(fixLongPath(name))
@@ -80,7 +98,7 @@ func lstatNolog(name string) (FileInfo, error) {
8098
if len(name) == 0 {
8199
return nil, &PathError{"Lstat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
82100
}
83-
if name == DevNull {
101+
if isNulName(name) {
84102
return &devNullStat, nil
85103
}
86104
namep, err := syscall.UTF16PtrFromString(fixLongPath(name))

0 commit comments

Comments
 (0)