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}