mirror of https://github.com/sqlite/sqlite
Added support for OS/2. Ticket #1817 (CVS 3198)
FossilOrigin-Name: 373246c2d1edaec1ce248ff875db48ce51d896f9
This commit is contained in:
parent
eb741d5dd2
commit
60a1e4b6ce
|
@ -125,7 +125,7 @@ TCC += -DSQLITE_OMIT_CURSOR
|
|||
LIBOBJ = alter.lo analyze.lo attach.lo auth.lo btree.lo build.lo \
|
||||
callback.lo complete.lo date.lo \
|
||||
delete.lo expr.lo func.lo hash.lo insert.lo \
|
||||
main.lo opcodes.lo os.lo os_unix.lo os_win.lo \
|
||||
main.lo opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \
|
||||
pager.lo parse.lo pragma.lo prepare.lo printf.lo random.lo \
|
||||
select.lo table.lo tokenize.lo trigger.lo update.lo \
|
||||
util.lo vacuum.lo \
|
||||
|
@ -156,6 +156,7 @@ SRC = \
|
|||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/os_os2.c \
|
||||
$(TOP)/src/pager.c \
|
||||
$(TOP)/src/pager.h \
|
||||
$(TOP)/src/parse.y \
|
||||
|
@ -193,6 +194,7 @@ TESTSRC = \
|
|||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/os_os2.c \
|
||||
$(TOP)/src/pager.c \
|
||||
$(TOP)/src/pragma.c \
|
||||
$(TOP)/src/printf.c \
|
||||
|
@ -257,7 +259,7 @@ libtclsqlite3.la: tclsqlite.lo libsqlite3.la
|
|||
|
||||
sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h
|
||||
$(LTLINK) $(READLINE_FLAGS) $(LIBPTHREAD) \
|
||||
-o sqlite3 $(TOP)/src/shell.c libsqlite3.la \
|
||||
-o $@ $(TOP)/src/shell.c libsqlite3.la \
|
||||
$(LIBREADLINE) $(TLIBS)
|
||||
|
||||
# This target creates a directory named "tsrc" and fills it with
|
||||
|
@ -352,6 +354,9 @@ os_unix.lo: $(TOP)/src/os_unix.c $(HDR)
|
|||
os_win.lo: $(TOP)/src/os_win.c $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)/src/os_win.c
|
||||
|
||||
os_os2.lo: $(TOP)/src/os_os2.c $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)/src/os_os2.c
|
||||
|
||||
parse.lo: parse.c $(HDR)
|
||||
$(LTCOMPILE) -c parse.c
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ ltmain="$ac_aux_dir/ltmain.sh"
|
|||
ofile="$default_ofile"
|
||||
with_gnu_ld="$lt_cv_prog_gnu_ld"
|
||||
|
||||
AC_CHECK_TOOL(AR, ar, false)
|
||||
AC_CHECK_TOOL(AR, ar, AC_CHECK_TOOL(AR, emxomfar, false))
|
||||
AC_CHECK_TOOL(RANLIB, ranlib, :)
|
||||
AC_CHECK_TOOL(STRIP, strip, :)
|
||||
|
||||
|
|
|
@ -463,7 +463,7 @@ ac_includes_default="\
|
|||
# include <unistd.h>
|
||||
#endif"
|
||||
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP CPP CXX CXXFLAGS ac_ct_CXX CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA AWK program_prefix VERSION RELEASE VERSION_NUMBER BUILD_CC BUILD_CFLAGS BUILD_LIBS TARGET_CC TARGET_CFLAGS TARGET_LINK TARGET_LFLAGS TARGET_RANLIB TARGET_AR THREADSAFE TARGET_THREAD_LIB XTHREADCONNECT THREADSOVERRIDELOCKS ALLOWRELEASE TEMP_STORE BUILD_EXEEXT OS_UNIX OS_WIN TARGET_EXEEXT TCL_VERSION TCL_BIN_DIR TCL_SRC_DIR TCL_LIBS TCL_INCLUDE_SPEC TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC HAVE_TCL TARGET_READLINE_LIBS TARGET_READLINE_INC TARGET_HAVE_READLINE TARGET_DEBUG TARGET_LIBS LIBOBJS LTLIBOBJS'
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP CPP CXX CXXFLAGS ac_ct_CXX CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA AWK program_prefix VERSION RELEASE VERSION_NUMBER BUILD_CC BUILD_CFLAGS BUILD_LIBS TARGET_CC TARGET_CFLAGS TARGET_LINK TARGET_LFLAGS TARGET_RANLIB TARGET_AR THREADSAFE TARGET_THREAD_LIB XTHREADCONNECT THREADSOVERRIDELOCKS ALLOWRELEASE TEMP_STORE BUILD_EXEEXT OS_UNIX OS_WIN OS_OS2 TARGET_EXEEXT TCL_VERSION TCL_BIN_DIR TCL_SRC_DIR TCL_LIBS TCL_INCLUDE_SPEC TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC HAVE_TCL TARGET_READLINE_LIBS TARGET_READLINE_INC TARGET_HAVE_READLINE TARGET_DEBUG TARGET_LIBS LIBOBJS LTLIBOBJS'
|
||||
ac_subst_files=''
|
||||
|
||||
# Initialize some variables set by options.
|
||||
|
@ -1502,7 +1502,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
|||
|
||||
|
||||
# The following RCS revision string applies to configure.in
|
||||
# $Revision: 1.39 $
|
||||
# $Revision: 1.40 $
|
||||
|
||||
#########
|
||||
# Programs needed
|
||||
|
@ -19695,13 +19695,26 @@ else
|
|||
TARGET_EXEEXT=$config_TARGET_EXEEXT
|
||||
fi
|
||||
if test "$TARGET_EXEEXT" = ".exe"; then
|
||||
OS_UNIX=0
|
||||
OS_WIN=1
|
||||
tclsubdir=win
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS -DOS_WIN=1"
|
||||
if test $OS2_SHELL ; then
|
||||
OS_UNIX=0
|
||||
OS_WIN=0
|
||||
OS_OS2=1
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS -DOS_OS2=1"
|
||||
if test "$ac_compiler_gnu" == "yes" ; then
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS -Zomf -Zexe -Zmap"
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -Zomf -Zexe"
|
||||
fi
|
||||
else
|
||||
OS_UNIX=0
|
||||
OS_WIN=1
|
||||
OS_OS2=0
|
||||
tclsubdir=win
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS -DOS_WIN=1"
|
||||
fi
|
||||
else
|
||||
OS_UNIX=1
|
||||
OS_WIN=0
|
||||
OS_OS2=0
|
||||
tclsubdir=unix
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS -DOS_UNIX=1"
|
||||
fi
|
||||
|
@ -21378,6 +21391,7 @@ s,@TEMP_STORE@,$TEMP_STORE,;t t
|
|||
s,@BUILD_EXEEXT@,$BUILD_EXEEXT,;t t
|
||||
s,@OS_UNIX@,$OS_UNIX,;t t
|
||||
s,@OS_WIN@,$OS_WIN,;t t
|
||||
s,@OS_OS2@,$OS_OS2,;t t
|
||||
s,@TARGET_EXEEXT@,$TARGET_EXEEXT,;t t
|
||||
s,@TCL_VERSION@,$TCL_VERSION,;t t
|
||||
s,@TCL_BIN_DIR@,$TCL_BIN_DIR,;t t
|
||||
|
|
24
configure.ac
24
configure.ac
|
@ -116,7 +116,7 @@ AC_INIT(src/sqlite.h.in)
|
|||
dnl Put the RCS revision string after AC_INIT so that it will also
|
||||
dnl show in in configure.
|
||||
# The following RCS revision string applies to configure.in
|
||||
# $Revision: 1.25 $
|
||||
# $Revision: 1.26 $
|
||||
|
||||
#########
|
||||
# Programs needed
|
||||
|
@ -407,13 +407,26 @@ else
|
|||
TARGET_EXEEXT=$config_TARGET_EXEEXT
|
||||
fi
|
||||
if test "$TARGET_EXEEXT" = ".exe"; then
|
||||
OS_UNIX=0
|
||||
OS_WIN=1
|
||||
tclsubdir=win
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS -DOS_WIN=1"
|
||||
if test $OS2_SHELL ; then
|
||||
OS_UNIX=0
|
||||
OS_WIN=0
|
||||
OS_OS2=1
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS -DOS_OS2=1"
|
||||
if test "$ac_compiler_gnu" == "yes" ; then
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS -Zomf -Zexe -Zmap"
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -Zomf -Zexe"
|
||||
fi
|
||||
else
|
||||
OS_UNIX=0
|
||||
OS_WIN=1
|
||||
OS_OS2=0
|
||||
tclsubdir=win
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS -DOS_WIN=1"
|
||||
fi
|
||||
else
|
||||
OS_UNIX=1
|
||||
OS_WIN=0
|
||||
OS_OS2=0
|
||||
tclsubdir=unix
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS -DOS_UNIX=1"
|
||||
fi
|
||||
|
@ -421,6 +434,7 @@ fi
|
|||
AC_SUBST(BUILD_EXEEXT)
|
||||
AC_SUBST(OS_UNIX)
|
||||
AC_SUBST(OS_WIN)
|
||||
AC_SUBST(OS_OS2)
|
||||
AC_SUBST(TARGET_EXEEXT)
|
||||
|
||||
##########
|
||||
|
|
7
main.mk
7
main.mk
|
@ -58,7 +58,7 @@ TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src
|
|||
LIBOBJ+= alter.o analyze.o attach.o auth.o btree.o build.o \
|
||||
callback.o complete.o date.o delete.o \
|
||||
expr.o func.o hash.o insert.o \
|
||||
main.o opcodes.o os.o os_unix.o os_win.o \
|
||||
main.o opcodes.o os.o os_os2.o os_unix.o os_win.o \
|
||||
pager.o parse.o pragma.o prepare.o printf.o random.o \
|
||||
select.o table.o tclsqlite.o tokenize.o trigger.o \
|
||||
update.o util.o vacuum.o \
|
||||
|
@ -87,6 +87,7 @@ SRC = \
|
|||
$(TOP)/src/legacy.c \
|
||||
$(TOP)/src/main.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os_os2.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/pager.c \
|
||||
|
@ -124,6 +125,7 @@ TESTSRC = \
|
|||
$(TOP)/src/date.c \
|
||||
$(TOP)/src/func.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os_os2.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/pager.c \
|
||||
|
@ -270,6 +272,9 @@ opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk
|
|||
os.o: $(TOP)/src/os.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/os.c
|
||||
|
||||
os_os2.o: $(TOP)/src/os_os2.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/os_os2.c
|
||||
|
||||
os_unix.o: $(TOP)/src/os_unix.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/os_unix.c
|
||||
|
||||
|
|
24
manifest
24
manifest
|
@ -1,10 +1,10 @@
|
|||
C Do\snot\srecord\sblank\slines\sin\sthe\scommand-line\sediting\shistory\sof\sthe\sshell.\s(CVS\s3197)
|
||||
D 2006-06-03T17:37:26
|
||||
F Makefile.in 5d8dff443383918b700e495de42ec65bc1c8865b
|
||||
C Added\ssupport\sfor\sOS/2.\s\sTicket\s#1817\s(CVS\s3198)
|
||||
D 2006-06-03T18:02:16
|
||||
F Makefile.in 87b6d483513ab8a4e763775bc5b434d6b5c34963
|
||||
F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
F VERSION 2bc3eace6a71bc4f2575679b944378b275e9412c
|
||||
F aclocal.m4 7daea4c35e88de30d5a3f6f7a2ab99720e803bbd
|
||||
F aclocal.m4 a8df0ae21d1ac797fa7d7eaa1703412bc61b973f
|
||||
F addopcodes.awk 701697fae48376375ec8532c3d04e910cfeef352
|
||||
F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248
|
||||
F art/SQLite.eps 9b43cc99cfd2be687d386faea6862ea68d6a72b2
|
||||
|
@ -12,14 +12,14 @@ F art/SQLite.gif 1bbb94484963f1382e27e1c5e86dd0c1061eba2b
|
|||
F art/SQLiteLogo3.tiff b9e6bf022ae939bc986cddb8ab99583ca1b02cb3
|
||||
F config.guess 2103e94b15dc57112d7b9ee152c6fac5288895b4
|
||||
F config.sub 9bf686ec001ae7bc53f5b3563c90c62d4c6d48be
|
||||
F configure d454f3ef3a1cf42e91e97d06c27179d56a77c005 x
|
||||
F configure.ac f6c5246585d14bc1ee1773ae5b71ae6cafa7494a
|
||||
F configure 6be7b37dd811c43f59c119aa5a713f688a2184c4 x
|
||||
F configure.ac 83eaf11869cd893db6126c0ce77381a9cd264bad
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
|
||||
F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
||||
F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
|
||||
F main.mk 33144e8ccfa885a4b0c1c03e85131bd6c541f30c
|
||||
F main.mk e3dd76266d1b62f1835b238bb0565900ab99fe14
|
||||
F mkdll.sh 919df5efde876194e3102c6ebc60657d38949909
|
||||
F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d
|
||||
F mkopcodeh.awk cde995d269aa06c94adbf6455bea0acedb913fa5
|
||||
|
@ -51,8 +51,10 @@ F src/legacy.c fa15d505dd4e45044177ee4d1c6aeaf8c836d390
|
|||
F src/main.c 928d93cfd5d72be3a619ee908182c9432151a99e
|
||||
F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
|
||||
F src/os.c 59f05de8c5777c34876607114a2fbe55ae578235
|
||||
F src/os.h 93035a0e3b9dd05cdd0aaef32ea28ca28e02fe78
|
||||
F src/os.h 46fad85c707ad8643622bab9d894a642940850aa
|
||||
F src/os_common.h 108cd719c96a2b714b64e02aeabbd40684274e6a
|
||||
F src/os_os2.c 123cb394c069bc8c6a305830ffa2bc5f72e5b83a
|
||||
F src/os_os2.h e5f17dd69333632bbc3112881ea407c37d245eb3
|
||||
F src/os_test.c 49833426101f99aee4bb5f6a44b7c4b2029fda1c
|
||||
F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3
|
||||
F src/os_unix.c 17d91581a0ab478a06cb6f257b707a4c4a93e5a7
|
||||
|
@ -356,7 +358,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
|||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
||||
P 4bf03c3bbc1303ed9b4059917e8d6a613b1510f3
|
||||
R b3aa39403a9b5a900b82638a005965c6
|
||||
P 0eabda82cd0d476a7e05ba4b027b819318aef9c3
|
||||
R 6acf85d509c19fb60080d44405f8852c
|
||||
U drh
|
||||
Z eb8ea770aee12d212e5ceb58cc64d4fe
|
||||
Z b6f82a7c0122f6042d20b908e87d0aa6
|
||||
|
|
|
@ -1 +1 @@
|
|||
0eabda82cd0d476a7e05ba4b027b819318aef9c3
|
||||
373246c2d1edaec1ce248ff875db48ce51d896f9
|
40
src/os.h
40
src/os.h
|
@ -27,12 +27,19 @@
|
|||
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
|
||||
# define OS_WIN 1
|
||||
# define OS_UNIX 0
|
||||
# define OS_OS2 0
|
||||
# elif defined(_EMX_) || defined(_OS2) || defined(OS2) || defined(OS_OS2)
|
||||
# define OS_WIN 0
|
||||
# define OS_UNIX 0
|
||||
# define OS_OS2 1
|
||||
# else
|
||||
# define OS_WIN 0
|
||||
# define OS_UNIX 1
|
||||
# define OS_OS2 0
|
||||
# endif
|
||||
# else
|
||||
# define OS_UNIX 0
|
||||
# define OS_OS2 0
|
||||
# endif
|
||||
#else
|
||||
# ifndef OS_WIN
|
||||
|
@ -47,6 +54,14 @@
|
|||
#if OS_WIN
|
||||
# include <windows.h>
|
||||
# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
|
||||
#elif OS_OS2
|
||||
# define INCL_DOSDATETIME
|
||||
# define INCL_DOSFILEMGR
|
||||
# define INCL_DOSERRORS
|
||||
# define INCL_DOSMISC
|
||||
# define INCL_DOSPROCESS
|
||||
# include <os2.h>
|
||||
# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP)
|
||||
#else
|
||||
# define SQLITE_TEMPNAME_SIZE 200
|
||||
#endif
|
||||
|
@ -72,7 +87,7 @@
|
|||
#endif
|
||||
|
||||
/*
|
||||
** Define the interfaces for Unix and for Windows.
|
||||
** Define the interfaces for Unix, Windows, and OS/2.
|
||||
*/
|
||||
#if OS_UNIX
|
||||
#define sqlite3OsOpenReadWrite sqlite3UnixOpenReadWrite
|
||||
|
@ -118,6 +133,29 @@
|
|||
#define sqlite3OsFree sqlite3GenericFree
|
||||
#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
|
||||
#endif
|
||||
#if OS_OS2
|
||||
#define sqlite3OsOpenReadWrite sqlite3Os2OpenReadWrite
|
||||
#define sqlite3OsOpenExclusive sqlite3Os2OpenExclusive
|
||||
#define sqlite3OsOpenReadOnly sqlite3Os2OpenReadOnly
|
||||
#define sqlite3OsDelete sqlite3Os2Delete
|
||||
#define sqlite3OsFileExists sqlite3Os2FileExists
|
||||
#define sqlite3OsFullPathname sqlite3Os2FullPathname
|
||||
#define sqlite3OsIsDirWritable sqlite3Os2IsDirWritable
|
||||
#define sqlite3OsSyncDirectory sqlite3Os2SyncDirectory
|
||||
#define sqlite3OsTempFileName sqlite3Os2TempFileName
|
||||
#define sqlite3OsRandomSeed sqlite3Os2RandomSeed
|
||||
#define sqlite3OsSleep sqlite3Os2Sleep
|
||||
#define sqlite3OsCurrentTime sqlite3Os2CurrentTime
|
||||
#define sqlite3OsEnterMutex sqlite3Os2EnterMutex
|
||||
#define sqlite3OsLeaveMutex sqlite3Os2LeaveMutex
|
||||
#define sqlite3OsInMutex sqlite3Os2InMutex
|
||||
#define sqlite3OsThreadSpecificData sqlite3Os2ThreadSpecificData
|
||||
#define sqlite3OsMalloc sqlite3GenericMalloc
|
||||
#define sqlite3OsRealloc sqlite3GenericRealloc
|
||||
#define sqlite3OsFree sqlite3GenericFree
|
||||
#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** If using an alternative OS interface, then we must have an "os_other.h"
|
||||
|
|
|
@ -0,0 +1,965 @@
|
|||
/*
|
||||
** 2006 Feb 14
|
||||
**
|
||||
** 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 OS/2.
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
|
||||
#if OS_OS2
|
||||
|
||||
/*
|
||||
** Macros used to determine whether or not to use threads.
|
||||
*/
|
||||
#if defined(THREADSAFE) && THREADSAFE
|
||||
# define SQLITE_OS2_THREADS 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Include code that is common to all os_*.c files
|
||||
*/
|
||||
#include "os_common.h"
|
||||
|
||||
/*
|
||||
** The os2File structure is subclass of OsFile specific for the OS/2
|
||||
** protability layer.
|
||||
*/
|
||||
typedef struct os2File os2File;
|
||||
struct os2File {
|
||||
IoMethod const *pMethod; /* Always the first entry */
|
||||
HFILE h; /* Handle for accessing the file */
|
||||
int delOnClose; /* True if file is to be deleted on close */
|
||||
char* pathToDel; /* Name of file to delete on close */
|
||||
unsigned char locktype; /* Type of lock currently held on this file */
|
||||
};
|
||||
|
||||
/*
|
||||
** Do not include any of the File I/O interface procedures if the
|
||||
** SQLITE_OMIT_DISKIO macro is defined (indicating that there database
|
||||
** will be in-memory only)
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DISKIO
|
||||
|
||||
/*
|
||||
** Delete the named file
|
||||
*/
|
||||
int sqlite3Os2Delete( const char *zFilename ){
|
||||
DosDelete( (PSZ)zFilename );
|
||||
TRACE2( "DELETE \"%s\"\n", zFilename );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the named file exists.
|
||||
*/
|
||||
int sqlite3Os2FileExists( const char *zFilename ){
|
||||
FILESTATUS3 fsts3ConfigInfo;
|
||||
memset(&fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo));
|
||||
return DosQueryPathInfo( (PSZ)zFilename, FIL_STANDARD,
|
||||
&fsts3ConfigInfo, sizeof(FILESTATUS3) ) == NO_ERROR;
|
||||
}
|
||||
|
||||
/* Forward declaration */
|
||||
int allocateOs2File( os2File *pInit, OsFile **pld );
|
||||
|
||||
/*
|
||||
** 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 sqlite3Os2OpenReadWrite(
|
||||
const char *zFilename,
|
||||
OsFile **pld,
|
||||
int *pReadonly
|
||||
){
|
||||
os2File f;
|
||||
HFILE hf;
|
||||
ULONG ulAction;
|
||||
APIRET rc;
|
||||
|
||||
assert( *pld == 0 );
|
||||
rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L,
|
||||
FILE_ARCHIVED | FILE_NORMAL,
|
||||
OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
|
||||
OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
|
||||
OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, (PEAOP2)NULL );
|
||||
if( rc != NO_ERROR ){
|
||||
rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L,
|
||||
FILE_ARCHIVED | FILE_NORMAL,
|
||||
OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
|
||||
OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
|
||||
OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY, (PEAOP2)NULL );
|
||||
if( rc != NO_ERROR ){
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
*pReadonly = 1;
|
||||
}
|
||||
else{
|
||||
*pReadonly = 0;
|
||||
}
|
||||
f.h = hf;
|
||||
f.locktype = NO_LOCK;
|
||||
f.delOnClose = 0;
|
||||
f.pathToDel = NULL;
|
||||
OpenCounter(+1);
|
||||
TRACE3( "OPEN R/W %d \"%s\"\n", hf, zFilename );
|
||||
return allocateOs2File( &f, pld );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** 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 sqlite3Os2OpenExclusive( const char *zFilename, OsFile **pld, int delFlag ){
|
||||
os2File f;
|
||||
HFILE hf;
|
||||
ULONG ulAction;
|
||||
APIRET rc;
|
||||
|
||||
assert( *pld == 0 );
|
||||
rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L, FILE_NORMAL,
|
||||
OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS,
|
||||
OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
|
||||
OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, (PEAOP2)NULL );
|
||||
if( rc != NO_ERROR ){
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
|
||||
f.h = hf;
|
||||
f.locktype = NO_LOCK;
|
||||
f.delOnClose = delFlag ? 1 : 0;
|
||||
f.pathToDel = delFlag ? sqlite3OsFullPathname( zFilename ) : NULL;
|
||||
OpenCounter( +1 );
|
||||
if( delFlag ) DosForceDelete( sqlite3OsFullPathname( zFilename ) );
|
||||
TRACE3( "OPEN EX %d \"%s\"\n", hf, sqlite3OsFullPathname ( zFilename ) );
|
||||
return allocateOs2File( &f, pld );
|
||||
}
|
||||
|
||||
/*
|
||||
** 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 sqlite3Os2OpenReadOnly( const char *zFilename, OsFile **pld ){
|
||||
os2File f;
|
||||
HFILE hf;
|
||||
ULONG ulAction;
|
||||
APIRET rc;
|
||||
|
||||
assert( *pld == 0 );
|
||||
rc = DosOpen( (PSZ)zFilename, &hf, &ulAction, 0L,
|
||||
FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
|
||||
OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_RANDOM |
|
||||
OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY, (PEAOP2)NULL );
|
||||
if( rc != NO_ERROR ){
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
f.h = hf;
|
||||
f.locktype = NO_LOCK;
|
||||
f.delOnClose = 0;
|
||||
f.pathToDel = NULL;
|
||||
OpenCounter( +1 );
|
||||
TRACE3( "OPEN RO %d \"%s\"\n", hf, zFilename );
|
||||
return allocateOs2File( &f, pld );
|
||||
}
|
||||
|
||||
/*
|
||||
** 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
|
||||
** OS/2 since OS/2 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 os2OpenDirectory(
|
||||
OsFile *id,
|
||||
const char *zDirname
|
||||
){
|
||||
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 sqlite3Os2TempFileName( char *zBuf ){
|
||||
static const unsigned char zChars[] =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
int i, j;
|
||||
PSZ zTempPath = 0;
|
||||
if( DosScanEnv( "TEMP", &zTempPath ) ){
|
||||
if( DosScanEnv( "TMP", &zTempPath ) ){
|
||||
if( DosScanEnv( "TMPDIR", &zTempPath ) ){
|
||||
ULONG ulDriveNum = 0, ulDriveMap = 0;
|
||||
DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap );
|
||||
sprintf( zTempPath, "%c:", (char)( 'A' + ulDriveNum - 1 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
for(;;){
|
||||
sprintf( zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath );
|
||||
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;
|
||||
if( !sqlite3OsFileExists( zBuf ) ) break;
|
||||
}
|
||||
TRACE2( "TEMP FILENAME: %s\n", zBuf );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close a file.
|
||||
*/
|
||||
int os2Close( OsFile **pld ){
|
||||
os2File *pFile;
|
||||
if( pld && (pFile = (os2File*)*pld)!=0 ){
|
||||
TRACE2( "CLOSE %d\n", pFile->h );
|
||||
DosClose( pFile->h );
|
||||
pFile->locktype = NO_LOCK;
|
||||
if( pFile->delOnClose != 0 ){
|
||||
DosForceDelete( pFile->pathToDel );
|
||||
}
|
||||
*pld = 0;
|
||||
OpenCounter( -1 );
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** 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 os2Read( OsFile *id, void *pBuf, int amt ){
|
||||
ULONG got;
|
||||
assert( id!=0 );
|
||||
SimulateIOError( SQLITE_IOERR );
|
||||
TRACE3( "READ %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
|
||||
DosRead( ((os2File*)id)->h, pBuf, amt, &got );
|
||||
return (got == (ULONG)amt) ? SQLITE_OK : SQLITE_IOERR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Write data from a buffer into a file. Return SQLITE_OK on success
|
||||
** or some other error code on failure.
|
||||
*/
|
||||
int os2Write( OsFile *id, const void *pBuf, int amt ){
|
||||
APIRET rc=NO_ERROR;
|
||||
ULONG wrote;
|
||||
assert( id!=0 );
|
||||
SimulateIOError( SQLITE_IOERR );
|
||||
SimulateDiskfullError;
|
||||
TRACE3( "WRITE %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
|
||||
while( amt > 0 &&
|
||||
(rc = DosWrite( ((os2File*)id)->h, (PVOID)pBuf, amt, &wrote )) && wrote > 0 ){
|
||||
amt -= wrote;
|
||||
pBuf = &((char*)pBuf)[wrote];
|
||||
}
|
||||
|
||||
return ( rc != NO_ERROR || amt > (int)wrote ) ? SQLITE_FULL : SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Move the read/write pointer in a file.
|
||||
*/
|
||||
int os2Seek( OsFile *id, i64 offset ){
|
||||
APIRET rc;
|
||||
ULONG filePointer = 0L;
|
||||
assert( id!=0 );
|
||||
rc = DosSetFilePtr( ((os2File*)id)->h, offset, FILE_BEGIN, &filePointer );
|
||||
TRACE3( "SEEK %d %lld\n", ((os2File*)id)->h, offset );
|
||||
return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Make sure all writes to a particular file are committed to disk.
|
||||
*/
|
||||
int os2Sync( OsFile *id, int dataOnly ){
|
||||
assert( id!=0 );
|
||||
TRACE3( "SYNC %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
|
||||
return DosResetBuffer( ((os2File*)id)->h ) ? SQLITE_IOERR : SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sync the directory zDirname. This is a no-op on operating systems other
|
||||
** than UNIX.
|
||||
*/
|
||||
int sqlite3Os2SyncDirectory( const char *zDirname ){
|
||||
SimulateIOError( SQLITE_IOERR );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Truncate an open file to a specified size
|
||||
*/
|
||||
int os2Truncate( OsFile *id, i64 nByte ){
|
||||
APIRET rc;
|
||||
ULONG upperBits = nByte>>32;
|
||||
assert( id!=0 );
|
||||
TRACE3( "TRUNCATE %d %lld\n", ((os2File*)id)->h, nByte );
|
||||
SimulateIOError( SQLITE_IOERR );
|
||||
rc = DosSetFilePtr( ((os2File*)id)->h, nByte, FILE_BEGIN, &upperBits );
|
||||
if( rc != NO_ERROR ){
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
rc = DosSetFilePtr( ((os2File*)id)->h, 0L, FILE_END, &upperBits );
|
||||
return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Determine the current size of a file in bytes
|
||||
*/
|
||||
int os2FileSize( OsFile *id, i64 *pSize ){
|
||||
APIRET rc;
|
||||
FILESTATUS3 fsts3FileInfo;
|
||||
memset(&fsts3FileInfo, 0, sizeof(fsts3FileInfo));
|
||||
assert( id!=0 );
|
||||
SimulateIOError( SQLITE_IOERR );
|
||||
rc = DosQueryFileInfo( ((os2File*)id)->h, FIL_STANDARD, &fsts3FileInfo, sizeof(FILESTATUS3) );
|
||||
if( rc == NO_ERROR ){
|
||||
*pSize = fsts3FileInfo.cbFile;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
else{
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Acquire a reader lock.
|
||||
*/
|
||||
static int getReadLock( os2File *id ){
|
||||
FILELOCK LockArea,
|
||||
UnlockArea;
|
||||
memset(&LockArea, 0, sizeof(LockArea));
|
||||
memset(&UnlockArea, 0, sizeof(UnlockArea));
|
||||
LockArea.lOffset = SHARED_FIRST;
|
||||
LockArea.lRange = SHARED_SIZE;
|
||||
UnlockArea.lOffset = 0L;
|
||||
UnlockArea.lRange = 0L;
|
||||
return DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L );
|
||||
}
|
||||
|
||||
/*
|
||||
** Undo a readlock
|
||||
*/
|
||||
static int unlockReadLock( os2File *id ){
|
||||
FILELOCK LockArea,
|
||||
UnlockArea;
|
||||
memset(&LockArea, 0, sizeof(LockArea));
|
||||
memset(&UnlockArea, 0, sizeof(UnlockArea));
|
||||
LockArea.lOffset = 0L;
|
||||
LockArea.lRange = 0L;
|
||||
UnlockArea.lOffset = SHARED_FIRST;
|
||||
UnlockArea.lRange = SHARED_SIZE;
|
||||
return DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L );
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
|
||||
/*
|
||||
** Check that a given pathname is a directory and is writable
|
||||
**
|
||||
*/
|
||||
int sqlite3Os2IsDirWritable( char *zDirname ){
|
||||
FILESTATUS3 fsts3ConfigInfo;
|
||||
APIRET rc = NO_ERROR;
|
||||
memset(&fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo));
|
||||
if( zDirname==0 ) return 0;
|
||||
if( strlen(zDirname)>CCHMAXPATH ) return 0;
|
||||
rc = DosQueryPathInfo( (PSZ)zDirname, FIL_STANDARD, &fsts3ConfigInfo, sizeof(FILESTATUS3) );
|
||||
if( rc != NO_ERROR ) return 0;
|
||||
if( (fsts3ConfigInfo.attrFile & FILE_DIRECTORY) != FILE_DIRECTORY ) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
|
||||
|
||||
/*
|
||||
** Lock the file with the lock specified by parameter locktype - one
|
||||
** of the following:
|
||||
**
|
||||
** (1) SHARED_LOCK
|
||||
** (2) RESERVED_LOCK
|
||||
** (3) PENDING_LOCK
|
||||
** (4) EXCLUSIVE_LOCK
|
||||
**
|
||||
** Sometimes when requesting one lock state, additional lock states
|
||||
** are inserted in between. The locking might fail on one of the later
|
||||
** transitions leaving the lock state different from what it started but
|
||||
** still short of its goal. The following chart shows the allowed
|
||||
** transitions and the inserted intermediate states:
|
||||
**
|
||||
** UNLOCKED -> SHARED
|
||||
** SHARED -> RESERVED
|
||||
** SHARED -> (PENDING) -> EXCLUSIVE
|
||||
** RESERVED -> (PENDING) -> EXCLUSIVE
|
||||
** PENDING -> EXCLUSIVE
|
||||
**
|
||||
** This routine will only increase a lock. The os2Unlock() routine
|
||||
** erases all locks at once and returns us immediately to locking level 0.
|
||||
** It is not possible to lower the locking level one step at a time. You
|
||||
** must go straight to locking level 0.
|
||||
*/
|
||||
int os2Lock( OsFile *id, int locktype ){
|
||||
APIRET rc = SQLITE_OK; /* Return code from subroutines */
|
||||
APIRET res = 1; /* Result of a windows lock call */
|
||||
int newLocktype; /* Set id->locktype to this value before exiting */
|
||||
int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
|
||||
FILELOCK LockArea,
|
||||
UnlockArea;
|
||||
os2File *pFile = (os2File*)id;
|
||||
memset(&LockArea, 0, sizeof(LockArea));
|
||||
memset(&UnlockArea, 0, sizeof(UnlockArea));
|
||||
assert( pFile!=0 );
|
||||
TRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype );
|
||||
|
||||
/* If there is already a lock of this type or more restrictive on the
|
||||
** OsFile, do nothing. Don't use the end_lock: exit path, as
|
||||
** sqlite3OsEnterMutex() hasn't been called yet.
|
||||
*/
|
||||
if( pFile->locktype>=locktype ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Make sure the locking sequence is correct
|
||||
*/
|
||||
assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
|
||||
assert( locktype!=PENDING_LOCK );
|
||||
assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
|
||||
|
||||
/* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
|
||||
** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
|
||||
** the PENDING_LOCK byte is temporary.
|
||||
*/
|
||||
newLocktype = pFile->locktype;
|
||||
if( pFile->locktype==NO_LOCK
|
||||
|| (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
|
||||
){
|
||||
int cnt = 3;
|
||||
|
||||
LockArea.lOffset = PENDING_BYTE;
|
||||
LockArea.lRange = 1L;
|
||||
UnlockArea.lOffset = 0L;
|
||||
UnlockArea.lRange = 0L;
|
||||
|
||||
while( cnt-->0 && (res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L) )!=NO_ERROR ){
|
||||
/* Try 3 times to get the pending lock. The pending lock might be
|
||||
** held by another reader process who will release it momentarily.
|
||||
*/
|
||||
TRACE2( "could not get a PENDING lock. cnt=%d\n", cnt );
|
||||
DosSleep(1);
|
||||
}
|
||||
gotPendingLock = res;
|
||||
}
|
||||
|
||||
/* Acquire a shared lock
|
||||
*/
|
||||
if( locktype==SHARED_LOCK && res ){
|
||||
assert( pFile->locktype==NO_LOCK );
|
||||
res = getReadLock(pFile);
|
||||
if( res == NO_ERROR ){
|
||||
newLocktype = SHARED_LOCK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Acquire a RESERVED lock
|
||||
*/
|
||||
if( locktype==RESERVED_LOCK && res ){
|
||||
assert( pFile->locktype==SHARED_LOCK );
|
||||
LockArea.lOffset = RESERVED_BYTE;
|
||||
LockArea.lRange = 1L;
|
||||
UnlockArea.lOffset = 0L;
|
||||
UnlockArea.lRange = 0L;
|
||||
res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
|
||||
if( res == NO_ERROR ){
|
||||
newLocktype = RESERVED_LOCK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Acquire a PENDING lock
|
||||
*/
|
||||
if( locktype==EXCLUSIVE_LOCK && res ){
|
||||
newLocktype = PENDING_LOCK;
|
||||
gotPendingLock = 0;
|
||||
}
|
||||
|
||||
/* Acquire an EXCLUSIVE lock
|
||||
*/
|
||||
if( locktype==EXCLUSIVE_LOCK && res ){
|
||||
assert( pFile->locktype>=SHARED_LOCK );
|
||||
res = unlockReadLock(pFile);
|
||||
TRACE2( "unreadlock = %d\n", res );
|
||||
LockArea.lOffset = SHARED_FIRST;
|
||||
LockArea.lRange = SHARED_SIZE;
|
||||
UnlockArea.lOffset = 0L;
|
||||
UnlockArea.lRange = 0L;
|
||||
res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
|
||||
if( res == NO_ERROR ){
|
||||
newLocktype = EXCLUSIVE_LOCK;
|
||||
}else{
|
||||
TRACE2( "error-code = %d\n", res );
|
||||
}
|
||||
}
|
||||
|
||||
/* If we are holding a PENDING lock that ought to be released, then
|
||||
** release it now.
|
||||
*/
|
||||
if( gotPendingLock && locktype==SHARED_LOCK ){
|
||||
LockArea.lOffset = 0L;
|
||||
LockArea.lRange = 0L;
|
||||
UnlockArea.lOffset = PENDING_BYTE;
|
||||
UnlockArea.lRange = 1L;
|
||||
DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
|
||||
}
|
||||
|
||||
/* Update the state of the lock has held in the file descriptor then
|
||||
** return the appropriate result code.
|
||||
*/
|
||||
if( res == NO_ERROR ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
TRACE4( "LOCK FAILED %d trying for %d but got %d\n", pFile->h,
|
||||
locktype, newLocktype );
|
||||
rc = SQLITE_BUSY;
|
||||
}
|
||||
pFile->locktype = newLocktype;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine checks if there is a RESERVED lock held on the specified
|
||||
** file by this or any other process. If such a lock is held, return
|
||||
** non-zero, otherwise zero.
|
||||
*/
|
||||
int os2CheckReservedLock( OsFile *id ){
|
||||
APIRET rc;
|
||||
os2File *pFile = (os2File*)id;
|
||||
assert( pFile!=0 );
|
||||
if( pFile->locktype>=RESERVED_LOCK ){
|
||||
rc = 1;
|
||||
TRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, rc );
|
||||
}else{
|
||||
FILELOCK LockArea,
|
||||
UnlockArea;
|
||||
memset(&LockArea, 0, sizeof(LockArea));
|
||||
memset(&UnlockArea, 0, sizeof(UnlockArea));
|
||||
LockArea.lOffset = RESERVED_BYTE;
|
||||
LockArea.lRange = 1L;
|
||||
UnlockArea.lOffset = 0L;
|
||||
UnlockArea.lRange = 0L;
|
||||
rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
|
||||
if( rc == NO_ERROR ){
|
||||
LockArea.lOffset = 0L;
|
||||
LockArea.lRange = 0L;
|
||||
UnlockArea.lOffset = RESERVED_BYTE;
|
||||
UnlockArea.lRange = 1L;
|
||||
rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
|
||||
}
|
||||
TRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, rc );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Lower the locking level on file descriptor id to locktype. locktype
|
||||
** must be either NO_LOCK or SHARED_LOCK.
|
||||
**
|
||||
** If the locking level of the file descriptor is already at or below
|
||||
** the requested locking level, this routine is a no-op.
|
||||
**
|
||||
** It is not possible for this routine to fail if the second argument
|
||||
** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
|
||||
** might return SQLITE_IOERR;
|
||||
*/
|
||||
int os2Unlock( OsFile *id, int locktype ){
|
||||
int type;
|
||||
APIRET rc = SQLITE_OK;
|
||||
os2File *pFile = (os2File*)id;
|
||||
FILELOCK LockArea,
|
||||
UnlockArea;
|
||||
memset(&LockArea, 0, sizeof(LockArea));
|
||||
memset(&UnlockArea, 0, sizeof(UnlockArea));
|
||||
assert( pFile!=0 );
|
||||
assert( locktype<=SHARED_LOCK );
|
||||
TRACE4( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype );
|
||||
type = pFile->locktype;
|
||||
if( type>=EXCLUSIVE_LOCK ){
|
||||
LockArea.lOffset = 0L;
|
||||
LockArea.lRange = 0L;
|
||||
UnlockArea.lOffset = SHARED_FIRST;
|
||||
UnlockArea.lRange = SHARED_SIZE;
|
||||
DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
|
||||
if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){
|
||||
/* This should never happen. We should always be able to
|
||||
** reacquire the read lock */
|
||||
rc = SQLITE_IOERR;
|
||||
}
|
||||
}
|
||||
if( type>=RESERVED_LOCK ){
|
||||
LockArea.lOffset = 0L;
|
||||
LockArea.lRange = 0L;
|
||||
UnlockArea.lOffset = RESERVED_BYTE;
|
||||
UnlockArea.lRange = 1L;
|
||||
DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
|
||||
}
|
||||
if( locktype==NO_LOCK && type>=SHARED_LOCK ){
|
||||
unlockReadLock(pFile);
|
||||
}
|
||||
if( type>=PENDING_LOCK ){
|
||||
LockArea.lOffset = 0L;
|
||||
LockArea.lRange = 0L;
|
||||
UnlockArea.lOffset = PENDING_BYTE;
|
||||
UnlockArea.lRange = 1L;
|
||||
DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
|
||||
}
|
||||
pFile->locktype = locktype;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** 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 *sqlite3Os2FullPathname( const char *zRelative ){
|
||||
char *zFull = 0;
|
||||
if( strchr(zRelative, ':') ){
|
||||
sqlite3SetString( &zFull, zRelative, (char*)0 );
|
||||
}else{
|
||||
char zBuff[SQLITE_TEMPNAME_SIZE - 2] = {0};
|
||||
char zDrive[1] = {0};
|
||||
ULONG cbzFullLen = SQLITE_TEMPNAME_SIZE;
|
||||
ULONG ulDriveNum = 0;
|
||||
ULONG ulDriveMap = 0;
|
||||
DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap );
|
||||
DosQueryCurrentDir( 0L, zBuff, &cbzFullLen );
|
||||
zFull = sqliteMalloc( cbzFullLen );
|
||||
sprintf( zDrive, "%c", (char)('A' + ulDriveNum - 1) );
|
||||
sqlite3SetString( &zFull, zDrive, ":\\", zBuff, "\\", zRelative, (char*)0 );
|
||||
}
|
||||
return zFull;
|
||||
}
|
||||
|
||||
/*
|
||||
** The fullSync option is meaningless on os2, or correct me if I'm wrong. This is a no-op.
|
||||
** From os_unix.c: Change the value of the fullsync flag in the given file descriptor.
|
||||
** From os_unix.c: ((unixFile*)id)->fullSync = v;
|
||||
*/
|
||||
static void os2SetFullSync( OsFile *id, int v ){
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the underlying file handle for an OsFile
|
||||
*/
|
||||
static int os2FileHandle( OsFile *id ){
|
||||
return (int)((os2File*)id)->h;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return an integer that indices the type of lock currently held
|
||||
** by this handle. (Used for testing and analysis only.)
|
||||
*/
|
||||
static int os2LockState( OsFile *id ){
|
||||
return ((os2File*)id)->locktype;
|
||||
}
|
||||
|
||||
/*
|
||||
** This vector defines all the methods that can operate on an OsFile
|
||||
** for os2.
|
||||
*/
|
||||
static const IoMethod sqlite3Os2IoMethod = {
|
||||
os2Close,
|
||||
os2OpenDirectory,
|
||||
os2Read,
|
||||
os2Write,
|
||||
os2Seek,
|
||||
os2Truncate,
|
||||
os2Sync,
|
||||
os2SetFullSync,
|
||||
os2FileHandle,
|
||||
os2FileSize,
|
||||
os2Lock,
|
||||
os2Unlock,
|
||||
os2LockState,
|
||||
os2CheckReservedLock,
|
||||
};
|
||||
|
||||
/*
|
||||
** Allocate memory for an OsFile. Initialize the new OsFile
|
||||
** to the value given in pInit and return a pointer to the new
|
||||
** OsFile. If we run out of memory, close the file and return NULL.
|
||||
*/
|
||||
int allocateOs2File( os2File *pInit, OsFile **pld ){
|
||||
os2File *pNew;
|
||||
pNew = sqliteMalloc( sizeof(*pNew) );
|
||||
if( pNew==0 ){
|
||||
DosClose( pInit->h );
|
||||
*pld = 0;
|
||||
return SQLITE_NOMEM;
|
||||
}else{
|
||||
*pNew = *pInit;
|
||||
pNew->pMethod = &sqlite3Os2IoMethod;
|
||||
pNew->locktype = NO_LOCK;
|
||||
*pld = (OsFile*)pNew;
|
||||
OpenCounter(+1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SQLITE_OMIT_DISKIO */
|
||||
/***************************************************************************
|
||||
** Everything above deals with file I/O. Everything that follows deals
|
||||
** with other miscellanous aspects of the operating system interface
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
** 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 sqlite3Os2RandomSeed( 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 );
|
||||
DosGetDateTime( (PDATETIME)zBuf );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sleep for a little while. Return the amount of time slept.
|
||||
*/
|
||||
int sqlite3Os2Sleep( int ms ){
|
||||
DosSleep( ms );
|
||||
return ms;
|
||||
}
|
||||
|
||||
/*
|
||||
** Static variables used for thread synchronization
|
||||
*/
|
||||
static int inMutex = 0;
|
||||
#ifdef SQLITE_OS2_THREADS
|
||||
static ULONG mutexOwner;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The following pair of routines 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 sqlite3Os2EnterMutex(){
|
||||
PTIB ptib;
|
||||
#ifdef SQLITE_OS2_THREADS
|
||||
DosEnterCritSec();
|
||||
DosGetInfoBlocks( &ptib, NULL );
|
||||
mutexOwner = ptib->tib_ptib2->tib2_ultid;
|
||||
#endif
|
||||
assert( !inMutex );
|
||||
inMutex = 1;
|
||||
}
|
||||
void sqlite3Os2LeaveMutex(){
|
||||
PTIB ptib;
|
||||
assert( inMutex );
|
||||
inMutex = 0;
|
||||
#ifdef SQLITE_OS2_THREADS
|
||||
DosGetInfoBlocks( &ptib, NULL );
|
||||
assert( mutexOwner == ptib->tib_ptib2->tib2_ultid );
|
||||
DosExitCritSec();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the mutex is currently held.
|
||||
**
|
||||
** If the thisThreadOnly parameter is true, return true if and only if the
|
||||
** calling thread holds the mutex. If the parameter is false, return
|
||||
** true if any thread holds the mutex.
|
||||
*/
|
||||
int sqlite3Os2InMutex( int thisThreadOnly ){
|
||||
#ifdef SQLITE_OS2_THREADS
|
||||
PTIB ptib;
|
||||
DosGetInfoBlocks( &ptib, NULL );
|
||||
return inMutex>0 && (thisThreadOnly==0 || mutexOwner==ptib->tib_ptib2->tib2_ultid);
|
||||
#else
|
||||
return inMutex>0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** 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 sqlite3Os2CurrentTime( double *prNow ){
|
||||
double now;
|
||||
USHORT second, minute, hour,
|
||||
day, month, year;
|
||||
DATETIME dt;
|
||||
DosGetDateTime( &dt );
|
||||
second = (USHORT)dt.seconds;
|
||||
minute = (USHORT)dt.minutes + dt.timezone;
|
||||
hour = (USHORT)dt.hours;
|
||||
day = (USHORT)dt.day;
|
||||
month = (USHORT)dt.month;
|
||||
year = (USHORT)dt.year;
|
||||
|
||||
/* Calculations from http://www.astro.keele.ac.uk/~rno/Astronomy/hjd.html
|
||||
http://www.astro.keele.ac.uk/~rno/Astronomy/hjd-0.1.c */
|
||||
/* Calculate the Julian days */
|
||||
now = day - 32076 +
|
||||
1461*(year + 4800 + (month - 14)/12)/4 +
|
||||
367*(month - 2 - (month - 14)/12*12)/12 -
|
||||
3*((year + 4900 + (month - 14)/12)/100)/4;
|
||||
|
||||
/* Add the fractional hours, mins and seconds */
|
||||
now += (hour + 12.0)/24.0;
|
||||
now += minute/1440.0;
|
||||
now += second/86400.0;
|
||||
*prNow = now;
|
||||
#ifdef SQLITE_TEST
|
||||
if( sqlite3_current_time ){
|
||||
*prNow = sqlite3_current_time/86400.0 + 2440587.5;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Remember the number of thread-specific-data blocks allocated.
|
||||
** Use this to verify that we are not leaking thread-specific-data.
|
||||
** Ticket #1601
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3_tsd_count = 0;
|
||||
# define TSD_COUNTER_INCR InterlockedIncrement( &sqlite3_tsd_count )
|
||||
# define TSD_COUNTER_DECR InterlockedDecrement( &sqlite3_tsd_count )
|
||||
#else
|
||||
# define TSD_COUNTER_INCR /* no-op */
|
||||
# define TSD_COUNTER_DECR /* no-op */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** If called with allocateFlag>1, then return a pointer to thread
|
||||
** specific data for the current thread. Allocate and zero the
|
||||
** thread-specific data if it does not already exist necessary.
|
||||
**
|
||||
** If called with allocateFlag==0, then check the current thread
|
||||
** specific data. Return it if it exists. If it does not exist,
|
||||
** then return NULL.
|
||||
**
|
||||
** If called with allocateFlag<0, check to see if the thread specific
|
||||
** data is allocated and is all zero. If it is then deallocate it.
|
||||
** Return a pointer to the thread specific data or NULL if it is
|
||||
** unallocated or gets deallocated.
|
||||
*/
|
||||
ThreadData *sqlite3Os2ThreadSpecificData( int allocateFlag ){
|
||||
static ThreadData **s_ppTsd = NULL;
|
||||
static const ThreadData zeroData = {0, 0, 0};
|
||||
ThreadData *pTsd;
|
||||
|
||||
if( !s_ppTsd ){
|
||||
sqlite3OsEnterMutex();
|
||||
if( !s_ppTsd ){
|
||||
PULONG pul;
|
||||
APIRET rc = DosAllocThreadLocalMemory(1, &pul);
|
||||
if( rc != NO_ERROR ){
|
||||
sqlite3OsLeaveMutex();
|
||||
return 0;
|
||||
}
|
||||
s_ppTsd = (ThreadData **)pul;
|
||||
}
|
||||
sqlite3OsLeaveMutex();
|
||||
}
|
||||
pTsd = *s_ppTsd;
|
||||
if( allocateFlag>0 ){
|
||||
if( !pTsd ){
|
||||
pTsd = sqlite3OsMalloc( sizeof(zeroData) );
|
||||
if( pTsd ){
|
||||
*pTsd = zeroData;
|
||||
*s_ppTsd = pTsd;
|
||||
TSD_COUNTER_INCR;
|
||||
}
|
||||
}
|
||||
}else if( pTsd!=0 && allocateFlag<0
|
||||
&& memcmp( pTsd, &zeroData, sizeof(ThreadData) )==0 ){
|
||||
sqlite3OsFree(pTsd);
|
||||
*s_ppTsd = NULL;
|
||||
TSD_COUNTER_DECR;
|
||||
pTsd = 0;
|
||||
}
|
||||
return pTsd;
|
||||
}
|
||||
#endif /* OS_OS2 */
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
** 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>
|
||||
|
||||
/*
|
||||
** 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.
|
||||
*/
|
||||
/* this mutex implementation only available with EMX */
|
||||
#if defined(THREADSAFE) && THREADSAFE
|
||||
# include <sys/builtin.h>
|
||||
# include <sys/smutex.h>
|
||||
# define SQLITE_OS2_THREADS 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** 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 {
|
||||
int 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
|
||||
|
||||
#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
|
||||
# define SQLITE_DEFAULT_FILE_PERMISSIONS 0600
|
||||
#endif
|
||||
|
||||
#endif /* _SQLITE_OS_OS2_H_ */
|
Loading…
Reference in New Issue