-C Fix\sissues\son\sunix\swith\sopening\sdatabase\sfiles\svia\ssymlinks\sthat\sare\snot\sin\sthe\scurrent\sworking\sdirectory.\sAnd\swith\snested\ssymlinks.
-D 2016-01-25T17:04:48.546
+C Simplify\sthe\sunixFullpathname()\sfunction.\sThis\sadds\sa\sdependency\son\slstat().
+D 2016-01-25T18:05:49.964
F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
-F src/os_unix.c cf524029242b4f878d6b97bad25cc2c0b66c2b31
+F src/os_unix.c 6604e7f9e5298b615f729b6bb3c22bd3545cdca6
F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 7ac017a498b6fb28343eef2d24e400c7800660d6
-R 0289127606d03bb3b649ecbd39bb14a5
-T *branch * follow-symlinks
-T *sym-follow-symlinks *
-T -sym-trunk *
+P 80398fd44fb232193450103808e1854e0eba5652
+R 084dee05e1353887f6af0d88670b22d0
U dan
-Z 3e18b3d01ba737d3635110839e378935
+Z 72572e009a3ce3b7747f3257ebf7dfc7
#endif
#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent)
+ { "lstat", (sqlite3_syscall_ptr)lstat, 0 },
+#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
}; /* End of the overrideable system calls */
}
/*
-** Buffer zOut contains a (possibly) relative pathname. Overwrite it with
-** the corresponding full pathname.
**
-** Parameter nOut is the allocated size of buffer zOut. nByte is the number
-** of bytes in the nul-terminated string that it contains (not including
-** the nul-terminator itself).
-**
-** Return SQLITE_OK if successful, or an SQLite error code otherwise.
*/
static int mkFullPathname(
- const char *zPath, /* Use this path to log any errors */
- char *zOut, /* IN/OUT: Buffer to modify */
- int nByte, /* size of nul-terminated zOut in bytes */
+ const char *zPath, /* Input path */
+ char *zOut, /* Output buffer */
int nOut /* Allocated size of buffer zOut */
){
- /* 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. */
- assert( nByte<nOut );
- testcase( nByte==nOut-5 );
- testcase( nByte==nOut-4 );
- if( zOut[0]!='/' && nByte<nOut-4 ){
- int nCwd;
- int nRem = nOut-nByte-1;
- memmove(&zOut[nRem], zOut, nByte+1);
- zOut[nRem-1] = '\0';
- if( osGetcwd(zOut, nRem-1)==0 ){
+ int nPath = sqlite3Strlen30(zPath);
+ int iOff = 0;
+ if( zPath[0]!='/' ){
+ if( osGetcwd(zOut, nOut-2)==0 ){
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
}
- nCwd = sqlite3Strlen30(zOut);
- assert( nCwd<=nRem-1 );
- zOut[nCwd] = '/';
- memmove(&zOut[nCwd+1], &zOut[nRem], nByte+1);
+ iOff = sqlite3Strlen30(zOut);
+ zOut[iOff++] = '/';
}
-
+ if( (iOff+nPath+1)>nOut ) return SQLITE_CANTOPEN_BKPT;
+ sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
return SQLITE_OK;
}
char *zOut /* Output buffer */
){
#if !defined(HAVE_READLINK)
- sqlite3_snprintf(nOut, zOut, "%s", zIn);
- nByte = sqlite3Strlen30(zOut);
- return mkFullPathname(zPath, zOut, sqlite3Strlen30(zOut), nOut);
+ return mkFullPathname(zPath, zOut, nOut);
#else
int rc = SQLITE_OK;
int nByte;
- int nLink = 0; /* Number of symbolic links followed so far */
+ int nLink = 1; /* Number of symbolic links followed so far */
int bLink; /* True for a symbolic link */
const char *zIn = zPath; /* Input path for each iteration of loop */
char *zDel = 0;
do {
- /* 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. */
- assert( (zDel==0 && zIn==zPath) || (zDel!=0 && zIn==zDel) );
- if( zDel ){
- assert( zIn==zDel );
- sqlite3_snprintf(nOut, zDel, "%s", zOut);
- }
- nByte = osReadlink(zIn, zOut, nOut-1);
- if( nByte<0 ){
- if( errno!=EINVAL && errno!=ENOENT ){
- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath);
- }else{
- sqlite3_snprintf(nOut, zOut, "%s", zIn);
- nByte = sqlite3Strlen30(zOut);
+ /* Call stat() on path zIn. Set bLink to true if the path is a symbolic
+ ** link, or false otherwise. */
+ int bLink = 0;
+ struct stat buf;
+ if( osLstat(zIn, &buf)!=0 ){
+ if( errno!=ENOENT ){
+ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "stat", zIn);
}
- bLink = 0;
- }else if( ++nLink>SQLITE_MAX_SYMLINKS ){
- sqlite3_log(SQLITE_CANTOPEN,
- "too many symbolic links (max=%d)", SQLITE_MAX_SYMLINKS
- );
- rc = SQLITE_CANTOPEN_BKPT;
}else{
- zOut[nByte] = '\0';
- if( zOut[0]!='/' ){
- int n;
- for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--);
- if( nByte+n+1>nOut ){
- rc = SQLITE_CANTOPEN_BKPT;
- }else{
- memmove(&zOut[n], zOut, nByte+1);
- memcpy(zOut, zIn, n);
- nByte += n;
- }
- }
+ bLink = S_ISLNK(buf.st_mode);
+ }
+
+ if( bLink ){
if( zDel==0 ){
zDel = sqlite3_malloc(nOut);
if( zDel==0 ) rc = SQLITE_NOMEM;
- zIn = (const char*)zDel;
+ }else if( ++nLink>SQLITE_MAX_SYMLINKS ){
+ rc = SQLITE_CANTOPEN_BKPT;
}
- bLink = 1;
+
+ if( rc==SQLITE_OK ){
+ nByte = osReadlink(zIn, zDel, nOut-1);
+ if( nByte<0 ){
+ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
+ }else if( zDel[0]!='/' ){
+ int n;
+ for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--);
+ if( nByte+n+1>nOut ){
+ rc = SQLITE_CANTOPEN_BKPT;
+ }else{
+ memmove(&zDel[n], zDel, nByte+1);
+ memcpy(zDel, zIn, n);
+ nByte += n;
+ }
+ zDel[nByte] = '\0';
+ }
+ }
+
+ zIn = zDel;
}
if( rc==SQLITE_OK ){
- rc = mkFullPathname(zPath, zOut, nByte, nOut);
+ assert( zIn!=zOut || zIn[0]=='/' );
+ rc = mkFullPathname(zIn, zOut, nOut);
}
- }while( bLink && rc==SQLITE_OK );
+ if( bLink==0 ) break;
+ zIn = zOut;
+ }while( rc==SQLITE_OK );
sqlite3_free(zDel);
return rc;
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==27 );
+ assert( ArraySize(aSyscall)==28 );
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){