r/sr/a=mkaply - OS/2 only
From Andy Willis/Andrew MacIntyre - OS/2 SQLite support
This commit is contained in:
mkaply%us.ibm.com 2005-08-02 17:34:56 +00:00
Родитель 52f8c2ecae
Коммит 3d36110950
3 изменённых файлов: 743 добавлений и 0 удалений

Просмотреть файл

@ -72,6 +72,7 @@ CSRCS = \
os_test.c \
os_unix.c \
os_win.c \
os_os2.c \
pager.c \
parse.c \
pragma.c \

685
db/sqlite3/src/os_os2.c Executable file
Просмотреть файл

@ -0,0 +1,685 @@
/*
** 2001 September 16
**
** 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 code that is specific to particular operating
** systems. The purpose of this file is to provide a uniform abstraction
** on which the rest of SQLite can operate.
*/
#include "sqliteInt.h"
#include "os.h"
#if OS_OS2
# include <time.h>
# include <errno.h>
# include <unistd.h>
# define INCL_DOSFILEMGR
# define INCL_DOSERRORS
# define INCL_DOSPROCESS
# include <os2.h>
# include <stdio.h>
# include <stdlib.h>
# include <io.h>
# include <share.h>
/*
** Include code that is common to all os_*.c files
*/
#include "os_common.h"
/*
** Macros used to determine whether or not to use threads. The
** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for
** Posix threads and SQLITE_W32_THREADS is defined if we are
** synchronizing using Win32 threads.
*/
#if defined(THREADSAFE) && THREADSAFE
/* this mutex implementation only available with EMX */
# include <sys/builtin.h>
# include <sys/smutex.h>
# define SQLITE_OS2_THREADS 1
#endif
/*
** Delete the named file
*/
int sqlite3OsDelete(const char *zFilename){
unlink(zFilename);
return SQLITE_OK;
}
/*
** Return TRUE if the named file exists.
*/
int sqlite3OsFileExists(const char *zFilename){
return access(zFilename, 0)==0;
}
#if 0 /* NOT USED */
/*
** Change the name of an existing file.
*/
int sqlite3OsFileRename(const char *zOldName, const char *zNewName){
if( link(zOldName, zNewName) ){
return SQLITE_ERROR;
}
unlink(zOldName);
return SQLITE_OK;
}
#endif /* NOT USED */
/*
** Attempt to open a file for both reading and writing. If that
** fails, try opening it read-only. If the file does not exist,
** try to create it.
**
** On success, a handle for the open file is written to *id
** and *pReadonly is set to 0 if the file was opened for reading and
** writing or 1 if the file was opened read-only. The function returns
** SQLITE_OK.
**
** On failure, the function returns SQLITE_CANTOPEN and leaves
** *id and *pReadonly unchanged.
*/
int sqlite3OsOpenReadWrite(
const char *zFilename,
OsFile *id,
int *pReadonly
){
id->h = sopen(zFilename, O_RDWR|O_CREAT|O_BINARY, SH_DENYNO, 0600);
if( id->h<0 ){
id->h = sopen(zFilename, O_RDONLY|O_BINARY, SH_DENYNO);
if( id->h<0 ){
return SQLITE_CANTOPEN;
}
*pReadonly = 1;
}else{
*pReadonly = 0;
}
id->locked = 0;
id->delOnClose = 0;
TRACE3("OPEN %-3d %s\n", id->h, zFilename);
OpenCounter(+1);
return SQLITE_OK;
}
/*
** Attempt to open a new file for exclusive access by this process.
** The file will be opened for both reading and writing. To avoid
** a potential security problem, we do not allow the file to have
** previously existed. Nor do we allow the file to be a symbolic
** link.
**
** If delFlag is true, then make arrangements to automatically delete
** the file when it is closed.
**
** On success, write the file handle into *id and return SQLITE_OK.
**
** On failure, return SQLITE_CANTOPEN.
*/
int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
if( access(zFilename, 0)==0 ){
return SQLITE_CANTOPEN;
}
id->h = sopen(zFilename, O_RDWR|O_CREAT|O_EXCL|O_BINARY, SH_DENYNO, 0600);
if( id->h<0 ){
return SQLITE_CANTOPEN;
}
id->locked = 0;
id->delOnClose = delFlag;
if (delFlag)
id->pathToDel = sqlite3OsFullPathname(zFilename);
TRACE3("OPEN-EX %-3d %s\n", id->h, zFilename);
OpenCounter(+1);
return SQLITE_OK;
}
/*
** Attempt to open a new file for read-only access.
**
** On success, write the file handle into *id and return SQLITE_OK.
**
** On failure, return SQLITE_CANTOPEN.
*/
int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){
id->h = sopen(zFilename, O_RDONLY|O_BINARY, SH_DENYNO, 0600);
if( id->h<0 ){
return SQLITE_CANTOPEN;
}
id->locked = 0;
id->delOnClose = 0;
TRACE3("OPEN-RO %-3d %s\n", id->h, zFilename);
OpenCounter(+1);
return SQLITE_OK;
}
/*
** Attempt to open a file descriptor for the directory that contains a
** file. This file descriptor can be used to fsync() the directory
** in order to make sure the creation of a new file is actually written
** to disk.
**
** This routine is only meaningful for Unix. It is a no-op under
** windows since windows does not support hard links.
**
** On success, a handle for a previously open file is at *id is
** updated with the new directory file descriptor and SQLITE_OK is
** returned.
**
** On failure, the function returns SQLITE_CANTOPEN and leaves
** *id unchanged.
*/
int sqlite3OsOpenDirectory(
const char *zDirname,
OsFile *id
){
return SQLITE_OK;
}
/*
** If the following global variable points to a string which is the
** name of a directory, then that directory will be used to store
** temporary files.
*/
char *sqlite3_temp_directory = 0;
/*
** Create a temporary file name in zBuf. zBuf must be big enough to
** hold at least SQLITE_TEMPNAME_SIZE characters.
*/
int sqlite3OsTempFileName(char *zBuf){
static const char *azDirs[] = {
"/temp", /* supercede from TEMP env var */
"/temp",
"/tmp",
".",
};
static const char zChars[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
int i, j;
struct stat buf;
const char *zDir = ".";
azDirs[0] = getenv("TEMP");
zDir = ".";
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
if( !azDirs[i] ) continue;
if( stat(azDirs[i], &buf) ) continue;
if( !S_ISDIR(buf.st_mode) ) continue;
if( access(azDirs[i], 07) ) continue;
zDir = azDirs[i];
break;
}
do{
snprintf(zBuf, SQLITE_TEMPNAME_SIZE, "%s/"TEMP_FILE_PREFIX, zDir);
j = strlen(zBuf);
sqlite3Randomness(15, &zBuf[j]);
for(i=0; i<15; i++, j++){
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
zBuf[j] = 0;
}while( access(zBuf,0)==0 );
return SQLITE_OK;
}
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
/*
** Check that a given pathname is a directory and is writable
**
*/
int sqlite3OsIsDirWritable(char *zBuf){
struct stat buf;
if( zBuf==0 ) return 0;
if( zBuf[0]==0 ) return 0;
if( stat(zBuf, &buf) ) return 0;
if( !S_ISDIR(buf.st_mode) ) return 0;
if( access(zBuf, 07) ) return 0;
return 1;
}
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
/*
** Read data from a file into a buffer. Return SQLITE_OK if all
** bytes were read successfully and SQLITE_IOERR if anything goes
** wrong.
*/
int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
int got;
SimulateIOError(SQLITE_IOERR);
TIMER_START;
got = read(id->h, pBuf, amt);
TIMER_END;
TRACE5("READ %-3d %5d %7d %d\n", id->h, got, last_page, TIMER_ELAPSED);
SEEK(0);
/* if( got<0 ) got = 0; */
if( got==amt ){
return SQLITE_OK;
}else{
return SQLITE_IOERR;
}
}
/*
** Write data from a buffer into a file. Return SQLITE_OK on success
** or some other error code on failure.
*/
int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
int wrote = 0;
assert( amt>0 );
SimulateIOError(SQLITE_IOERR);
SimulateDiskfullError;
TIMER_START;
wrote = write(id->h, pBuf, amt);
TIMER_END;
if ( wrote<0 ){
return SQLITE_IOERR;
}
TRACE5("WRITE %-3d %5d %7d %d\n", id->h, got, last_page, TIMER_ELAPSED);
SEEK(0);
if( (wrote - amt)>0 ){
return SQLITE_FULL;
}
return SQLITE_OK;
}
/*
** Move the read/write pointer in a file.
*/
int sqlite3OsSeek(OsFile *id, i64 offset){
SEEK(offset/1024 + 1);
long pos;
pos = lseek(id->h, offset, SEEK_SET);
if ( pos<0 )
return SQLITE_IOERR;
return SQLITE_OK;
}
#ifdef SQLITE_TEST
/*
** Count the number of fullsyncs and normal syncs. This is used to test
** that syncs and fullsyncs are occuring at the right times.
*/
int sqlite3_sync_count = 0;
int sqlite3_fullsync_count = 0;
#endif
/*
** The fsync() system call does not work as advertised on many
** unix systems. The following procedure is an attempt to make
** it work better.
**
** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful
** for testing when we want to run through the test suite quickly.
** You are strongly advised *not* to deploy with SQLITE_NO_SYNC
** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
** or power failure will likely corrupt the database file.
*/
static int full_fsync(int fd, int fullSync){
int rc;
/* Record the number of times that we do a normal fsync() and
** FULLSYNC. This is used during testing to verify that this procedure
** gets called with the correct arguments.
*/
#ifdef SQLITE_TEST
if( fullSync ) sqlite3_fullsync_count++;
sqlite3_sync_count++;
#endif
/* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
** no-op
*/
#ifdef SQLITE_NO_SYNC
rc = SQLITE_OK;
#else
#ifdef F_FULLFSYNC
if( fullSync ){
rc = fcntl(fd, F_FULLFSYNC, 0);
}else{
rc = 1;
}
/* If the FULLSYNC failed, try to do a normal fsync() */
if( rc ) rc = fsync(fd);
#else
rc = fsync(fd);
#endif /* defined(F_FULLFSYNC) */
#endif /* defined(SQLITE_NO_SYNC) */
return rc;
}
/*
** Make sure all writes to a particular file are committed to disk.
**
** Under Unix, also make sure that the directory entry for the file
** has been created by fsync-ing the directory that contains the file.
** If we do not do this and we encounter a power failure, the directory
** entry for the journal might not exist after we reboot. The next
** SQLite to access the file will not know that the journal exists (because
** the directory entry for the journal was never created) and the transaction
** will not roll back - possibly leading to database corruption.
*/
int sqlite3OsSync(OsFile *id){
SimulateIOError(SQLITE_IOERR);
TRACE2("SYNC %-3d\n", id->h);
if( full_fsync(id->h, id->fullSync)){
return SQLITE_IOERR;
}else{
return SQLITE_OK;
}
}
/*
** Sync the directory zDirname. This is a no-op on operating systems other
** than UNIX.
*/
int sqlite3OsSyncDirectory(const char *zDirname){
SimulateIOError(SQLITE_IOERR);
return SQLITE_OK;
}
/*
** Truncate an open file to a specified size
*/
int sqlite3OsTruncate(OsFile *id, i64 nByte){
SimulateIOError(SQLITE_IOERR);
return ftruncate(id->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;
}
/*
** Determine the current size of a file in bytes
*/
int sqlite3OsFileSize(OsFile *id, i64 *pSize){
struct stat buf;
SimulateIOError(SQLITE_IOERR);
if( fstat(id->h, &buf)!=0 ){
return SQLITE_IOERR;
}
*pSize = buf.st_size;
return SQLITE_OK;
}
#define N_LOCKBYTE 0x7fffffffL
#define FIRST_LOCKBYTE 0L
/*
** Change the status of the lock on the file "id" to be a readlock.
** If the file was write locked, then this reduces the lock to a read.
** If the file was read locked, then this acquires a new read lock.
**
** Return SQLITE_OK on success and SQLITE_BUSY on failure. If this
** library was compiled with large file support (LFS) but LFS is not
** available on the host, then an SQLITE_NOLFS is returned.
*/
int sqlite3OsCheckReservedLock(OsFile *id){
int rc;
if( id->locked>0 ){
rc = SQLITE_OK;
}else{
APIRET s;
FILELOCK ulock = {0L, 0L};
FILELOCK lock = {FIRST_LOCKBYTE, N_LOCKBYTE};
long readlock = 1L;
if( id->locked<0 ){
ulock.lOffset = lock.lOffset;
ulock.lRange = lock.lRange;
readlock += 2L; /* atomic unlock/lock */
}
s = DosSetFileLocks(id->h, &ulock, &lock, 0L, readlock);
if( s!=NO_ERROR ){
rc = 1;
}else{
rc = 0;
id->locked = 1;
}
}
return rc;
}
#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
/*
** Change the lock status to be an exclusive or write lock. Return
** SQLITE_OK on success and SQLITE_BUSY on a failure. If this
** library was compiled with large file support (LFS) but LFS is not
** available on the host, then an SQLITE_NOLFS is returned.
*/
int sqlite3OsLock(OsFile *id, int locktype){
int rc;
if( id->locked<0 ){
rc = SQLITE_OK;
}else{
APIRET s;
FILELOCK ulock = {0L, 0L};
FILELOCK lock = {FIRST_LOCKBYTE, N_LOCKBYTE};
long writelock = 0L;
if( id->locked>0 ){
ulock.lOffset = lock.lOffset;
ulock.lRange = lock.lRange;
writelock += 2L; /* atomic unlock/lock */
}
s = DosSetFileLocks(id->h, &ulock, &lock, 0L, writelock);
if( s!=NO_ERROR ){
rc = SQLITE_BUSY;
}else{
rc = SQLITE_OK;
id->locked = -1;
}
}
return rc;
}
/*
** Unlock the given file descriptor. If the file descriptor was
** not previously locked, then this routine is a no-op. If this
** library was compiled with large file support (LFS) but LFS is not
** available on the host, then an SQLITE_NOLFS is returned.
*/
int sqlite3OsUnlock(OsFile *id, int locktype){
int rc;
if( id->locked==0 ){
rc = SQLITE_OK;
}else{
APIRET s;
FILELOCK ulock = {FIRST_LOCKBYTE, N_LOCKBYTE};
FILELOCK lock = {0L, 0L};
s = DosSetFileLocks(id->h, &ulock, &lock, 0L, 0L);
if( s!=NO_ERROR ){
rc = SQLITE_BUSY;
}else{
rc = SQLITE_OK;
id->locked = 0;
}
}
return rc;
}
/*
** Close a file.
*/
int sqlite3OsClose(OsFile *id){
close(id->h);
if( id->delOnClose ){
unlink(id->pathToDel);
sqliteFree(id->pathToDel);
}
TRACE2("CLOSE %-3d\n", id->h);
id->isOpen = 0;
OpenCounter(-1);
return SQLITE_OK;
}
/*
** Get information to seed the random number generator. The seed
** is written into the buffer zBuf[256]. The calling function must
** supply a sufficiently large buffer.
*/
int sqlite3OsRandomSeed(char *zBuf){
/* We have to initialize zBuf to prevent valgrind from reporting
** errors. The reports issued by valgrind are incorrect - we would
** prefer that the randomness be increased by making use of the
** uninitialized space in zBuf - but valgrind errors tend to worry
** some users. Rather than argue, it seems easier just to initialize
** the whole array and silence valgrind, even if that means less randomness
** in the random seed.
**
** When testing, initializing zBuf[] to zero is all we do. That means
** that we always use the same random number sequence.* This makes the
** tests repeatable.
*/
memset(zBuf, 0, 256);
#if !defined(SQLITE_TEST)
{
int pid;
time((time_t*)zBuf);
pid = getpid();
memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid));
}
#endif
return SQLITE_OK;
}
/*
** Sleep for a little while. Return the amount of time slept.
*/
int sqlite3OsSleep(int ms){
APIRET rc;
rc = DosSleep(ms);
return ms;
}
/*
** Static variables used for thread synchronization
*/
static int inMutex = 0;
#ifdef SQLITE_OS2_THREADS
static _smutex mutex = 0;
#endif
/*
** The following pair of routine implement mutual exclusion for
** multi-threaded processes. Only a single thread is allowed to
** executed code that is surrounded by EnterMutex() and LeaveMutex().
**
** SQLite uses only a single Mutex. There is not much critical
** code and what little there is executes quickly and without blocking.
*/
void sqlite3OsEnterMutex(){
#ifdef SQLITE_OS2_THREADS
_smutex_request(&mutex);
#endif
assert( !inMutex );
inMutex = 1;
}
void sqlite3OsLeaveMutex(){
assert( inMutex );
inMutex = 0;
#ifdef SQLITE_OS2_THREADS
_smutex_release(&mutex);
#endif
}
/*
** Turn a relative pathname into a full pathname. Return a pointer
** to the full pathname stored in space obtained from sqliteMalloc().
** The calling function is responsible for freeing this space once it
** is no longer needed.
*/
char *sqlite3OsFullPathname(const char *zRelative){
char *zFull = 0;
char zPath[260]; /* max OS/2 path length, incl drive */
if( !_abspath(zPath, zRelative, sizeof(zPath)) ){
sqlite3SetString(&zFull, zPath, 0);
}else{
char zBuf[260];
snprintf(zPath, sizeof(zPath), "%s/%s",
getcwd(zBuf, sizeof(zBuf)), zRelative);
sqlite3SetString(&zFull, zPath, 0);
}
return zFull;
}
/*
** The following variable, if set to a non-zero value, becomes the result
** returned from sqlite3OsCurrentTime(). This is used for testing.
*/
#ifdef SQLITE_TEST
int sqlite3_current_time = 0;
#endif
/*
** Find the current time (in Universal Coordinated Time). Write the
** current time and date as a Julian Day number into *prNow and
** return 0. Return 1 if the time and date cannot be found.
*/
int sqlite3OsCurrentTime(double *prNow){
time_t t;
time(&t);
*prNow = t/86400.0 + 2440587.5;
#ifdef SQLITE_TEST
if( sqlite3_current_time ){
*prNow = sqlite_current_time/86400.0 + 2440587.5;
}
#endif
return 0;
}
#if 0 /* NOT USED */
/*
** Find the time that the file was last modified. Write the
** modification time and date as a Julian Day number into *prNow and
** return SQLITE_OK. Return SQLITE_ERROR if the modification
** time cannot be found.
*/
int sqlite3OsFileModTime(OsFile *id, double *prNow){
int rc;
struct stat statbuf;
if( fstat(id->h, &statbuf)==0 ){
*prNow = statbuf.st_mtime/86400.0 + 2440587.5;
rc = SQLITE_OK;
}else{
rc = SQLITE_ERROR;
}
return rc;
}
#endif /* NOT USED */
#endif /* OS_OS2 */

