aboutsummaryrefslogtreecommitdiff
path: root/src/os_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/os_unix.c')
-rw-r--r--src/os_unix.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/src/os_unix.c b/src/os_unix.c
index a760e2c14..d463e5917 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -212,6 +212,7 @@ struct unixFile {
UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
const char *zPath; /* Name of the file */
unixShm *pShm; /* Shared memory segment information */
+ int readOnlyShm; /* True to open shared-memory read-only */
int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
#if SQLITE_ENABLE_LOCKING_STYLE
int openFlags; /* The flags specified at open() */
@@ -3452,6 +3453,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
case SQLITE_FCNTL_SIZE_HINT: {
return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
}
+ case SQLITE_FCNTL_READONLY_SHM: {
+ ((unixFile*)id)->readOnlyShm = (pArg!=0);
+ return SQLITE_OK;
+ }
#ifndef NDEBUG
/* The pager calls this method to signal that it has done
** a rollback and that the database is therefore unchanged and
@@ -3541,6 +3546,7 @@ struct unixShmNode {
char **apRegion; /* Array of mapped shared-memory regions */
int nRef; /* Number of unixShm objects pointing to this */
unixShm *pFirst; /* All unixShm objects pointing to this */
+ u8 readOnly; /* True if this is a read-only mapping */
#ifdef SQLITE_DEBUG
u8 exclMask; /* Mask of exclusive locks held */
u8 sharedMask; /* Mask of shared locks held */
@@ -3780,29 +3786,48 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
}
if( pInode->bProcessLock==0 ){
- pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
- (sStat.st_mode & 0777));
+ int flags = (pDbFd->readOnlyShm ? O_RDONLY : O_RDWR|O_CREAT);
+ pShmNode->h = robust_open(zShmFilename, flags, (sStat.st_mode & 0777));
if( pShmNode->h<0 ){
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
goto shm_open_err;
}
+ pShmNode->readOnly = pDbFd->readOnlyShm;
/* Check to see if another process is holding the dead-man switch.
- ** If not, truncate the file to zero length.
- */
- rc = SQLITE_OK;
- if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
- if( robust_ftruncate(pShmNode->h, 0) ){
- rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
+ ** If not, zero the first few bytes of the shared-memory file to make
+ ** sure it is not mistaken for valid by code in wal.c. Except, if this
+ ** is a read-only connection to the shared-memory then it is not possible
+ ** to check check if another process is holding a read-lock on the DMS
+ ** byte, as we cannot attempt a write-lock via a read-only file
+ ** descriptor. So in this case, we just assume the shared-memory
+ ** contents are Ok and proceed. */
+ if( pShmNode->readOnly==0 ){
+ rc = SQLITE_OK;
+ if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
+ if( pDbFd->readOnlyShm ){
+ rc = SQLITE_IOERR_SHMOPEN;
+ }else if( 4!=osWrite(pShmNode->h, "\00\00\00\00", 4) ){
+ rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
+ }
}
+ if( rc==SQLITE_OK ){
+ rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
+ }
+ if( rc ) goto shm_open_err;
}
- if( rc==SQLITE_OK ){
- rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
- }
- if( rc ) goto shm_open_err;
}
}
+ /* If the unixShmNode is read-only, but SQLITE_FCNTL_READONLY_SHM has not
+ ** been set for file-descriptor pDbFd, return an error. The wal.c module
+ ** will then call this function again with SQLITE_FCNTL_READONLY_SHM set.
+ */
+ else if( pShmNode->readOnly && !pDbFd->readOnlyShm ){
+ rc = SQLITE_IOERR_SHMOPEN;
+ goto shm_open_err;
+ }
+
/* Make the new connection a child of the unixShmNode */
p->pShmNode = pShmNode;
#ifdef SQLITE_DEBUG
@@ -3923,7 +3948,7 @@ static int unixShmMap(
while(pShmNode->nRegion<=iRegion){
void *pMem;
if( pShmNode->h>=0 ){
- pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE,
+ pMem = mmap(0, szRegion, PROT_READ|(!pShmNode->readOnly?PROT_WRITE:0),
MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
);
if( pMem==MAP_FAILED ){