DBD-SQLcipher
view release on metacpan or search on metacpan
291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163#define osStat ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent)
/*
** The DJGPP compiler environment looks mostly like Unix, but it
** lacks the
fcntl
()
system
call. So redefine
fcntl
() to be something
** that always succeeds. This means that locking does not occur under
** DJGPP. But it is DOS - what did you expect?
*/
#ifdef __DJGPP__
{
"fstat"
, 0, 0 },
#define osFstat(a,b,c) 0
#else
{
"fstat"
, (sqlite3_syscall_ptr)fstat, 0 },
#define osFstat ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
#endif
{
"ftruncate"
, (sqlite3_syscall_ptr)ftruncate, 0 },
#define osFtruncate ((int(*)(int,off_t))aSyscall[6].pCurrent)
{
"fcntl"
, (sqlite3_syscall_ptr)
fcntl
, 0 },
#define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388
if
( fd>=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break;
osClose(fd);
sqlite3_log(SQLITE_WARNING,
"attempt to open \"%s\" as file descriptor %d"
, z, fd);
fd = -1;
if
( osOpen(
"/dev/null"
, f, m)<0 ) break;
}
if
( fd>=0 ){
if
( m!=0 ){
struct
stat
statbuf;
if
( osFstat(fd,
&statbuf
)==0
&& statbuf.st_size==0
&& (statbuf.st_mode&0777)!=m
){
osFchmod(fd, m);
}
}
#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
}
297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775** file descriptors opened on different file names.
**
** among competing threads of the same process. POSIX locks will work fine
** to synchronize access
for
threads in separate processes, but not
** threads within the same process.
**
** To work
around
the problem, SQLite
has
to manage file locks internally
** on its own. Whenever a new database is opened, we have to find the
** specific inode of the database file (the inode is determined by the
** st_dev and st_ino fields of the
stat
structure that fstat() fills in)
** and check
for
locks already existing on that inode. When locks are
** created or removed, we have to look at
our
own internal record of the
** locks to see
if
another thread
has
previously set a
lock
on that same
** inode.
**
** canonical filename and implemented in the previous division.)
**
** The sqlite3_file structure
for
POSIX is
no
longer just an integer file
300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042
struct unixFileId fileId; /* Lookup key
for
the unixInodeInfo */
struct
stat
statbuf; /* Low-level file information */
unixInodeInfo
*pInode
= 0; /* Candidate unixInodeInfo object */
assert( unixMutexHeld() );
/* Get low-level information about the file that we can used to
** create a unique name
for
the file.
*/
fd = pFile->h;
rc = osFstat(fd,
&statbuf
);
if
( rc!=0 ){
pFile->lastErrno = errno;
#ifdef EOVERFLOW
if
( pFile->lastErrno==EOVERFLOW )
return
SQLITE_NOLFS;
#endif
return
SQLITE_IOERR;
}
#ifdef __APPLE__
/* On OS X on an msdos filesystem, the inode number is reported
300483004930050300513005230053300543005530056300573005830059300603006130062300633006430065300663006730068
** in the header of every SQLite database. In this way,
if
there
** is a race condition such that another thread
has
already populated
** the first page of the database,
no
damage is done.
*/
if
( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
do
{ rc = osWrite(fd,
"S"
, 1); }
while
( rc<0 && errno==EINTR );
if
( rc!=1 ){
pFile->lastErrno = errno;
return
SQLITE_IOERR;
}
rc = osFstat(fd,
&statbuf
);
if
( rc!=0 ){
pFile->lastErrno = errno;
return
SQLITE_IOERR;
}
}
#endif
memset(
&fileId
, 0, sizeof(fileId));
fileId.dev = statbuf.st_dev;
#if OS_VXWORKS
301173011830119301203012130122301233012430125301263012730128301293013030131301323013330134301353013630137** Issue sqlite3_log(SQLITE_WARNING,...) messages
if
anything is not right.
*/
static void verifyDbFile(unixFile
*pFile
){
struct
stat
buf;
int
rc;
if
( pFile->ctrlFlags & UNIXFILE_WARNED ){
/* One or more of the following warnings have already been issued. Do not
** repeat them so as not to clutter the error
log
*/
return
;
}
rc = osFstat(pFile->h,
&buf
);
if
( rc!=0 ){
sqlite3_log(SQLITE_WARNING,
"cannot fstat db file %s"
, pFile->zPath);
pFile->ctrlFlags |= UNIXFILE_WARNED;
return
;
}
if
( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){
sqlite3_log(SQLITE_WARNING,
"file unlinked while open: %s"
, pFile->zPath);
pFile->ctrlFlags |= UNIXFILE_WARNED;
return
;
}
324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448
}
}
/*
** Determine the current size of a file in bytes
*/
static
int
unixFileSize(sqlite3_file
*id
, i64
*pSize
){
int
rc;
struct
stat
buf;
assert( id );
rc = osFstat(((unixFile*)id)->h,
&buf
);
SimulateIOError( rc=1 );
if
( rc!=0 ){
((unixFile*)id)->lastErrno = errno;
return
SQLITE_IOERR_FSTAT;
}
*pSize
= buf.st_size;
/* When opening a zero-size database, the findInodeInfo() procedure
** writes a single byte into that file in order to work
around
a bug
** in the OS-X msdos filesystem. In order to avoid problems
with
upper
3246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487/*
** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
** file-control operation. Enlarge the database to nBytes in size
** (rounded up to the
next
chunk-size). If the database is already
** nBytes or larger, this routine is a
no
-op.
*/
static
int
fcntlSizeHint(unixFile
*pFile
, i64 nByte){
if
( pFile->szChunk>0 ){
i64 nSize; /* Required file size */
struct
stat
buf; /* Used to hold
return
values
of fstat() */
if
( osFstat(pFile->h,
&buf
) )
return
SQLITE_IOERR_FSTAT;
nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
if
( nSize>(i64)buf.st_size ){
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
/* The code below is handling the
return
value of osFallocate()
** correctly. posix_fallocate() is
defined
to "returns zero on success,
** or an error number on failure". See the manpage
for
details. */
int
err;
do
{
330303303133032330333303433035330363303733038330393304033041330423304333044330453304633047330483304933050330513305233053330543305533056
memset(p, 0, sizeof(
*p
));
assert( pDbFd->pShm==0 );
/* Check to see
if
a unixShmNode object already
exists
. Reuse an existing
** one
if
present. Create a new one
if
necessary.
*/
unixEnterMutex();
pInode = pDbFd->pInode;
pShmNode = pInode->pShmNode;
if
( pShmNode==0 ){
struct
stat
sStat; /* fstat() info
for
database file */
/* Call fstat() to figure out the permissions on the database file. If
** a new *-shm file is created, an attempt will be made to create it
**
with
the same permissions.
*/
if
( osFstat(pDbFd->h,
&sStat
) && pInode->bProcessLock==0 ){
rc = SQLITE_IOERR_FSTAT;
goto
shm_open_err;
}
#ifdef SQLITE_SHM_DIRECTORY
nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31;
#else
nShmFilename = 6 + (
int
)strlen(pDbFd->zPath);
#endif
pShmNode = sqlite3_malloc( sizeof(
*pShmNode
) + nShmFilename );
331873318833189331903319133192331933319433195331963319733198331993320033201332023320333204332053320633207332083320933210332113321233213332143321533216assert( pShmNode->pInode==pDbFd->pInode );
assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
/* Minimum number of regions required to be mapped. */
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
if
( pShmNode->nRegion<nReqRegion ){
char *
*apNew
; /* New apRegion[] array */
int
nByte = nReqRegion
*szRegion
; /* Minimum required file size */
struct
stat
sStat; /* Used by fstat() */
pShmNode->szRegion = szRegion;
if
( pShmNode->h>=0 ){
/* The requested region is not mapped into this processes address space.
** Check to see
if
it
has
been allocated (i.e.
if
the wal-
index
file is
** large enough to contain the requested region).
*/
if
( osFstat(pShmNode->h,
&sStat
) ){
rc = SQLITE_IOERR_SHMSIZE;
goto
shmpage_out;
}
if
( sStat.st_size<nByte ){
/* The requested memory region does not exist. If bExtend is set to
** false,
exit
early.
*pp
will be set to NULL and SQLITE_OK returned.
*/
if
( !bExtend ){
goto
shmpage_out;
335953359633597335983359933600336013360233603336043360533606336073360833609336103361133612336133361433615*/
static
int
unixMapfile(unixFile
*pFd
, i64 nByte){
i64 nMap = nByte;
int
rc;
assert( nMap>=0 || pFd->nFetchOut==0 );
if
( pFd->nFetchOut>0 )
return
SQLITE_OK;
if
( nMap<0 ){
struct
stat
statbuf; /* Low-level file information */
rc = osFstat(pFd->h,
&statbuf
);
if
( rc!=SQLITE_OK ){
return
SQLITE_IOERR_FSTAT;
}
nMap = statbuf.st_size;
}
if
( nMap>pFd->mmapSizeMax ){
nMap = pFd->mmapSizeMax;
}
if
( nMap!=pFd->mmapSize ){
3406734068340693407034071340723407334074340753407634077340783407934080340813408234083340843408534086340873408834089340903409134092340933409434095340963409734098
|| pLockingStyle ==
&nfsIoMethods
#endif
){
unixEnterMutex();
rc = findInodeInfo(pNew,
&pNew
->pInode);
if
( rc!=SQLITE_OK ){
/* If an error occurred in findInodeInfo(),
close
the file descriptor
** immediately,
before
releasing the mutex. findInodeInfo() may fail
** in two scenarios:
**
** (a) A call to fstat() failed.
** (b) A malloc failed.
**
** Scenario (b) may only occur
if
the process is holding
no
other
** file descriptors
open
on the same file. If there were other file
** descriptors on this file, then
no
malloc would be required by
** findInodeInfo(). If this is the case, it is quite safe to
close
** handle h - as it is guaranteed that
no
posix locks will be released
** by doing so.
**
** If scenario (a) caused the error then things are not so safe. The
** implicit assumption here is that
if
fstat() fails, things are in
** such bad shape that dropping a
lock
or two doesn't matter much.
*/
robust_close(pNew, h, __LINE__);
h = -1;
}
unixLeaveMutex();
}
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
else
if
( pLockingStyle ==
&afpIoMethods
){
34282342833428434285342863428734288342893429034291342923429334294342953429634297342983429934300343013430234303343043430534306*/
static UnixUnusedFd
*findReusableFd
(const char
*zPath
,
int
flags){
UnixUnusedFd
*pUnused
= 0;
/* Do not search
for
an unused file descriptor on vxworks. Not because
** vxworks would not benefit from the change (it might, we're not sure),
** but because
no
way to test it is currently available. It is better
** not to risk breaking vxworks support
for
the sake of such an obscure
** feature. */
#if !OS_VXWORKS
struct
stat
sStat; /* Results of
stat
() call */
/* A
stat
() call may fail
for
various reasons. If this happens, it is
** almost certain that an
open
() call on the same path will also fail.
** For this reason,
if
an error occurs in the
stat
() call here, it is
** ignored and -1 is returned. The
caller
will
try
to
open
a new file
** descriptor on the same path, fail, and
return
an error to SQLite.
**
** Even
if
a subsequent
open
() call does succeed, the consequences of
** not searching
for
a reusable file descriptor are not dire. */
if
( 0==osStat(zPath,
&sStat
) ){
unixInodeInfo
*pInode
;
unixEnterMutex();
pInode = inodeList;
343503435134352343533435434355343563435734358343593436034361343623436334364343653436634367343683436934370
uid_t
*pUid
, /* OUT: uid to set on the file */
gid_t
*pGid
/* OUT: gid to set on the file */
){
int
rc = SQLITE_OK; /* Return Code */
*pMode
= 0;
*pUid
= 0;
*pGid
= 0;
if
( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
char zDb[MAX_PATHNAME+1]; /* Database file path */
int
nDb; /* Number of valid bytes in zDb */
struct
stat
sStat; /* Output of
stat
() on database file */
/* zPath is a path to a WAL or journal file. The following block derives
** the path to the associated database file from zPath. This block handles
** the following naming conventions:
**
**
"<path to db>-journal"
**
"<path to db>-wal"
**
"<path to db>-journalNN"
**
"<path to db>-walNN"
**
3549235493354943549535496354973549835499355003550135502355033550435505355063550735508355093551035511rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
nTries ++;
if
( rc==SQLITE_BUSY ){
/* If the
lock
failed (busy):
* 1st
try
: get the mod
time
of the conch,
wait
0.5s and
try
again.
* 2nd
try
: fail
if
the mod
time
changed or host id is different,
wait
* 10 sec and
try
again
* 3rd
try
: break the
lock
unless
the mod
time
has
changed.
*/
struct
stat
buf;
if
( osFstat(conchFile->h,
&buf
) ){
pFile->lastErrno = errno;
return
SQLITE_IOERR_LOCK;
}
if
( nTries==1 ){
conchModTime = buf.st_mtimespec;
usleep(500000); /*
wait
0.5 sec and
try
the
lock
again*/
continue
;
}
356813568235683356843568535686356873568835689356903569135692356933569435695356963569735698356993570035701
}
writeSize = PROXY_PATHINDEX + strlen(
&writeBuffer
[PROXY_PATHINDEX]);
robust_ftruncate(conchFile->h, writeSize);
rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
fsync(conchFile->h);
/* If we created a new conch file (not just updated the contents of a
** valid conch file),
try
to match the permissions of the database
*/
if
( rc==SQLITE_OK && createConch ){
struct
stat
buf;
int
err = osFstat(pFile->h,
&buf
);
if
( err==0 ){
mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
S_IROTH|S_IWOTH);
/*
try
to match the database file R/W permissions, ignore failure */
#ifndef SQLITE_PROXY_DEBUG
osFchmod(conchFile->h, cmode);
#else
do
{
rc = osFchmod(conchFile->h, cmode);
}
while
( rc==(-1) && errno==EINTR );
( run in 0.514 second using v1.01-cache-2.11-cpan-49f99fa48dc )