github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/os/stat_windows.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package os 6 7 import ( 8 "syscall" 9 "unsafe" 10 ) 11 12 // Stat returns the FileInfo structure describing file. 13 // If there is an error, it will be of type *PathError. 14 func (file *File) Stat() (fi FileInfo, err error) { 15 if file == nil { 16 return nil, ErrInvalid 17 } 18 if file == nil || file.fd < 0 { 19 return nil, syscall.EINVAL 20 } 21 if file.isdir() { 22 // I don't know any better way to do that for directory 23 return Stat(file.name) 24 } 25 if file.name == DevNull { 26 return &devNullStat, nil 27 } 28 var d syscall.ByHandleFileInformation 29 e := syscall.GetFileInformationByHandle(syscall.Handle(file.fd), &d) 30 if e != nil { 31 return nil, &PathError{"GetFileInformationByHandle", file.name, e} 32 } 33 return &fileStat{ 34 name: basename(file.name), 35 sys: syscall.Win32FileAttributeData{ 36 FileAttributes: d.FileAttributes, 37 CreationTime: d.CreationTime, 38 LastAccessTime: d.LastAccessTime, 39 LastWriteTime: d.LastWriteTime, 40 FileSizeHigh: d.FileSizeHigh, 41 FileSizeLow: d.FileSizeLow, 42 }, 43 vol: d.VolumeSerialNumber, 44 idxhi: d.FileIndexHigh, 45 idxlo: d.FileIndexLow, 46 }, nil 47 } 48 49 // Stat returns a FileInfo structure describing the named file. 50 // If there is an error, it will be of type *PathError. 51 func Stat(name string) (fi FileInfo, err error) { 52 if len(name) == 0 { 53 return nil, &PathError{"Stat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)} 54 } 55 if name == DevNull { 56 return &devNullStat, nil 57 } 58 fs := &fileStat{name: basename(name)} 59 namep, e := syscall.UTF16PtrFromString(name) 60 if e != nil { 61 return nil, &PathError{"Stat", name, e} 62 } 63 e = syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fs.sys))) 64 if e != nil { 65 return nil, &PathError{"GetFileAttributesEx", name, e} 66 } 67 fs.path = name 68 if !isAbs(fs.path) { 69 cwd, _ := Getwd() 70 fs.path = cwd + `\` + fs.path 71 } 72 return fs, nil 73 } 74 75 // Lstat returns the FileInfo structure describing the named file. 76 // If the file is a symbolic link, the returned FileInfo 77 // describes the symbolic link. Lstat makes no attempt to follow the link. 78 // If there is an error, it will be of type *PathError. 79 func Lstat(name string) (fi FileInfo, err error) { 80 // No links on Windows 81 return Stat(name) 82 } 83 84 // basename removes trailing slashes and the leading 85 // directory name and drive letter from path name. 86 func basename(name string) string { 87 // Remove drive letter 88 if len(name) == 2 && name[1] == ':' { 89 name = "." 90 } else if len(name) > 2 && name[1] == ':' { 91 name = name[2:] 92 } 93 i := len(name) - 1 94 // Remove trailing slashes 95 for ; i > 0 && (name[i] == '/' || name[i] == '\\'); i-- { 96 name = name[:i] 97 } 98 // Remove leading directory name 99 for i--; i >= 0; i-- { 100 if name[i] == '/' || name[i] == '\\' { 101 name = name[i+1:] 102 break 103 } 104 } 105 return name 106 } 107 108 func isSlash(c uint8) bool { 109 return c == '\\' || c == '/' 110 } 111 112 func isAbs(path string) (b bool) { 113 v := volumeName(path) 114 if v == "" { 115 return false 116 } 117 path = path[len(v):] 118 if path == "" { 119 return false 120 } 121 return isSlash(path[0]) 122 } 123 124 func volumeName(path string) (v string) { 125 if len(path) < 2 { 126 return "" 127 } 128 // with drive letter 129 c := path[0] 130 if path[1] == ':' && 131 ('0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 132 'A' <= c && c <= 'Z') { 133 return path[:2] 134 } 135 // is it UNC 136 if l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) && 137 !isSlash(path[2]) && path[2] != '.' { 138 // first, leading `\\` and next shouldn't be `\`. its server name. 139 for n := 3; n < l-1; n++ { 140 // second, next '\' shouldn't be repeated. 141 if isSlash(path[n]) { 142 n++ 143 // third, following something characters. its share name. 144 if !isSlash(path[n]) { 145 if path[n] == '.' { 146 break 147 } 148 for ; n < l; n++ { 149 if isSlash(path[n]) { 150 break 151 } 152 } 153 return path[:n] 154 } 155 break 156 } 157 } 158 } 159 return "" 160 }