Source file src/pkg/os/stat_windows.go
1
2
3
4
5 package os
6
7 import (
8 "internal/syscall/windows"
9 "syscall"
10 "unsafe"
11 )
12
13
14
15 func isNulName(name string) bool {
16 if len(name) != 3 {
17 return false
18 }
19 if name[0] != 'n' && name[0] != 'N' {
20 return false
21 }
22 if name[1] != 'u' && name[1] != 'U' {
23 return false
24 }
25 if name[2] != 'l' && name[2] != 'L' {
26 return false
27 }
28 return true
29 }
30
31
32
33 func (file *File) Stat() (FileInfo, error) {
34 if file == nil {
35 return nil, ErrInvalid
36 }
37
38 if file.isdir() {
39
40 return Stat(file.dirinfo.path)
41 }
42 if isNulName(file.name) {
43 return &devNullStat, nil
44 }
45
46 ft, err := file.pfd.GetFileType()
47 if err != nil {
48 return nil, &PathError{"GetFileType", file.name, err}
49 }
50 switch ft {
51 case syscall.FILE_TYPE_PIPE, syscall.FILE_TYPE_CHAR:
52 return &fileStat{name: basename(file.name), filetype: ft}, nil
53 }
54
55 fs, err := newFileStatFromGetFileInformationByHandle(file.name, file.pfd.Sysfd)
56 if err != nil {
57 return nil, err
58 }
59 fs.filetype = ft
60 return fs, err
61 }
62
63
64 func stat(funcname, name string, createFileAttrs uint32) (FileInfo, error) {
65 if len(name) == 0 {
66 return nil, &PathError{funcname, name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
67 }
68 if isNulName(name) {
69 return &devNullStat, nil
70 }
71 namep, err := syscall.UTF16PtrFromString(fixLongPath(name))
72 if err != nil {
73 return nil, &PathError{funcname, name, err}
74 }
75
76
77
78 var fa syscall.Win32FileAttributeData
79 err = syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fa)))
80 if err == nil && fa.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
81
82 fs := &fileStat{
83 FileAttributes: fa.FileAttributes,
84 CreationTime: fa.CreationTime,
85 LastAccessTime: fa.LastAccessTime,
86 LastWriteTime: fa.LastWriteTime,
87 FileSizeHigh: fa.FileSizeHigh,
88 FileSizeLow: fa.FileSizeLow,
89 }
90 if err := fs.saveInfoFromPath(name); err != nil {
91 return nil, err
92 }
93 return fs, nil
94 }
95
96
97 if err == windows.ERROR_SHARING_VIOLATION {
98 var fd syscall.Win32finddata
99 sh, err := syscall.FindFirstFile(namep, &fd)
100 if err != nil {
101 return nil, &PathError{"FindFirstFile", name, err}
102 }
103 syscall.FindClose(sh)
104 fs := newFileStatFromWin32finddata(&fd)
105 if err := fs.saveInfoFromPath(name); err != nil {
106 return nil, err
107 }
108 return fs, nil
109 }
110
111
112 h, err := syscall.CreateFile(namep, 0, 0, nil,
113 syscall.OPEN_EXISTING, createFileAttrs, 0)
114 if err != nil {
115 return nil, &PathError{"CreateFile", name, err}
116 }
117 defer syscall.CloseHandle(h)
118
119 return newFileStatFromGetFileInformationByHandle(name, h)
120 }
121
122
123 func statNolog(name string) (FileInfo, error) {
124 return stat("Stat", name, syscall.FILE_FLAG_BACKUP_SEMANTICS)
125 }
126
127
128 func lstatNolog(name string) (FileInfo, error) {
129 attrs := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS)
130
131
132 attrs |= syscall.FILE_FLAG_OPEN_REPARSE_POINT
133 return stat("Lstat", name, attrs)
134 }
135
View as plain text