Hi,
When SQLite fails to create a file it tries reopening readonly and only if that
fails too it logs the error.
However by that time the original error (for file creation) is lost.
Testcase:
$ cat >testcase.sh <<END
mkdir /tmp/foo && sqlite3 /tmp/foo/x.db <<EOF
pragma journal_mode=wal;
create table x(x int);
EOF
chmod -w /tmp/foo
gcc sqlite3.c testcase.c -ldl -DSQLITE_THREADSAFE=0 -o testcase
strace -e open ./testcase /tmp/foo/x.db
END
$ cat >testcase.c <<EOF
#include <sqlite3.h>
#include <stdio.h>
static void qlog(void *parg, int errcode, const char *msg)
{
fprintf(stderr,"SQLite error %x: %s\n", errcode, msg);
}
int main(int argc, char *argv[])
{
const char *path = argv[1];
sqlite3 *handle = NULL;
int ret = 0;
char *errmsg = NULL;
if (argc != 2) {
fprintf(stderr,"Usage: %s </path/to/db>\n", argv[0]);
return 1;
}
sqlite3_config(SQLITE_CONFIG_LOG, qlog, NULL);
if (sqlite3_open_v2(path, &handle, SQLITE_OPEN_READWRITE, NULL)) {
fprintf(stderr, "Failed to open database: %s\n",
sqlite3_errmsg(handle));
ret = 2;
} else if (sqlite3_exec(handle, "PRAGMA synchronous = NORMAL", NULL, NULL,
&errmsg)) {
fprintf(stderr, "exec failed: %s\n", errmsg);
sqlite3_free(errmsg);
ret = 3;
}
sqlite3_close(handle);
return ret;
}
EOF
$ sh testcase.sh
wal
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/tmp/foo/x.db", O_RDWR|O_CLOEXEC) = 3
open("/tmp/foo/x.db-wal", O_RDWR|O_CREAT|O_CLOEXEC, 0644) = -1 EACCES
(Permission denied)
open("/tmp/foo/x.db-wal", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or
directory)
SQLite error e: cannot open file at line 30945 of [f73337e3e2]
SQLite error e: os_unix.c:30945: (2) open(/tmp/foo/x.db-wal) - No such file or
directory
SQLite error e: unable to open database file
exec failed: unable to open database file
+++ exited with 3 +++
Would it be possible to save the errno when 1st robust_open fails, and report
both errno when the 2nd open fails here?
fd = robust_open(zName, openFlags, openMode);
OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags));
if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
/* Failed to open the file for read/write access. Try read-only. */
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
openFlags &= ~(O_RDWR|O_CREAT);
flags |= SQLITE_OPEN_READONLY;
openFlags |= O_RDONLY;
isReadonly = 1;
fd = robust_open(zName, openFlags, openMode);
}
if( fd<0 ){
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
goto open_finished;
}
Best regards,
--Edwin