github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/os/file_windows.go (about) 1 //go:build windows 2 3 // Portions copyright 2009 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 package os 8 9 import ( 10 "internal/syscall/windows" 11 "syscall" 12 "unicode/utf16" 13 ) 14 15 const DevNull = "NUL" 16 17 type syscallFd = syscall.Handle 18 19 // Symlink is a stub, it is not implemented. 20 func Symlink(oldname, newname string) error { 21 return ErrNotImplemented 22 } 23 24 // Readlink is a stub (for now), always returning the string it was given 25 func Readlink(name string) (string, error) { 26 return name, nil 27 } 28 29 func rename(oldname, newname string) error { 30 e := windows.Rename(fixLongPath(oldname), fixLongPath(newname)) 31 if e != nil { 32 return &LinkError{"rename", oldname, newname, e} 33 } 34 return nil 35 } 36 37 type file struct { 38 handle FileHandle 39 name string 40 appendMode bool 41 } 42 43 func (f *file) close() error { 44 return f.handle.Close() 45 } 46 47 func NewFile(fd uintptr, name string) *File { 48 return &File{&file{handle: unixFileHandle(fd), name: name}} 49 } 50 51 func Pipe() (r *File, w *File, err error) { 52 var p [2]syscall.Handle 53 e := handleSyscallError(syscall.Pipe(p[:])) 54 if e != nil { 55 return nil, nil, err 56 } 57 r = NewFile(uintptr(p[0]), "|0") 58 w = NewFile(uintptr(p[1]), "|1") 59 return 60 } 61 62 func tempDir() string { 63 n := uint32(syscall.MAX_PATH) 64 for { 65 b := make([]uint16, n) 66 n, _ = syscall.GetTempPath(uint32(len(b)), &b[0]) 67 if n > uint32(len(b)) { 68 continue 69 } 70 if n == 3 && b[1] == ':' && b[2] == '\\' { 71 // Do nothing for path, like C:\. 72 } else if n > 0 && b[n-1] == '\\' { 73 // Otherwise remove terminating \. 74 n-- 75 } 76 return string(utf16.Decode(b[:n])) 77 } 78 } 79 80 // ReadAt reads up to len(b) bytes from the File starting at the given absolute offset. 81 // It returns the number of bytes read and any error encountered, possibly io.EOF. 82 // At end of file, Pread returns 0, io.EOF. 83 // TODO: move to file_anyos once ReadAt is implemented for windows 84 func (f unixFileHandle) ReadAt(b []byte, offset int64) (n int, err error) { 85 return -1, ErrNotImplemented 86 } 87 88 // WriteAt writes len(b) bytes to the File starting at byte offset off. 89 // It returns the number of bytes written and an error, if any. 90 // WriteAt returns a non-nil error when n != len(b). 91 // 92 // If file was opened with the O_APPEND flag, WriteAt returns an error. 93 // 94 // TODO: move to file_anyos once WriteAt is implemented for windows. 95 func (f unixFileHandle) WriteAt(b []byte, offset int64) (n int, err error) { 96 return -1, ErrNotImplemented 97 } 98 99 // Seek wraps syscall.Seek. 100 func (f unixFileHandle) Seek(offset int64, whence int) (int64, error) { 101 newoffset, err := syscall.Seek(syscallFd(f), offset, whence) 102 return newoffset, handleSyscallError(err) 103 } 104 105 func (f unixFileHandle) Sync() error { 106 return ErrNotImplemented 107 } 108 109 // isWindowsNulName reports whether name is os.DevNull ('NUL') on Windows. 110 // True is returned if name is 'NUL' whatever the case. 111 func isWindowsNulName(name string) bool { 112 if len(name) != 3 { 113 return false 114 } 115 if name[0] != 'n' && name[0] != 'N' { 116 return false 117 } 118 if name[1] != 'u' && name[1] != 'U' { 119 return false 120 } 121 if name[2] != 'l' && name[2] != 'L' { 122 return false 123 } 124 return true 125 }