57
db/sqlite3/src/os_os2.h Executable file
Просмотреть файл

@ -0,0 +1,57 @@
/*
** 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 header file defined OS-specific features for OS/2.
*/
#ifndef _SQLITE_OS_OS2_H_
#define _SQLITE_OS_OS2_H_
/*
** standard include files.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/*
** The OsFile structure is a operating-system independing representation
** of an open file handle. It is defined differently for each architecture.
**
** This is the definition for Unix.
**
** OsFile.locktype takes one of the values SHARED_LOCK, RESERVED_LOCK,
** PENDING_LOCK or EXCLUSIVE_LOCK.
*/
typedef struct OsFile OsFile;
struct OsFile {
unsigned long h; /* The file descriptor (LHANDLE) */
int locked; /* True if this user holds the lock */
int delOnClose; /* True if file is to be deleted on close */
char *pathToDel; /* Name of file to delete on close */
unsigned char locktype; /* The type of lock held on this fd */
unsigned char isOpen; /* True if needs to be closed */
unsigned char fullSync;
};
/*
** Maximum number of characters in a temporary file name
*/
#define SQLITE_TEMPNAME_SIZE 200
/*
** Minimum interval supported by sqlite3OsSleep().
*/
#define SQLITE_MIN_SLEEP_MS 1
#endif /* _SQLITE_OS_OS2_H_ */