From f789c2fb8b8c2194c400cef1b8ffeec9f2e0b14f Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Thu, 16 Mar 2023 12:27:44 +0000 Subject: [PATCH] OPEN_NOFOLLOW. --- backup.go | 2 +- conn.go | 8 ++++++-- const.go | 2 ++ driver/driver.go | 2 +- tests/conn_test.go | 2 +- vfs.go | 14 +++++++++++--- 6 files changed, 22 insertions(+), 8 deletions(-) diff --git a/backup.go b/backup.go index c931347..fe726f2 100644 --- a/backup.go +++ b/backup.go @@ -33,7 +33,7 @@ func (src *Conn) Backup(srcDB, dstURI string) error { // // https://www.sqlite.org/backup.html func (dst *Conn) Restore(dstDB, srcURI string) error { - src, err := dst.openDB(srcURI, OPEN_READWRITE|OPEN_CREATE|OPEN_URI) + src, err := dst.openDB(srcURI, OPEN_READONLY|OPEN_URI) if err != nil { return err } diff --git a/conn.go b/conn.go index 43ae40d..8c8ed3b 100644 --- a/conn.go +++ b/conn.go @@ -26,19 +26,23 @@ type Conn struct { pending *Stmt } -// Open calls [OpenFlags] with [OPEN_READWRITE], [OPEN_CREATE] and [OPEN_URI]. +// Open calls [OpenFlags] with [OPEN_READWRITE], [OPEN_CREATE], [OPEN_URI] and [OPEN_NOFOLLOW]. func Open(filename string) (*Conn, error) { - return newConn(filename, OPEN_READWRITE|OPEN_CREATE|OPEN_URI) + return newConn(filename, OPEN_READWRITE|OPEN_CREATE|OPEN_URI|OPEN_NOFOLLOW) } // OpenFlags opens an SQLite database file as specified by the filename argument. // +// If none of the required flags is used, a combination of [OPEN_READWRITE] and [OPEN_CREATE] is used. // If a URI filename is used, PRAGMA statements to execute can be specified using "_pragma": // // sqlite3.Open("file:demo.db?_pragma=busy_timeout(10000)&_pragma=locking_mode(normal)") // // https://www.sqlite.org/c3ref/open.html func OpenFlags(filename string, flags OpenFlag) (*Conn, error) { + if flags&(OPEN_READONLY|OPEN_READWRITE|OPEN_CREATE) == 0 { + flags |= OPEN_READWRITE | OPEN_CREATE + } return newConn(filename, flags) } diff --git a/const.go b/const.go index 94497bc..b2fb261 100644 --- a/const.go +++ b/const.go @@ -7,6 +7,8 @@ const ( _ROW = 100 /* sqlite3_step() has another row ready */ _DONE = 101 /* sqlite3_step() has finished executing */ + _OK_SYMLINK = (_OK | (2 << 8)) /* internal use only */ + _UTF8 = 1 _MAX_STRING = 512 // Used for short strings: names, error messages… diff --git a/driver/driver.go b/driver/driver.go index 06dc4df..be551de 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -44,7 +44,7 @@ func init() { type sqlite struct{} func (sqlite) Open(name string) (_ driver.Conn, err error) { - c, err := sqlite3.OpenFlags(name, sqlite3.OPEN_READWRITE|sqlite3.OPEN_CREATE|sqlite3.OPEN_URI|sqlite3.OPEN_EXRESCODE) + c, err := sqlite3.Open(name) if err != nil { return nil, err } diff --git a/tests/conn_test.go b/tests/conn_test.go index 57ed67b..a5baf1a 100644 --- a/tests/conn_test.go +++ b/tests/conn_test.go @@ -13,7 +13,7 @@ import ( func TestConn_Open_dir(t *testing.T) { t.Parallel() - _, err := sqlite3.Open(".") + _, err := sqlite3.OpenFlags(".", 0) if err == nil { t.Fatal("want error") } diff --git a/vfs.go b/vfs.go index bd2228a..9bd9913 100644 --- a/vfs.go +++ b/vfs.go @@ -143,7 +143,7 @@ func vfsFullPathname(ctx context.Context, mod api.Module, pVfs, zRelative, nFull rel := memory{mod}.readString(zRelative, _MAX_PATHNAME) abs, err := filepath.Abs(rel) if err != nil { - return uint32(IOERR) + return uint32(CANTOPEN_FULLPATH) } // Consider either using [filepath.EvalSymlinks] to canonicalize the path (as the Unix VFS does). @@ -155,10 +155,18 @@ func vfsFullPathname(ctx context.Context, mod api.Module, pVfs, zRelative, nFull return uint32(CANTOPEN_FULLPATH) } mem := memory{mod}.view(zFull, size) - mem[len(abs)] = 0 copy(mem, abs) - return _OK + + if fi, err := os.Lstat(abs); err == nil { + if fi.Mode()&fs.ModeSymlink != 0 { + return _OK_SYMLINK + } + return _OK + } else if errors.Is(err, fs.ErrNotExist) { + return _OK + } + return uint32(CANTOPEN_FULLPATH) } func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath, syncDir uint32) uint32 {