mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 05:59:14 +00:00
Use access syscall.
This commit is contained in:
45
vfs.go
45
vfs.go
@@ -9,7 +9,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/ncruces/julianday"
|
||||
@@ -185,47 +184,14 @@ func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath, syncDir uint32)
|
||||
}
|
||||
|
||||
func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath uint32, flags _AccessFlag, pResOut uint32) uint32 {
|
||||
// Consider using [syscall.Access] for [ACCESS_READWRITE]/[ACCESS_READ]
|
||||
// (as the Unix VFS does).
|
||||
|
||||
path := memory{mod}.readString(zPath, _MAX_PATHNAME)
|
||||
fi, err := os.Stat(path)
|
||||
|
||||
ok, rc := vfsOS.Access(path, flags)
|
||||
var res uint32
|
||||
switch {
|
||||
case flags == _ACCESS_EXISTS:
|
||||
switch {
|
||||
case err == nil:
|
||||
res = 1
|
||||
case errors.Is(err, fs.ErrNotExist):
|
||||
res = 0
|
||||
default:
|
||||
return uint32(IOERR_ACCESS)
|
||||
}
|
||||
|
||||
case err == nil:
|
||||
var want fs.FileMode = syscall.S_IRUSR
|
||||
if flags == _ACCESS_READWRITE {
|
||||
want |= syscall.S_IWUSR
|
||||
}
|
||||
if fi.IsDir() {
|
||||
want |= syscall.S_IXUSR
|
||||
}
|
||||
if fi.Mode()&want == want {
|
||||
res = 1
|
||||
} else {
|
||||
res = 0
|
||||
}
|
||||
|
||||
case errors.Is(err, fs.ErrPermission):
|
||||
res = 0
|
||||
|
||||
default:
|
||||
return uint32(IOERR_ACCESS)
|
||||
if ok {
|
||||
res = 1
|
||||
}
|
||||
|
||||
memory{mod}.writeUint32(pResOut, res)
|
||||
return _OK
|
||||
return uint32(rc)
|
||||
}
|
||||
|
||||
func vfsOpen(ctx context.Context, mod api.Module, pVfs, zName, pFile uint32, flags OpenFlag, pOutFlags uint32) uint32 {
|
||||
@@ -322,9 +288,6 @@ func vfsSync(ctx context.Context, mod api.Module, pFile, flags uint32) uint32 {
|
||||
}
|
||||
|
||||
func vfsFileSize(ctx context.Context, mod api.Module, pFile, pSize uint32) uint32 {
|
||||
// This uses [os.File.Seek] because we don't care about the offset for reading/writing.
|
||||
// But consider using [os.File.Stat] instead (as other VFSes do).
|
||||
|
||||
file := vfsFile.GetOS(ctx, mod, pFile)
|
||||
off, err := file.Seek(0, io.SeekEnd)
|
||||
if err != nil {
|
||||
|
||||
78
vfs_unix.go
78
vfs_unix.go
@@ -3,15 +3,33 @@
|
||||
package sqlite3
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func (vfsOSMethods) OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) {
|
||||
func (vfsOSMethods) OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
|
||||
return os.OpenFile(name, flag, perm)
|
||||
}
|
||||
|
||||
func (vfsOSMethods) Access(path string, flags _AccessFlag) (bool, xErrorCode) {
|
||||
var access uint32 = unix.F_OK
|
||||
switch flags {
|
||||
case _ACCESS_READWRITE:
|
||||
access = unix.R_OK | unix.W_OK
|
||||
case _ACCESS_READ:
|
||||
access = unix.R_OK
|
||||
}
|
||||
|
||||
err := unix.Access(path, access)
|
||||
if err == nil {
|
||||
return true, _OK
|
||||
}
|
||||
return false, _OK
|
||||
}
|
||||
|
||||
func (vfsOSMethods) GetExclusiveLock(file *os.File) xErrorCode {
|
||||
// Acquire the EXCLUSIVE lock.
|
||||
return vfsOS.writeLock(file, _SHARED_FIRST, _SHARED_SIZE)
|
||||
@@ -39,8 +57,8 @@ func (vfsOSMethods) ReleaseLock(file *os.File, _ vfsLockState) xErrorCode {
|
||||
}
|
||||
|
||||
func (vfsOSMethods) unlock(file *os.File, start, len int64) xErrorCode {
|
||||
err := vfsOS.fcntlSetLock(file, &syscall.Flock_t{
|
||||
Type: syscall.F_UNLCK,
|
||||
err := vfsOS.fcntlSetLock(file, &unix.Flock_t{
|
||||
Type: unix.F_UNLCK,
|
||||
Start: start,
|
||||
Len: len,
|
||||
})
|
||||
@@ -51,85 +69,85 @@ func (vfsOSMethods) unlock(file *os.File, start, len int64) xErrorCode {
|
||||
}
|
||||
|
||||
func (vfsOSMethods) readLock(file *os.File, start, len int64) xErrorCode {
|
||||
return vfsOS.lockErrorCode(vfsOS.fcntlSetLock(file, &syscall.Flock_t{
|
||||
Type: syscall.F_RDLCK,
|
||||
return vfsOS.lockErrorCode(vfsOS.fcntlSetLock(file, &unix.Flock_t{
|
||||
Type: unix.F_RDLCK,
|
||||
Start: start,
|
||||
Len: len,
|
||||
}), IOERR_RDLOCK)
|
||||
}
|
||||
|
||||
func (vfsOSMethods) writeLock(file *os.File, start, len int64) xErrorCode {
|
||||
return vfsOS.lockErrorCode(vfsOS.fcntlSetLock(file, &syscall.Flock_t{
|
||||
Type: syscall.F_WRLCK,
|
||||
return vfsOS.lockErrorCode(vfsOS.fcntlSetLock(file, &unix.Flock_t{
|
||||
Type: unix.F_WRLCK,
|
||||
Start: start,
|
||||
Len: len,
|
||||
}), IOERR_LOCK)
|
||||
}
|
||||
|
||||
func (vfsOSMethods) checkLock(file *os.File, start, len int64) (bool, xErrorCode) {
|
||||
lock := syscall.Flock_t{
|
||||
Type: syscall.F_RDLCK,
|
||||
lock := unix.Flock_t{
|
||||
Type: unix.F_RDLCK,
|
||||
Start: start,
|
||||
Len: len,
|
||||
}
|
||||
if vfsOS.fcntlGetLock(file, &lock) != nil {
|
||||
return false, IOERR_CHECKRESERVEDLOCK
|
||||
}
|
||||
return lock.Type != syscall.F_UNLCK, _OK
|
||||
return lock.Type != unix.F_UNLCK, _OK
|
||||
}
|
||||
|
||||
func (vfsOSMethods) fcntlGetLock(file *os.File, lock *syscall.Flock_t) error {
|
||||
func (vfsOSMethods) fcntlGetLock(file *os.File, lock *unix.Flock_t) error {
|
||||
var F_OFD_GETLK int
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/fcntl.h
|
||||
F_OFD_GETLK = 36 // F_OFD_GETLK
|
||||
F_OFD_GETLK = 36
|
||||
case "darwin":
|
||||
// https://github.com/apple/darwin-xnu/blob/main/bsd/sys/fcntl.h
|
||||
F_OFD_GETLK = 92 // F_OFD_GETLK
|
||||
F_OFD_GETLK = 92
|
||||
case "illumos":
|
||||
// https://github.com/illumos/illumos-gate/blob/master/usr/src/uts/common/sys/fcntl.h
|
||||
F_OFD_GETLK = 47 // F_OFD_GETLK
|
||||
F_OFD_GETLK = 47
|
||||
default:
|
||||
return notImplErr
|
||||
}
|
||||
return syscall.FcntlFlock(file.Fd(), F_OFD_GETLK, lock)
|
||||
return unix.FcntlFlock(file.Fd(), F_OFD_GETLK, lock)
|
||||
}
|
||||
|
||||
func (vfsOSMethods) fcntlSetLock(file *os.File, lock *syscall.Flock_t) error {
|
||||
func (vfsOSMethods) fcntlSetLock(file *os.File, lock *unix.Flock_t) error {
|
||||
var F_OFD_SETLK int
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/fcntl.h
|
||||
F_OFD_SETLK = 37 // F_OFD_SETLK
|
||||
F_OFD_SETLK = 37
|
||||
case "darwin":
|
||||
// https://github.com/apple/darwin-xnu/blob/main/bsd/sys/fcntl.h
|
||||
F_OFD_SETLK = 90 // F_OFD_SETLK
|
||||
F_OFD_SETLK = 90
|
||||
case "illumos":
|
||||
// https://github.com/illumos/illumos-gate/blob/master/usr/src/uts/common/sys/fcntl.h
|
||||
F_OFD_SETLK = 48 // F_OFD_SETLK
|
||||
F_OFD_SETLK = 48
|
||||
default:
|
||||
return notImplErr
|
||||
}
|
||||
return syscall.FcntlFlock(file.Fd(), F_OFD_SETLK, lock)
|
||||
return unix.FcntlFlock(file.Fd(), F_OFD_SETLK, lock)
|
||||
}
|
||||
|
||||
func (vfsOSMethods) lockErrorCode(err error, def xErrorCode) xErrorCode {
|
||||
if err == nil {
|
||||
return _OK
|
||||
}
|
||||
if errno, ok := err.(syscall.Errno); ok {
|
||||
if errno, ok := err.(unix.Errno); ok {
|
||||
switch errno {
|
||||
case
|
||||
syscall.EACCES,
|
||||
syscall.EAGAIN,
|
||||
syscall.EBUSY,
|
||||
syscall.EINTR,
|
||||
syscall.ENOLCK,
|
||||
syscall.EDEADLK,
|
||||
syscall.ETIMEDOUT:
|
||||
unix.EACCES,
|
||||
unix.EAGAIN,
|
||||
unix.EBUSY,
|
||||
unix.EINTR,
|
||||
unix.ENOLCK,
|
||||
unix.EDEADLK,
|
||||
unix.ETIMEDOUT:
|
||||
return xErrorCode(BUSY)
|
||||
case syscall.EPERM:
|
||||
case unix.EPERM:
|
||||
return xErrorCode(PERM)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,54 @@
|
||||
package sqlite3
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func (vfsOSMethods) OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) {
|
||||
func (vfsOSMethods) OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
|
||||
return osOpenFile(name, flag, perm)
|
||||
}
|
||||
|
||||
func (vfsOSMethods) Access(path string, flags _AccessFlag) (bool, xErrorCode) {
|
||||
fi, err := os.Stat(path)
|
||||
|
||||
switch {
|
||||
case flags == _ACCESS_EXISTS:
|
||||
switch {
|
||||
case err == nil:
|
||||
return true, _OK
|
||||
case errors.Is(err, fs.ErrNotExist):
|
||||
return false, _OK
|
||||
default:
|
||||
return false, IOERR_ACCESS
|
||||
}
|
||||
|
||||
case err == nil:
|
||||
var want fs.FileMode = syscall.S_IRUSR
|
||||
if flags == _ACCESS_READWRITE {
|
||||
want |= syscall.S_IWUSR
|
||||
}
|
||||
if fi.IsDir() {
|
||||
want |= syscall.S_IXUSR
|
||||
}
|
||||
if fi.Mode()&want == want {
|
||||
return true, _OK
|
||||
} else {
|
||||
return false, _OK
|
||||
}
|
||||
|
||||
case errors.Is(err, fs.ErrPermission):
|
||||
return false, _OK
|
||||
|
||||
default:
|
||||
return false, IOERR_ACCESS
|
||||
}
|
||||
}
|
||||
|
||||
func (vfsOSMethods) GetExclusiveLock(file *os.File) xErrorCode {
|
||||
// Release the SHARED lock.
|
||||
vfsOS.unlock(file, _SHARED_FIRST, _SHARED_SIZE)
|
||||
|
||||
Reference in New Issue
Block a user