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  }