aboutsummaryrefslogtreecommitdiff
path: root/src/os_unix.c
diff options
context:
space:
mode:
authordan <dan@noemail.net>2015-11-02 15:08:56 +0000
committerdan <dan@noemail.net>2015-11-02 15:08:56 +0000
commitf0db464b9334307c5d33ae12485a6541d03e7844 (patch)
treed8205e2a5885f9f6b4469c867a773b2b281189c2 /src/os_unix.c
parent153110a7dadd49d5ded395a61242dc046334870c (diff)
parent245fdc60d645214b745542b8f73d6efbc556d143 (diff)
downloadsqlite-f0db464b9334307c5d33ae12485a6541d03e7844.tar.gz
sqlite-f0db464b9334307c5d33ae12485a6541d03e7844.zip
On unix, if a file is opened via a symlink, create, read and write journal and wal files based on the name of the actual db file, not the symlink.
FossilOrigin-Name: 6d5ce3ede4c7038c19a77268a5a7b9d5650933c2
Diffstat (limited to 'src/os_unix.c')
-rw-r--r--src/os_unix.c54
1 files changed, 47 insertions, 7 deletions
diff --git a/src/os_unix.c b/src/os_unix.c
index fb2a8ca91..b322d238e 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -464,6 +464,9 @@ static struct unix_syscall {
{ "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 },
#define osGetpagesize ((int(*)(void))aSyscall[24].pCurrent)
+ { "readlink", (sqlite3_syscall_ptr)readlink, 0 },
+#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[25].pCurrent)
+
#endif
}; /* End of the overrideable system calls */
@@ -6026,6 +6029,7 @@ static int unixFullPathname(
int nOut, /* Size of output buffer in bytes */
char *zOut /* Output buffer */
){
+ int nByte;
/* It's odd to simulate an io-error here, but really this is just
** using the io-error infrastructure to test that SQLite handles this
@@ -6037,17 +6041,53 @@ static int unixFullPathname(
assert( pVfs->mxPathname==MAX_PATHNAME );
UNUSED_PARAMETER(pVfs);
- zOut[nOut-1] = '\0';
- if( zPath[0]=='/' ){
- sqlite3_snprintf(nOut, zOut, "%s", zPath);
+ /* Attempt to resolve the path as if it were a symbolic link. If it is
+ ** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if
+ ** the identified file is not a symbolic link or does not exist, then
+ ** zPath is copied directly into zOut. Either way, nByte is left set to
+ ** the size of the string copied into zOut[] in bytes. */
+ nByte = osReadlink(zPath, zOut, nOut-1);
+ if( nByte<0 ){
+ if( errno!=EINVAL && errno!=ENOENT ){
+ return unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath);
+ }
+ zOut[nOut-1] = '\0';
+ sqlite3_snprintf(nOut-1, zOut, "%s", zPath);
+ nByte = sqlite3Strlen30(zOut);
}else{
+ zOut[nByte] = '\0';
+ }
+
+ /* If buffer zOut[] now contains an absolute path there is nothing more
+ ** to do. If it contains a relative path, do the following:
+ **
+ ** * move the relative path string so that it is at the end of th
+ ** zOut[] buffer.
+ ** * Call getcwd() to read the path of the current working directory
+ ** into the start of the zOut[] buffer.
+ ** * Append a '/' character to the cwd string and move the
+ ** relative path back within the buffer so that it immediately
+ ** follows the '/'.
+ **
+ ** This code is written so that if the combination of the CWD and relative
+ ** path are larger than the allocated size of zOut[] the CWD is silently
+ ** truncated to make it fit. This is Ok, as SQLite refuses to open any
+ ** file for which this function returns a full path larger than (nOut-8)
+ ** bytes in size. */
+ if( zOut[0]!='/' ){
int nCwd;
- if( osGetcwd(zOut, nOut-1)==0 ){
+ int nRem = nOut-nByte-1;
+ memmove(&zOut[nRem], zOut, nByte+1);
+ zOut[nRem-1] = '\0';
+ if( osGetcwd(zOut, nRem-1)==0 ){
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
}
- nCwd = (int)strlen(zOut);
- sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
+ nCwd = sqlite3Strlen30(zOut);
+ assert( nCwd<=nRem-1 );
+ zOut[nCwd] = '/';
+ memmove(&zOut[nCwd+1], &zOut[nRem], nByte+1);
}
+
return SQLITE_OK;
}
@@ -7542,7 +7582,7 @@ int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==25 );
+ assert( ArraySize(aSyscall)==26 );
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){