SQLite

Check-in [a678e85402]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Have os_unix.c reuse cached file-descriptors in the case when a read-write fd is requested on a read-only file and a read-only fd returned.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: a678e85402af08c1e387bf30ff2205f84dd7da749755da565d70f831c007a3d9
User & Date: dan 2024-03-21 11:37:36.346
Context
2024-03-21
11:46
Enhancements to testrunner.tcl: (1) Add the "--config CONFIGS" option, to that only configuration named on the comma-separated list CONFIGS are run. (2) Add the "--omit CONFIGS" to omit configuration on the CONFIGS list (3) Add the Android configuration to "release" (check-in: 4ccb372967 user: drh tags: trunk)
11:37
Have os_unix.c reuse cached file-descriptors in the case when a read-write fd is requested on a read-only file and a read-only fd returned. (check-in: a678e85402 user: dan tags: trunk)
10:35
Fix all test cases so that they work with SQLITE_ALLOW_ROWID_IN_VIEW. (check-in: 66c69e2f20 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/os_unix.c.
6394
6395
6396
6397
6398
6399
6400

6401
6402
6403
6404
6405





6406

6407
6408
6409
6410
6411
6412
6413
    if( fd<0 ){
      if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){
        /* If unable to create a journal because the directory is not
        ** writable, change the error code to indicate that. */
        rc = SQLITE_READONLY_DIRECTORY;
      }else if( errno!=EISDIR && isReadWrite ){
        /* 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 ){
      int rc2 = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
      if( rc==SQLITE_OK ) rc = rc2;
      goto open_finished;
    }







>





>
>
>
>
>
|
>







6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
    if( fd<0 ){
      if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){
        /* If unable to create a journal because the directory is not
        ** writable, change the error code to indicate that. */
        rc = SQLITE_READONLY_DIRECTORY;
      }else if( errno!=EISDIR && isReadWrite ){
        /* Failed to open the file for read/write access. Try read-only. */
        UnixUnusedFd *pReadonly = 0;
        flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
        openFlags &= ~(O_RDWR|O_CREAT);
        flags |= SQLITE_OPEN_READONLY;
        openFlags |= O_RDONLY;
        isReadonly = 1;
        pReadonly = findReusableFd(zName, flags);
        if( pReadonly ){
          fd = pReadonly->fd;
          sqlite3_free(pReadonly);
        }else{
          fd = robust_open(zName, openFlags, openMode);
        }
      }
    }
    if( fd<0 ){
      int rc2 = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
      if( rc==SQLITE_OK ) rc = rc2;
      goto open_finished;
    }
Added test/readonly.test.












































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 2024 March 21
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests for using databases in read-only mode on
# unix.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
set ::testprefix readonly

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2), (3, 4), (5, 6);
}

db close
file attributes test.db -permissions r--r--r--

sqlite3 db test.db

do_catchsql_test 1.1 {
  INSERT INTO t1 VALUES(7, 8);
} {1 {attempt to write a readonly database}}

do_execsql_test 1.2 {
  BEGIN;
    SELECT * FROM t1;
} {1 2 3 4 5 6}

# The following attempts to open a read/write fd on the database 20,000 
# times. And each time instead opens a read-only fd. At one point this
# was failing to reuse cached fds, causing a "too many open file-descriptors"
# error.
do_test 1.3 {
  for {set ii 0} {$ii < 20000} {incr ii} {
    sqlite3 db2 test.db
    db2 close
  }
  set {} {} 
} {}


finish_test