| OLD | NEW |
| 1 /* | 1 /* |
| 2 ** 2004 May 22 | 2 ** 2004 May 22 |
| 3 ** | 3 ** |
| 4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
| 5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
| 6 ** | 6 ** |
| 7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
| 8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
| 9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
| 10 ** | 10 ** |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 | 197 |
| 198 /* | 198 /* |
| 199 ** The unixFile structure is subclass of sqlite3_file specific to the unix | 199 ** The unixFile structure is subclass of sqlite3_file specific to the unix |
| 200 ** VFS implementations. | 200 ** VFS implementations. |
| 201 */ | 201 */ |
| 202 typedef struct unixFile unixFile; | 202 typedef struct unixFile unixFile; |
| 203 struct unixFile { | 203 struct unixFile { |
| 204 sqlite3_io_methods const *pMethod; /* Always the first entry */ | 204 sqlite3_io_methods const *pMethod; /* Always the first entry */ |
| 205 unixInodeInfo *pInode; /* Info about locks on this inode */ | 205 unixInodeInfo *pInode; /* Info about locks on this inode */ |
| 206 int h; /* The file descriptor */ | 206 int h; /* The file descriptor */ |
| 207 int dirfd; /* File descriptor for the directory */ |
| 207 unsigned char eFileLock; /* The type of lock held on this fd */ | 208 unsigned char eFileLock; /* The type of lock held on this fd */ |
| 208 unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ | 209 unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ |
| 209 int lastErrno; /* The unix errno from last I/O error */ | 210 int lastErrno; /* The unix errno from last I/O error */ |
| 210 void *lockingContext; /* Locking style specific state */ | 211 void *lockingContext; /* Locking style specific state */ |
| 211 UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ | 212 UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ |
| 212 const char *zPath; /* Name of the file */ | 213 const char *zPath; /* Name of the file */ |
| 213 unixShm *pShm; /* Shared memory segment information */ | 214 unixShm *pShm; /* Shared memory segment information */ |
| 214 int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ | 215 int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ |
| 215 #if SQLITE_ENABLE_LOCKING_STYLE | 216 #if SQLITE_ENABLE_LOCKING_STYLE |
| 216 int openFlags; /* The flags specified at open() */ | 217 int openFlags; /* The flags specified at open() */ |
| (...skipping 23 matching lines...) Expand all Loading... |
| 240 */ | 241 */ |
| 241 char aPadding[32]; | 242 char aPadding[32]; |
| 242 #endif | 243 #endif |
| 243 }; | 244 }; |
| 244 | 245 |
| 245 /* | 246 /* |
| 246 ** Allowed values for the unixFile.ctrlFlags bitmask: | 247 ** Allowed values for the unixFile.ctrlFlags bitmask: |
| 247 */ | 248 */ |
| 248 #define UNIXFILE_EXCL 0x01 /* Connections from one process only */ | 249 #define UNIXFILE_EXCL 0x01 /* Connections from one process only */ |
| 249 #define UNIXFILE_RDONLY 0x02 /* Connection is read only */ | 250 #define UNIXFILE_RDONLY 0x02 /* Connection is read only */ |
| 250 #define UNIXFILE_DIRSYNC 0x04 /* Directory sync needed */ | |
| 251 | 251 |
| 252 /* | 252 /* |
| 253 ** Include code that is common to all os_*.c files | 253 ** Include code that is common to all os_*.c files |
| 254 */ | 254 */ |
| 255 #include "os_common.h" | 255 #include "os_common.h" |
| 256 | 256 |
| 257 /* | 257 /* |
| 258 ** Define various macros that are missing from some systems. | 258 ** Define various macros that are missing from some systems. |
| 259 */ | 259 */ |
| 260 #ifndef O_LARGEFILE | 260 #ifndef O_LARGEFILE |
| (...skipping 13 matching lines...) Expand all Loading... |
| 274 /* | 274 /* |
| 275 ** The threadid macro resolves to the thread-id or to 0. Used for | 275 ** The threadid macro resolves to the thread-id or to 0. Used for |
| 276 ** testing and debugging only. | 276 ** testing and debugging only. |
| 277 */ | 277 */ |
| 278 #if SQLITE_THREADSAFE | 278 #if SQLITE_THREADSAFE |
| 279 #define threadid pthread_self() | 279 #define threadid pthread_self() |
| 280 #else | 280 #else |
| 281 #define threadid 0 | 281 #define threadid 0 |
| 282 #endif | 282 #endif |
| 283 | 283 |
| 284 /* Forward reference */ | |
| 285 static int openDirectory(const char*, int*); | |
| 286 | |
| 287 /* | 284 /* |
| 288 ** Many system calls are accessed through pointer-to-functions so that | 285 ** Many system calls are accessed through pointer-to-functions so that |
| 289 ** they may be overridden at runtime to facilitate fault injection during | 286 ** they may be overridden at runtime to facilitate fault injection during |
| 290 ** testing and sandboxing. The following array holds the names and pointers | 287 ** testing and sandboxing. The following array holds the names and pointers |
| 291 ** to all overrideable system calls. | 288 ** to all overrideable system calls. |
| 292 */ | 289 */ |
| 293 static struct unix_syscall { | 290 static struct unix_syscall { |
| 294 const char *zName; /* Name of the sytem call */ | 291 const char *zName; /* Name of the sytem call */ |
| 295 sqlite3_syscall_ptr pCurrent; /* Current value of the system call */ | 292 sqlite3_syscall_ptr pCurrent; /* Current value of the system call */ |
| 296 sqlite3_syscall_ptr pDefault; /* Default value */ | 293 sqlite3_syscall_ptr pDefault; /* Default value */ |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 #endif | 370 #endif |
| 374 #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) | 371 #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) |
| 375 | 372 |
| 376 #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE | 373 #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE |
| 377 { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, | 374 { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, |
| 378 #else | 375 #else |
| 379 { "fallocate", (sqlite3_syscall_ptr)0, 0 }, | 376 { "fallocate", (sqlite3_syscall_ptr)0, 0 }, |
| 380 #endif | 377 #endif |
| 381 #define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent) | 378 #define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent) |
| 382 | 379 |
| 383 { "unlink", (sqlite3_syscall_ptr)unlink, 0 }, | |
| 384 #define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent) | |
| 385 | |
| 386 { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 }, | |
| 387 #define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent) | |
| 388 | |
| 389 }; /* End of the overrideable system calls */ | 380 }; /* End of the overrideable system calls */ |
| 390 | 381 |
| 391 /* | 382 /* |
| 392 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the | 383 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the |
| 393 ** "unix" VFSes. Return SQLITE_OK opon successfully updating the | 384 ** "unix" VFSes. Return SQLITE_OK opon successfully updating the |
| 394 ** system call pointer, or SQLITE_NOTFOUND if there is no configurable | 385 ** system call pointer, or SQLITE_NOTFOUND if there is no configurable |
| 395 ** system call named zName. | 386 ** system call named zName. |
| 396 */ | 387 */ |
| 397 static int unixSetSystemCall( | 388 static int unixSetSystemCall( |
| 398 sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */ | 389 sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */ |
| (...skipping 1334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1733 ** common to all locking schemes. It closes the directory and file | 1724 ** common to all locking schemes. It closes the directory and file |
| 1734 ** handles, if they are valid, and sets all fields of the unixFile | 1725 ** handles, if they are valid, and sets all fields of the unixFile |
| 1735 ** structure to 0. | 1726 ** structure to 0. |
| 1736 ** | 1727 ** |
| 1737 ** It is *not* necessary to hold the mutex when this routine is called, | 1728 ** It is *not* necessary to hold the mutex when this routine is called, |
| 1738 ** even on VxWorks. A mutex will be acquired on VxWorks by the | 1729 ** even on VxWorks. A mutex will be acquired on VxWorks by the |
| 1739 ** vxworksReleaseFileId() routine. | 1730 ** vxworksReleaseFileId() routine. |
| 1740 */ | 1731 */ |
| 1741 static int closeUnixFile(sqlite3_file *id){ | 1732 static int closeUnixFile(sqlite3_file *id){ |
| 1742 unixFile *pFile = (unixFile*)id; | 1733 unixFile *pFile = (unixFile*)id; |
| 1734 if( pFile->dirfd>=0 ){ |
| 1735 robust_close(pFile, pFile->dirfd, __LINE__); |
| 1736 pFile->dirfd=-1; |
| 1737 } |
| 1743 if( pFile->h>=0 ){ | 1738 if( pFile->h>=0 ){ |
| 1744 robust_close(pFile, pFile->h, __LINE__); | 1739 robust_close(pFile, pFile->h, __LINE__); |
| 1745 pFile->h = -1; | 1740 pFile->h = -1; |
| 1746 } | 1741 } |
| 1747 #if OS_VXWORKS | 1742 #if OS_VXWORKS |
| 1748 if( pFile->pId ){ | 1743 if( pFile->pId ){ |
| 1749 if( pFile->isDelete ){ | 1744 if( pFile->isDelete ){ |
| 1750 osUnlink(pFile->pId->zCanonicalName); | 1745 unlink(pFile->pId->zCanonicalName); |
| 1751 } | 1746 } |
| 1752 vxworksReleaseFileId(pFile->pId); | 1747 vxworksReleaseFileId(pFile->pId); |
| 1753 pFile->pId = 0; | 1748 pFile->pId = 0; |
| 1754 } | 1749 } |
| 1755 #endif | 1750 #endif |
| 1756 OSTRACE(("CLOSE %-3d\n", pFile->h)); | 1751 OSTRACE(("CLOSE %-3d\n", pFile->h)); |
| 1757 OpenCounter(-1); | 1752 OpenCounter(-1); |
| 1758 sqlite3_free(pFile->pUnused); | 1753 sqlite3_free(pFile->pUnused); |
| 1759 memset(pFile, 0, sizeof(unixFile)); | 1754 memset(pFile, 0, sizeof(unixFile)); |
| 1760 return SQLITE_OK; | 1755 return SQLITE_OK; |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1987 /* To downgrade to shared, simply update our internal notion of the | 1982 /* To downgrade to shared, simply update our internal notion of the |
| 1988 ** lock state. No need to mess with the file on disk. | 1983 ** lock state. No need to mess with the file on disk. |
| 1989 */ | 1984 */ |
| 1990 if( eFileLock==SHARED_LOCK ){ | 1985 if( eFileLock==SHARED_LOCK ){ |
| 1991 pFile->eFileLock = SHARED_LOCK; | 1986 pFile->eFileLock = SHARED_LOCK; |
| 1992 return SQLITE_OK; | 1987 return SQLITE_OK; |
| 1993 } | 1988 } |
| 1994 | 1989 |
| 1995 /* To fully unlock the database, delete the lock file */ | 1990 /* To fully unlock the database, delete the lock file */ |
| 1996 assert( eFileLock==NO_LOCK ); | 1991 assert( eFileLock==NO_LOCK ); |
| 1997 if( osUnlink(zLockFile) ){ | 1992 if( unlink(zLockFile) ){ |
| 1998 int rc = 0; | 1993 int rc = 0; |
| 1999 int tErrno = errno; | 1994 int tErrno = errno; |
| 2000 if( ENOENT != tErrno ){ | 1995 if( ENOENT != tErrno ){ |
| 2001 rc = SQLITE_IOERR_UNLOCK; | 1996 rc = SQLITE_IOERR_UNLOCK; |
| 2002 } | 1997 } |
| 2003 if( IS_LOCK_ERROR(rc) ){ | 1998 if( IS_LOCK_ERROR(rc) ){ |
| 2004 pFile->lastErrno = tErrno; | 1999 pFile->lastErrno = tErrno; |
| 2005 } | 2000 } |
| 2006 return rc; | 2001 return rc; |
| 2007 } | 2002 } |
| (...skipping 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3224 #endif /* OS_VXWORKS */ | 3219 #endif /* OS_VXWORKS */ |
| 3225 #endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */ | 3220 #endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */ |
| 3226 | 3221 |
| 3227 if( OS_VXWORKS && rc!= -1 ){ | 3222 if( OS_VXWORKS && rc!= -1 ){ |
| 3228 rc = 0; | 3223 rc = 0; |
| 3229 } | 3224 } |
| 3230 return rc; | 3225 return rc; |
| 3231 } | 3226 } |
| 3232 | 3227 |
| 3233 /* | 3228 /* |
| 3234 ** Open a file descriptor to the directory containing file zFilename. | |
| 3235 ** If successful, *pFd is set to the opened file descriptor and | |
| 3236 ** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM | |
| 3237 ** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined | |
| 3238 ** value. | |
| 3239 ** | |
| 3240 ** The directory file descriptor is used for only one thing - to | |
| 3241 ** fsync() a directory to make sure file creation and deletion events | |
| 3242 ** are flushed to disk. Such fsyncs are not needed on newer | |
| 3243 ** journaling filesystems, but are required on older filesystems. | |
| 3244 ** | |
| 3245 ** This routine can be overridden using the xSetSysCall interface. | |
| 3246 ** The ability to override this routine was added in support of the | |
| 3247 ** chromium sandbox. Opening a directory is a security risk (we are | |
| 3248 ** told) so making it overrideable allows the chromium sandbox to | |
| 3249 ** replace this routine with a harmless no-op. To make this routine | |
| 3250 ** a no-op, replace it with a stub that returns SQLITE_OK but leaves | |
| 3251 ** *pFd set to a negative number. | |
| 3252 ** | |
| 3253 ** If SQLITE_OK is returned, the caller is responsible for closing | |
| 3254 ** the file descriptor *pFd using close(). | |
| 3255 */ | |
| 3256 static int openDirectory(const char *zFilename, int *pFd){ | |
| 3257 int ii; | |
| 3258 int fd = -1; | |
| 3259 char zDirname[MAX_PATHNAME+1]; | |
| 3260 | |
| 3261 sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename); | |
| 3262 for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--); | |
| 3263 if( ii>0 ){ | |
| 3264 zDirname[ii] = '\0'; | |
| 3265 fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0); | |
| 3266 if( fd>=0 ){ | |
| 3267 #ifdef FD_CLOEXEC | |
| 3268 osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); | |
| 3269 #endif | |
| 3270 OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); | |
| 3271 } | |
| 3272 } | |
| 3273 *pFd = fd; | |
| 3274 return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); | |
| 3275 } | |
| 3276 | |
| 3277 /* | |
| 3278 ** Make sure all writes to a particular file are committed to disk. | 3229 ** Make sure all writes to a particular file are committed to disk. |
| 3279 ** | 3230 ** |
| 3280 ** If dataOnly==0 then both the file itself and its metadata (file | 3231 ** If dataOnly==0 then both the file itself and its metadata (file |
| 3281 ** size, access time, etc) are synced. If dataOnly!=0 then only the | 3232 ** size, access time, etc) are synced. If dataOnly!=0 then only the |
| 3282 ** file data is synced. | 3233 ** file data is synced. |
| 3283 ** | 3234 ** |
| 3284 ** Under Unix, also make sure that the directory entry for the file | 3235 ** Under Unix, also make sure that the directory entry for the file |
| 3285 ** has been created by fsync-ing the directory that contains the file. | 3236 ** has been created by fsync-ing the directory that contains the file. |
| 3286 ** If we do not do this and we encounter a power failure, the directory | 3237 ** If we do not do this and we encounter a power failure, the directory |
| 3287 ** entry for the journal might not exist after we reboot. The next | 3238 ** entry for the journal might not exist after we reboot. The next |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3307 SimulateDiskfullError( return SQLITE_FULL ); | 3258 SimulateDiskfullError( return SQLITE_FULL ); |
| 3308 | 3259 |
| 3309 assert( pFile ); | 3260 assert( pFile ); |
| 3310 OSTRACE(("SYNC %-3d\n", pFile->h)); | 3261 OSTRACE(("SYNC %-3d\n", pFile->h)); |
| 3311 rc = full_fsync(pFile->h, isFullsync, isDataOnly); | 3262 rc = full_fsync(pFile->h, isFullsync, isDataOnly); |
| 3312 SimulateIOError( rc=1 ); | 3263 SimulateIOError( rc=1 ); |
| 3313 if( rc ){ | 3264 if( rc ){ |
| 3314 pFile->lastErrno = errno; | 3265 pFile->lastErrno = errno; |
| 3315 return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath); | 3266 return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath); |
| 3316 } | 3267 } |
| 3317 | 3268 if( pFile->dirfd>=0 ){ |
| 3318 /* Also fsync the directory containing the file if the DIRSYNC flag | 3269 OSTRACE(("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd, |
| 3319 ** is set. This is a one-time occurrance. Many systems (examples: AIX) | |
| 3320 ** are unable to fsync a directory, so ignore errors on the fsync. | |
| 3321 */ | |
| 3322 if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){ | |
| 3323 int dirfd; | |
| 3324 OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath, | |
| 3325 HAVE_FULLFSYNC, isFullsync)); | 3270 HAVE_FULLFSYNC, isFullsync)); |
| 3326 rc = osOpenDirectory(pFile->zPath, &dirfd); | 3271 #ifndef SQLITE_DISABLE_DIRSYNC |
| 3327 if( rc==SQLITE_OK && dirfd>=0 ){ | 3272 /* The directory sync is only attempted if full_fsync is |
| 3328 full_fsync(dirfd, 0, 0); | 3273 ** turned off or unavailable. If a full_fsync occurred above, |
| 3329 robust_close(pFile, dirfd, __LINE__); | 3274 ** then the directory sync is superfluous. |
| 3330 }else if( rc==SQLITE_CANTOPEN ){ | 3275 */ |
| 3331 rc = SQLITE_OK; | 3276 if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){ |
| 3277 /* |
| 3278 ** We have received multiple reports of fsync() returning |
| 3279 ** errors when applied to directories on certain file systems. |
| 3280 ** A failed directory sync is not a big deal. So it seems |
| 3281 ** better to ignore the error. Ticket #1657 |
| 3282 */ |
| 3283 /* pFile->lastErrno = errno; */ |
| 3284 /* return SQLITE_IOERR; */ |
| 3332 } | 3285 } |
| 3333 pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC; | 3286 #endif |
| 3287 /* Only need to sync once, so close the directory when we are done */ |
| 3288 robust_close(pFile, pFile->dirfd, __LINE__); |
| 3289 pFile->dirfd = -1; |
| 3334 } | 3290 } |
| 3335 return rc; | 3291 return rc; |
| 3336 } | 3292 } |
| 3337 | 3293 |
| 3338 /* | 3294 /* |
| 3339 ** Truncate an open file to a specified size | 3295 ** Truncate an open file to a specified size |
| 3340 */ | 3296 */ |
| 3341 static int unixTruncate(sqlite3_file *id, i64 nByte){ | 3297 static int unixTruncate(sqlite3_file *id, i64 nByte){ |
| 3342 unixFile *pFile = (unixFile *)id; | 3298 unixFile *pFile = (unixFile *)id; |
| 3343 int rc; | 3299 int rc; |
| (...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4147 sqlite3_free(p); | 4103 sqlite3_free(p); |
| 4148 pDbFd->pShm = 0; | 4104 pDbFd->pShm = 0; |
| 4149 sqlite3_mutex_leave(pShmNode->mutex); | 4105 sqlite3_mutex_leave(pShmNode->mutex); |
| 4150 | 4106 |
| 4151 /* If pShmNode->nRef has reached 0, then close the underlying | 4107 /* If pShmNode->nRef has reached 0, then close the underlying |
| 4152 ** shared-memory file, too */ | 4108 ** shared-memory file, too */ |
| 4153 unixEnterMutex(); | 4109 unixEnterMutex(); |
| 4154 assert( pShmNode->nRef>0 ); | 4110 assert( pShmNode->nRef>0 ); |
| 4155 pShmNode->nRef--; | 4111 pShmNode->nRef--; |
| 4156 if( pShmNode->nRef==0 ){ | 4112 if( pShmNode->nRef==0 ){ |
| 4157 if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename); | 4113 if( deleteFlag && pShmNode->h>=0 ) unlink(pShmNode->zFilename); |
| 4158 unixShmPurge(pDbFd); | 4114 unixShmPurge(pDbFd); |
| 4159 } | 4115 } |
| 4160 unixLeaveMutex(); | 4116 unixLeaveMutex(); |
| 4161 | 4117 |
| 4162 return SQLITE_OK; | 4118 return SQLITE_OK; |
| 4163 } | 4119 } |
| 4164 | 4120 |
| 4165 | 4121 |
| 4166 #else | 4122 #else |
| 4167 # define unixShmMap 0 | 4123 # define unixShmMap 0 |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4455 | 4411 |
| 4456 | 4412 |
| 4457 /**************************************************************************** | 4413 /**************************************************************************** |
| 4458 **************************** sqlite3_vfs methods **************************** | 4414 **************************** sqlite3_vfs methods **************************** |
| 4459 ** | 4415 ** |
| 4460 ** This division contains the implementation of methods on the | 4416 ** This division contains the implementation of methods on the |
| 4461 ** sqlite3_vfs object. | 4417 ** sqlite3_vfs object. |
| 4462 */ | 4418 */ |
| 4463 | 4419 |
| 4464 /* | 4420 /* |
| 4465 ** Initializes a unixFile structure with zeros. | |
| 4466 */ | |
| 4467 void initUnixFile(sqlite3_file* file) { | |
| 4468 memset(file, 0, sizeof(unixFile)); | |
| 4469 } | |
| 4470 | |
| 4471 /* | |
| 4472 ** Initialize the contents of the unixFile structure pointed to by pId. | 4421 ** Initialize the contents of the unixFile structure pointed to by pId. |
| 4473 */ | 4422 */ |
| 4474 int fillInUnixFile( | 4423 static int fillInUnixFile( |
| 4475 sqlite3_vfs *pVfs, /* Pointer to vfs object */ | 4424 sqlite3_vfs *pVfs, /* Pointer to vfs object */ |
| 4476 int h, /* Open file descriptor of file being opened */ | 4425 int h, /* Open file descriptor of file being opened */ |
| 4477 int syncDir, /* True to sync directory on first sync */ | 4426 int dirfd, /* Directory file descriptor */ |
| 4478 sqlite3_file *pId, /* Write to the unixFile structure here */ | 4427 sqlite3_file *pId, /* Write to the unixFile structure here */ |
| 4479 const char *zFilename, /* Name of the file being opened */ | 4428 const char *zFilename, /* Name of the file being opened */ |
| 4480 int noLock, /* Omit locking if true */ | 4429 int noLock, /* Omit locking if true */ |
| 4481 int isDelete, /* Delete on close if true */ | 4430 int isDelete, /* Delete on close if true */ |
| 4482 int isReadOnly /* True if the file is opened read-only */ | 4431 int isReadOnly /* True if the file is opened read-only */ |
| 4483 ){ | 4432 ){ |
| 4484 const sqlite3_io_methods *pLockingStyle; | 4433 const sqlite3_io_methods *pLockingStyle; |
| 4485 unixFile *pNew = (unixFile *)pId; | 4434 unixFile *pNew = (unixFile *)pId; |
| 4486 int rc = SQLITE_OK; | 4435 int rc = SQLITE_OK; |
| 4487 | 4436 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4498 */ | 4447 */ |
| 4499 #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE | 4448 #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 4500 assert( zFilename==0 || zFilename[0]=='/' | 4449 assert( zFilename==0 || zFilename[0]=='/' |
| 4501 || pVfs->pAppData==(void*)&autolockIoFinder ); | 4450 || pVfs->pAppData==(void*)&autolockIoFinder ); |
| 4502 #else | 4451 #else |
| 4503 assert( zFilename==0 || zFilename[0]=='/' ); | 4452 assert( zFilename==0 || zFilename[0]=='/' ); |
| 4504 #endif | 4453 #endif |
| 4505 | 4454 |
| 4506 OSTRACE(("OPEN %-3d %s\n", h, zFilename)); | 4455 OSTRACE(("OPEN %-3d %s\n", h, zFilename)); |
| 4507 pNew->h = h; | 4456 pNew->h = h; |
| 4457 pNew->dirfd = dirfd; |
| 4508 pNew->zPath = zFilename; | 4458 pNew->zPath = zFilename; |
| 4509 if( strcmp(pVfs->zName,"unix-excl")==0 ){ | 4459 if( memcmp(pVfs->zName,"unix-excl",10)==0 ){ |
| 4510 pNew->ctrlFlags = UNIXFILE_EXCL; | 4460 pNew->ctrlFlags = UNIXFILE_EXCL; |
| 4511 }else{ | 4461 }else{ |
| 4512 pNew->ctrlFlags = 0; | 4462 pNew->ctrlFlags = 0; |
| 4513 } | 4463 } |
| 4514 if( isReadOnly ){ | 4464 if( isReadOnly ){ |
| 4515 pNew->ctrlFlags |= UNIXFILE_RDONLY; | 4465 pNew->ctrlFlags |= UNIXFILE_RDONLY; |
| 4516 } | 4466 } |
| 4517 if( syncDir ){ | |
| 4518 pNew->ctrlFlags |= UNIXFILE_DIRSYNC; | |
| 4519 } | |
| 4520 | 4467 |
| 4521 #if OS_VXWORKS | 4468 #if OS_VXWORKS |
| 4522 pNew->pId = vxworksFindFileId(zFilename); | 4469 pNew->pId = vxworksFindFileId(zFilename); |
| 4523 if( pNew->pId==0 ){ | 4470 if( pNew->pId==0 ){ |
| 4524 noLock = 1; | 4471 noLock = 1; |
| 4525 rc = SQLITE_NOMEM; | 4472 rc = SQLITE_NOMEM; |
| 4526 } | 4473 } |
| 4527 #endif | 4474 #endif |
| 4528 | 4475 |
| 4529 if( noLock ){ | 4476 if( noLock ){ |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4636 } | 4583 } |
| 4637 unixLeaveMutex(); | 4584 unixLeaveMutex(); |
| 4638 } | 4585 } |
| 4639 #endif | 4586 #endif |
| 4640 | 4587 |
| 4641 pNew->lastErrno = 0; | 4588 pNew->lastErrno = 0; |
| 4642 #if OS_VXWORKS | 4589 #if OS_VXWORKS |
| 4643 if( rc!=SQLITE_OK ){ | 4590 if( rc!=SQLITE_OK ){ |
| 4644 if( h>=0 ) robust_close(pNew, h, __LINE__); | 4591 if( h>=0 ) robust_close(pNew, h, __LINE__); |
| 4645 h = -1; | 4592 h = -1; |
| 4646 osUnlink(zFilename); | 4593 unlink(zFilename); |
| 4647 isDelete = 0; | 4594 isDelete = 0; |
| 4648 } | 4595 } |
| 4649 pNew->isDelete = isDelete; | 4596 pNew->isDelete = isDelete; |
| 4650 #endif | 4597 #endif |
| 4651 if( rc!=SQLITE_OK ){ | 4598 if( rc!=SQLITE_OK ){ |
| 4599 if( dirfd>=0 ) robust_close(pNew, dirfd, __LINE__); |
| 4652 if( h>=0 ) robust_close(pNew, h, __LINE__); | 4600 if( h>=0 ) robust_close(pNew, h, __LINE__); |
| 4653 }else{ | 4601 }else{ |
| 4654 pNew->pMethod = pLockingStyle; | 4602 pNew->pMethod = pLockingStyle; |
| 4655 OpenCounter(+1); | 4603 OpenCounter(+1); |
| 4656 } | 4604 } |
| 4657 return rc; | 4605 return rc; |
| 4658 } | 4606 } |
| 4659 | 4607 |
| 4660 /* | 4608 /* |
| 4609 ** Open a file descriptor to the directory containing file zFilename. |
| 4610 ** If successful, *pFd is set to the opened file descriptor and |
| 4611 ** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM |
| 4612 ** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined |
| 4613 ** value. |
| 4614 ** |
| 4615 ** If SQLITE_OK is returned, the caller is responsible for closing |
| 4616 ** the file descriptor *pFd using close(). |
| 4617 */ |
| 4618 static int openDirectory(const char *zFilename, int *pFd){ |
| 4619 int ii; |
| 4620 int fd = -1; |
| 4621 char zDirname[MAX_PATHNAME+1]; |
| 4622 |
| 4623 sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename); |
| 4624 for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--); |
| 4625 if( ii>0 ){ |
| 4626 zDirname[ii] = '\0'; |
| 4627 fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0); |
| 4628 if( fd>=0 ){ |
| 4629 #ifdef FD_CLOEXEC |
| 4630 osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); |
| 4631 #endif |
| 4632 OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); |
| 4633 } |
| 4634 } |
| 4635 *pFd = fd; |
| 4636 return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); |
| 4637 } |
| 4638 |
| 4639 /* |
| 4661 ** Return the name of a directory in which to put temporary files. | 4640 ** Return the name of a directory in which to put temporary files. |
| 4662 ** If no suitable temporary file directory can be found, return NULL. | 4641 ** If no suitable temporary file directory can be found, return NULL. |
| 4663 */ | 4642 */ |
| 4664 static const char *unixTempFileDir(void){ | 4643 static const char *unixTempFileDir(void){ |
| 4665 static const char *azDirs[] = { | 4644 static const char *azDirs[] = { |
| 4666 0, | 4645 0, |
| 4667 0, | 4646 0, |
| 4668 "/var/tmp", | 4647 "/var/tmp", |
| 4669 "/usr/tmp", | 4648 "/usr/tmp", |
| 4670 "/tmp", | 4649 "/tmp", |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4764 struct stat sStat; /* Results of stat() call */ | 4743 struct stat sStat; /* Results of stat() call */ |
| 4765 | 4744 |
| 4766 /* A stat() call may fail for various reasons. If this happens, it is | 4745 /* A stat() call may fail for various reasons. If this happens, it is |
| 4767 ** almost certain that an open() call on the same path will also fail. | 4746 ** almost certain that an open() call on the same path will also fail. |
| 4768 ** For this reason, if an error occurs in the stat() call here, it is | 4747 ** For this reason, if an error occurs in the stat() call here, it is |
| 4769 ** ignored and -1 is returned. The caller will try to open a new file | 4748 ** ignored and -1 is returned. The caller will try to open a new file |
| 4770 ** descriptor on the same path, fail, and return an error to SQLite. | 4749 ** descriptor on the same path, fail, and return an error to SQLite. |
| 4771 ** | 4750 ** |
| 4772 ** Even if a subsequent open() call does succeed, the consequences of | 4751 ** Even if a subsequent open() call does succeed, the consequences of |
| 4773 ** not searching for a resusable file descriptor are not dire. */ | 4752 ** not searching for a resusable file descriptor are not dire. */ |
| 4774 if( 0==osStat(zPath, &sStat) ){ | 4753 if( 0==stat(zPath, &sStat) ){ |
| 4775 unixInodeInfo *pInode; | 4754 unixInodeInfo *pInode; |
| 4776 | 4755 |
| 4777 unixEnterMutex(); | 4756 unixEnterMutex(); |
| 4778 pInode = inodeList; | 4757 pInode = inodeList; |
| 4779 while( pInode && (pInode->fileId.dev!=sStat.st_dev | 4758 while( pInode && (pInode->fileId.dev!=sStat.st_dev |
| 4780 || pInode->fileId.ino!=sStat.st_ino) ){ | 4759 || pInode->fileId.ino!=sStat.st_ino) ){ |
| 4781 pInode = pInode->pNext; | 4760 pInode = pInode->pNext; |
| 4782 } | 4761 } |
| 4783 if( pInode ){ | 4762 if( pInode ){ |
| 4784 UnixUnusedFd **pp; | 4763 UnixUnusedFd **pp; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4834 ** | 4813 ** |
| 4835 ** where NNNN is a 4 digit decimal number. The NNNN naming schemes are | 4814 ** where NNNN is a 4 digit decimal number. The NNNN naming schemes are |
| 4836 ** used by the test_multiplex.c module. | 4815 ** used by the test_multiplex.c module. |
| 4837 */ | 4816 */ |
| 4838 nDb = sqlite3Strlen30(zPath) - 1; | 4817 nDb = sqlite3Strlen30(zPath) - 1; |
| 4839 while( nDb>0 && zPath[nDb]!='l' ) nDb--; | 4818 while( nDb>0 && zPath[nDb]!='l' ) nDb--; |
| 4840 nDb -= ((flags & SQLITE_OPEN_WAL) ? 3 : 7); | 4819 nDb -= ((flags & SQLITE_OPEN_WAL) ? 3 : 7); |
| 4841 memcpy(zDb, zPath, nDb); | 4820 memcpy(zDb, zPath, nDb); |
| 4842 zDb[nDb] = '\0'; | 4821 zDb[nDb] = '\0'; |
| 4843 | 4822 |
| 4844 if( 0==osStat(zDb, &sStat) ){ | 4823 if( 0==stat(zDb, &sStat) ){ |
| 4845 *pMode = sStat.st_mode & 0777; | 4824 *pMode = sStat.st_mode & 0777; |
| 4846 }else{ | 4825 }else{ |
| 4847 rc = SQLITE_IOERR_FSTAT; | 4826 rc = SQLITE_IOERR_FSTAT; |
| 4848 } | 4827 } |
| 4849 }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){ | 4828 }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){ |
| 4850 *pMode = 0600; | 4829 *pMode = 0600; |
| 4851 }else{ | 4830 }else{ |
| 4852 *pMode = SQLITE_DEFAULT_FILE_PERMISSIONS; | 4831 *pMode = SQLITE_DEFAULT_FILE_PERMISSIONS; |
| 4853 } | 4832 } |
| 4854 return rc; | 4833 return rc; |
| 4855 } | 4834 } |
| 4856 | 4835 |
| 4857 /* | 4836 /* |
| 4858 ** Initializes a unixFile structure with zeros. | |
| 4859 */ | |
| 4860 void chromium_sqlite3_initialize_unix_sqlite3_file(sqlite3_file* file) { | |
| 4861 memset(file, 0, sizeof(unixFile)); | |
| 4862 } | |
| 4863 | |
| 4864 int chromium_sqlite3_fill_in_unix_sqlite3_file(sqlite3_vfs* vfs, | |
| 4865 int fd, | |
| 4866 int dirfd, | |
| 4867 sqlite3_file* file, | |
| 4868 const char* fileName, | |
| 4869 int noLock, | |
| 4870 int isDelete) { | |
| 4871 return fillInUnixFile(vfs, fd, dirfd, file, fileName, noLock, isDelete, 0); | |
| 4872 } | |
| 4873 | |
| 4874 /* | |
| 4875 ** Search for an unused file descriptor that was opened on the database file. | |
| 4876 ** If a suitable file descriptor if found, then it is stored in *fd; otherwise, | |
| 4877 ** *fd is not modified. | |
| 4878 ** | |
| 4879 ** If a reusable file descriptor is not found, and a new UnixUnusedFd cannot | |
| 4880 ** be allocated, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK is returned. | |
| 4881 */ | |
| 4882 int chromium_sqlite3_get_reusable_file_handle(sqlite3_file* file, | |
| 4883 const char* fileName, | |
| 4884 int flags, | |
| 4885 int* fd) { | |
| 4886 unixFile* unixSQLite3File = (unixFile*)file; | |
| 4887 int fileType = flags & 0xFFFFFF00; | |
| 4888 if (fileType == SQLITE_OPEN_MAIN_DB) { | |
| 4889 UnixUnusedFd *unusedFd = findReusableFd(fileName, flags); | |
| 4890 if (unusedFd) { | |
| 4891 *fd = unusedFd->fd; | |
| 4892 } else { | |
| 4893 unusedFd = sqlite3_malloc(sizeof(*unusedFd)); | |
| 4894 if (!unusedFd) { | |
| 4895 return SQLITE_NOMEM; | |
| 4896 } | |
| 4897 } | |
| 4898 unixSQLite3File->pUnused = unusedFd; | |
| 4899 } | |
| 4900 return SQLITE_OK; | |
| 4901 } | |
| 4902 | |
| 4903 /* | |
| 4904 ** Marks 'fd' as the unused file descriptor for 'pFile'. | |
| 4905 */ | |
| 4906 void chromium_sqlite3_update_reusable_file_handle(sqlite3_file* file, | |
| 4907 int fd, | |
| 4908 int flags) { | |
| 4909 unixFile* unixSQLite3File = (unixFile*)file; | |
| 4910 if (unixSQLite3File->pUnused) { | |
| 4911 unixSQLite3File->pUnused->fd = fd; | |
| 4912 unixSQLite3File->pUnused->flags = flags; | |
| 4913 } | |
| 4914 } | |
| 4915 | |
| 4916 /* | |
| 4917 ** Destroys pFile's field that keeps track of the unused file descriptor. | |
| 4918 */ | |
| 4919 void chromium_sqlite3_destroy_reusable_file_handle(sqlite3_file* file) { | |
| 4920 unixFile* unixSQLite3File = (unixFile*)file; | |
| 4921 sqlite3_free(unixSQLite3File->pUnused); | |
| 4922 } | |
| 4923 | |
| 4924 /* | |
| 4925 ** Open the file zPath. | 4837 ** Open the file zPath. |
| 4926 ** | 4838 ** |
| 4927 ** Previously, the SQLite OS layer used three functions in place of this | 4839 ** Previously, the SQLite OS layer used three functions in place of this |
| 4928 ** one: | 4840 ** one: |
| 4929 ** | 4841 ** |
| 4930 ** sqlite3OsOpenReadWrite(); | 4842 ** sqlite3OsOpenReadWrite(); |
| 4931 ** sqlite3OsOpenReadOnly(); | 4843 ** sqlite3OsOpenReadOnly(); |
| 4932 ** sqlite3OsOpenExclusive(); | 4844 ** sqlite3OsOpenExclusive(); |
| 4933 ** | 4845 ** |
| 4934 ** These calls correspond to the following combinations of flags: | 4846 ** These calls correspond to the following combinations of flags: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4945 */ | 4857 */ |
| 4946 static int unixOpen( | 4858 static int unixOpen( |
| 4947 sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */ | 4859 sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */ |
| 4948 const char *zPath, /* Pathname of file to be opened */ | 4860 const char *zPath, /* Pathname of file to be opened */ |
| 4949 sqlite3_file *pFile, /* The file descriptor to be filled in */ | 4861 sqlite3_file *pFile, /* The file descriptor to be filled in */ |
| 4950 int flags, /* Input flags to control the opening */ | 4862 int flags, /* Input flags to control the opening */ |
| 4951 int *pOutFlags /* Output flags returned to SQLite core */ | 4863 int *pOutFlags /* Output flags returned to SQLite core */ |
| 4952 ){ | 4864 ){ |
| 4953 unixFile *p = (unixFile *)pFile; | 4865 unixFile *p = (unixFile *)pFile; |
| 4954 int fd = -1; /* File descriptor returned by open() */ | 4866 int fd = -1; /* File descriptor returned by open() */ |
| 4867 int dirfd = -1; /* Directory file descriptor */ |
| 4955 int openFlags = 0; /* Flags to pass to open() */ | 4868 int openFlags = 0; /* Flags to pass to open() */ |
| 4956 int eType = flags&0xFFFFFF00; /* Type of file to open */ | 4869 int eType = flags&0xFFFFFF00; /* Type of file to open */ |
| 4957 int noLock; /* True to omit locking primitives */ | 4870 int noLock; /* True to omit locking primitives */ |
| 4958 int rc = SQLITE_OK; /* Function Return Code */ | 4871 int rc = SQLITE_OK; /* Function Return Code */ |
| 4959 | 4872 |
| 4960 int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); | 4873 int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); |
| 4961 int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); | 4874 int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); |
| 4962 int isCreate = (flags & SQLITE_OPEN_CREATE); | 4875 int isCreate = (flags & SQLITE_OPEN_CREATE); |
| 4963 int isReadonly = (flags & SQLITE_OPEN_READONLY); | 4876 int isReadonly = (flags & SQLITE_OPEN_READONLY); |
| 4964 int isReadWrite = (flags & SQLITE_OPEN_READWRITE); | 4877 int isReadWrite = (flags & SQLITE_OPEN_READWRITE); |
| 4965 #if SQLITE_ENABLE_LOCKING_STYLE | 4878 #if SQLITE_ENABLE_LOCKING_STYLE |
| 4966 int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY); | 4879 int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY); |
| 4967 #endif | 4880 #endif |
| 4968 | 4881 |
| 4969 /* If creating a master or main-file journal, this function will open | 4882 /* If creating a master or main-file journal, this function will open |
| 4970 ** a file-descriptor on the directory too. The first time unixSync() | 4883 ** a file-descriptor on the directory too. The first time unixSync() |
| 4971 ** is called the directory file descriptor will be fsync()ed and close()d. | 4884 ** is called the directory file descriptor will be fsync()ed and close()d. |
| 4972 */ | 4885 */ |
| 4973 int syncDir = (isCreate && ( | 4886 int isOpenDirectory = (isCreate && ( |
| 4974 eType==SQLITE_OPEN_MASTER_JOURNAL | 4887 eType==SQLITE_OPEN_MASTER_JOURNAL |
| 4975 || eType==SQLITE_OPEN_MAIN_JOURNAL | 4888 || eType==SQLITE_OPEN_MAIN_JOURNAL |
| 4976 || eType==SQLITE_OPEN_WAL | 4889 || eType==SQLITE_OPEN_WAL |
| 4977 )); | 4890 )); |
| 4978 | 4891 |
| 4979 /* If argument zPath is a NULL pointer, this function is required to open | 4892 /* If argument zPath is a NULL pointer, this function is required to open |
| 4980 ** a temporary file. Use this buffer to store the file name in. | 4893 ** a temporary file. Use this buffer to store the file name in. |
| 4981 */ | 4894 */ |
| 4982 char zTmpname[MAX_PATHNAME+1]; | 4895 char zTmpname[MAX_PATHNAME+1]; |
| 4983 const char *zName = zPath; | 4896 const char *zName = zPath; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 5001 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL ); | 4914 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL ); |
| 5002 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); | 4915 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); |
| 5003 | 4916 |
| 5004 /* Assert that the upper layer has set one of the "file-type" flags. */ | 4917 /* Assert that the upper layer has set one of the "file-type" flags. */ |
| 5005 assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB | 4918 assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB |
| 5006 || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL | 4919 || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL |
| 5007 || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL | 4920 || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL |
| 5008 || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL | 4921 || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL |
| 5009 ); | 4922 ); |
| 5010 | 4923 |
| 5011 chromium_sqlite3_initialize_unix_sqlite3_file(pFile); | 4924 memset(p, 0, sizeof(unixFile)); |
| 5012 | 4925 |
| 5013 if( eType==SQLITE_OPEN_MAIN_DB ){ | 4926 if( eType==SQLITE_OPEN_MAIN_DB ){ |
| 5014 rc = chromium_sqlite3_get_reusable_file_handle(pFile, zName, flags, &fd); | 4927 UnixUnusedFd *pUnused; |
| 5015 if( rc!=SQLITE_OK ){ | 4928 pUnused = findReusableFd(zName, flags); |
| 5016 return rc; | 4929 if( pUnused ){ |
| 4930 fd = pUnused->fd; |
| 4931 }else{ |
| 4932 pUnused = sqlite3_malloc(sizeof(*pUnused)); |
| 4933 if( !pUnused ){ |
| 4934 return SQLITE_NOMEM; |
| 4935 } |
| 5017 } | 4936 } |
| 4937 p->pUnused = pUnused; |
| 5018 }else if( !zName ){ | 4938 }else if( !zName ){ |
| 5019 /* If zName is NULL, the upper layer is requesting a temp file. */ | 4939 /* If zName is NULL, the upper layer is requesting a temp file. */ |
| 5020 assert(isDelete && !syncDir); | 4940 assert(isDelete && !isOpenDirectory); |
| 5021 rc = unixGetTempname(MAX_PATHNAME+1, zTmpname); | 4941 rc = unixGetTempname(MAX_PATHNAME+1, zTmpname); |
| 5022 if( rc!=SQLITE_OK ){ | 4942 if( rc!=SQLITE_OK ){ |
| 5023 return rc; | 4943 return rc; |
| 5024 } | 4944 } |
| 5025 zName = zTmpname; | 4945 zName = zTmpname; |
| 5026 } | 4946 } |
| 5027 | 4947 |
| 5028 /* Determine the value of the flags parameter passed to POSIX function | 4948 /* Determine the value of the flags parameter passed to POSIX function |
| 5029 ** open(). These must be calculated even if open() is not called, as | 4949 ** open(). These must be calculated even if open() is not called, as |
| 5030 ** they may be stored as part of the file handle and used by the | 4950 ** they may be stored as part of the file handle and used by the |
| (...skipping 26 matching lines...) Expand all Loading... |
| 5057 if( fd<0 ){ | 4977 if( fd<0 ){ |
| 5058 rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); | 4978 rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); |
| 5059 goto open_finished; | 4979 goto open_finished; |
| 5060 } | 4980 } |
| 5061 } | 4981 } |
| 5062 assert( fd>=0 ); | 4982 assert( fd>=0 ); |
| 5063 if( pOutFlags ){ | 4983 if( pOutFlags ){ |
| 5064 *pOutFlags = flags; | 4984 *pOutFlags = flags; |
| 5065 } | 4985 } |
| 5066 | 4986 |
| 5067 chromium_sqlite3_update_reusable_file_handle(pFile, fd, flags); | 4987 if( p->pUnused ){ |
| 4988 p->pUnused->fd = fd; |
| 4989 p->pUnused->flags = flags; |
| 4990 } |
| 5068 | 4991 |
| 5069 if( isDelete ){ | 4992 if( isDelete ){ |
| 5070 #if OS_VXWORKS | 4993 #if OS_VXWORKS |
| 5071 zPath = zName; | 4994 zPath = zName; |
| 5072 #else | 4995 #else |
| 5073 osUnlink(zName); | 4996 unlink(zName); |
| 5074 #endif | 4997 #endif |
| 5075 } | 4998 } |
| 5076 #if SQLITE_ENABLE_LOCKING_STYLE | 4999 #if SQLITE_ENABLE_LOCKING_STYLE |
| 5077 else{ | 5000 else{ |
| 5078 p->openFlags = openFlags; | 5001 p->openFlags = openFlags; |
| 5079 } | 5002 } |
| 5080 #endif | 5003 #endif |
| 5081 | 5004 |
| 5005 if( isOpenDirectory ){ |
| 5006 rc = openDirectory(zPath, &dirfd); |
| 5007 if( rc!=SQLITE_OK ){ |
| 5008 /* It is safe to close fd at this point, because it is guaranteed not |
| 5009 ** to be open on a database file. If it were open on a database file, |
| 5010 ** it would not be safe to close as this would release any locks held |
| 5011 ** on the file by this process. */ |
| 5012 assert( eType!=SQLITE_OPEN_MAIN_DB ); |
| 5013 robust_close(p, fd, __LINE__); |
| 5014 goto open_finished; |
| 5015 } |
| 5016 } |
| 5017 |
| 5082 #ifdef FD_CLOEXEC | 5018 #ifdef FD_CLOEXEC |
| 5083 osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); | 5019 osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); |
| 5084 #endif | 5020 #endif |
| 5085 | 5021 |
| 5086 noLock = eType!=SQLITE_OPEN_MAIN_DB; | 5022 noLock = eType!=SQLITE_OPEN_MAIN_DB; |
| 5087 | 5023 |
| 5088 | 5024 |
| 5089 #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE | 5025 #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE |
| 5090 struct statfs fsInfo; | 5026 struct statfs fsInfo; |
| 5091 if( fstatfs(fd, &fsInfo) == -1 ){ | 5027 if( fstatfs(fd, &fsInfo) == -1 ){ |
| 5092 ((unixFile*)pFile)->lastErrno = errno; | 5028 ((unixFile*)pFile)->lastErrno = errno; |
| 5029 if( dirfd>=0 ) robust_close(p, dirfd, __LINE__); |
| 5093 robust_close(p, fd, __LINE__); | 5030 robust_close(p, fd, __LINE__); |
| 5094 return SQLITE_IOERR_ACCESS; | 5031 return SQLITE_IOERR_ACCESS; |
| 5095 } | 5032 } |
| 5096 if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { | 5033 if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { |
| 5097 ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; | 5034 ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; |
| 5098 } | 5035 } |
| 5099 #endif | 5036 #endif |
| 5100 | 5037 |
| 5101 #if SQLITE_ENABLE_LOCKING_STYLE | 5038 #if SQLITE_ENABLE_LOCKING_STYLE |
| 5102 #if SQLITE_PREFER_PROXY_LOCKING | 5039 #if SQLITE_PREFER_PROXY_LOCKING |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5114 struct statfs fsInfo; | 5051 struct statfs fsInfo; |
| 5115 if( statfs(zPath, &fsInfo) == -1 ){ | 5052 if( statfs(zPath, &fsInfo) == -1 ){ |
| 5116 /* In theory, the close(fd) call is sub-optimal. If the file opened | 5053 /* In theory, the close(fd) call is sub-optimal. If the file opened |
| 5117 ** with fd is a database file, and there are other connections open | 5054 ** with fd is a database file, and there are other connections open |
| 5118 ** on that file that are currently holding advisory locks on it, | 5055 ** on that file that are currently holding advisory locks on it, |
| 5119 ** then the call to close() will cancel those locks. In practice, | 5056 ** then the call to close() will cancel those locks. In practice, |
| 5120 ** we're assuming that statfs() doesn't fail very often. At least | 5057 ** we're assuming that statfs() doesn't fail very often. At least |
| 5121 ** not while other file descriptors opened by the same process on | 5058 ** not while other file descriptors opened by the same process on |
| 5122 ** the same file are working. */ | 5059 ** the same file are working. */ |
| 5123 p->lastErrno = errno; | 5060 p->lastErrno = errno; |
| 5061 if( dirfd>=0 ){ |
| 5062 robust_close(p, dirfd, __LINE__); |
| 5063 } |
| 5124 robust_close(p, fd, __LINE__); | 5064 robust_close(p, fd, __LINE__); |
| 5125 rc = SQLITE_IOERR_ACCESS; | 5065 rc = SQLITE_IOERR_ACCESS; |
| 5126 goto open_finished; | 5066 goto open_finished; |
| 5127 } | 5067 } |
| 5128 useProxy = !(fsInfo.f_flags&MNT_LOCAL); | 5068 useProxy = !(fsInfo.f_flags&MNT_LOCAL); |
| 5129 } | 5069 } |
| 5130 if( useProxy ){ | 5070 if( useProxy ){ |
| 5131 rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock, | 5071 rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, |
| 5132 isDelete, isReadonly); | 5072 isDelete, isReadonly); |
| 5133 if( rc==SQLITE_OK ){ | 5073 if( rc==SQLITE_OK ){ |
| 5134 rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); | 5074 rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); |
| 5135 if( rc!=SQLITE_OK ){ | 5075 if( rc!=SQLITE_OK ){ |
| 5136 /* Use unixClose to clean up the resources added in fillInUnixFile | 5076 /* Use unixClose to clean up the resources added in fillInUnixFile |
| 5137 ** and clear all the structure's references. Specifically, | 5077 ** and clear all the structure's references. Specifically, |
| 5138 ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op | 5078 ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op |
| 5139 */ | 5079 */ |
| 5140 unixClose(pFile); | 5080 unixClose(pFile); |
| 5141 return rc; | 5081 return rc; |
| 5142 } | 5082 } |
| 5143 } | 5083 } |
| 5144 goto open_finished; | 5084 goto open_finished; |
| 5145 } | 5085 } |
| 5146 } | 5086 } |
| 5147 #endif | 5087 #endif |
| 5148 | 5088 |
| 5149 rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock, | 5089 rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, |
| 5150 isDelete, isReadonly); | 5090 isDelete, isReadonly); |
| 5151 open_finished: | 5091 open_finished: |
| 5152 if( rc!=SQLITE_OK ){ | 5092 if( rc!=SQLITE_OK ){ |
| 5153 chromium_sqlite3_destroy_reusable_file_handle(pFile); | 5093 sqlite3_free(p->pUnused); |
| 5154 } | 5094 } |
| 5155 return rc; | 5095 return rc; |
| 5156 } | 5096 } |
| 5157 | 5097 |
| 5158 | 5098 |
| 5159 /* | 5099 /* |
| 5160 ** Delete the file at zPath. If the dirSync argument is true, fsync() | 5100 ** Delete the file at zPath. If the dirSync argument is true, fsync() |
| 5161 ** the directory after deleting the file. | 5101 ** the directory after deleting the file. |
| 5162 */ | 5102 */ |
| 5163 static int unixDelete( | 5103 static int unixDelete( |
| 5164 sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */ | 5104 sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */ |
| 5165 const char *zPath, /* Name of file to be deleted */ | 5105 const char *zPath, /* Name of file to be deleted */ |
| 5166 int dirSync /* If true, fsync() directory after deleting file */ | 5106 int dirSync /* If true, fsync() directory after deleting file */ |
| 5167 ){ | 5107 ){ |
| 5168 int rc = SQLITE_OK; | 5108 int rc = SQLITE_OK; |
| 5169 UNUSED_PARAMETER(NotUsed); | 5109 UNUSED_PARAMETER(NotUsed); |
| 5170 SimulateIOError(return SQLITE_IOERR_DELETE); | 5110 SimulateIOError(return SQLITE_IOERR_DELETE); |
| 5171 if( osUnlink(zPath)==(-1) && errno!=ENOENT ){ | 5111 if( unlink(zPath)==(-1) && errno!=ENOENT ){ |
| 5172 return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath); | 5112 return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath); |
| 5173 } | 5113 } |
| 5174 #ifndef SQLITE_DISABLE_DIRSYNC | 5114 #ifndef SQLITE_DISABLE_DIRSYNC |
| 5175 if( dirSync ){ | 5115 if( dirSync ){ |
| 5176 int fd; | 5116 int fd; |
| 5177 rc = osOpenDirectory(zPath, &fd); | 5117 rc = openDirectory(zPath, &fd); |
| 5178 if( rc==SQLITE_OK ){ | 5118 if( rc==SQLITE_OK ){ |
| 5179 #if OS_VXWORKS | 5119 #if OS_VXWORKS |
| 5180 if( fsync(fd)==-1 ) | 5120 if( fsync(fd)==-1 ) |
| 5181 #else | 5121 #else |
| 5182 if( fsync(fd) ) | 5122 if( fsync(fd) ) |
| 5183 #endif | 5123 #endif |
| 5184 { | 5124 { |
| 5185 rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); | 5125 rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); |
| 5186 } | 5126 } |
| 5187 robust_close(0, fd, __LINE__); | 5127 robust_close(0, fd, __LINE__); |
| 5188 }else if( rc==SQLITE_CANTOPEN ){ | |
| 5189 rc = SQLITE_OK; | |
| 5190 } | 5128 } |
| 5191 } | 5129 } |
| 5192 #endif | 5130 #endif |
| 5193 return rc; | 5131 return rc; |
| 5194 } | 5132 } |
| 5195 | 5133 |
| 5196 /* | 5134 /* |
| 5197 ** Test the existance of or access permissions of file zPath. The | 5135 ** Test the existance of or access permissions of file zPath. The |
| 5198 ** test performed depends on the value of flags: | 5136 ** test performed depends on the value of flags: |
| 5199 ** | 5137 ** |
| (...skipping 22 matching lines...) Expand all Loading... |
| 5222 case SQLITE_ACCESS_READ: | 5160 case SQLITE_ACCESS_READ: |
| 5223 amode = R_OK; | 5161 amode = R_OK; |
| 5224 break; | 5162 break; |
| 5225 | 5163 |
| 5226 default: | 5164 default: |
| 5227 assert(!"Invalid flags argument"); | 5165 assert(!"Invalid flags argument"); |
| 5228 } | 5166 } |
| 5229 *pResOut = (osAccess(zPath, amode)==0); | 5167 *pResOut = (osAccess(zPath, amode)==0); |
| 5230 if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){ | 5168 if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){ |
| 5231 struct stat buf; | 5169 struct stat buf; |
| 5232 if( 0==osStat(zPath, &buf) && buf.st_size==0 ){ | 5170 if( 0==stat(zPath, &buf) && buf.st_size==0 ){ |
| 5233 *pResOut = 0; | 5171 *pResOut = 0; |
| 5234 } | 5172 } |
| 5235 } | 5173 } |
| 5236 return SQLITE_OK; | 5174 return SQLITE_OK; |
| 5237 } | 5175 } |
| 5238 | 5176 |
| 5239 | 5177 |
| 5240 /* | 5178 /* |
| 5241 ** Turn a relative pathname into a full pathname. The relative path | 5179 ** Turn a relative pathname into a full pathname. The relative path |
| 5242 ** is stored as a nul-terminated string in the buffer pointed to by | 5180 ** is stored as a nul-terminated string in the buffer pointed to by |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5741 ** | 5679 ** |
| 5742 ** The caller is responsible not only for closing the file descriptor | 5680 ** The caller is responsible not only for closing the file descriptor |
| 5743 ** but also for freeing the memory associated with the file descriptor. | 5681 ** but also for freeing the memory associated with the file descriptor. |
| 5744 */ | 5682 */ |
| 5745 static int proxyCreateUnixFile( | 5683 static int proxyCreateUnixFile( |
| 5746 const char *path, /* path for the new unixFile */ | 5684 const char *path, /* path for the new unixFile */ |
| 5747 unixFile **ppFile, /* unixFile created and returned by ref */ | 5685 unixFile **ppFile, /* unixFile created and returned by ref */ |
| 5748 int islockfile /* if non zero missing dirs will be created */ | 5686 int islockfile /* if non zero missing dirs will be created */ |
| 5749 ) { | 5687 ) { |
| 5750 int fd = -1; | 5688 int fd = -1; |
| 5689 int dirfd = -1; |
| 5751 unixFile *pNew; | 5690 unixFile *pNew; |
| 5752 int rc = SQLITE_OK; | 5691 int rc = SQLITE_OK; |
| 5753 int openFlags = O_RDWR | O_CREAT; | 5692 int openFlags = O_RDWR | O_CREAT; |
| 5754 sqlite3_vfs dummyVfs; | 5693 sqlite3_vfs dummyVfs; |
| 5755 int terrno = 0; | 5694 int terrno = 0; |
| 5756 UnixUnusedFd *pUnused = NULL; | 5695 UnixUnusedFd *pUnused = NULL; |
| 5757 | 5696 |
| 5758 /* 1. first try to open/create the file | 5697 /* 1. first try to open/create the file |
| 5759 ** 2. if that fails, and this is a lock file (not-conch), try creating | 5698 ** 2. if that fails, and this is a lock file (not-conch), try creating |
| 5760 ** the parent directories and then try again. | 5699 ** the parent directories and then try again. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5805 } | 5744 } |
| 5806 memset(pNew, 0, sizeof(unixFile)); | 5745 memset(pNew, 0, sizeof(unixFile)); |
| 5807 pNew->openFlags = openFlags; | 5746 pNew->openFlags = openFlags; |
| 5808 memset(&dummyVfs, 0, sizeof(dummyVfs)); | 5747 memset(&dummyVfs, 0, sizeof(dummyVfs)); |
| 5809 dummyVfs.pAppData = (void*)&autolockIoFinder; | 5748 dummyVfs.pAppData = (void*)&autolockIoFinder; |
| 5810 dummyVfs.zName = "dummy"; | 5749 dummyVfs.zName = "dummy"; |
| 5811 pUnused->fd = fd; | 5750 pUnused->fd = fd; |
| 5812 pUnused->flags = openFlags; | 5751 pUnused->flags = openFlags; |
| 5813 pNew->pUnused = pUnused; | 5752 pNew->pUnused = pUnused; |
| 5814 | 5753 |
| 5815 rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0); | 5754 rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0, 0); |
| 5816 if( rc==SQLITE_OK ){ | 5755 if( rc==SQLITE_OK ){ |
| 5817 *ppFile = pNew; | 5756 *ppFile = pNew; |
| 5818 return SQLITE_OK; | 5757 return SQLITE_OK; |
| 5819 } | 5758 } |
| 5820 end_create_proxy: | 5759 end_create_proxy: |
| 5821 robust_close(pNew, fd, __LINE__); | 5760 robust_close(pNew, fd, __LINE__); |
| 5822 sqlite3_free(pNew); | 5761 sqlite3_free(pNew); |
| 5823 sqlite3_free(pUnused); | 5762 sqlite3_free(pUnused); |
| 5824 return rc; | 5763 return rc; |
| 5825 } | 5764 } |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5919 } | 5858 } |
| 5920 rc = 0; | 5859 rc = 0; |
| 5921 fprintf(stderr, "broke stale lock on %s\n", cPath); | 5860 fprintf(stderr, "broke stale lock on %s\n", cPath); |
| 5922 robust_close(pFile, conchFile->h, __LINE__); | 5861 robust_close(pFile, conchFile->h, __LINE__); |
| 5923 conchFile->h = fd; | 5862 conchFile->h = fd; |
| 5924 conchFile->openFlags = O_RDWR | O_CREAT; | 5863 conchFile->openFlags = O_RDWR | O_CREAT; |
| 5925 | 5864 |
| 5926 end_breaklock: | 5865 end_breaklock: |
| 5927 if( rc ){ | 5866 if( rc ){ |
| 5928 if( fd>=0 ){ | 5867 if( fd>=0 ){ |
| 5929 osUnlink(tPath); | 5868 unlink(tPath); |
| 5930 robust_close(pFile, fd, __LINE__); | 5869 robust_close(pFile, fd, __LINE__); |
| 5931 } | 5870 } |
| 5932 fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg); | 5871 fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg); |
| 5933 } | 5872 } |
| 5934 return rc; | 5873 return rc; |
| 5935 } | 5874 } |
| 5936 | 5875 |
| 5937 /* Take the requested lock on the conch file and break a stale lock if the | 5876 /* Take the requested lock on the conch file and break a stale lock if the |
| 5938 ** host id matches. | 5877 ** host id matches. |
| 5939 */ | 5878 */ |
| (...skipping 802 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6742 #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) | 6681 #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) |
| 6743 UNIXVFS("unix-afp", afpIoFinder ), | 6682 UNIXVFS("unix-afp", afpIoFinder ), |
| 6744 UNIXVFS("unix-nfs", nfsIoFinder ), | 6683 UNIXVFS("unix-nfs", nfsIoFinder ), |
| 6745 UNIXVFS("unix-proxy", proxyIoFinder ), | 6684 UNIXVFS("unix-proxy", proxyIoFinder ), |
| 6746 #endif | 6685 #endif |
| 6747 }; | 6686 }; |
| 6748 unsigned int i; /* Loop counter */ | 6687 unsigned int i; /* Loop counter */ |
| 6749 | 6688 |
| 6750 /* Double-check that the aSyscall[] array has been constructed | 6689 /* Double-check that the aSyscall[] array has been constructed |
| 6751 ** correctly. See ticket [bb3a86e890c8e96ab] */ | 6690 ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 6752 assert( ArraySize(aSyscall)==18 ); | 6691 assert( ArraySize(aSyscall)==16 ); |
| 6753 | 6692 |
| 6754 /* Register all VFSes defined in the aVfs[] array */ | 6693 /* Register all VFSes defined in the aVfs[] array */ |
| 6755 for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ | 6694 for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ |
| 6756 sqlite3_vfs_register(&aVfs[i], i==0); | 6695 sqlite3_vfs_register(&aVfs[i], i==0); |
| 6757 } | 6696 } |
| 6758 return SQLITE_OK; | 6697 return SQLITE_OK; |
| 6759 } | 6698 } |
| 6760 | 6699 |
| 6761 /* | 6700 /* |
| 6762 ** Shutdown the operating system interface. | 6701 ** Shutdown the operating system interface. |
| 6763 ** | 6702 ** |
| 6764 ** Some operating systems might need to do some cleanup in this routine, | 6703 ** Some operating systems might need to do some cleanup in this routine, |
| 6765 ** to release dynamically allocated objects. But not on unix. | 6704 ** to release dynamically allocated objects. But not on unix. |
| 6766 ** This routine is a no-op for unix. | 6705 ** This routine is a no-op for unix. |
| 6767 */ | 6706 */ |
| 6768 int sqlite3_os_end(void){ | 6707 int sqlite3_os_end(void){ |
| 6769 return SQLITE_OK; | 6708 return SQLITE_OK; |
| 6770 } | 6709 } |
| 6771 | 6710 |
| 6772 #endif /* SQLITE_OS_UNIX */ | 6711 #endif /* SQLITE_OS_UNIX */ |
| OLD | NEW |