...

Source file src/os/file_posix.go

Documentation: os

		 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  //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
		 6  // +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows
		 7  
		 8  package os
		 9  
		10  import (
		11  	"runtime"
		12  	"syscall"
		13  	"time"
		14  )
		15  
		16  func sigpipe() // implemented in package runtime
		17  
		18  // Close closes the File, rendering it unusable for I/O.
		19  // On files that support SetDeadline, any pending I/O operations will
		20  // be canceled and return immediately with an error.
		21  // Close will return an error if it has already been called.
		22  func (f *File) Close() error {
		23  	if f == nil {
		24  		return ErrInvalid
		25  	}
		26  	return f.file.close()
		27  }
		28  
		29  // read reads up to len(b) bytes from the File.
		30  // It returns the number of bytes read and an error, if any.
		31  func (f *File) read(b []byte) (n int, err error) {
		32  	n, err = f.pfd.Read(b)
		33  	runtime.KeepAlive(f)
		34  	return n, err
		35  }
		36  
		37  // pread reads len(b) bytes from the File starting at byte offset off.
		38  // It returns the number of bytes read and the error, if any.
		39  // EOF is signaled by a zero count with err set to nil.
		40  func (f *File) pread(b []byte, off int64) (n int, err error) {
		41  	n, err = f.pfd.Pread(b, off)
		42  	runtime.KeepAlive(f)
		43  	return n, err
		44  }
		45  
		46  // write writes len(b) bytes to the File.
		47  // It returns the number of bytes written and an error, if any.
		48  func (f *File) write(b []byte) (n int, err error) {
		49  	n, err = f.pfd.Write(b)
		50  	runtime.KeepAlive(f)
		51  	return n, err
		52  }
		53  
		54  // pwrite writes len(b) bytes to the File starting at byte offset off.
		55  // It returns the number of bytes written and an error, if any.
		56  func (f *File) pwrite(b []byte, off int64) (n int, err error) {
		57  	n, err = f.pfd.Pwrite(b, off)
		58  	runtime.KeepAlive(f)
		59  	return n, err
		60  }
		61  
		62  // syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
		63  func syscallMode(i FileMode) (o uint32) {
		64  	o |= uint32(i.Perm())
		65  	if i&ModeSetuid != 0 {
		66  		o |= syscall.S_ISUID
		67  	}
		68  	if i&ModeSetgid != 0 {
		69  		o |= syscall.S_ISGID
		70  	}
		71  	if i&ModeSticky != 0 {
		72  		o |= syscall.S_ISVTX
		73  	}
		74  	// No mapping for Go's ModeTemporary (plan9 only).
		75  	return
		76  }
		77  
		78  // See docs in file.go:Chmod.
		79  func chmod(name string, mode FileMode) error {
		80  	longName := fixLongPath(name)
		81  	e := ignoringEINTR(func() error {
		82  		return syscall.Chmod(longName, syscallMode(mode))
		83  	})
		84  	if e != nil {
		85  		return &PathError{Op: "chmod", Path: name, Err: e}
		86  	}
		87  	return nil
		88  }
		89  
		90  // See docs in file.go:(*File).Chmod.
		91  func (f *File) chmod(mode FileMode) error {
		92  	if err := f.checkValid("chmod"); err != nil {
		93  		return err
		94  	}
		95  	if e := f.pfd.Fchmod(syscallMode(mode)); e != nil {
		96  		return f.wrapErr("chmod", e)
		97  	}
		98  	return nil
		99  }
	 100  
	 101  // Chown changes the numeric uid and gid of the named file.
	 102  // If the file is a symbolic link, it changes the uid and gid of the link's target.
	 103  // A uid or gid of -1 means to not change that value.
	 104  // If there is an error, it will be of type *PathError.
	 105  //
	 106  // On Windows or Plan 9, Chown always returns the syscall.EWINDOWS or
	 107  // EPLAN9 error, wrapped in *PathError.
	 108  func Chown(name string, uid, gid int) error {
	 109  	e := ignoringEINTR(func() error {
	 110  		return syscall.Chown(name, uid, gid)
	 111  	})
	 112  	if e != nil {
	 113  		return &PathError{Op: "chown", Path: name, Err: e}
	 114  	}
	 115  	return nil
	 116  }
	 117  
	 118  // Lchown changes the numeric uid and gid of the named file.
	 119  // If the file is a symbolic link, it changes the uid and gid of the link itself.
	 120  // If there is an error, it will be of type *PathError.
	 121  //
	 122  // On Windows, it always returns the syscall.EWINDOWS error, wrapped
	 123  // in *PathError.
	 124  func Lchown(name string, uid, gid int) error {
	 125  	e := ignoringEINTR(func() error {
	 126  		return syscall.Lchown(name, uid, gid)
	 127  	})
	 128  	if e != nil {
	 129  		return &PathError{Op: "lchown", Path: name, Err: e}
	 130  	}
	 131  	return nil
	 132  }
	 133  
	 134  // Chown changes the numeric uid and gid of the named file.
	 135  // If there is an error, it will be of type *PathError.
	 136  //
	 137  // On Windows, it always returns the syscall.EWINDOWS error, wrapped
	 138  // in *PathError.
	 139  func (f *File) Chown(uid, gid int) error {
	 140  	if err := f.checkValid("chown"); err != nil {
	 141  		return err
	 142  	}
	 143  	if e := f.pfd.Fchown(uid, gid); e != nil {
	 144  		return f.wrapErr("chown", e)
	 145  	}
	 146  	return nil
	 147  }
	 148  
	 149  // Truncate changes the size of the file.
	 150  // It does not change the I/O offset.
	 151  // If there is an error, it will be of type *PathError.
	 152  func (f *File) Truncate(size int64) error {
	 153  	if err := f.checkValid("truncate"); err != nil {
	 154  		return err
	 155  	}
	 156  	if e := f.pfd.Ftruncate(size); e != nil {
	 157  		return f.wrapErr("truncate", e)
	 158  	}
	 159  	return nil
	 160  }
	 161  
	 162  // Sync commits the current contents of the file to stable storage.
	 163  // Typically, this means flushing the file system's in-memory copy
	 164  // of recently written data to disk.
	 165  func (f *File) Sync() error {
	 166  	if err := f.checkValid("sync"); err != nil {
	 167  		return err
	 168  	}
	 169  	if e := f.pfd.Fsync(); e != nil {
	 170  		return f.wrapErr("sync", e)
	 171  	}
	 172  	return nil
	 173  }
	 174  
	 175  // Chtimes changes the access and modification times of the named
	 176  // file, similar to the Unix utime() or utimes() functions.
	 177  //
	 178  // The underlying filesystem may truncate or round the values to a
	 179  // less precise time unit.
	 180  // If there is an error, it will be of type *PathError.
	 181  func Chtimes(name string, atime time.Time, mtime time.Time) error {
	 182  	var utimes [2]syscall.Timespec
	 183  	utimes[0] = syscall.NsecToTimespec(atime.UnixNano())
	 184  	utimes[1] = syscall.NsecToTimespec(mtime.UnixNano())
	 185  	if e := syscall.UtimesNano(fixLongPath(name), utimes[0:]); e != nil {
	 186  		return &PathError{Op: "chtimes", Path: name, Err: e}
	 187  	}
	 188  	return nil
	 189  }
	 190  
	 191  // Chdir changes the current working directory to the file,
	 192  // which must be a directory.
	 193  // If there is an error, it will be of type *PathError.
	 194  func (f *File) Chdir() error {
	 195  	if err := f.checkValid("chdir"); err != nil {
	 196  		return err
	 197  	}
	 198  	if e := f.pfd.Fchdir(); e != nil {
	 199  		return f.wrapErr("chdir", e)
	 200  	}
	 201  	return nil
	 202  }
	 203  
	 204  // setDeadline sets the read and write deadline.
	 205  func (f *File) setDeadline(t time.Time) error {
	 206  	if err := f.checkValid("SetDeadline"); err != nil {
	 207  		return err
	 208  	}
	 209  	return f.pfd.SetDeadline(t)
	 210  }
	 211  
	 212  // setReadDeadline sets the read deadline.
	 213  func (f *File) setReadDeadline(t time.Time) error {
	 214  	if err := f.checkValid("SetReadDeadline"); err != nil {
	 215  		return err
	 216  	}
	 217  	return f.pfd.SetReadDeadline(t)
	 218  }
	 219  
	 220  // setWriteDeadline sets the write deadline.
	 221  func (f *File) setWriteDeadline(t time.Time) error {
	 222  	if err := f.checkValid("SetWriteDeadline"); err != nil {
	 223  		return err
	 224  	}
	 225  	return f.pfd.SetWriteDeadline(t)
	 226  }
	 227  
	 228  // checkValid checks whether f is valid for use.
	 229  // If not, it returns an appropriate error, perhaps incorporating the operation name op.
	 230  func (f *File) checkValid(op string) error {
	 231  	if f == nil {
	 232  		return ErrInvalid
	 233  	}
	 234  	return nil
	 235  }
	 236  
	 237  // ignoringEINTR makes a function call and repeats it if it returns an
	 238  // EINTR error. This appears to be required even though we install all
	 239  // signal handlers with SA_RESTART: see #22838, #38033, #38836, #40846.
	 240  // Also #20400 and #36644 are issues in which a signal handler is
	 241  // installed without setting SA_RESTART. None of these are the common case,
	 242  // but there are enough of them that it seems that we can't avoid
	 243  // an EINTR loop.
	 244  func ignoringEINTR(fn func() error) error {
	 245  	for {
	 246  		err := fn()
	 247  		if err != syscall.EINTR {
	 248  			return err
	 249  		}
	 250  	}
	 251  }
	 252  

View as plain text