summaryrefslogtreecommitdiff
path: root/vendor/github.com/ncruces/go-sqlite3/util/osutil
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/ncruces/go-sqlite3/util/osutil')
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/util/osutil/open.go16
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/util/osutil/open_windows.go112
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/util/osutil/osfs.go33
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/util/osutil/osutil.go2
4 files changed, 163 insertions, 0 deletions
diff --git a/vendor/github.com/ncruces/go-sqlite3/util/osutil/open.go b/vendor/github.com/ncruces/go-sqlite3/util/osutil/open.go
new file mode 100644
index 000000000..0242ad032
--- /dev/null
+++ b/vendor/github.com/ncruces/go-sqlite3/util/osutil/open.go
@@ -0,0 +1,16 @@
+//go:build !windows
+
+package osutil
+
+import (
+ "io/fs"
+ "os"
+)
+
+// OpenFile behaves the same as [os.OpenFile],
+// except on Windows it sets [syscall.FILE_SHARE_DELETE].
+//
+// See: https://go.dev/issue/32088#issuecomment-502850674
+func OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
+ return os.OpenFile(name, flag, perm)
+}
diff --git a/vendor/github.com/ncruces/go-sqlite3/util/osutil/open_windows.go b/vendor/github.com/ncruces/go-sqlite3/util/osutil/open_windows.go
new file mode 100644
index 000000000..277f58bc3
--- /dev/null
+++ b/vendor/github.com/ncruces/go-sqlite3/util/osutil/open_windows.go
@@ -0,0 +1,112 @@
+package osutil
+
+import (
+ "io/fs"
+ "os"
+ . "syscall"
+ "unsafe"
+)
+
+// OpenFile behaves the same as [os.OpenFile],
+// except on Windows it sets [syscall.FILE_SHARE_DELETE].
+//
+// See: https://go.dev/issue/32088#issuecomment-502850674
+func OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
+ if name == "" {
+ return nil, &os.PathError{Op: "open", Path: name, Err: ENOENT}
+ }
+ r, e := syscallOpen(name, flag, uint32(perm.Perm()))
+ if e != nil {
+ return nil, &os.PathError{Op: "open", Path: name, Err: e}
+ }
+ return os.NewFile(uintptr(r), name), nil
+}
+
+// syscallOpen is a copy of [syscall.Open]
+// that uses [syscall.FILE_SHARE_DELETE].
+//
+// https://go.dev/src/syscall/syscall_windows.go
+func syscallOpen(path string, mode int, perm uint32) (fd Handle, err error) {
+ if len(path) == 0 {
+ return InvalidHandle, ERROR_FILE_NOT_FOUND
+ }
+ pathp, err := UTF16PtrFromString(path)
+ if err != nil {
+ return InvalidHandle, err
+ }
+ var access uint32
+ switch mode & (O_RDONLY | O_WRONLY | O_RDWR) {
+ case O_RDONLY:
+ access = GENERIC_READ
+ case O_WRONLY:
+ access = GENERIC_WRITE
+ case O_RDWR:
+ access = GENERIC_READ | GENERIC_WRITE
+ }
+ if mode&O_CREAT != 0 {
+ access |= GENERIC_WRITE
+ }
+ if mode&O_APPEND != 0 {
+ access &^= GENERIC_WRITE
+ access |= FILE_APPEND_DATA
+ }
+ sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)
+ var sa *SecurityAttributes
+ if mode&O_CLOEXEC == 0 {
+ sa = makeInheritSa()
+ }
+ var createmode uint32
+ switch {
+ case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
+ createmode = CREATE_NEW
+ case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC):
+ createmode = CREATE_ALWAYS
+ case mode&O_CREAT == O_CREAT:
+ createmode = OPEN_ALWAYS
+ case mode&O_TRUNC == O_TRUNC:
+ createmode = TRUNCATE_EXISTING
+ default:
+ createmode = OPEN_EXISTING
+ }
+ var attrs uint32 = FILE_ATTRIBUTE_NORMAL
+ if perm&S_IWRITE == 0 {
+ attrs = FILE_ATTRIBUTE_READONLY
+ if createmode == CREATE_ALWAYS {
+ const _ERROR_BAD_NETPATH = Errno(53)
+ // We have been asked to create a read-only file.
+ // If the file already exists, the semantics of
+ // the Unix open system call is to preserve the
+ // existing permissions. If we pass CREATE_ALWAYS
+ // and FILE_ATTRIBUTE_READONLY to CreateFile,
+ // and the file already exists, CreateFile will
+ // change the file permissions.
+ // Avoid that to preserve the Unix semantics.
+ h, e := CreateFile(pathp, access, sharemode, sa, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
+ switch e {
+ case ERROR_FILE_NOT_FOUND, _ERROR_BAD_NETPATH, ERROR_PATH_NOT_FOUND:
+ // File does not exist. These are the same
+ // errors as Errno.Is checks for ErrNotExist.
+ // Carry on to create the file.
+ default:
+ // Success or some different error.
+ return h, e
+ }
+ }
+ }
+ if createmode == OPEN_EXISTING && access == GENERIC_READ {
+ // Necessary for opening directory handles.
+ attrs |= FILE_FLAG_BACKUP_SEMANTICS
+ }
+ if mode&O_SYNC != 0 {
+ const _FILE_FLAG_WRITE_THROUGH = 0x80000000
+ attrs |= _FILE_FLAG_WRITE_THROUGH
+ }
+ return CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0)
+}
+
+func makeInheritSa() *SecurityAttributes {
+ var sa SecurityAttributes
+ sa.Length = uint32(unsafe.Sizeof(sa))
+ sa.InheritHandle = 1
+ return &sa
+}
diff --git a/vendor/github.com/ncruces/go-sqlite3/util/osutil/osfs.go b/vendor/github.com/ncruces/go-sqlite3/util/osutil/osfs.go
new file mode 100644
index 000000000..2e1195934
--- /dev/null
+++ b/vendor/github.com/ncruces/go-sqlite3/util/osutil/osfs.go
@@ -0,0 +1,33 @@
+package osutil
+
+import (
+ "io/fs"
+ "os"
+)
+
+// FS implements [fs.FS], [fs.StatFS], and [fs.ReadFileFS]
+// using package [os].
+//
+// This filesystem does not respect [fs.ValidPath] rules,
+// and fails [testing/fstest.TestFS]!
+//
+// Still, it can be a useful tool to unify implementations
+// that can access either the [os] filesystem or an [fs.FS].
+// It's OK to use this to open files, but you should avoid
+// opening directories, resolving paths, or walking the file system.
+type FS struct{}
+
+// Open implements [fs.FS].
+func (FS) Open(name string) (fs.File, error) {
+ return OpenFile(name, os.O_RDONLY, 0)
+}
+
+// ReadFileFS implements [fs.StatFS].
+func (FS) Stat(name string) (fs.FileInfo, error) {
+ return os.Stat(name)
+}
+
+// ReadFile implements [fs.ReadFileFS].
+func (FS) ReadFile(name string) ([]byte, error) {
+ return os.ReadFile(name)
+}
diff --git a/vendor/github.com/ncruces/go-sqlite3/util/osutil/osutil.go b/vendor/github.com/ncruces/go-sqlite3/util/osutil/osutil.go
new file mode 100644
index 000000000..7fbd04787
--- /dev/null
+++ b/vendor/github.com/ncruces/go-sqlite3/util/osutil/osutil.go
@@ -0,0 +1,2 @@
+// Package osutil implements operating system utility functions.
+package osutil