Bart Friederichs
Bart Friederichs

Reputation: 33553

SQLite3 sqlite3_open succeeds, sqlite3_exec fails with CANTOPEN (error 14)

I have this code, which uses SQLite in C:

int settings_set(const char *name, const char *value) {
    int r = SQLITE_ERROR;
    int res = sqlite3_open(PERSISTENTDB, &db_persistent);
    if (SQLITE_OK == res) {
        char *sql = sqlite3_mprintf("REPLACE INTO settings VALUES ('%q', '%q')", name, value);
        r = sqlite3_exec(db_persistent, sql, 0, 0, 0);
        if (SQLITE_OK == r) {
            log_write(LVL_NOTICE, "[data] set setting '%s' to '%s'\n", name, value);
        } else {
            log_write(LVL_NOTICE, "[data] failed to set setting '%s' to '%s': code %d\n", name, value, r);
        }
        sqlite3_close(db_persistent);
        sqlite3_free(sql);
    } else {
        log_write(LVL_NOTICE, "[data] settings_set(): could not open persistent database: code %d\n", res);
    }

    return r;
}

When this code is run as root (the database file is set rw-rw-rw- and owned by root), this works fine. When run as nobody, I get an error code 14 (SQLITE_CANTOPEN) on the sqlite3_exec call. So, apparently the sqlite3_open call succeeds. I would expect this error to occur on the open call.

Upvotes: 1

Views: 1114

Answers (1)

Mat
Mat

Reputation: 206861

Your non-root user probably doesn't have the permission to create and write to new files in the directory hosting the database.

The documentation for that error code states:

The file in question might be a primary database file or on of several temporary disk files.

SQLite creates temporary files, at least when you modify the database. If your non-root process can't create those, you'll get that error. You could verify that by running your program in strace, e.g. something like:

strace -e trace=open ./a.out

You'll see which calls to open are failing (probably for the journal file), and for what reason.

Upvotes: 4

Related Questions