📄 os_unix.c
字号:
/*** 2004 May 22**** The author disclaims copyright to this source code. In place of** a legal notice, here is a blessing:**** May you do good and not evil.** May you find forgiveness for yourself and forgive others.** May you share freely, never taking more than you give.************************************************************************************ This file contains the VFS implementation for unix-like operating systems** include Linux, MacOSX, *BSD, QNX, VxWorks, AIX, HPUX, and others.**** There are actually several different VFS implementations in this file.** The differences are in the way that file locking is done. The default** implementation uses Posix Advisory Locks. Alternative implementations** use flock(), dot-files, various proprietary locking schemas, or simply** skip locking all together.**** This source file is organized into divisions where the logic for various** subfunctions is contained within the appropriate division. PLEASE** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed** in the correct division and should be clearly labeled.**** The layout of divisions is as follows:**** * General-purpose declarations and utility functions.** * Unique file ID logic used by VxWorks.** * Various locking primitive implementations (all except proxy locking):** + for Posix Advisory Locks** + for no-op locks** + for dot-file locks** + for flock() locking** + for named semaphore locks (VxWorks only)** + for AFP filesystem locks (MacOSX only)** * sqlite3_file methods not associated with locking.** * Definitions of sqlite3_io_methods objects for all locking** methods plus "finder" functions for each locking method.** * sqlite3_vfs method implementations.** * Locking primitives for the proxy uber-locking-method. (MacOSX only)** * Definitions of sqlite3_vfs objects for all locking methods** plus implementations of sqlite3_os_init() and sqlite3_os_end().**** $Id: os_unix.c,v 1.241 2009/02/09 17:34:07 drh Exp $*/#include "sqliteInt.h"#if SQLITE_OS_UNIX /* This file is used on unix only *//*** There are various methods for file locking used for concurrency** control:**** 1. POSIX locking (the default),** 2. No locking,** 3. Dot-file locking,** 4. flock() locking,** 5. AFP locking (OSX only),** 6. Named POSIX semaphores (VXWorks only),** 7. proxy locking. (OSX only)**** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE** is defined to 1. The SQLITE_ENABLE_LOCKING_STYLE also enables automatic** selection of the appropriate locking style based on the filesystem** where the database is located. */#if !defined(SQLITE_ENABLE_LOCKING_STYLE)# if defined(__APPLE__)# define SQLITE_ENABLE_LOCKING_STYLE 1# else# define SQLITE_ENABLE_LOCKING_STYLE 0# endif#endif/*** Define the OS_VXWORKS pre-processor macro to 1 if building on ** vxworks, or 0 otherwise.*/#ifndef OS_VXWORKS# if defined(__RTP__) || defined(_WRS_KERNEL)# define OS_VXWORKS 1# else# define OS_VXWORKS 0# endif#endif/*** These #defines should enable >2GB file support on Posix if the** underlying operating system supports it. If the OS lacks** large file support, these should be no-ops.**** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch** on the compiler command line. This is necessary if you are compiling** on a recent machine (ex: RedHat 7.2) but you want your code to work** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2** without this option, LFS is enable. But LFS does not exist in the kernel** in RedHat 6.0, so the code won't work. Hence, for maximum binary** portability you should omit LFS.**** The previous paragraph was written in 2005. (This paragraph is written** on 2008-11-28.) These days, all Linux kernels support large files, so** you should probably leave LFS enabled. But some embedded platforms might** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.*/#ifndef SQLITE_DISABLE_LFS# define _LARGE_FILE 1# ifndef _FILE_OFFSET_BITS# define _FILE_OFFSET_BITS 64# endif# define _LARGEFILE_SOURCE 1#endif/*** standard include files.*/#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <time.h>#include <sys/time.h>#include <errno.h>#if SQLITE_ENABLE_LOCKING_STYLE# include <sys/ioctl.h># if OS_VXWORKS# include <semaphore.h># include <limits.h># else# include <sys/file.h># include <sys/param.h># include <sys/mount.h># endif#endif /* SQLITE_ENABLE_LOCKING_STYLE *//*** If we are to be thread-safe, include the pthreads header and define** the SQLITE_UNIX_THREADS macro.*/#if SQLITE_THREADSAFE# include <pthread.h># define SQLITE_UNIX_THREADS 1#endif/*** Default permissions when creating a new file*/#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644#endif/* ** Default permissions when creating auto proxy dir */#ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS# define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755#endif/*** Maximum supported path-length.*/#define MAX_PATHNAME 512/*** Only set the lastErrno if the error code is a real error and not ** a normal expected return code of SQLITE_BUSY or SQLITE_OK*/#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY))/*** The unixFile structure is subclass of sqlite3_file specific to the unix** VFS implementations.*/typedef struct unixFile unixFile;struct unixFile { sqlite3_io_methods const *pMethod; /* Always the first entry */ struct unixOpenCnt *pOpen; /* Info about all open fd's on this inode */ struct unixLockInfo *pLock; /* Info about locks on this inode */ int h; /* The file descriptor */ int dirfd; /* File descriptor for the directory */ unsigned char locktype; /* The type of lock held on this fd */ int lastErrno; /* The unix errno from the last I/O error */ void *lockingContext; /* Locking style specific state */#if SQLITE_ENABLE_LOCKING_STYLE int openFlags; /* The flags specified at open() */#endif#if SQLITE_THREADSAFE && defined(__linux__) pthread_t tid; /* The thread that "owns" this unixFile */#endif#if OS_VXWORKS int isDelete; /* Delete on close if true */ struct vxworksFileId *pId; /* Unique file ID */#endif#ifndef NDEBUG /* The next group of variables are used to track whether or not the ** transaction counter in bytes 24-27 of database files are updated ** whenever any part of the database changes. An assertion fault will ** occur if a file is updated without also updating the transaction ** counter. This test is made to avoid new problems similar to the ** one described by ticket #3584. */ unsigned char transCntrChng; /* True if the transaction counter changed */ unsigned char dbUpdate; /* True if any part of database file changed */ unsigned char inNormalWrite; /* True if in a normal write operation */ /* If true, that means we are dealing with a database file that has ** a range of locking bytes from PENDING_BYTE through PENDING_BYTE+511 ** which should never be read or written. Asserts() will verify this */ unsigned char isLockable; /* True if file might be locked */#endif#ifdef SQLITE_TEST /* In test mode, increase the size of this structure a bit so that ** it is larger than the struct CrashFile defined in test6.c. */ char aPadding[32];#endif};/*** Include code that is common to all os_*.c files*/#include "os_common.h"/*** Define various macros that are missing from some systems.*/#ifndef O_LARGEFILE# define O_LARGEFILE 0#endif#ifdef SQLITE_DISABLE_LFS# undef O_LARGEFILE# define O_LARGEFILE 0#endif#ifndef O_NOFOLLOW# define O_NOFOLLOW 0#endif#ifndef O_BINARY# define O_BINARY 0#endif/*** The DJGPP compiler environment looks mostly like Unix, but it** lacks the fcntl() system call. So redefine fcntl() to be something** that always succeeds. This means that locking does not occur under** DJGPP. But it is DOS - what did you expect?*/#ifdef __DJGPP__# define fcntl(A,B,C) 0#endif/*** The threadid macro resolves to the thread-id or to 0. Used for** testing and debugging only.*/#if SQLITE_THREADSAFE#define threadid pthread_self()#else#define threadid 0#endif/*** Helper functions to obtain and relinquish the global mutex.*/static void unixEnterMutex(void){ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));}static void unixLeaveMutex(void){ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));}#ifdef SQLITE_DEBUG/*** Helper function for printing out trace information from debugging** binaries. This returns the string represetation of the supplied** integer lock-type.*/static const char *locktypeName(int locktype){ switch( locktype ){ case NO_LOCK: return "NONE"; case SHARED_LOCK: return "SHARED"; case RESERVED_LOCK: return "RESERVED"; case PENDING_LOCK: return "PENDING"; case EXCLUSIVE_LOCK: return "EXCLUSIVE"; } return "ERROR";}#endif#ifdef SQLITE_LOCK_TRACE/*** Print out information about all locking operations.**** This routine is used for troubleshooting locks on multithreaded** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE** command-line option on the compiler. This code is normally** turned off.*/static int lockTrace(int fd, int op, struct flock *p){ char *zOpName, *zType; int s; int savedErrno; if( op==F_GETLK ){ zOpName = "GETLK"; }else if( op==F_SETLK ){ zOpName = "SETLK"; }else{ s = fcntl(fd, op, p); sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s); return s; } if( p->l_type==F_RDLCK ){ zType = "RDLCK"; }else if( p->l_type==F_WRLCK ){ zType = "WRLCK"; }else if( p->l_type==F_UNLCK ){ zType = "UNLCK"; }else{ assert( 0 ); } assert( p->l_whence==SEEK_SET ); s = fcntl(fd, op, p); savedErrno = errno; sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n", threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len, (int)p->l_pid, s); if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){ struct flock l2; l2 = *p; fcntl(fd, F_GETLK, &l2); if( l2.l_type==F_RDLCK ){ zType = "RDLCK"; }else if( l2.l_type==F_WRLCK ){ zType = "WRLCK"; }else if( l2.l_type==F_UNLCK ){ zType = "UNLCK"; }else{ assert( 0 ); } sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n", zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid); } errno = savedErrno; return s;}#define fcntl lockTrace#endif /* SQLITE_LOCK_TRACE *//*** This routine translates a standard POSIX errno code into something** useful to the clients of the sqlite3 functions. Specifically, it is** intended to translate a variety of "try again" errors into SQLITE_BUSY** and a variety of "please close the file descriptor NOW" errors into ** SQLITE_IOERR** ** Errors during initialization of locks, or file system support for locks,** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.*/static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) { switch (posixError) { case 0: return SQLITE_OK; case EAGAIN: case ETIMEDOUT: case EBUSY: case EINTR: case ENOLCK: /* random NFS retry error, unless during file system support * introspection, in which it actually means what it says */ return SQLITE_BUSY; case EACCES: /* EACCES is like EAGAIN during locking operations, but not any other time*/ if( (sqliteIOErr == SQLITE_IOERR_LOCK) || (sqliteIOErr == SQLITE_IOERR_UNLOCK) || (sqliteIOErr == SQLITE_IOERR_RDLOCK) || (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){ return SQLITE_BUSY; } /* else fall through */ case EPERM: return SQLITE_PERM; case EDEADLK: return SQLITE_IOERR_BLOCKED; #if EOPNOTSUPP!=ENOTSUP case EOPNOTSUPP: /* something went terribly awry, unless during file system support * introspection, in which it actually means what it says */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -