Source file
src/os/stat_windows.go
Documentation: os
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
37
38
39 if err == windows.ERROR_SHARING_VIOLATION {
40 var fd syscall.Win32finddata
41 sh, err := syscall.FindFirstFile(namep, &fd)
42 if err != nil {
43 return nil, &PathError{Op: "FindFirstFile", Path: name, Err: err}
44 }
45 syscall.FindClose(sh)
46 if fd.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
47
48 fs := newFileStatFromWin32finddata(&fd)
49 if err := fs.saveInfoFromPath(name); err != nil {
50 return nil, err
51 }
52 return fs, nil
53 }
54 }
55
56 if err == nil && fa.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
57
58
59 fs := &fileStat{
60 FileAttributes: fa.FileAttributes,
61 CreationTime: fa.CreationTime,
62 LastAccessTime: fa.LastAccessTime,
63 LastWriteTime: fa.LastWriteTime,
64 FileSizeHigh: fa.FileSizeHigh,
65 FileSizeLow: fa.FileSizeLow,
66 }
67 if err := fs.saveInfoFromPath(name); err != nil {
68 return nil, err
69 }
70 return fs, nil
71 }
72
73
74
75
76
77 h, err := syscall.CreateFile(namep, 0, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, 0)
78 if err != nil {
79
80
81
82 return nil, &PathError{Op: "CreateFile", Path: name, Err: err}
83 }
84
85 fi, err := statHandle(name, h)
86 syscall.CloseHandle(h)
87 if err == nil && followSurrogates && fi.(*fileStat).isReparseTagNameSurrogate() {
88
89
90
91 h, err = syscall.CreateFile(namep, 0, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
92 if err != nil {
93
94 return nil, &PathError{Op: "CreateFile", Path: name, Err: err}
95 }
96 defer syscall.CloseHandle(h)
97 return statHandle(name, h)
98 }
99 return fi, err
100 }
101
102 func statHandle(name string, h syscall.Handle) (FileInfo, error) {
103 ft, err := syscall.GetFileType(h)
104 if err != nil {
105 return nil, &PathError{Op: "GetFileType", Path: name, Err: err}
106 }
107 switch ft {
108 case syscall.FILE_TYPE_PIPE, syscall.FILE_TYPE_CHAR:
109 return &fileStat{name: basename(name), filetype: ft}, nil
110 }
111 fs, err := newFileStatFromGetFileInformationByHandle(name, h)
112 if err != nil {
113 return nil, err
114 }
115 fs.filetype = ft
116 return fs, err
117 }
118
119
120 func statNolog(name string) (FileInfo, error) {
121 return stat("Stat", name, true)
122 }
123
124
125 func lstatNolog(name string) (FileInfo, error) {
126 followSurrogates := false
127 if name != "" && IsPathSeparator(name[len(name)-1]) {
128
129
130
131
132
133 followSurrogates = true
134 }
135 return stat("Lstat", name, followSurrogates)
136 }
137
View as plain text