~ubuntu-branches/ubuntu/utopic/golang/utopic

« back to all changes in this revision

Viewing changes to src/pkg/os/stat_windows.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
package os
6
6
 
7
7
import (
8
 
        "sync"
9
8
        "syscall"
10
 
        "time"
11
9
        "unsafe"
12
10
)
13
11
 
22
20
                return Stat(file.name)
23
21
        }
24
22
        if file.name == DevNull {
25
 
                return statDevNull()
 
23
                return &devNullStat, nil
26
24
        }
27
25
        var d syscall.ByHandleFileInformation
28
26
        e := syscall.GetFileInformationByHandle(syscall.Handle(file.fd), &d)
30
28
                return nil, &PathError{"GetFileInformationByHandle", file.name, e}
31
29
        }
32
30
        return &fileStat{
33
 
                name:    basename(file.name),
34
 
                size:    mkSize(d.FileSizeHigh, d.FileSizeLow),
35
 
                modTime: mkModTime(d.LastWriteTime),
36
 
                mode:    mkMode(d.FileAttributes),
37
 
                sys:     mkSysFromFI(&d),
 
31
                name: basename(file.name),
 
32
                sys: syscall.Win32FileAttributeData{
 
33
                        FileAttributes: d.FileAttributes,
 
34
                        CreationTime:   d.CreationTime,
 
35
                        LastAccessTime: d.LastAccessTime,
 
36
                        LastWriteTime:  d.LastWriteTime,
 
37
                        FileSizeHigh:   d.FileSizeHigh,
 
38
                        FileSizeLow:    d.FileSizeLow,
 
39
                },
 
40
                vol:   d.VolumeSerialNumber,
 
41
                idxhi: d.FileIndexHigh,
 
42
                idxlo: d.FileIndexLow,
38
43
        }, nil
39
44
}
40
45
 
45
50
                return nil, &PathError{"Stat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
46
51
        }
47
52
        if name == DevNull {
48
 
                return statDevNull()
49
 
        }
50
 
        var d syscall.Win32FileAttributeData
51
 
        e := syscall.GetFileAttributesEx(syscall.StringToUTF16Ptr(name), syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&d)))
 
53
                return &devNullStat, nil
 
54
        }
 
55
        fs := &fileStat{name: basename(name)}
 
56
        namep, e := syscall.UTF16PtrFromString(name)
 
57
        if e != nil {
 
58
                return nil, &PathError{"Stat", name, e}
 
59
        }
 
60
        e = syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fs.sys)))
52
61
        if e != nil {
53
62
                return nil, &PathError{"GetFileAttributesEx", name, e}
54
63
        }
55
 
        path := name
56
 
        if !isAbs(path) {
 
64
        fs.path = name
 
65
        if !isAbs(fs.path) {
57
66
                cwd, _ := Getwd()
58
 
                path = cwd + `\` + path
 
67
                fs.path = cwd + `\` + fs.path
59
68
        }
60
 
        return &fileStat{
61
 
                name:    basename(name),
62
 
                size:    mkSize(d.FileSizeHigh, d.FileSizeLow),
63
 
                modTime: mkModTime(d.LastWriteTime),
64
 
                mode:    mkMode(d.FileAttributes),
65
 
                sys:     mkSys(path, d.LastAccessTime, d.CreationTime),
66
 
        }, nil
 
69
        return fs, nil
67
70
}
68
71
 
69
72
// Lstat returns the FileInfo structure describing the named file.
75
78
        return Stat(name)
76
79
}
77
80
 
78
 
// statDevNull return FileInfo structure describing DevNull file ("NUL").
79
 
// It creates invented data, since none of windows api will return
80
 
// that information.
81
 
func statDevNull() (fi FileInfo, err error) {
82
 
        return &fileStat{
83
 
                name: DevNull,
84
 
                mode: ModeDevice | ModeCharDevice | 0666,
85
 
                sys: &winSys{
86
 
                        // hopefully this will work for SameFile
87
 
                        vol:   0,
88
 
                        idxhi: 0,
89
 
                        idxlo: 0,
90
 
                },
91
 
        }, nil
92
 
}
93
 
 
94
81
// basename removes trailing slashes and the leading
95
82
// directory name and drive letter from path name.
96
83
func basename(name string) string {
168
155
        }
169
156
        return ""
170
157
}
171
 
 
172
 
type winSys struct {
173
 
        sync.Mutex
174
 
        path              string
175
 
        atime, ctime      syscall.Filetime
176
 
        vol, idxhi, idxlo uint32
177
 
}
178
 
 
179
 
func mkSize(hi, lo uint32) int64 {
180
 
        return int64(hi)<<32 + int64(lo)
181
 
}
182
 
 
183
 
func mkModTime(mtime syscall.Filetime) time.Time {
184
 
        return time.Unix(0, mtime.Nanoseconds())
185
 
}
186
 
 
187
 
func mkMode(fa uint32) (m FileMode) {
188
 
        if fa&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
189
 
                m |= ModeDir
190
 
        }
191
 
        if fa&syscall.FILE_ATTRIBUTE_READONLY != 0 {
192
 
                m |= 0444
193
 
        } else {
194
 
                m |= 0666
195
 
        }
196
 
        return m
197
 
}
198
 
 
199
 
func mkSys(path string, atime, ctime syscall.Filetime) *winSys {
200
 
        return &winSys{
201
 
                path:  path,
202
 
                atime: atime,
203
 
                ctime: ctime,
204
 
        }
205
 
}
206
 
 
207
 
func mkSysFromFI(i *syscall.ByHandleFileInformation) *winSys {
208
 
        return &winSys{
209
 
                atime: i.LastAccessTime,
210
 
                ctime: i.CreationTime,
211
 
                vol:   i.VolumeSerialNumber,
212
 
                idxhi: i.FileIndexHigh,
213
 
                idxlo: i.FileIndexLow,
214
 
        }
215
 
}
216
 
 
217
 
func (s *winSys) loadFileId() error {
218
 
        if s.path == "" {
219
 
                // already done
220
 
                return nil
221
 
        }
222
 
        s.Lock()
223
 
        defer s.Unlock()
224
 
        h, e := syscall.CreateFile(syscall.StringToUTF16Ptr(s.path), 0, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
225
 
        if e != nil {
226
 
                return e
227
 
        }
228
 
        defer syscall.CloseHandle(h)
229
 
        var i syscall.ByHandleFileInformation
230
 
        e = syscall.GetFileInformationByHandle(syscall.Handle(h), &i)
231
 
        if e != nil {
232
 
                return e
233
 
        }
234
 
        s.path = ""
235
 
        s.vol = i.VolumeSerialNumber
236
 
        s.idxhi = i.FileIndexHigh
237
 
        s.idxlo = i.FileIndexLow
238
 
        return nil
239
 
}
240
 
 
241
 
func sameFile(sys1, sys2 interface{}) bool {
242
 
        s1 := sys1.(*winSys)
243
 
        s2 := sys2.(*winSys)
244
 
        e := s1.loadFileId()
245
 
        if e != nil {
246
 
                panic(e)
247
 
        }
248
 
        e = s2.loadFileId()
249
 
        if e != nil {
250
 
                panic(e)
251
 
        }
252
 
        return s1.vol == s2.vol && s1.idxhi == s2.idxhi && s1.idxlo == s2.idxlo
253
 
}
254
 
 
255
 
// For testing.
256
 
func atime(fi FileInfo) time.Time {
257
 
        return time.Unix(0, fi.Sys().(*winSys).atime.Nanoseconds())
258
 
}