1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
|
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
|
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
-
-
-
+
-
-
-
-
-
+
-
-
-
-
+
+
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
+
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
|
** connections from reading or writing the database.
**
** (2) An application crash or power loss can leave stale lock files
** sitting around that need to be cleared manually.
**
** Nevertheless, a dotlock is an appropriate locking mode for use if no
** other locking strategy is available.
**
** Dotfile locking works by creating a file in the same directory as the
** database and with the same name but with a ".lock" extension added.
** The existance of a lock file implies an EXCLUSIVE lock. All other lock
** types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
*/
/*
** The file suffix added to the data base filename in order to create the
** lock file.
*/
#define DOTLOCK_SUFFIX ".lock"
/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. If such a lock is held, set *pResOut
** to a non-zero value otherwise *pResOut is set to zero. The return value
/* Dotlock-style reserved lock checking following the behavior of
** unixCheckReservedLock, see the unixCheckReservedLock function comments */
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
**
** In dotfile locking, either a lock exists or it does not. So in this
** variation of CheckReservedLock(), *pResOut is set to true if any lock
** is held on the file and false if the file is unlocked.
*/
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
int rc = SQLITE_OK;
int reserved = 0;
unixFile *pFile = (unixFile*)id;
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
/* Check if a thread in this process holds such a lock */
if( pFile->locktype>SHARED_LOCK ){
reserved = 1;
}
/* Either this connection or some other connection in the same process
/* Otherwise see if some other process holds it. */
if( !reserved ){
char *zLockFile = (char *)pFile->lockingContext;
struct stat statBuf;
** holds a lock on the file. No need to check further. */
if( lstat(zLockFile, &statBuf)==0 ){
/* file exists, someone else has the lock */
reserved = 1;
}else{
reserved = 1;
}else{
/* file does not exist, we could have it if we want it */
int tErrno = errno;
if( ENOENT != tErrno ){
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
pFile->lastErrno = tErrno;
}
/* The lock is held if and only if the lockfile exists */
const char *zLockFile = (const char*)pFile->lockingContext;
reserved = access(zLockFile, 0)==0;
}
}
}
OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
*pResOut = reserved;
return rc;
}
/*
** Lock the file with the lock specified by parameter locktype - one
** of the following:
**
** (1) SHARED_LOCK
** (2) RESERVED_LOCK
** (3) PENDING_LOCK
** (4) EXCLUSIVE_LOCK
**
** Sometimes when requesting one lock state, additional lock states
** are inserted in between. The locking might fail on one of the later
** transitions leaving the lock state different from what it started but
** still short of its goal. The following chart shows the allowed
** transitions and the inserted intermediate states:
**
** UNLOCKED -> SHARED
** SHARED -> RESERVED
** SHARED -> (PENDING) -> EXCLUSIVE
** RESERVED -> (PENDING) -> EXCLUSIVE
** PENDING -> EXCLUSIVE
**
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
**
** With dotfile locking, we really only support state (4): EXCLUSIVE.
** But we track the other locking levels internally.
*/
static int dotlockLock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
int fd;
char *zLockFile = (char *)pFile->lockingContext;
int rc=SQLITE_OK;
int rc = SQLITE_OK;
/* if we already have a lock, it is exclusive.
** Just adjust level and punt on outta here. */
if (pFile->locktype > NO_LOCK) {
/* If we have any lock, then the lock file already exists. All we have
** to do is adjust our internal record of the lock level.
*/
if( pFile->locktype > NO_LOCK ){
pFile->locktype = locktype;
#if !OS_VXWORKS
/* Always update the timestamp on the old file */
utimes(zLockFile, NULL);
#endif
rc = SQLITE_OK;
return SQLITE_OK;
goto dotlock_end_lock;
}
/* check to see if lock file already exists */
struct stat statBuf;
if (lstat(zLockFile,&statBuf) == 0){
rc = SQLITE_BUSY; /* it does, busy */
goto dotlock_end_lock;
}
/* grab an exclusive lock */
fd = open(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600);
if( fd<0 ){
/* failed to open/create the file, someone else may have stolen the lock */
int tErrno = errno;
if( EEXIST == tErrno ){
rc = SQLITE_BUSY;
} else {
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
}
goto dotlock_end_lock;
return rc;
}
if( close(fd) ){
pFile->lastErrno = errno;
rc = SQLITE_IOERR_CLOSE;
}
/* got it, set the type and return ok */
pFile->locktype = locktype;
dotlock_end_lock:
return rc;
}
/*
** Lower the locking level on file descriptor pFile to locktype. locktype
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
**
** When the locking level reaches NO_LOCK, delete the lock file.
*/
static int dotlockUnlock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
char *zLockFile = (char *)pFile->lockingContext;
assert( pFile );
OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
pFile->locktype, getpid());
assert( locktype<=SHARED_LOCK );
/* no-op if possible */
if( pFile->locktype==locktype ){
return SQLITE_OK;
}
/* shared can just be set because we always have an exclusive */
if (locktype==SHARED_LOCK) {
pFile->locktype = locktype;
/* To downgrade to shared, simply update our internal notion of the
** lock state. No need to mess with the file on disk.
*/
if( locktype==SHARED_LOCK ){
pFile->locktype = SHARED_LOCK;
return SQLITE_OK;
}
/* To fully unlock the database, delete the lock file */
/* no, really, unlock. */
if (unlink(zLockFile) ) {
assert( locktype==NO_LOCK );
if( unlink(zLockFile) ){
int rc, tErrno = errno;
if( ENOENT != tErrno ){
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
}
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
|
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
|
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
|
-
-
+
+
+
+
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
+
-
+
+
-
+
-
-
-
-
+
+
+
-
+
-
-
-
-
+
+
+
+
+
|
/*
** Here ends the implementation of all sqlite3_file methods.
**
********************** End sqlite3_file Methods *******************************
******************************************************************************/
/*
** The following constant array describes all of the methods for the
** sqlite3_file object for each of the various locking modes.
** Each instance of this macro generates two objects:
**
** * A constant sqlite3_io_methods object call METHOD that has locking
** methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
**
** The order in which the methods are defined is important and must
** agree with the numeric values of the method identifier constants.
** * An I/O method finder function called FINDER that returns a pointer
** For example, LOCKING_STYLE_UNIX has a numeric value of zero, so
** it must be the 0-th entry in the array.
** to the METHOD object in the previous bullet.
*/
#define IOMETHODS(xClose, xLock, xUnlock, xCheckReservedLock) { \
1, /* iVersion */ \
xClose, /* xClose */ \
unixRead, /* xRead */ \
unixWrite, /* xWrite */ \
unixTruncate, /* xTruncate */ \
unixSync, /* xSync */ \
unixFileSize, /* xFileSize */ \
xLock, /* xLock */ \
xUnlock, /* xUnlock */ \
xCheckReservedLock, /* xCheckReservedLock */ \
unixFileControl, /* xFileControl */ \
unixSectorSize, /* xSectorSize */ \
unixDeviceCharacteristics /* xDeviceCapabilities */ \
}
static sqlite3_io_methods aIoMethod[] = {
IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock),
IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock),
IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock),
#define IOMETHODS(FINDER, METHOD, CLOSE, LOCK, UNLOCK, CKLOCK) \
static const sqlite3_io_methods METHOD = { \
1, /* iVersion */ \
CLOSE, /* xClose */ \
unixRead, /* xRead */ \
unixWrite, /* xWrite */ \
unixTruncate, /* xTruncate */ \
unixSync, /* xSync */ \
unixFileSize, /* xFileSize */ \
LOCK, /* xLock */ \
UNLOCK, /* xUnlock */ \
CKLOCK, /* xCheckReservedLock */ \
unixFileControl, /* xFileControl */ \
unixSectorSize, /* xSectorSize */ \
unixDeviceCharacteristics /* xDeviceCapabilities */ \
}; \
static const sqlite3_io_methods *FINDER(const char *z, int h){ \
UNUSED_PARAMETER(z); UNUSED_PARAMETER(h); \
return &METHOD; \
}
/*
** Here are all of the sqlite3_io_methods objects for each of the
** locking strategies. Functions that return pointers to these methods
** are also created.
*/
IOMETHODS(
posixIoFinder, /* Finder function name */
posixIoMethods, /* sqlite3_io_methods object name */
unixClose, /* xClose method */
unixLock, /* xLock method */
unixUnlock, /* xUnlock method */
unixCheckReservedLock /* xCheckReservedLock method */
);
IOMETHODS(
nolockIoFinder, /* Finder function name */
nolockIoMethods, /* sqlite3_io_methods object name */
nolockClose, /* xClose method */
nolockLock, /* xLock method */
nolockUnlock, /* xUnlock method */
nolockCheckReservedLock /* xCheckReservedLock method */
);
IOMETHODS(
dotlockIoFinder, /* Finder function name */
dotlockIoMethods, /* sqlite3_io_methods object name */
dotlockClose, /* xClose method */
dotlockLock, /* xLock method */
dotlockUnlock, /* xUnlock method */
dotlockCheckReservedLock /* xCheckReservedLock method */
);
#if SQLITE_ENABLE_LOCKING_STYLE
IOMETHODS(
flockIoFinder, /* Finder function name */
flockIoMethods, /* sqlite3_io_methods object name */
flockClose, /* xClose method */
flockLock, /* xLock method */
flockUnlock, /* xUnlock method */
flockCheckReservedLock /* xCheckReservedLock method */
);
#endif
#if OS_VXWORKS
IOMETHODS(semClose, semLock, semUnlock, semCheckReservedLock),
#elif SQLITE_ENABLE_LOCKING_STYLE
IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock),
IOMETHODS(
semIoFinder, /* Finder function name */
semIoMethods, /* sqlite3_io_methods object name */
semClose, /* xClose method */
semLock, /* xLock method */
semUnlock, /* xUnlock method */
semCheckReservedLock /* xCheckReservedLock method */
);
#endif
#if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE
IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock),
IOMETHODS(proxyClose, proxyLock, proxyUnlock, proxyCheckReservedLock),
IOMETHODS(
afpIoFinder, /* Finder function name */
afpIoMethods, /* sqlite3_io_methods object name */
afpClose, /* xClose method */
afpLock, /* xLock method */
afpUnlock, /* xUnlock method */
afpCheckReservedLock /* xCheckReservedLock method */
);
IOMETHODS(
proxyIoFinder, /* Finder function name */
proxyIoMethods, /* sqlite3_io_methods object name */
proxyClose, /* xClose method */
proxyLock, /* xLock method */
proxyUnlock, /* xUnlock method */
proxyCheckReservedLock /* xCheckReservedLock method */
);
#endif
/* The order of the IOMETHODS macros above is important. It must be the
** same order as the LOCKING_STYLE numbers
*/
};
#if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE
/*
** This procedure attempts to determine the best locking strategy for
** the given database file. It then returns the sqlite3_io_methods
** object that implements that strategy.
**
** This is for MacOSX only.
*/
static const sqlite3_io_methods *autolockIoFinder(
const char *filePath, /* name of the database file */
int fd /* file descriptor open on the database file */
){
static const struct Mapping {
const char *zFilesystem;
const sqlite3_io_methods *pMethods;
} aMap[] = {
{ "hfs", &posixIoMethods },
{ "ufs", &posixIoMethods },
{ "afpfs", &afpIoMethods },
#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB
{ "smbfs", &afpIoMethods },
#else
{ "smbfs", &flockIoMethods },
#endif
{ "webdav", &nolockIoMethods },
{ 0, 0 }
};
int i;
struct statfs fsInfo;
struct flock lockInfo;
if( !filePath ){
return &nolockIoMethods;
}
if( statfs(filePath, &fsInfo) != -1 ){
if( fsInfo.f_flags & MNT_RDONLY ){
return &nolockIoMethods;
}
for(i=0; aMap[i].zFilesystem; i++){
if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
return aMap[i].pMethods;
}
}
}
/* Default case. Handles, amongst others, "nfs".
** Test byte-range lock using fcntl(). If the call succeeds,
** assume that the file-system supports POSIX style locks.
*/
lockInfo.l_len = 1;
lockInfo.l_start = 0;
lockInfo.l_whence = SEEK_SET;
lockInfo.l_type = F_RDLCK;
if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) {
return &posixIoMethods;
}else{
return &dotlockIoMethods;
}
}
#endif /* defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE */
/*
** An abstract type for a pointer to a IO method finder function:
*/
typedef const sqlite3_io_methods *(*finder_type)(const char*,int);
/****************************************************************************
**************************** sqlite3_vfs methods ****************************
**
** This division contains the implementation of methods on the
** sqlite3_vfs object.
*/
/*
/*
** If SQLITE_ENABLE_LOCKING_STYLE is defined, this function Examines the
** f_fstypename entry in the statfs structure as returned by stat() for
** the file system hosting the database file and selects the appropriate
** locking style based on its value. These values and assignments are
** based on Darwin/OSX behavior and have not been thoroughly tested on
** other systems.
**
** If SQLITE_ENABLE_LOCKING_STYLE is not defined, this function always
** returns LOCKING_STYLE_POSIX.
*/
#if SQLITE_ENABLE_LOCKING_STYLE
static int detectLockingStyle(
sqlite3_vfs *pVfs,
const char *filePath,
int fd
){
#if OS_VXWORKS
if( !filePath ){
return LOCKING_STYLE_NONE;
}
if( pVfs->pAppData ){
return SQLITE_PTR_TO_INT(pVfs->pAppData);
}
if (access(filePath, 0) != -1){
return testLockingStyle(fd);
}
#else
struct Mapping {
const char *zFilesystem;
int eLockingStyle;
} aMap[] = {
{ "hfs", LOCKING_STYLE_POSIX },
{ "ufs", LOCKING_STYLE_POSIX },
{ "afpfs", LOCKING_STYLE_AFP },
#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB
{ "smbfs", LOCKING_STYLE_AFP },
#else
{ "smbfs", LOCKING_STYLE_FLOCK },
#endif
{ "webdav", LOCKING_STYLE_NONE },
{ 0, 0 }
};
int i;
struct statfs fsInfo;
if( !filePath ){
return LOCKING_STYLE_NONE;
}
if( pVfs && pVfs->pAppData ){
return SQLITE_PTR_TO_INT(pVfs->pAppData);
}
if( statfs(filePath, &fsInfo) != -1 ){
if( fsInfo.f_flags & MNT_RDONLY ){
return LOCKING_STYLE_NONE;
}
for(i=0; aMap[i].zFilesystem; i++){
if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
return aMap[i].eLockingStyle;
}
}
}
/* Default case. Handles, amongst others, "nfs". */
return testLockingStyle(fd);
#endif /* if OS_VXWORKS */
return LOCKING_STYLE_POSIX;
}
#else
#define detectLockingStyle(x,y,z) LOCKING_STYLE_POSIX
#endif /* if SQLITE_ENABLE_LOCKING_STYLE */
/*
** Initialize the contents of the unixFile structure pointed to by pId.
**
** When locking extensions are enabled, the filepath and locking style
** are needed to determine the unixFile pMethod to use for locking operations.
** The locking-style specific lockingContext data structure is created
** and assigned here also.
*/
static int fillInUnixFile(
sqlite3_vfs *pVfs, /* Pointer to vfs object */
int h, /* Open file descriptor of file being opened */
int dirfd, /* Directory file descriptor */
sqlite3_file *pId, /* Write to the unixFile structure here */
const char *zFilename, /* Name of the file being opened */
int noLock, /* Omit locking if true */
int isDelete /* Delete on close if true */
){
int eLockingStyle;
const sqlite3_io_methods *pLockingStyle;
unixFile *pNew = (unixFile *)pId;
int rc = SQLITE_OK;
assert( pNew->pLock==NULL );
assert( pNew->pOpen==NULL );
/* Parameter isDelete is only used on vxworks. Parameter pVfs is only
** used if ENABLE_LOCKING_STYLE is defined. Express this explicitly
** here to prevent compiler warnings about unused parameters.
*/
#if !OS_VXWORKS
if( !OS_VXWORKS ) UNUSED_PARAMETER(isDelete);
if( !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(pVfs);
if( !OS_VXWORKS && !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(zFilename);
UNUSED_PARAMETER(isDelete);
#endif
#if !SQLITE_ENABLE_LOCKING_STYLE
UNUSED_PARAMETER(pVfs);
#endif
#if !OS_VXWORKS && !SQLITE_ENABLE_LOCKING_STYLE
UNUSED_PARAMETER(zFilename);
#endif
OSTRACE3("OPEN %-3d %s\n", h, zFilename);
pNew->h = h;
pNew->dirfd = dirfd;
SET_THREADID(pNew);
#if OS_VXWORKS
pNew->pId = vxworksFindFileId(zFilename);
if( pNew->pId==0 ){
noLock = 1;
rc = SQLITE_NOMEM;
}
#endif
if( noLock ){
eLockingStyle = LOCKING_STYLE_NONE;
pLockingStyle = &nolockIoMethods;
}else{
eLockingStyle = detectLockingStyle(pVfs, zFilename, h);
pLockingStyle = (*(finder_type)pVfs->pAppData)(zFilename, h);
#if SQLITE_ENABLE_LOCKING_STYLE
/* Cache zFilename in the locking context (AFP and dotlock override) for
** proxyLock activation is possible (remote proxy is based on db name)
** zFilename remains valid until file is closed, to support */
pNew->lockingContext = (void*)zFilename;
#endif
}
if( pLockingStyle == &posixIoMethods ){
unixEnterMutex();
rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
unixLeaveMutex();
}
switch( eLockingStyle ){
case LOCKING_STYLE_POSIX: {
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
else if( pLockingStyle == &apfIoMethods ){
/* AFP locking uses the file path so it needs to be included in
** the afpLockingContext.
*/
afpLockingContext *pCtx;
pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
if( pCtx==0 ){
rc = SQLITE_NOMEM;
}else{
/* NB: zFilename exists and remains valid until the file is closed
** according to requirement F11141. So we do not need to make a
** copy of the filename. */
pCtx->dbPath = zFilename;
srandomdev();
unixEnterMutex();
rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
unixLeaveMutex();
rc = findLockInfo(pNew, NULL, &pNew->pOpen);
unixLeaveMutex();
break;
}
}
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
else if( pLockingStyle == &dotlockIoMethods ){
#if !OS_VXWORKS
case LOCKING_STYLE_AFP: {
/* AFP locking uses the file path so it needs to be included in
** the afpLockingContext.
*/
afpLockingContext *pCtx;
pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
if( pCtx==0 ){
rc = SQLITE_NOMEM;
}else{
/* NB: zFilename exists and remains valid until the file is closed
** according to requirement F11141. So we do not need to make a
** copy of the filename. */
pCtx->dbPath = zFilename;
srandomdev();
unixEnterMutex();
rc = findLockInfo(pNew, NULL, &pNew->pOpen);
unixLeaveMutex();
}
break;
}
#endif
case LOCKING_STYLE_DOTFILE: {
/* Dotfile locking uses the file path so it needs to be included in
** the dotlockLockingContext
*/
char *zLockFile;
int nFilename;
nFilename = strlen(zFilename) + 6;
zLockFile = (char *)sqlite3_malloc(nFilename);
if( zLockFile==0 ){
rc = SQLITE_NOMEM;
}else{
sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
}
pNew->lockingContext = zLockFile;
/* Dotfile locking uses the file path so it needs to be included in
** the dotlockLockingContext
*/
char *zLockFile;
int nFilename;
nFilename = strlen(zFilename) + 6;
zLockFile = (char *)sqlite3_malloc(nFilename);
if( zLockFile==0 ){
rc = SQLITE_NOMEM;
}else{
sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
}
pNew->lockingContext = zLockFile;
break;
}
}
#endif
#if OS_VXWORKS
case LOCKING_STYLE_NAMEDSEM: {
/* Named semaphore locking uses the file path so it needs to be
** included in the semLockingContext
*/
unixEnterMutex();
rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){
char *zSemName = pNew->pOpen->aSemName;
int n;
sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem",
pNew->pId->zCanonicalName);
for( n=0; zSemName[n]; n++ )
if( zSemName[n]=='/' ) zSemName[n] = '_';
pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
if( pNew->pOpen->pSem == SEM_FAILED ){
rc = SQLITE_NOMEM;
pNew->pOpen->aSemName[0] = '\0';
}
}
unixLeaveMutex();
else if( pLockingStyle == &semIoMethods ){
/* Named semaphore locking uses the file path so it needs to be
** included in the semLockingContext
*/
unixEnterMutex();
rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){
char *zSemName = pNew->pOpen->aSemName;
int n;
sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem",
pNew->pId->zCanonicalName);
for( n=0; zSemName[n]; n++ )
if( zSemName[n]=='/' ) zSemName[n] = '_';
pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
if( pNew->pOpen->pSem == SEM_FAILED ){
rc = SQLITE_NOMEM;
pNew->pOpen->aSemName[0] = '\0';
}
}
unixLeaveMutex();
break;
}
}
#endif
case LOCKING_STYLE_FLOCK:
case LOCKING_STYLE_NONE:
break;
#endif
}
pNew->lastErrno = 0;
#if OS_VXWORKS
if( rc!=SQLITE_OK ){
unlink(zFilename);
isDelete = 0;
}
pNew->isDelete = isDelete;
#endif
if( rc!=SQLITE_OK ){
if( dirfd>=0 ) close(dirfd); /* silent leak if fail, already in error */
close(h);
}else{
pNew->pMethod = &aIoMethod[eLockingStyle-1];
pNew->pMethod = pLockingStyle;
OpenCounter(+1);
}
return rc;
}
#if SQLITE_ENABLE_LOCKING_STYLE
static sqlite3_io_methods *ioMethodForLockingStyle(int style){
return &aIoMethod[style];
}
static int getDbPathForUnixFile(unixFile *pFile, char *dbPath){
#if defined(__DARWIN__)
if( pFile->pMethod==ioMethodForLockingStyle(LOCKING_STYLE_AFP) ){
if( pFile->pMethod == &afpIoMethods ){
/* afp style keeps a reference to the db path in the filePath field
** of the struct */
assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath,
strcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath)
MAXPATHLEN);
return SQLITE_OK;
}
if( pFile->pMethod==ioMethodForLockingStyle(LOCKING_STYLE_DOTFILE) ){
}else
#endif
if( pFile->pMethod == &dotlockIoMethods ){
/* dot lock style uses the locking context to store the dot lock
** file path */
int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
strlcpy(dbPath, (char *)pFile->lockingContext, len + 1);
memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
return SQLITE_OK;
}
/* all other styles use the locking context to store the db file path */
strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
}else{
/* all other styles use the locking context to store the db file path */
assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
strcpy(dbPath, (char *)pFile->lockingContext);
}
return SQLITE_OK;
}
#endif
/*
** Open a file descriptor to the directory containing file zFilename.
** If successful, *pFd is set to the opened file descriptor and
|
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
|
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
|
-
+
-
-
+
+
-
+
+
-
-
-
-
+
+
+
+
+
+
-
+
+
-
+
-
-
+
+
|
*/
int sqlite3_os_init(void){
/* Macro to define the static contents of an sqlite3_vfs structure for
** the unix backend. The two parameters are the values to use for
** the sqlite3_vfs.zName and sqlite3_vfs.pAppData fields, respectively.
**
*/
#define UNIXVFS(zVfsName, pVfsAppData) { \
#define UNIXVFS(VFSNAME, FINDER) { \
1, /* iVersion */ \
sizeof(unixFile), /* szOsFile */ \
MAX_PATHNAME, /* mxPathname */ \
0, /* pNext */ \
zVfsName, /* zName */ \
(void *)pVfsAppData, /* pAppData */ \
VFSNAME, /* zName */ \
(void*)FINDER, /* pAppData */ \
unixOpen, /* xOpen */ \
unixDelete, /* xDelete */ \
unixAccess, /* xAccess */ \
unixFullPathname, /* xFullPathname */ \
unixDlOpen, /* xDlOpen */ \
unixDlError, /* xDlError */ \
unixDlSym, /* xDlSym */ \
unixDlClose, /* xDlClose */ \
unixRandomness, /* xRandomness */ \
unixSleep, /* xSleep */ \
unixCurrentTime, /* xCurrentTime */ \
unixGetLastError /* xGetLastError */ \
}
int i;
unsigned int i;
static sqlite3_vfs aVfs[] = {
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
UNIXVFS("unix", LOCKING_STYLE_AUTOMATIC),
UNIXVFS("unix-posix", LOCKING_STYLE_POSIX),
UNIXVFS("unix-none", LOCKING_STYLE_NONE),
UNIXVFS("unix-dotfile", LOCKING_STYLE_DOTFILE),
UNIXVFS("unix", autolockIoFinder ),
#else
UNIXVFS("unix", posixIoFinder ),
#endif
UNIXVFS("unix-none", nolockIoFinder ),
UNIXVFS("unix-dotfile", dotlockIoFinder ),
#if OS_VXWORKS
UNIXVFS("unix-namedsem",LOCKING_STYLE_NAMEDSEM),
UNIXVFS("unix-namedsem", semIoFinder ),
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
UNIXVFS("unix-posix", posixIoFinder ),
UNIXVFS("unix-flock", LOCKING_STYLE_FLOCK),
UNIXVFS("unix-flock", flockIoFinder ),
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
UNIXVFS("unix-afp", LOCKING_STYLE_AFP),
UNIXVFS("unix-proxy", LOCKING_STYLE_PROXY)
UNIXVFS("unix-afp", afpIoFinder ),
UNIXVFS("unix-proxy", proxyIoFinder ),
#endif
};
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
sqlite3_vfs_register(&aVfs[i], i==0);
}
return SQLITE_OK;
}
|