func (file *file) close() error { if file == nil { return syscall.EINVAL } if file.isdir() && file.dirinfo.isempty { // "special" empty directories return nil } if file.fd == syscall.InvalidHandle { return syscall.EINVAL } var e error if file.isdir() { e = syscall.FindClose(syscall.Handle(file.fd)) } else { e = syscall.CloseHandle(syscall.Handle(file.fd)) } var err error if e != nil { err = &PathError{"close", file.name, e} } file.fd = syscall.InvalidHandle // so it can't be closed again // no need for a finalizer anymore runtime.SetFinalizer(file, nil) return err }
// normBase retruns the last element of path. func normBase(path string) (string, error) { p, err := syscall.UTF16PtrFromString(path) if err != nil { return "", err } var data syscall.Win32finddata h, err := syscall.FindFirstFile(p, &data) if err != nil { return "", err } syscall.FindClose(h) return syscall.UTF16ToString(data.FileName[:]), nil }
// Close closes the File, rendering it unusable for I/O. // It returns an Error, if any. func (file *File) Close() Error { if file == nil || file.fd < 0 { return EINVAL } var e int if file.isdir() { e = syscall.FindClose(syscall.Handle(file.fd)) } else { e = syscall.CloseHandle(syscall.Handle(file.fd)) } var err Error if e != 0 { err = &PathError{"close", file.name, Errno(e)} } file.fd = syscall.InvalidHandle // so it can't be closed again // no need for a finalizer anymore runtime.SetFinalizer(file, nil) return err }
// Lstat returns the FileInfo structure describing the named file. // If the file is a symbolic link, the returned FileInfo // describes the symbolic link. Lstat makes no attempt to follow the link. // If there is an error, it will be of type *PathError. func Lstat(name string) (FileInfo, error) { if len(name) == 0 { return nil, &PathError{"Lstat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)} } if name == DevNull { return &devNullStat, nil } fs := &fileStat{name: basename(name)} namep, e := syscall.UTF16PtrFromString(fixLongPath(name)) if e != nil { return nil, &PathError{"Lstat", name, e} } e = syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fs.sys))) if e != nil { if e != windows.ERROR_SHARING_VIOLATION { return nil, &PathError{"GetFileAttributesEx", name, e} } // try FindFirstFile now that GetFileAttributesEx failed var fd syscall.Win32finddata h, e2 := syscall.FindFirstFile(namep, &fd) if e2 != nil { return nil, &PathError{"FindFirstFile", name, e} } syscall.FindClose(h) fs.sys.FileAttributes = fd.FileAttributes fs.sys.CreationTime = fd.CreationTime fs.sys.LastAccessTime = fd.LastAccessTime fs.sys.LastWriteTime = fd.LastWriteTime fs.sys.FileSizeHigh = fd.FileSizeHigh fs.sys.FileSizeLow = fd.FileSizeLow } fs.path = name if !isAbs(fs.path) { fs.path, e = syscall.FullPath(fs.path) if e != nil { return nil, e } } return fs, nil }
func TestWin32finddata(t *testing.T) { dir, err := ioutil.TempDir("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } defer os.RemoveAll(dir) path := filepath.Join(dir, "long_name.and_extension") f, err := os.Create(path) if err != nil { t.Fatalf("failed to create %v: %v", path, err) } f.Close() type X struct { fd syscall.Win32finddata got byte pad [10]byte // to protect ourselves } var want byte = 2 // it is unlikely to have this character in the filename x := X{got: want} pathp, _ := syscall.UTF16PtrFromString(path) h, err := syscall.FindFirstFile(pathp, &(x.fd)) if err != nil { t.Fatalf("FindFirstFile failed: %v", err) } err = syscall.FindClose(h) if err != nil { t.Fatalf("FindClose failed: %v", err) } if x.got != want { t.Fatalf("memory corruption: want=%d got=%d", want, x.got) } }
func (this *FileInfo) close() { syscall.FindClose(this.handle) }