os_unix.go

  1//go:build unix
  2
  3package vfs
  4
  5import (
  6	"os"
  7	"syscall"
  8
  9	"golang.org/x/sys/unix"
 10)
 11
 12const (
 13	isUnix      = true
 14	_O_NOFOLLOW = unix.O_NOFOLLOW
 15)
 16
 17func osAccess(path string, flags AccessFlag) error {
 18	var access uint32 // unix.F_OK
 19	switch flags {
 20	case ACCESS_READWRITE:
 21		access = unix.R_OK | unix.W_OK
 22	case ACCESS_READ:
 23		access = unix.R_OK
 24	}
 25	return unix.Access(path, access)
 26}
 27
 28func osReadAt(file *os.File, p []byte, off int64) (int, error) {
 29	n, err := file.ReadAt(p, off)
 30	if errno, ok := err.(unix.Errno); ok {
 31		switch errno {
 32		case
 33			unix.ERANGE,
 34			unix.EIO,
 35			unix.ENXIO:
 36			return n, _IOERR_CORRUPTFS
 37		}
 38	}
 39	return n, err
 40}
 41
 42func osWriteAt(file *os.File, p []byte, off int64) (int, error) {
 43	n, err := file.WriteAt(p, off)
 44	if errno, ok := err.(unix.Errno); ok && errno == unix.ENOSPC {
 45		return n, _FULL
 46	}
 47	return n, err
 48}
 49
 50func osSetMode(file *os.File, modeof string) error {
 51	fi, err := os.Stat(modeof)
 52	if err != nil {
 53		return err
 54	}
 55	file.Chmod(fi.Mode())
 56	if sys, ok := fi.Sys().(*syscall.Stat_t); ok {
 57		file.Chown(int(sys.Uid), int(sys.Gid))
 58	}
 59	return nil
 60}
 61
 62func osTestLock(file *os.File, start, len int64) (int16, _ErrorCode) {
 63	lock := unix.Flock_t{
 64		Type:  unix.F_WRLCK,
 65		Start: start,
 66		Len:   len,
 67	}
 68	for {
 69		err := unix.FcntlFlock(file.Fd(), unix.F_GETLK, &lock)
 70		if err == nil {
 71			return lock.Type, _OK
 72		}
 73		if err != unix.EINTR {
 74			return 0, _IOERR_CHECKRESERVEDLOCK
 75		}
 76	}
 77}
 78
 79func osLockErrorCode(err error, def _ErrorCode) _ErrorCode {
 80	if err == nil {
 81		return _OK
 82	}
 83	if errno, ok := err.(unix.Errno); ok {
 84		switch errno {
 85		case
 86			unix.EACCES,
 87			unix.EAGAIN,
 88			unix.EBUSY,
 89			unix.EINTR,
 90			unix.ENOLCK,
 91			unix.EDEADLK,
 92			unix.ETIMEDOUT:
 93			return _BUSY
 94		case unix.EPERM:
 95			return _PERM
 96		}
 97		// notest // usually EWOULDBLOCK == EAGAIN
 98		if errno == unix.EWOULDBLOCK && unix.EWOULDBLOCK != unix.EAGAIN {
 99			return _BUSY
100		}
101	}
102	return def
103}