diff options
| author | 2025-11-05 21:58:38 +0100 | |
|---|---|---|
| committer | 2025-11-17 14:12:41 +0100 | |
| commit | d0c551acb5ab79efafd325f5b19c76a3de835356 (patch) | |
| tree | ba9462cdc5081015fbd6bf5d98d9f39334d13207 /vendor/github.com/ncruces/go-sqlite3/vfs | |
| parent | [performance] when transforming media, perform read operations of large files... (diff) | |
| download | gotosocial-d0c551acb5ab79efafd325f5b19c76a3de835356.tar.xz | |
[chore] update dependencies (#4542)
- github.com/minio/minio-go/v7: v7.0.95 -> v7.0.97
- github.com/ncruces/go-sqlite3: v0.29.1 -> v0.30.0
- github.com/tdewolff/minify/v2: v2.24.5 -> v2.24.6
- codeberg.org/gruf/go-mmap: fixes build for BSD platforms
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4542
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
Diffstat (limited to 'vendor/github.com/ncruces/go-sqlite3/vfs')
20 files changed, 327 insertions, 271 deletions
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/README.md b/vendor/github.com/ncruces/go-sqlite3/vfs/README.md index 68cb92dcc..f34e08b64 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/README.md +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/README.md @@ -20,11 +20,12 @@ The main differences to be aware of are ### File Locking POSIX advisory locks, -which SQLite uses on [Unix](https://github.com/sqlite/sqlite/blob/5d60f4/src/os_unix.c#L13-L14), -are [broken by design](https://github.com/sqlite/sqlite/blob/5d60f4/src/os_unix.c#L1074-L1162). +which SQLite uses on [Unix](https://github.com/sqlite/sqlite/blob/41fda52/src/os_unix.c#L13-L14), +are [broken by design](https://github.com/sqlite/sqlite/blob/41fda52/src/os_unix.c#L1188-L1276). Instead, on Linux and macOS, this package uses -[OFD locks](https://gnu.org/software/libc/manual/html_node/Open-File-Description-Locks.html) +[OFD locks](https://sourceware.org/glibc/manual/2.25/html_node/Open-File-Description-Locks.html) to synchronize access to database files. +OFD locks require [Linux 3.15](https://lwn.net/Articles/586904/). This package can also use [BSD locks](https://man.freebsd.org/cgi/man.cgi?query=flock&sektion=2), @@ -73,7 +74,7 @@ to check if your build supports shared memory. ### Blocking Locks -On Windows and macOS, this package implements +On macOS, this package implements [Wal-mode blocking locks](https://sqlite.org/src/doc/tip/doc/wal-lock.md). ### Batch-Atomic Write diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/api.go b/vendor/github.com/ncruces/go-sqlite3/vfs/api.go index a0d36b214..4f4f833bb 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/api.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/api.go @@ -10,7 +10,8 @@ import ( // A VFS defines the interface between the SQLite core and the underlying operating system. // -// Use sqlite3.ErrorCode or sqlite3.ExtendedErrorCode to return specific error codes to SQLite. +// Use [SystemError], sqlite3.ErrorCode, or sqlite3.ExtendedErrorCode +// to return specific error codes to SQLite. // // https://sqlite.org/c3ref/vfs.html type VFS interface { @@ -31,8 +32,9 @@ type VFSFilename interface { // A File represents an open file in the OS interface layer. // -// Use sqlite3.ErrorCode or sqlite3.ExtendedErrorCode to return specific error codes to SQLite. -// In particular, sqlite3.BUSY is necessary to correctly implement lock methods. +// Use [SystemError], sqlite3.ErrorCode, or sqlite3.ExtendedErrorCode +// to return specific error codes to SQLite. +// In particular, sqlite3.BUSY is needed to correctly implement lock methods. // // https://sqlite.org/c3ref/io_methods.html type File interface { @@ -193,8 +195,8 @@ type FileSharedMemory interface { // SharedMemory is a shared-memory WAL-index implementation. // Use [NewSharedMemory] to create a shared-memory. type SharedMemory interface { - shmMap(context.Context, api.Module, int32, int32, bool) (ptr_t, _ErrorCode) - shmLock(int32, int32, _ShmFlag) _ErrorCode + shmMap(context.Context, api.Module, int32, int32, bool) (ptr_t, error) + shmLock(int32, int32, _ShmFlag) error shmUnmap(bool) shmBarrier() io.Closer @@ -205,6 +207,10 @@ type blockingSharedMemory interface { shmEnableBlocking(block bool) } +// FileControl makes it easy to forward all fileControl methods, +// which we want to do for the checksum VFS. +// However, this is not a safe default, and other VFSes +// should explicitly wrap the methods they want to wrap. type fileControl interface { File fileControl(ctx context.Context, mod api.Module, op _FcntlOpcode, pArg ptr_t) _ErrorCode diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/const.go b/vendor/github.com/ncruces/go-sqlite3/vfs/const.go index 9ed67e385..ffb84dd76 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/const.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/const.go @@ -20,11 +20,11 @@ type ( type _ErrorCode uint32 func (e _ErrorCode) Error() string { - return util.ErrorCodeString(uint32(e)) + return util.ErrorCodeString(e) } const ( - _OK _ErrorCode = util.OK + _OK = util.OK _ERROR _ErrorCode = util.ERROR _PERM _ErrorCode = util.PERM _BUSY _ErrorCode = util.BUSY diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/file.go b/vendor/github.com/ncruces/go-sqlite3/vfs/file.go index bdebdf6aa..1ae6cdd9c 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/file.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/file.go @@ -40,7 +40,7 @@ func evalSymlinks(path string) (string, error) { func (vfsOS) Delete(path string, syncDir bool) error { err := os.Remove(path) if errors.Is(err, fs.ErrNotExist) { - return _IOERR_DELETE_NOENT + return sysError{err, _IOERR_DELETE_NOENT} } if err != nil { return err @@ -48,12 +48,12 @@ func (vfsOS) Delete(path string, syncDir bool) error { if isUnix && syncDir { f, err := os.Open(filepath.Dir(path)) if err != nil { - return _OK + return nil } defer f.Close() err = osSync(f, 0, SYNC_FULL) if err != nil { - return _IOERR_DIR_FSYNC + return sysError{err, _IOERR_DIR_FSYNC} } } return nil @@ -108,14 +108,14 @@ func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error } if err != nil { if name == nil { - return nil, flags, _IOERR_GETTEMPPATH + return nil, flags, sysError{err, _IOERR_GETTEMPPATH} } if errors.Is(err, syscall.EISDIR) { - return nil, flags, _CANTOPEN_ISDIR + return nil, flags, sysError{err, _CANTOPEN_ISDIR} } if isCreate && isJournl && errors.Is(err, fs.ErrPermission) && osAccess(name.String(), ACCESS_EXISTS) != nil { - return nil, flags, _READONLY_DIRECTORY + return nil, flags, sysError{err, _READONLY_DIRECTORY} } return nil, flags, err } @@ -123,7 +123,7 @@ func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error if modeof := name.URIParameter("modeof"); modeof != "" { if err = osSetMode(f, modeof); err != nil { f.Close() - return nil, flags, _IOERR_FSTAT + return nil, flags, sysError{err, _IOERR_FSTAT} } } if isUnix && flags&OPEN_DELETEONCLOSE != 0 { @@ -193,7 +193,7 @@ func (f *vfsFile) Sync(flags SyncFlag) error { defer d.Close() err = osSync(f.File, f.flags, flags) if err != nil { - return _IOERR_DIR_FSYNC + return sysError{err, _IOERR_DIR_FSYNC} } } return nil diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go b/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go index be16b3dde..4d4fc4ae7 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go @@ -120,7 +120,7 @@ func (n *Filename) URIParameter(key string) string { } // Parse the format from: - // https://github.com/sqlite/sqlite/blob/b74eb0/src/pager.c#L4797-L4840 + // https://github.com/sqlite/sqlite/blob/41fda52/src/pager.c#L4821-L4864 // This avoids having to alloc/free the key just to find a value. for { k := util.ReadString(n.mod, ptr, _MAX_NAME) @@ -160,7 +160,7 @@ func (n *Filename) URIParameters() url.Values { var params url.Values // Parse the format from: - // https://github.com/sqlite/sqlite/blob/b74eb0/src/pager.c#L4797-L4840 + // https://github.com/sqlite/sqlite/blob/41fda52/src/pager.c#L4821-L4864 // This is the only way to support multiple valued keys. for { k := util.ReadString(n.mod, ptr, _MAX_NAME) diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go b/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go index 253057aea..84c6e8da0 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go @@ -51,8 +51,8 @@ func (f *vfsFile) Lock(lock LockLevel) error { if f.lock != LOCK_NONE { panic(util.AssertErr()) } - if rc := osGetSharedLock(f.File); rc != _OK { - return rc + if err := osGetSharedLock(f.File); err != nil { + return err } f.lock = LOCK_SHARED return nil @@ -62,8 +62,8 @@ func (f *vfsFile) Lock(lock LockLevel) error { if f.lock != LOCK_SHARED { panic(util.AssertErr()) } - if rc := osGetReservedLock(f.File); rc != _OK { - return rc + if err := osGetReservedLock(f.File); err != nil { + return err } f.lock = LOCK_RESERVED return nil @@ -73,8 +73,8 @@ func (f *vfsFile) Lock(lock LockLevel) error { if f.lock <= LOCK_NONE || f.lock >= LOCK_EXCLUSIVE { panic(util.AssertErr()) } - if rc := osGetExclusiveLock(f.File, &f.lock); rc != _OK { - return rc + if err := osGetExclusiveLock(f.File, &f.lock); err != nil { + return err } f.lock = LOCK_EXCLUSIVE return nil @@ -101,14 +101,14 @@ func (f *vfsFile) Unlock(lock LockLevel) error { switch lock { case LOCK_SHARED: - rc := osDowngradeLock(f.File, f.lock) + err := osDowngradeLock(f.File, f.lock) f.lock = LOCK_SHARED - return rc + return err case LOCK_NONE: - rc := osReleaseLock(f.File, f.lock) + err := osReleaseLock(f.File, f.lock) f.lock = LOCK_NONE - return rc + return err default: panic(util.AssertErr()) diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_bsd.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_bsd.go index 4542f8e7c..a70579d2c 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_bsd.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_bsd.go @@ -8,13 +8,13 @@ import ( "golang.org/x/sys/unix" ) -func osGetSharedLock(file *os.File) _ErrorCode { +func osGetSharedLock(file *os.File) error { return osFlock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK) } -func osGetReservedLock(file *os.File) _ErrorCode { - rc := osFlock(file, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK) - if rc == _BUSY { +func osGetReservedLock(file *os.File) error { + err := osFlock(file, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK) + if err == _BUSY { // The documentation states that a lock is upgraded by // releasing the previous lock, then acquiring the new lock. // Going over the source code of various BSDs, though, @@ -26,19 +26,19 @@ func osGetReservedLock(file *os.File) _ErrorCode { // and invoke the busy handler if appropriate. return _BUSY_SNAPSHOT } - return rc + return err } -func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode { +func osGetExclusiveLock(file *os.File, state *LockLevel) error { if *state >= LOCK_RESERVED { - return _OK + return nil } return osGetReservedLock(file) } -func osDowngradeLock(file *os.File, _ LockLevel) _ErrorCode { - rc := osFlock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK) - if rc == _BUSY { +func osDowngradeLock(file *os.File, _ LockLevel) error { + err := osFlock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK) + if err == _BUSY { // The documentation states that a lock is downgraded by // releasing the previous lock then acquiring the new lock. // Going over the source code of various BSDs, though, @@ -46,44 +46,44 @@ func osDowngradeLock(file *os.File, _ LockLevel) _ErrorCode { // Return IOERR_RDLOCK, as BUSY would cause an assert to fail. return _IOERR_RDLOCK } - return _OK + return err } -func osReleaseLock(file *os.File, _ LockLevel) _ErrorCode { +func osReleaseLock(file *os.File, _ LockLevel) error { for { err := unix.Flock(int(file.Fd()), unix.LOCK_UN) if err == nil { - return _OK + return nil } if err != unix.EINTR { - return _IOERR_UNLOCK + return sysError{err, _IOERR_UNLOCK} } } } -func osCheckReservedLock(file *os.File) (bool, _ErrorCode) { +func osCheckReservedLock(file *os.File) (bool, error) { // Test the RESERVED lock with fcntl(F_GETLK). // This only works on systems where fcntl and flock are compatible. // However, SQLite only calls this while holding a shared lock, // so the difference is immaterial. - lock, rc := osTestLock(file, _RESERVED_BYTE, 1) - return lock == unix.F_WRLCK, rc + lock, err := osTestLock(file, _RESERVED_BYTE, 1, _IOERR_CHECKRESERVEDLOCK) + return lock == unix.F_WRLCK, err } -func osFlock(file *os.File, how int, def _ErrorCode) _ErrorCode { +func osFlock(file *os.File, how int, def _ErrorCode) error { err := unix.Flock(int(file.Fd()), how) return osLockErrorCode(err, def) } -func osReadLock(file *os.File, start, len int64) _ErrorCode { +func osReadLock(file *os.File, start, len int64) error { return osLock(file, unix.F_RDLCK, start, len, _IOERR_RDLOCK) } -func osWriteLock(file *os.File, start, len int64) _ErrorCode { +func osWriteLock(file *os.File, start, len int64) error { return osLock(file, unix.F_WRLCK, start, len, _IOERR_LOCK) } -func osLock(file *os.File, typ int16, start, len int64, def _ErrorCode) _ErrorCode { +func osLock(file *os.File, typ int16, start, len int64, def _ErrorCode) error { err := unix.FcntlFlock(file.Fd(), unix.F_SETLK, &unix.Flock_t{ Type: typ, Start: start, @@ -92,7 +92,7 @@ func osLock(file *os.File, typ int16, start, len int64, def _ErrorCode) _ErrorCo return osLockErrorCode(err, def) } -func osUnlock(file *os.File, start, len int64) _ErrorCode { +func osUnlock(file *os.File, start, len int64) error { lock := unix.Flock_t{ Type: unix.F_UNLCK, Start: start, @@ -101,10 +101,10 @@ func osUnlock(file *os.File, start, len int64) _ErrorCode { for { err := unix.FcntlFlock(file.Fd(), unix.F_SETLK, &lock) if err == nil { - return _OK + return nil } if err != unix.EINTR { - return _IOERR_UNLOCK + return sysError{err, _IOERR_UNLOCK} } } } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go index 9bb8b559c..6748c2991 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go @@ -75,15 +75,15 @@ func osAllocate(file *os.File, size int64) error { return file.Truncate(size) } -func osReadLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { +func osReadLock(file *os.File, start, len int64, timeout time.Duration) error { return osLock(file, unix.F_RDLCK, start, len, timeout, _IOERR_RDLOCK) } -func osWriteLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { +func osWriteLock(file *os.File, start, len int64, timeout time.Duration) error { return osLock(file, unix.F_WRLCK, start, len, timeout, _IOERR_LOCK) } -func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, def _ErrorCode) _ErrorCode { +func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, def _ErrorCode) error { lock := &flocktimeout_t{fl: unix.Flock_t{ Type: typ, Start: start, @@ -103,7 +103,7 @@ func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, d return osLockErrorCode(err, def) } -func osUnlock(file *os.File, start, len int64) _ErrorCode { +func osUnlock(file *os.File, start, len int64) error { lock := unix.Flock_t{ Type: unix.F_UNLCK, Start: start, @@ -112,10 +112,10 @@ func osUnlock(file *os.File, start, len int64) _ErrorCode { for { err := unix.FcntlFlock(file.Fd(), _F_OFD_SETLK, &lock) if err == nil { - return _OK + return nil } if err != unix.EINTR { - return _IOERR_UNLOCK + return sysError{err, _IOERR_UNLOCK} } } } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_dotlk.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_dotlk.go index 7a9c38897..b64e8ec05 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_dotlk.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_dotlk.go @@ -23,7 +23,7 @@ type vfsDotLocker struct { reserved *os.File // +checklocks:vfsDotLocksMtx } -func osGetSharedLock(file *os.File) _ErrorCode { +func osGetSharedLock(file *os.File) error { vfsDotLocksMtx.Lock() defer vfsDotLocksMtx.Unlock() @@ -34,7 +34,7 @@ func osGetSharedLock(file *os.File) _ErrorCode { if errors.Is(err, fs.ErrExist) { return _BUSY // Another process has the lock. } - return _IOERR_LOCK + return sysError{err, _IOERR_LOCK} } locker = &vfsDotLocker{} vfsDotLocks[name] = locker @@ -44,10 +44,10 @@ func osGetSharedLock(file *os.File) _ErrorCode { return _BUSY } locker.shared++ - return _OK + return nil } -func osGetReservedLock(file *os.File) _ErrorCode { +func osGetReservedLock(file *os.File) error { vfsDotLocksMtx.Lock() defer vfsDotLocksMtx.Unlock() @@ -61,10 +61,10 @@ func osGetReservedLock(file *os.File) _ErrorCode { return _BUSY } locker.reserved = file - return _OK + return nil } -func osGetExclusiveLock(file *os.File, _ *LockLevel) _ErrorCode { +func osGetExclusiveLock(file *os.File, _ *LockLevel) error { vfsDotLocksMtx.Lock() defer vfsDotLocksMtx.Unlock() @@ -81,10 +81,10 @@ func osGetExclusiveLock(file *os.File, _ *LockLevel) _ErrorCode { if locker.shared > 1 { return _BUSY } - return _OK + return nil } -func osDowngradeLock(file *os.File, _ LockLevel) _ErrorCode { +func osDowngradeLock(file *os.File, _ LockLevel) error { vfsDotLocksMtx.Lock() defer vfsDotLocksMtx.Unlock() @@ -100,10 +100,10 @@ func osDowngradeLock(file *os.File, _ LockLevel) _ErrorCode { if locker.pending == file { locker.pending = nil } - return _OK + return nil } -func osReleaseLock(file *os.File, state LockLevel) _ErrorCode { +func osReleaseLock(file *os.File, state LockLevel) error { vfsDotLocksMtx.Lock() defer vfsDotLocksMtx.Unlock() @@ -115,7 +115,7 @@ func osReleaseLock(file *os.File, state LockLevel) _ErrorCode { if locker.shared == 1 { if err := dotlk.Unlock(name + ".lock"); err != nil { - return _IOERR_UNLOCK + return sysError{err, _IOERR_UNLOCK} } delete(vfsDotLocks, name) } @@ -127,17 +127,14 @@ func osReleaseLock(file *os.File, state LockLevel) _ErrorCode { locker.pending = nil } locker.shared-- - return _OK + return nil } -func osCheckReservedLock(file *os.File) (bool, _ErrorCode) { +func osCheckReservedLock(file *os.File) (bool, error) { vfsDotLocksMtx.Lock() defer vfsDotLocksMtx.Unlock() name := file.Name() locker := vfsDotLocks[name] - if locker == nil { - return false, _OK - } - return locker.reserved != nil, _OK + return locker != nil && locker.reserved != nil, nil } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go index 893f1512c..1f7705ca0 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go @@ -44,15 +44,15 @@ func osAllocate(file *os.File, size int64) error { } -func osReadLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { +func osReadLock(file *os.File, start, len int64, timeout time.Duration) error { return osLock(file, unix.F_RDLCK, start, len, timeout, _IOERR_RDLOCK) } -func osWriteLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { +func osWriteLock(file *os.File, start, len int64, timeout time.Duration) error { return osLock(file, unix.F_WRLCK, start, len, timeout, _IOERR_LOCK) } -func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, def _ErrorCode) _ErrorCode { +func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, def _ErrorCode) error { lock := unix.Flock_t{ Type: typ, Start: start, @@ -68,7 +68,7 @@ func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, d return osLockErrorCode(err, def) } -func osUnlock(file *os.File, start, len int64) _ErrorCode { +func osUnlock(file *os.File, start, len int64) error { lock := unix.Flock_t{ Type: unix.F_UNLCK, Start: start, @@ -77,10 +77,10 @@ func osUnlock(file *os.File, start, len int64) _ErrorCode { for { err := unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLK, &lock) if err == nil { - return _OK + return nil } if err != unix.EINTR { - return _IOERR_UNLOCK + return sysError{err, _IOERR_UNLOCK} } } } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_ofd.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_ofd.go index d93050e8a..e917e12d4 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_ofd.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_ofd.go @@ -9,25 +9,25 @@ import ( "golang.org/x/sys/unix" ) -func osGetSharedLock(file *os.File) _ErrorCode { +func osGetSharedLock(file *os.File) error { // Test the PENDING lock before acquiring a new SHARED lock. - if lock, _ := osTestLock(file, _PENDING_BYTE, 1); lock == unix.F_WRLCK { + if lock, _ := osTestLock(file, _PENDING_BYTE, 1, _IOERR); lock == unix.F_WRLCK { return _BUSY } // Acquire the SHARED lock. return osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0) } -func osGetReservedLock(file *os.File) _ErrorCode { +func osGetReservedLock(file *os.File) error { // Acquire the RESERVED lock. return osWriteLock(file, _RESERVED_BYTE, 1, 0) } -func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode { +func osGetExclusiveLock(file *os.File, state *LockLevel) error { if *state == LOCK_RESERVED { // A PENDING lock is needed before acquiring an EXCLUSIVE lock. - if rc := osWriteLock(file, _PENDING_BYTE, 1, -1); rc != _OK { - return rc + if err := osWriteLock(file, _PENDING_BYTE, 1, -1); err != nil { + return err } *state = LOCK_PENDING } @@ -35,10 +35,10 @@ func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode { return osWriteLock(file, _SHARED_FIRST, _SHARED_SIZE, time.Millisecond) } -func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode { +func osDowngradeLock(file *os.File, state LockLevel) error { if state >= LOCK_EXCLUSIVE { // Downgrade to a SHARED lock. - if rc := osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0); rc != _OK { + if err := osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0); err != nil { // notest // this should never happen return _IOERR_RDLOCK } @@ -47,13 +47,13 @@ func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode { return osUnlock(file, _PENDING_BYTE, 2) } -func osReleaseLock(file *os.File, _ LockLevel) _ErrorCode { +func osReleaseLock(file *os.File, _ LockLevel) error { // Release all locks. return osUnlock(file, 0, 0) } -func osCheckReservedLock(file *os.File) (bool, _ErrorCode) { +func osCheckReservedLock(file *os.File) (bool, error) { // Test the RESERVED lock. - lock, rc := osTestLock(file, _RESERVED_BYTE, 1) - return lock == unix.F_WRLCK, rc + lock, err := osTestLock(file, _RESERVED_BYTE, 1, _IOERR_CHECKRESERVEDLOCK) + return lock == unix.F_WRLCK, err } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix.go index ec312ccd3..69fdc8fbe 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix.go @@ -33,7 +33,7 @@ func osReadAt(file *os.File, p []byte, off int64) (int, error) { unix.ERANGE, unix.EIO, unix.ENXIO: - return n, _IOERR_CORRUPTFS + return n, sysError{err, _IOERR_CORRUPTFS} } } return n, err @@ -42,7 +42,7 @@ func osReadAt(file *os.File, p []byte, off int64) (int, error) { func osWriteAt(file *os.File, p []byte, off int64) (int, error) { n, err := file.WriteAt(p, off) if errno, ok := err.(unix.Errno); ok && errno == unix.ENOSPC { - return n, _FULL + return n, sysError{err, _FULL} } return n, err } @@ -59,7 +59,7 @@ func osSetMode(file *os.File, modeof string) error { return nil } -func osTestLock(file *os.File, start, len int64) (int16, _ErrorCode) { +func osTestLock(file *os.File, start, len int64, def _ErrorCode) (int16, error) { lock := unix.Flock_t{ Type: unix.F_WRLCK, Start: start, @@ -68,17 +68,17 @@ func osTestLock(file *os.File, start, len int64) (int16, _ErrorCode) { for { err := unix.FcntlFlock(file.Fd(), unix.F_GETLK, &lock) if err == nil { - return lock.Type, _OK + return lock.Type, nil } if err != unix.EINTR { - return 0, _IOERR_CHECKRESERVEDLOCK + return 0, sysError{err, def} } } } -func osLockErrorCode(err error, def _ErrorCode) _ErrorCode { +func osLockErrorCode(err error, def _ErrorCode) error { if err == nil { - return _OK + return nil } if errno, ok := err.(unix.Errno); ok { switch errno { @@ -92,12 +92,12 @@ func osLockErrorCode(err error, def _ErrorCode) _ErrorCode { unix.ETIMEDOUT: return _BUSY case unix.EPERM: - return _PERM + return sysError{err, _PERM} } // notest // usually EWOULDBLOCK == EAGAIN if errno == unix.EWOULDBLOCK && unix.EWOULDBLOCK != unix.EAGAIN { return _BUSY } } - return def + return sysError{err, def} } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go index 0a6693de5..eb843e39a 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go @@ -20,31 +20,31 @@ func osWriteAt(file *os.File, p []byte, off int64) (int, error) { case windows.ERROR_HANDLE_DISK_FULL, windows.ERROR_DISK_FULL: - return n, _FULL + return n, sysError{err, _FULL} } } return n, err } -func osGetSharedLock(file *os.File) _ErrorCode { +func osGetSharedLock(file *os.File) error { // Acquire the PENDING lock temporarily before acquiring a new SHARED lock. - rc := osReadLock(file, _PENDING_BYTE, 1, 0) - if rc == _OK { + err := osReadLock(file, _PENDING_BYTE, 1, 0) + if err == nil { // Acquire the SHARED lock. - rc = osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0) + err = osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0) // Release the PENDING lock. osUnlock(file, _PENDING_BYTE, 1) } - return rc + return err } -func osGetReservedLock(file *os.File) _ErrorCode { +func osGetReservedLock(file *os.File) error { // Acquire the RESERVED lock. return osWriteLock(file, _RESERVED_BYTE, 1, 0) } -func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode { +func osGetExclusiveLock(file *os.File, state *LockLevel) error { // A PENDING lock is needed before releasing the SHARED lock. if *state < LOCK_PENDING { // If we were RESERVED, we can block indefinitely. @@ -52,8 +52,8 @@ func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode { if *state == LOCK_RESERVED { timeout = -1 } - if rc := osWriteLock(file, _PENDING_BYTE, 1, timeout); rc != _OK { - return rc + if err := osWriteLock(file, _PENDING_BYTE, 1, timeout); err != nil { + return err } *state = LOCK_PENDING } @@ -63,25 +63,25 @@ func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode { // Acquire the EXCLUSIVE lock. // Can't wait here, because the file is not OVERLAPPED. - rc := osWriteLock(file, _SHARED_FIRST, _SHARED_SIZE, 0) + err := osWriteLock(file, _SHARED_FIRST, _SHARED_SIZE, 0) - if rc != _OK { + if err != nil { // Reacquire the SHARED lock. - if rc := osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0); rc != _OK { + if err := osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0); err != nil { // notest // this should never happen return _IOERR_RDLOCK } } - return rc + return err } -func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode { +func osDowngradeLock(file *os.File, state LockLevel) error { if state >= LOCK_EXCLUSIVE { // Release the EXCLUSIVE lock while holding the PENDING lock. osUnlock(file, _SHARED_FIRST, _SHARED_SIZE) // Reacquire the SHARED lock. - if rc := osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0); rc != _OK { + if err := osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0); err != nil { // notest // this should never happen return _IOERR_RDLOCK } @@ -94,10 +94,10 @@ func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode { if state >= LOCK_PENDING { osUnlock(file, _PENDING_BYTE, 1) } - return _OK + return nil } -func osReleaseLock(file *os.File, state LockLevel) _ErrorCode { +func osReleaseLock(file *os.File, state LockLevel) error { // Release all locks, PENDING must be last. if state >= LOCK_RESERVED { osUnlock(file, _RESERVED_BYTE, 1) @@ -108,31 +108,32 @@ func osReleaseLock(file *os.File, state LockLevel) _ErrorCode { if state >= LOCK_PENDING { osUnlock(file, _PENDING_BYTE, 1) } - return _OK + return nil } -func osCheckReservedLock(file *os.File) (bool, _ErrorCode) { +func osCheckReservedLock(file *os.File) (bool, error) { // Test the RESERVED lock. - rc := osLock(file, 0, _RESERVED_BYTE, 1, 0, _IOERR_CHECKRESERVEDLOCK) - if rc == _BUSY { - return true, _OK + err := osLock(file, 0, _RESERVED_BYTE, 1, 0, _IOERR_CHECKRESERVEDLOCK) + if err == _BUSY { + return true, nil } - if rc == _OK { + if err == nil { // Release the RESERVED lock. osUnlock(file, _RESERVED_BYTE, 1) + return false, nil } - return false, rc + return false, err } -func osReadLock(file *os.File, start, len uint32, timeout time.Duration) _ErrorCode { +func osReadLock(file *os.File, start, len uint32, timeout time.Duration) error { return osLock(file, 0, start, len, timeout, _IOERR_RDLOCK) } -func osWriteLock(file *os.File, start, len uint32, timeout time.Duration) _ErrorCode { +func osWriteLock(file *os.File, start, len uint32, timeout time.Duration) error { return osLock(file, windows.LOCKFILE_EXCLUSIVE_LOCK, start, len, timeout, _IOERR_LOCK) } -func osLock(file *os.File, flags, start, len uint32, timeout time.Duration, def _ErrorCode) _ErrorCode { +func osLock(file *os.File, flags, start, len uint32, timeout time.Duration, def _ErrorCode) error { var err error switch { default: @@ -143,16 +144,16 @@ func osLock(file *os.File, flags, start, len uint32, timeout time.Duration, def return osLockErrorCode(err, def) } -func osUnlock(file *os.File, start, len uint32) _ErrorCode { +func osUnlock(file *os.File, start, len uint32) error { err := windows.UnlockFileEx(windows.Handle(file.Fd()), 0, len, 0, &windows.Overlapped{Offset: start}) if err == windows.ERROR_NOT_LOCKED { - return _OK + return nil } if err != nil { - return _IOERR_UNLOCK + return sysError{err, _IOERR_UNLOCK} } - return _OK + return nil } func osLockEx(file *os.File, flags, start, len uint32) error { @@ -160,9 +161,9 @@ func osLockEx(file *os.File, flags, start, len uint32) error { 0, len, 0, &windows.Overlapped{Offset: start}) } -func osLockErrorCode(err error, def _ErrorCode) _ErrorCode { +func osLockErrorCode(err error, def _ErrorCode) error { if err == nil { - return _OK + return nil } if errno, ok := err.(windows.Errno); ok { // https://devblogs.microsoft.com/oldnewthing/20140905-00/?p=63 @@ -175,5 +176,5 @@ func osLockErrorCode(err error, def _ErrorCode) _ErrorCode { return _BUSY } } - return def + return sysError{err, def} } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go index be1495d99..ebf8418cc 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go @@ -3,6 +3,7 @@ package vfs import ( + "cmp" "context" "errors" "io" @@ -68,9 +69,9 @@ func (s *vfsShm) Close() error { panic(util.AssertErr()) } -func (s *vfsShm) shmOpen() (rc _ErrorCode) { +func (s *vfsShm) shmOpen() (err error) { if s.vfsShmParent != nil { - return _OK + return nil } vfsShmListMtx.Lock() @@ -80,7 +81,7 @@ func (s *vfsShm) shmOpen() (rc _ErrorCode) { // Closing it would release all POSIX locks on it. fi, err := os.Stat(s.path) if err != nil && !errors.Is(err, fs.ErrNotExist) { - return _IOERR_FSTAT + return sysError{err, _IOERR_FSTAT} } // Find a shared file, increase the reference count. @@ -88,7 +89,7 @@ func (s *vfsShm) shmOpen() (rc _ErrorCode) { if g != nil && os.SameFile(fi, g.info) { s.vfsShmParent = g g.refs++ - return _OK + return nil } } @@ -96,34 +97,34 @@ func (s *vfsShm) shmOpen() (rc _ErrorCode) { f, err := os.OpenFile(s.path, os.O_RDWR|os.O_CREATE|_O_NOFOLLOW, 0666) if err != nil { - return _CANTOPEN + return sysError{err, _CANTOPEN} } defer func() { - if rc != _OK { + if err != nil { f.Close() } }() // Dead man's switch. - if lock, rc := osTestLock(f, _SHM_DMS, 1); rc != _OK { - return _IOERR_LOCK + if lock, err := osTestLock(f, _SHM_DMS, 1, _IOERR_LOCK); err != nil { + return err } else if lock == unix.F_WRLCK { return _BUSY } else if lock == unix.F_UNLCK { - if rc := osWriteLock(f, _SHM_DMS, 1); rc != _OK { - return rc + if err := osWriteLock(f, _SHM_DMS, 1); err != nil { + return err } if err := f.Truncate(0); err != nil { - return _IOERR_SHMOPEN + return sysError{err, _IOERR_SHMOPEN} } } - if rc := osReadLock(f, _SHM_DMS, 1); rc != _OK { - return rc + if err := osReadLock(f, _SHM_DMS, 1); err != nil { + return err } fi, err = f.Stat() if err != nil { - return _IOERR_FSTAT + return sysError{err, _IOERR_FSTAT} } // Add the new shared file. @@ -134,53 +135,57 @@ func (s *vfsShm) shmOpen() (rc _ErrorCode) { for i, g := range vfsShmList { if g == nil { vfsShmList[i] = s.vfsShmParent - return _OK + return nil } } vfsShmList = append(vfsShmList, s.vfsShmParent) - return _OK + return nil } -func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, _ErrorCode) { +func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, error) { // Ensure size is a multiple of the OS page size. if int(size)&(unix.Getpagesize()-1) != 0 { return 0, _IOERR_SHMMAP } - if rc := s.shmOpen(); rc != _OK { - return 0, rc + if err := s.shmOpen(); err != nil { + return 0, err } // Check if file is big enough. o, err := s.Seek(0, io.SeekEnd) if err != nil { - return 0, _IOERR_SHMSIZE + return 0, sysError{err, _IOERR_SHMSIZE} } if n := (int64(id) + 1) * int64(size); n > o { if !extend { - return 0, _OK + return 0, nil } - if osAllocate(s.File, n) != nil { - return 0, _IOERR_SHMSIZE + if err := osAllocate(s.File, n); err != nil { + return 0, sysError{err, _IOERR_SHMSIZE} } } r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size, false) if err != nil { - return 0, _IOERR_SHMMAP + return 0, err } s.regions = append(s.regions, r) - return r.Ptr, _OK + return r.Ptr, nil } -func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode { +func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) error { + if s.vfsShmParent == nil { + return _IOERR_SHMLOCK + } + s.Lock() defer s.Unlock() // Check if we can obtain/release locks locally. - rc := s.shmMemLock(offset, n, flags) - if rc != _OK { - return rc + err := s.shmMemLock(offset, n, flags) + if err != nil { + return err } // Obtain/release the appropriate file locks. @@ -192,36 +197,38 @@ func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode { for i := begin; i < end; i++ { if s.vfsShmParent.lock[i] != 0 { if i > begin { - rc |= osUnlock(s.File, _SHM_BASE+int64(begin), int64(i-begin)) + err = cmp.Or(err, + osUnlock(s.File, _SHM_BASE+int64(begin), int64(i-begin))) } begin = i + 1 } } if end > begin { - rc |= osUnlock(s.File, _SHM_BASE+int64(begin), int64(end-begin)) + err = cmp.Or(err, + osUnlock(s.File, _SHM_BASE+int64(begin), int64(end-begin))) } - return rc + return err case flags&_SHM_SHARED != 0: // Acquiring a new shared lock on the file is only necessary // if there was a new shared lock in the range. for i := offset; i < offset+n; i++ { if s.vfsShmParent.lock[i] == 1 { - rc = osReadLock(s.File, _SHM_BASE+int64(offset), int64(n)) + err = osReadLock(s.File, _SHM_BASE+int64(offset), int64(n)) break } } case flags&_SHM_EXCLUSIVE != 0: // Acquiring an exclusive lock on the file is always necessary. - rc = osWriteLock(s.File, _SHM_BASE+int64(offset), int64(n)) + err = osWriteLock(s.File, _SHM_BASE+int64(offset), int64(n)) default: panic(util.AssertErr()) } - // Release the local locks we had acquired. - if rc != _OK { + if err != nil { + // Release the local locks we had acquired. s.shmMemLock(offset, n, flags^(_SHM_UNLOCK|_SHM_LOCK)) } - return rc + return err } func (s *vfsShm) shmUnmap(delete bool) { diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_copy.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_copy.go index db8ddb4b8..8e40aafb7 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_copy.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_copy.go @@ -31,8 +31,8 @@ const ( // // https://sqlite.org/walformat.html#the_wal_index_file_format -func (s *vfsShm) shmAcquire(ptr *_ErrorCode) { - if ptr != nil && *ptr != _OK { +func (s *vfsShm) shmAcquire(errp *error) { + if errp != nil && *errp != nil { return } if len(s.ptrs) == 0 || shmEqual(s.shadow[0][:], s.shared[0][:]) { diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_dotlk.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_dotlk.go index cb697a9c8..8f2bc6ce1 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_dotlk.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_dotlk.go @@ -59,16 +59,16 @@ func (s *vfsShm) Close() error { } if err := dotlk.Unlock(s.path); err != nil { - return _IOERR_UNLOCK + return sysError{err, _IOERR_UNLOCK} } delete(vfsShmList, s.path) s.vfsShmParent = nil return nil } -func (s *vfsShm) shmOpen() _ErrorCode { +func (s *vfsShm) shmOpen() error { if s.vfsShmParent != nil { - return _OK + return nil } vfsShmListMtx.Lock() @@ -78,7 +78,7 @@ func (s *vfsShm) shmOpen() _ErrorCode { if g, ok := vfsShmList[s.path]; ok { s.vfsShmParent = g g.refs++ - return _OK + return nil } // Dead man's switch. @@ -87,16 +87,16 @@ func (s *vfsShm) shmOpen() _ErrorCode { return _BUSY } if err != nil { - return _IOERR_LOCK + return sysError{err, _IOERR_LOCK} } // Add the new shared buffer. s.vfsShmParent = &vfsShmParent{} vfsShmList[s.path] = s.vfsShmParent - return _OK + return nil } -func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, _ErrorCode) { +func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, error) { if size != _WALINDEX_PGSZ { return 0, _IOERR_SHMMAP } @@ -105,8 +105,8 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext s.free = mod.ExportedFunction("sqlite3_free") s.alloc = mod.ExportedFunction("sqlite3_malloc64") } - if rc := s.shmOpen(); rc != _OK { - return 0, rc + if err := s.shmOpen(); err != nil { + return 0, err } s.Lock() @@ -116,7 +116,7 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext // Extend shared memory. if int(id) >= len(s.shared) { if !extend { - return 0, _OK + return 0, nil } s.shared = append(s.shared, make([][_WALINDEX_PGSZ]byte, int(id)-len(s.shared)+1)...) } @@ -140,16 +140,20 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext } s.shadow[0][4] = 1 - return s.ptrs[id], _OK + return s.ptrs[id], nil } -func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) (rc _ErrorCode) { +func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) (err error) { + if s.vfsShmParent == nil { + return _IOERR_SHMLOCK + } + s.Lock() defer s.Unlock() switch { case flags&_SHM_LOCK != 0: - defer s.shmAcquire(&rc) + defer s.shmAcquire(&err) case flags&_SHM_EXCLUSIVE != 0: s.shmRelease() } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_memlk.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_memlk.go index 5c8071ebe..d23c26c3b 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_memlk.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_memlk.go @@ -5,7 +5,7 @@ package vfs import "github.com/ncruces/go-sqlite3/internal/util" // +checklocks:s.Mutex -func (s *vfsShm) shmMemLock(offset, n int32, flags _ShmFlag) _ErrorCode { +func (s *vfsShm) shmMemLock(offset, n int32, flags _ShmFlag) error { switch { case flags&_SHM_UNLOCK != 0: for i := offset; i < offset+n; i++ { @@ -48,6 +48,5 @@ func (s *vfsShm) shmMemLock(offset, n int32, flags _ShmFlag) _ErrorCode { default: panic(util.AssertErr()) } - - return _OK + return nil } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_ofd.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_ofd.go index b0f50fcb5..de31e59d6 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_ofd.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_ofd.go @@ -27,7 +27,10 @@ type vfsShm struct { var _ blockingSharedMemory = &vfsShm{} -func (s *vfsShm) shmOpen() _ErrorCode { +func (s *vfsShm) shmOpen() error { + if s.fileLock { + return nil + } if s.File == nil { f, err := os.OpenFile(s.path, os.O_RDWR|os.O_CREATE|_O_NOFOLLOW, 0666) @@ -37,17 +40,15 @@ func (s *vfsShm) shmOpen() _ErrorCode { s.readOnly = true } if err != nil { - return _CANTOPEN + return sysError{err, _CANTOPEN} } + s.fileLock = false s.File = f } - if s.fileLock { - return _OK - } // Dead man's switch. - if lock, rc := osTestLock(s.File, _SHM_DMS, 1); rc != _OK { - return _IOERR_LOCK + if lock, err := osTestLock(s.File, _SHM_DMS, 1, _IOERR_LOCK); err != nil { + return err } else if lock == unix.F_WRLCK { return _BUSY } else if lock == unix.F_UNLCK { @@ -61,54 +62,57 @@ func (s *vfsShm) shmOpen() _ErrorCode { // but only downgrade it to a shared lock. // So no point in blocking here. // The call below to obtain the shared DMS lock may use a blocking lock. - if rc := osWriteLock(s.File, _SHM_DMS, 1, 0); rc != _OK { - return rc + if err := osWriteLock(s.File, _SHM_DMS, 1, 0); err != nil { + return err } if err := s.Truncate(0); err != nil { - return _IOERR_SHMOPEN + return sysError{err, _IOERR_SHMOPEN} } } - rc := osReadLock(s.File, _SHM_DMS, 1, time.Millisecond) - s.fileLock = rc == _OK - return rc + err := osReadLock(s.File, _SHM_DMS, 1, time.Millisecond) + s.fileLock = err == nil + return err } -func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, _ErrorCode) { +func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, error) { // Ensure size is a multiple of the OS page size. if int(size)&(unix.Getpagesize()-1) != 0 { return 0, _IOERR_SHMMAP } - if rc := s.shmOpen(); rc != _OK { - return 0, rc + if err := s.shmOpen(); err != nil { + return 0, err } // Check if file is big enough. o, err := s.Seek(0, io.SeekEnd) if err != nil { - return 0, _IOERR_SHMSIZE + return 0, sysError{err, _IOERR_SHMSIZE} } if n := (int64(id) + 1) * int64(size); n > o { if !extend { - return 0, _OK + return 0, nil } - if s.readOnly || osAllocate(s.File, n) != nil { + if s.readOnly { return 0, _IOERR_SHMSIZE } + if err := osAllocate(s.File, n); err != nil { + return 0, sysError{err, _IOERR_SHMSIZE} + } } r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size, s.readOnly) if err != nil { - return 0, _IOERR_SHMMAP + return 0, err } s.regions = append(s.regions, r) if s.readOnly { return r.Ptr, _READONLY } - return r.Ptr, _OK + return r.Ptr, nil } -func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode { +func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) error { // Argument check. switch { case n <= 0: @@ -129,6 +133,10 @@ func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode { panic(util.AssertErr()) } + if s.File == nil { + return _IOERR_SHMLOCK + } + var timeout time.Duration if s.blocking { timeout = time.Millisecond @@ -163,6 +171,7 @@ func (s *vfsShm) shmUnmap(delete bool) { } s.Close() s.File = nil + s.fileLock = false } func (s *vfsShm) shmBarrier() { diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_windows.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_windows.go index 0be523ad6..ad3e153ae 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_windows.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_windows.go @@ -40,32 +40,33 @@ func (s *vfsShm) Close() error { return s.File.Close() } -func (s *vfsShm) shmOpen() _ErrorCode { +func (s *vfsShm) shmOpen() error { + if s.fileLock { + return nil + } if s.File == nil { f, err := os.OpenFile(s.path, os.O_RDWR|os.O_CREATE, 0666) if err != nil { - return _CANTOPEN + return sysError{err, _CANTOPEN} } + s.fileLock = false s.File = f } - if s.fileLock { - return _OK - } // Dead man's switch. - if rc := osWriteLock(s.File, _SHM_DMS, 1, 0); rc == _OK { + if osWriteLock(s.File, _SHM_DMS, 1, 0) == nil { err := s.Truncate(0) osUnlock(s.File, _SHM_DMS, 1) if err != nil { - return _IOERR_SHMOPEN + return sysError{err, _IOERR_SHMOPEN} } } - rc := osReadLock(s.File, _SHM_DMS, 1, 0) - s.fileLock = rc == _OK - return rc + err := osReadLock(s.File, _SHM_DMS, 1, 0) + s.fileLock = err == nil + return err } -func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (_ ptr_t, rc _ErrorCode) { +func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (_ ptr_t, err error) { // Ensure size is a multiple of the OS page size. if size != _WALINDEX_PGSZ || (windows.Getpagesize()-1)&_WALINDEX_PGSZ != 0 { return 0, _IOERR_SHMMAP @@ -75,23 +76,23 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext s.free = mod.ExportedFunction("sqlite3_free") s.alloc = mod.ExportedFunction("sqlite3_malloc64") } - if rc := s.shmOpen(); rc != _OK { - return 0, rc + if err := s.shmOpen(); err != nil { + return 0, err } - defer s.shmAcquire(&rc) + defer s.shmAcquire(&err) // Check if file is big enough. o, err := s.Seek(0, io.SeekEnd) if err != nil { - return 0, _IOERR_SHMSIZE + return 0, sysError{err, _IOERR_SHMSIZE} } if n := (int64(id) + 1) * int64(size); n > o { if !extend { - return 0, _OK + return 0, nil } - if osAllocate(s.File, n) != nil { - return 0, _IOERR_SHMSIZE + if err := osAllocate(s.File, n); err != nil { + return 0, sysError{err, _IOERR_SHMSIZE} } } @@ -99,7 +100,7 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext for int(id) >= len(s.shared) { r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size) if err != nil { - return 0, _IOERR_SHMMAP + return 0, err } s.regions = append(s.regions, r) s.shared = append(s.shared, r.Data) @@ -124,13 +125,17 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext } s.shadow[0][4] = 1 - return s.ptrs[id], _OK + return s.ptrs[id], nil } -func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) (rc _ErrorCode) { +func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) (err error) { + if s.File == nil { + return _IOERR_SHMLOCK + } + switch { case flags&_SHM_LOCK != 0: - defer s.shmAcquire(&rc) + defer s.shmAcquire(&err) case flags&_SHM_EXCLUSIVE != 0: s.shmRelease() } @@ -168,6 +173,7 @@ func (s *vfsShm) shmUnmap(delete bool) { // Close the file. s.Close() s.File = nil + s.fileLock = false if delete { os.Remove(s.path) } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go b/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go index aef81c3f2..569346fb2 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go @@ -102,7 +102,7 @@ func vfsFullPathname(ctx context.Context, mod api.Module, pVfs, zRelative ptr_t, } util.WriteString(mod, zFull, path) - return vfsErrorCode(err, _CANTOPEN_FULLPATH) + return vfsErrorCode(ctx, err, _CANTOPEN_FULLPATH) } func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath ptr_t, syncDir int32) _ErrorCode { @@ -110,7 +110,7 @@ func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath ptr_t, syncDir i path := util.ReadString(mod, zPath, _MAX_PATHNAME) err := vfs.Delete(path, syncDir != 0) - return vfsErrorCode(err, _IOERR_DELETE) + return vfsErrorCode(ctx, err, _IOERR_DELETE) } func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath ptr_t, flags AccessFlag, pResOut ptr_t) _ErrorCode { @@ -119,7 +119,7 @@ func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath ptr_t, flags Acc ok, err := vfs.Access(path, flags) util.WriteBool(mod, pResOut, ok) - return vfsErrorCode(err, _IOERR_ACCESS) + return vfsErrorCode(ctx, err, _IOERR_ACCESS) } func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile ptr_t, flags OpenFlag, pOutFlags, pOutVFS ptr_t) _ErrorCode { @@ -134,7 +134,7 @@ func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile ptr_t, flag file, flags, err = vfs.Open(name.String(), flags) } if err != nil { - return vfsErrorCode(err, _CANTOPEN) + return vfsErrorCode(ctx, err, _CANTOPEN) } if file, ok := file.(FilePowersafeOverwrite); ok { @@ -155,7 +155,7 @@ func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile ptr_t, flag func vfsClose(ctx context.Context, mod api.Module, pFile ptr_t) _ErrorCode { err := vfsFileClose(ctx, mod, pFile) - return vfsErrorCode(err, _IOERR_CLOSE) + return vfsErrorCode(ctx, err, _IOERR_CLOSE) } func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf ptr_t, iAmt int32, iOfst int64) _ErrorCode { @@ -167,7 +167,7 @@ func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf ptr_t, iAmt int32, return _OK } if err != io.EOF { - return vfsErrorCode(err, _IOERR_READ) + return vfsErrorCode(ctx, err, _IOERR_READ) } clear(buf[n:]) return _IOERR_SHORT_READ @@ -178,45 +178,45 @@ func vfsWrite(ctx context.Context, mod api.Module, pFile, zBuf ptr_t, iAmt int32 buf := util.View(mod, zBuf, int64(iAmt)) _, err := file.WriteAt(buf, iOfst) - return vfsErrorCode(err, _IOERR_WRITE) + return vfsErrorCode(ctx, err, _IOERR_WRITE) } func vfsTruncate(ctx context.Context, mod api.Module, pFile ptr_t, nByte int64) _ErrorCode { file := vfsFileGet(ctx, mod, pFile).(File) err := file.Truncate(nByte) - return vfsErrorCode(err, _IOERR_TRUNCATE) + return vfsErrorCode(ctx, err, _IOERR_TRUNCATE) } func vfsSync(ctx context.Context, mod api.Module, pFile ptr_t, flags SyncFlag) _ErrorCode { file := vfsFileGet(ctx, mod, pFile).(File) err := file.Sync(flags) - return vfsErrorCode(err, _IOERR_FSYNC) + return vfsErrorCode(ctx, err, _IOERR_FSYNC) } func vfsFileSize(ctx context.Context, mod api.Module, pFile, pSize ptr_t) _ErrorCode { file := vfsFileGet(ctx, mod, pFile).(File) size, err := file.Size() util.Write64(mod, pSize, size) - return vfsErrorCode(err, _IOERR_SEEK) + return vfsErrorCode(ctx, err, _IOERR_SEEK) } func vfsLock(ctx context.Context, mod api.Module, pFile ptr_t, eLock LockLevel) _ErrorCode { file := vfsFileGet(ctx, mod, pFile).(File) err := file.Lock(eLock) - return vfsErrorCode(err, _IOERR_LOCK) + return vfsErrorCode(ctx, err, _IOERR_LOCK) } func vfsUnlock(ctx context.Context, mod api.Module, pFile ptr_t, eLock LockLevel) _ErrorCode { file := vfsFileGet(ctx, mod, pFile).(File) err := file.Unlock(eLock) - return vfsErrorCode(err, _IOERR_UNLOCK) + return vfsErrorCode(ctx, err, _IOERR_UNLOCK) } func vfsCheckReservedLock(ctx context.Context, mod api.Module, pFile, pResOut ptr_t) _ErrorCode { file := vfsFileGet(ctx, mod, pFile).(File) locked, err := file.CheckReservedLock() util.WriteBool(mod, pResOut, locked) - return vfsErrorCode(err, _IOERR_CHECKRESERVEDLOCK) + return vfsErrorCode(ctx, err, _IOERR_CHECKRESERVEDLOCK) } func vfsFileControl(ctx context.Context, mod api.Module, pFile ptr_t, op _FcntlOpcode, pArg ptr_t) _ErrorCode { @@ -268,20 +268,20 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt if file, ok := file.(FileSizeHint); ok { size := util.Read64[int64](mod, pArg) err := file.SizeHint(size) - return vfsErrorCode(err, _IOERR_TRUNCATE) + return vfsErrorCode(ctx, err, _IOERR_TRUNCATE) } case _FCNTL_HAS_MOVED: if file, ok := file.(FileHasMoved); ok { moved, err := file.HasMoved() util.WriteBool(mod, pArg, moved) - return vfsErrorCode(err, _IOERR_FSTAT) + return vfsErrorCode(ctx, err, _IOERR_FSTAT) } case _FCNTL_OVERWRITE: if file, ok := file.(FileOverwrite); ok { err := file.Overwrite() - return vfsErrorCode(err, _IOERR) + return vfsErrorCode(ctx, err, _IOERR) } case _FCNTL_SYNC: @@ -291,29 +291,29 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt name = util.ReadString(mod, pArg, _MAX_PATHNAME) } err := file.SyncSuper(name) - return vfsErrorCode(err, _IOERR) + return vfsErrorCode(ctx, err, _IOERR) } case _FCNTL_COMMIT_PHASETWO: if file, ok := file.(FileCommitPhaseTwo); ok { err := file.CommitPhaseTwo() - return vfsErrorCode(err, _IOERR) + return vfsErrorCode(ctx, err, _IOERR) } case _FCNTL_BEGIN_ATOMIC_WRITE: if file, ok := file.(FileBatchAtomicWrite); ok { err := file.BeginAtomicWrite() - return vfsErrorCode(err, _IOERR_BEGIN_ATOMIC) + return vfsErrorCode(ctx, err, _IOERR_BEGIN_ATOMIC) } case _FCNTL_COMMIT_ATOMIC_WRITE: if file, ok := file.(FileBatchAtomicWrite); ok { err := file.CommitAtomicWrite() - return vfsErrorCode(err, _IOERR_COMMIT_ATOMIC) + return vfsErrorCode(ctx, err, _IOERR_COMMIT_ATOMIC) } case _FCNTL_ROLLBACK_ATOMIC_WRITE: if file, ok := file.(FileBatchAtomicWrite); ok { err := file.RollbackAtomicWrite() - return vfsErrorCode(err, _IOERR_ROLLBACK_ATOMIC) + return vfsErrorCode(ctx, err, _IOERR_ROLLBACK_ATOMIC) } case _FCNTL_CKPT_START: @@ -338,7 +338,7 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt out, err := file.Pragma(strings.ToLower(name), value) - ret := vfsErrorCode(err, _ERROR) + ret := vfsErrorCode(ctx, err, _ERROR) if ret == _ERROR { out = err.Error() } @@ -407,14 +407,15 @@ func vfsShmBarrier(ctx context.Context, mod api.Module, pFile ptr_t) { func vfsShmMap(ctx context.Context, mod api.Module, pFile ptr_t, iRegion, szRegion, bExtend int32, pp ptr_t) _ErrorCode { shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory() - p, rc := shm.shmMap(ctx, mod, iRegion, szRegion, bExtend != 0) + p, err := shm.shmMap(ctx, mod, iRegion, szRegion, bExtend != 0) util.Write32(mod, pp, p) - return rc + return vfsErrorCode(ctx, err, _IOERR_SHMMAP) } func vfsShmLock(ctx context.Context, mod api.Module, pFile ptr_t, offset, n int32, flags _ShmFlag) _ErrorCode { shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory() - return shm.shmLock(offset, n, flags) + err := shm.shmLock(offset, n, flags) + return vfsErrorCode(ctx, err, _IOERR_SHMLOCK) } func vfsShmUnmap(ctx context.Context, mod api.Module, pFile ptr_t, bDelete int32) _ErrorCode { @@ -454,13 +455,38 @@ func vfsFileClose(ctx context.Context, mod api.Module, pFile ptr_t) error { return util.DelHandle(ctx, id) } -func vfsErrorCode(err error, def _ErrorCode) _ErrorCode { - if err == nil { - return _OK +func vfsErrorCode(ctx context.Context, err error, code _ErrorCode) _ErrorCode { + var sys error + + switch err := err.(type) { + case nil: + code = _OK + case _ErrorCode: + code = err + case sysError: + code = err.code + sys = err.error + default: + switch v := reflect.ValueOf(err); v.Kind() { + case reflect.Uint8, reflect.Uint16: + code = _ErrorCode(v.Uint()) + } } - switch v := reflect.ValueOf(err); v.Kind() { - case reflect.Uint8, reflect.Uint16, reflect.Uint32: - return _ErrorCode(v.Uint()) + + util.SetSystemError(ctx, sys) + return code +} + +// SystemError tags an error with a given +// sqlite3.ErrorCode or sqlite3.ExtendedErrorCode. +func SystemError[T interface{ ~uint8 | ~uint16 }](err error, code T) error { + if err == nil { + return nil } - return def + return sysError{error: err, code: _ErrorCode(code)} +} + +type sysError struct { + error + code _ErrorCode } |
