Source file
src/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 (file *File) Stat() (FileInfo, error) {
16 if file == nil {
17 return nil, ErrInvalid
18 }
19 return statHandle(file.name, file.pfd.Sysfd)
20 }
21
22
23 func stat(funcname, name string, followSurrogates bool) (FileInfo, error) {
24 if len(name) == 0 {
25 return nil, &PathError{Op: funcname, Path: name, Err: syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
26 }
27 namep, err := syscall.UTF16PtrFromString(fixLongPath(name))
28 if err != nil {
29 return nil, &PathError{Op: funcname, Path: name, Err: err}
30 }
31
32
33
34 var fa syscall.Win32FileAttributeData
35 err = syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fa)))
36 if err == nil && fa.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
37
38
39 fs := newFileStatFromWin32FileAttributeData(&fa)
40 if err := fs.saveInfoFromPath(name); err != nil {
41 return nil, err
42 }
43 return fs, nil
44 }
45
46
47
48 if err == windows.ERROR_SHARING_VIOLATION {
49 var fd syscall.Win32finddata
50 sh, err := syscall.FindFirstFile(namep, &fd)
51 if err != nil {
52 return nil, &PathError{Op: "FindFirstFile", Path: name, Err: err}
53 }
54 syscall.FindClose(sh)
55 if fd.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
56
57 fs := newFileStatFromWin32finddata(&fd)
58 if err := fs.saveInfoFromPath(name); err != nil {
59 return nil, err
60 }
61 return fs, nil
62 }
63 }
64
65
66
67
68
69 var flags uint32 = syscall.FILE_FLAG_BACKUP_SEMANTICS | syscall.FILE_FLAG_OPEN_REPARSE_POINT
70 h, err := syscall.CreateFile(namep, 0, 0, nil, syscall.OPEN_EXISTING, flags, 0)
71
72 if err == windows.ERROR_INVALID_PARAMETER {
73
74
75
76
77 h, err = syscall.CreateFile(namep, syscall.GENERIC_READ, 0, nil, syscall.OPEN_EXISTING, flags, 0)
78 }
79 if err != nil {
80
81
82
83 return nil, &PathError{Op: "CreateFile", Path: name, Err: err}
84 }
85
86 fi, err := statHandle(name, h)
87 syscall.CloseHandle(h)
88 if err == nil && followSurrogates && fi.(*fileStat).isReparseTagNameSurrogate() {
89
90
91
92 h, err = syscall.CreateFile(namep, 0, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
93 if err != nil {
94
95 return nil, &PathError{Op: "CreateFile", Path: name, Err: err}
96 }
97 defer syscall.CloseHandle(h)
98 return statHandle(name, h)
99 }
100 return fi, err
101 }
102
103 func statHandle(name string, h syscall.Handle) (FileInfo, error) {
104 ft, err := syscall.GetFileType(h)
105 if err != nil {
106 return nil, &PathError{Op: "GetFileType", Path: name, Err: err}
107 }
108 switch ft {
109 case syscall.FILE_TYPE_PIPE, syscall.FILE_TYPE_CHAR:
110 return &fileStat{name: basename(name), filetype: ft}, nil
111 }
112 fs, err := newFileStatFromGetFileInformationByHandle(name, h)
113 if err != nil {
114 return nil, err
115 }
116 fs.filetype = ft
117 return fs, err
118 }
119
120
121 func statNolog(name string) (FileInfo, error) {
122 return stat("Stat", name, true)
123 }
124
125
126 func lstatNolog(name string) (FileInfo, error) {
127 followSurrogates := false
128 if name != "" && IsPathSeparator(name[len(name)-1]) {
129
130
131
132
133
134 followSurrogates = true
135 }
136 return stat("Lstat", name, followSurrogates)
137 }
138
View as plain text