/ Check-in [373246c2]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Added support for OS/2. Ticket #1817 (CVS 3198)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:373246c2d1edaec1ce248ff875db48ce51d896f9
User & Date: drh 2006-06-03 18:02:16
Context
2006-06-03
18:04
Remove unused variables from vdbe.c. (CVS 3199) check-in: d54750ae user: drh tags: trunk
18:02
Added support for OS/2. Ticket #1817 (CVS 3198) check-in: 373246c2 user: drh tags: trunk
17:37
Do not record blank lines in the command-line editing history of the shell. (CVS 3197) check-in: 0eabda82 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Makefile.in.

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
...
152
153
154
155
156
157
158

159
160
161
162
163
164
165
...
189
190
191
192
193
194
195

196
197
198
199
200
201
202
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
...
347
348
349
350
351
352
353



354
355
356
357
358
359
360
TCC += -DSQLITE_OMIT_CURSOR

# Object files for the SQLite library.
#
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 \
         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 \
         vdbe.lo vdbeapi.lo vdbeaux.lo vdbefifo.lo vdbemem.lo \
         where.lo utf.lo legacy.lo

# All of the source code files.
................................................................................
  $(TOP)/src/hash.h \
  $(TOP)/src/insert.c \
  $(TOP)/src/legacy.c \
  $(TOP)/src/main.c \
  $(TOP)/src/os.c \
  $(TOP)/src/os_unix.c \
  $(TOP)/src/os_win.c \

  $(TOP)/src/pager.c \
  $(TOP)/src/pager.h \
  $(TOP)/src/parse.y \
  $(TOP)/src/pragma.c \
  $(TOP)/src/prepare.c \
  $(TOP)/src/printf.c \
  $(TOP)/src/random.c \
................................................................................
TESTSRC = \
  $(TOP)/src/btree.c \
  $(TOP)/src/date.c \
  $(TOP)/src/func.c \
  $(TOP)/src/os.c \
  $(TOP)/src/os_unix.c \
  $(TOP)/src/os_win.c \

  $(TOP)/src/pager.c \
  $(TOP)/src/pragma.c \
  $(TOP)/src/printf.c \
  $(TOP)/src/test1.c \
  $(TOP)/src/test2.c \
  $(TOP)/src/test3.c \
  $(TOP)/src/test4.c \
................................................................................
	$(LTLINK) -o libtclsqlite3.la tclsqlite.lo \
		$(LIBOBJ) @TCL_STUB_LIB_SPEC@ $(LIBPTHREAD) \
                -rpath $(libdir)/sqlite \
		-version-info "8:6:8"

sqlite3$(TEXE):	$(TOP)/src/shell.c libsqlite3.la sqlite3.h
	$(LTLINK) $(READLINE_FLAGS) $(LIBPTHREAD) \
		-o sqlite3 $(TOP)/src/shell.c libsqlite3.la \
		$(LIBREADLINE) $(TLIBS)

# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
# build on the target system.  Some of the C source code and header
# files are automatically generated.  This target takes care of
# all that automatic generation.
................................................................................
	$(LTCOMPILE) -c $(TOP)/src/os.c

os_unix.lo:	$(TOP)/src/os_unix.c $(HDR)
	$(LTCOMPILE) -c $(TOP)/src/os_unix.c

os_win.lo:	$(TOP)/src/os_win.c $(HDR)
	$(LTCOMPILE) -c $(TOP)/src/os_win.c




parse.lo:	parse.c $(HDR)
	$(LTCOMPILE) -c parse.c

parse.h:	parse.c

parse.c:	$(TOP)/src/parse.y lemon$(BEXE) $(TOP)/addopcodes.awk







|







 







>







 







>







 







|







 







>
>
>







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
...
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
TCC += -DSQLITE_OMIT_CURSOR

# Object files for the SQLite library.
#
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 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 \
         vdbe.lo vdbeapi.lo vdbeaux.lo vdbefifo.lo vdbemem.lo \
         where.lo utf.lo legacy.lo

# All of the source code files.
................................................................................
  $(TOP)/src/hash.h \
  $(TOP)/src/insert.c \
  $(TOP)/src/legacy.c \
  $(TOP)/src/main.c \
  $(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 \
  $(TOP)/src/pragma.c \
  $(TOP)/src/prepare.c \
  $(TOP)/src/printf.c \
  $(TOP)/src/random.c \
................................................................................
TESTSRC = \
  $(TOP)/src/btree.c \
  $(TOP)/src/date.c \
  $(TOP)/src/func.c \
  $(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 \
  $(TOP)/src/test1.c \
  $(TOP)/src/test2.c \
  $(TOP)/src/test3.c \
  $(TOP)/src/test4.c \
................................................................................
	$(LTLINK) -o libtclsqlite3.la tclsqlite.lo \
		$(LIBOBJ) @TCL_STUB_LIB_SPEC@ $(LIBPTHREAD) \
                -rpath $(libdir)/sqlite \
		-version-info "8:6:8"

sqlite3$(TEXE):	$(TOP)/src/shell.c libsqlite3.la sqlite3.h
	$(LTLINK) $(READLINE_FLAGS) $(LIBPTHREAD) \
		-o $@ $(TOP)/src/shell.c libsqlite3.la \
		$(LIBREADLINE) $(TLIBS)

# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
# build on the target system.  Some of the C source code and header
# files are automatically generated.  This target takes care of
# all that automatic generation.
................................................................................
	$(LTCOMPILE) -c $(TOP)/src/os.c

os_unix.lo:	$(TOP)/src/os_unix.c $(HDR)
	$(LTCOMPILE) -c $(TOP)/src/os_unix.c

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

parse.h:	parse.c

parse.c:	$(TOP)/src/parse.y lemon$(BEXE) $(TOP)/addopcodes.awk

Changes to aclocal.m4.

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# All known linkers require a `.a' archive for static linking (except M$VC,
# which needs '.lib').
libext=a
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(RANLIB, ranlib, :)
AC_CHECK_TOOL(STRIP, strip, :)

old_CC="$CC"
old_CFLAGS="$CFLAGS"

# Set sane defaults for various variables







|







147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# All known linkers require a `.a' archive for static linking (except M$VC,
# which needs '.lib').
libext=a
ltmain="$ac_aux_dir/ltmain.sh"
ofile="$default_ofile"
with_gnu_ld="$lt_cv_prog_gnu_ld"

AC_CHECK_TOOL(AR, ar, AC_CHECK_TOOL(AR, emxomfar, false))
AC_CHECK_TOOL(RANLIB, ranlib, :)
AC_CHECK_TOOL(STRIP, strip, :)

old_CC="$CC"
old_CFLAGS="$CFLAGS"

# Set sane defaults for various variables

Changes to configure.

459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
....
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
.....
19691
19692
19693
19694
19695
19696
19697

19698









19699

19700
19701

19702
19703
19704

19705
19706
19707
19708
19709
19710
19711
.....
21374
21375
21376
21377
21378
21379
21380

21381
21382
21383
21384
21385
21386
21387
#  include <stdint.h>
# endif
#endif
#if HAVE_UNISTD_H
# 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_files=''

# Initialize some variables set by options.
ac_init_help=
ac_init_version=false
# The variables have the same names as the options, with
# dashes changed to underlines.
................................................................................






# The following RCS revision string applies to configure.in
# $Revision: 1.39 $

#########
# Programs needed
#
# Check whether --enable-shared or --disable-shared was given.
if test "${enable_shared+set}" = set; then
  enableval="$enable_shared"
................................................................................
fi
if test "$cross" = "0"; then
  TARGET_EXEEXT=$BUILD_EXEEXT
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"

else
  OS_UNIX=1
  OS_WIN=0

  tclsubdir=unix
  TARGET_CFLAGS="$TARGET_CFLAGS -DOS_UNIX=1"
fi




................................................................................
s,@XTHREADCONNECT@,$XTHREADCONNECT,;t t
s,@THREADSOVERRIDELOCKS@,$THREADSOVERRIDELOCKS,;t t
s,@ALLOWRELEASE@,$ALLOWRELEASE,;t t
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,@TARGET_EXEEXT@,$TARGET_EXEEXT,;t t
s,@TCL_VERSION@,$TCL_VERSION,;t t
s,@TCL_BIN_DIR@,$TCL_BIN_DIR,;t t
s,@TCL_SRC_DIR@,$TCL_SRC_DIR,;t t
s,@TCL_LIBS@,$TCL_LIBS,;t t
s,@TCL_INCLUDE_SPEC@,$TCL_INCLUDE_SPEC,;t t
s,@TCL_LIB_FILE@,$TCL_LIB_FILE,;t t







|







 







|







 







>
|
>
>
>
>
>
>
>
>
>
|
>
|
|
>



>







 







>







459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
....
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
.....
19691
19692
19693
19694
19695
19696
19697
19698
19699
19700
19701
19702
19703
19704
19705
19706
19707
19708
19709
19710
19711
19712
19713
19714
19715
19716
19717
19718
19719
19720
19721
19722
19723
19724
.....
21387
21388
21389
21390
21391
21392
21393
21394
21395
21396
21397
21398
21399
21400
21401
#  include <stdint.h>
# endif
#endif
#if HAVE_UNISTD_H
# 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 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.
ac_init_help=
ac_init_version=false
# The variables have the same names as the options, with
# dashes changed to underlines.
................................................................................






# The following RCS revision string applies to configure.in
# $Revision: 1.40 $

#########
# Programs needed
#
# Check whether --enable-shared or --disable-shared was given.
if test "${enable_shared+set}" = set; then
  enableval="$enable_shared"
................................................................................
fi
if test "$cross" = "0"; then
  TARGET_EXEEXT=$BUILD_EXEEXT
else
  TARGET_EXEEXT=$config_TARGET_EXEEXT
fi
if test "$TARGET_EXEEXT" = ".exe"; then
  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




................................................................................
s,@XTHREADCONNECT@,$XTHREADCONNECT,;t t
s,@THREADSOVERRIDELOCKS@,$THREADSOVERRIDELOCKS,;t t
s,@ALLOWRELEASE@,$ALLOWRELEASE,;t t
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
s,@TCL_SRC_DIR@,$TCL_SRC_DIR,;t t
s,@TCL_LIBS@,$TCL_LIBS,;t t
s,@TCL_INCLUDE_SPEC@,$TCL_INCLUDE_SPEC,;t t
s,@TCL_LIB_FILE@,$TCL_LIB_FILE,;t t

Changes to configure.ac.

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
403
404
405
406
407
408
409

410









411

412
413

414
415
416

417
418
419
420
421
422
423

424
425
426
427
428
429
430
# the corresponding code.
#
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 $

#########
# Programs needed
#
AC_PROG_LIBTOOL
AC_PROG_INSTALL
AC_PROG_AWK
................................................................................
fi
if test "$cross" = "0"; then
  TARGET_EXEEXT=$BUILD_EXEEXT
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"

else
  OS_UNIX=1
  OS_WIN=0

  tclsubdir=unix
  TARGET_CFLAGS="$TARGET_CFLAGS -DOS_UNIX=1"
fi

AC_SUBST(BUILD_EXEEXT)
AC_SUBST(OS_UNIX)
AC_SUBST(OS_WIN)

AC_SUBST(TARGET_EXEEXT)

##########
# Extract generic linker options from the environment.
#
if test "$config_TARGET_LIBS" != ""; then
  TARGET_LIBS=$config_TARGET_LIBS







|







 







>
|
>
>
>
>
>
>
>
>
>
|
>
|
|
>



>







>







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
# the corresponding code.
#
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.26 $

#########
# Programs needed
#
AC_PROG_LIBTOOL
AC_PROG_INSTALL
AC_PROG_AWK
................................................................................
fi
if test "$cross" = "0"; then
  TARGET_EXEEXT=$BUILD_EXEEXT
else
  TARGET_EXEEXT=$config_TARGET_EXEEXT
fi
if test "$TARGET_EXEEXT" = ".exe"; then
  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

AC_SUBST(BUILD_EXEEXT)
AC_SUBST(OS_UNIX)
AC_SUBST(OS_WIN)
AC_SUBST(OS_OS2)
AC_SUBST(TARGET_EXEEXT)

##########
# Extract generic linker options from the environment.
#
if test "$config_TARGET_LIBS" != ""; then
  TARGET_LIBS=$config_TARGET_LIBS

Changes to main.mk.

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
..
83
84
85
86
87
88
89

90
91
92
93
94
95
96
...
120
121
122
123
124
125
126

127
128
129
130
131
132
133
...
265
266
267
268
269
270
271



272
273
274
275
276
277
278
TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src

# Object files for the SQLite library.
#
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 \
         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 \
         vdbe.o vdbeapi.o vdbeaux.o vdbefifo.o vdbemem.o \
         where.o utf.o legacy.o

# All of the source code files.
................................................................................
  $(TOP)/src/func.c \
  $(TOP)/src/hash.c \
  $(TOP)/src/hash.h \
  $(TOP)/src/insert.c \
  $(TOP)/src/legacy.c \
  $(TOP)/src/main.c \
  $(TOP)/src/os.c \

  $(TOP)/src/os_unix.c \
  $(TOP)/src/os_win.c \
  $(TOP)/src/pager.c \
  $(TOP)/src/pager.h \
  $(TOP)/src/parse.y \
  $(TOP)/src/pragma.c \
  $(TOP)/src/prepare.c \
................................................................................
# Source code to the test files.
#
TESTSRC = \
  $(TOP)/src/btree.c \
  $(TOP)/src/date.c \
  $(TOP)/src/func.c \
  $(TOP)/src/os.c \

  $(TOP)/src/os_unix.c \
  $(TOP)/src/os_win.c \
  $(TOP)/src/pager.c \
  $(TOP)/src/pragma.c \
  $(TOP)/src/printf.c \
  $(TOP)/src/test1.c \
  $(TOP)/src/test2.c \
................................................................................
	sort -n -b +2 opcodes.h | $(NAWK) -f $(TOP)/mkopcodec.awk >opcodes.c

opcodes.h:	parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk
	cat parse.h $(TOP)/src/vdbe.c | $(NAWK) -f $(TOP)/mkopcodeh.awk >opcodes.h

os.o:	$(TOP)/src/os.c $(HDR)
	$(TCCX) -c $(TOP)/src/os.c




os_unix.o:	$(TOP)/src/os_unix.c $(HDR)
	$(TCCX) -c $(TOP)/src/os_unix.c

os_win.o:	$(TOP)/src/os_win.c $(HDR)
	$(TCCX) -c $(TOP)/src/os_win.c








|







 







>







 







>







 







>
>
>







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
...
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
...
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src

# Object files for the SQLite library.
#
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_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 \
         vdbe.o vdbeapi.o vdbeaux.o vdbefifo.o vdbemem.o \
         where.o utf.o legacy.o

# All of the source code files.
................................................................................
  $(TOP)/src/func.c \
  $(TOP)/src/hash.c \
  $(TOP)/src/hash.h \
  $(TOP)/src/insert.c \
  $(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 \
  $(TOP)/src/pager.h \
  $(TOP)/src/parse.y \
  $(TOP)/src/pragma.c \
  $(TOP)/src/prepare.c \
................................................................................
# Source code to the test files.
#
TESTSRC = \
  $(TOP)/src/btree.c \
  $(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 \
  $(TOP)/src/pragma.c \
  $(TOP)/src/printf.c \
  $(TOP)/src/test1.c \
  $(TOP)/src/test2.c \
................................................................................
	sort -n -b +2 opcodes.h | $(NAWK) -f $(TOP)/mkopcodec.awk >opcodes.c

opcodes.h:	parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk
	cat parse.h $(TOP)/src/vdbe.c | $(NAWK) -f $(TOP)/mkopcodeh.awk >opcodes.h

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

os_win.o:	$(TOP)/src/os_win.c $(HDR)
	$(TCCX) -c $(TOP)/src/os_win.c

Changes to src/os.h.

23
24
25
26
27
28
29





30
31
32

33
34
35

36
37
38
39
40
41
42
..
43
44
45
46
47
48
49








50
51
52
53
54
55
56
..
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
...
114
115
116
117
118
119
120























121
122
123
124
125
126
127
*/
#if !defined(OS_UNIX) && !defined(OS_OTHER)
# define OS_OTHER 0
# ifndef OS_WIN
#   if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
#     define OS_WIN 1
#     define OS_UNIX 0





#   else
#     define OS_WIN 0
#     define OS_UNIX 1

#  endif
# else
#  define OS_UNIX 0

# endif
#else
# ifndef OS_WIN
#  define OS_WIN 0
# endif
#endif

................................................................................

/*
** Define the maximum size of a temporary filename
*/
#if OS_WIN
# include <windows.h>
# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)








#else
# define SQLITE_TEMPNAME_SIZE 200
#endif

/* If the SET_FULLSYNC macro is not defined above, then make it
** a no-op
*/
................................................................................
** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line.
*/
#ifndef TEMP_FILE_PREFIX
# define TEMP_FILE_PREFIX "sqlite_"
#endif

/*
** Define the interfaces for Unix and for Windows.
*/
#if OS_UNIX
#define sqlite3OsOpenReadWrite      sqlite3UnixOpenReadWrite
#define sqlite3OsOpenExclusive      sqlite3UnixOpenExclusive
#define sqlite3OsOpenReadOnly       sqlite3UnixOpenReadOnly
#define sqlite3OsDelete             sqlite3UnixDelete
#define sqlite3OsFileExists         sqlite3UnixFileExists
................................................................................
#define sqlite3OsInMutex            sqlite3WinInMutex
#define sqlite3OsThreadSpecificData sqlite3WinThreadSpecificData
#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"
** header file available for that interface.  Presumably the "os_other.h"
** header file contains #defines similar to those above.
*/
#if OS_OTHER







>
>
>
>
>



>



>







 







>
>
>
>
>
>
>
>







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
..
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
*/
#if !defined(OS_UNIX) && !defined(OS_OTHER)
# define OS_OTHER 0
# ifndef OS_WIN
#   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
#  define OS_WIN 0
# endif
#endif

................................................................................

/*
** Define the maximum size of a temporary filename
*/
#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

/* If the SET_FULLSYNC macro is not defined above, then make it
** a no-op
*/
................................................................................
** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line.
*/
#ifndef TEMP_FILE_PREFIX
# define TEMP_FILE_PREFIX "sqlite_"
#endif

/*
** Define the interfaces for Unix, Windows, and OS/2.
*/
#if OS_UNIX
#define sqlite3OsOpenReadWrite      sqlite3UnixOpenReadWrite
#define sqlite3OsOpenExclusive      sqlite3UnixOpenExclusive
#define sqlite3OsOpenReadOnly       sqlite3UnixOpenReadOnly
#define sqlite3OsDelete             sqlite3UnixDelete
#define sqlite3OsFileExists         sqlite3UnixFileExists
................................................................................
#define sqlite3OsInMutex            sqlite3WinInMutex
#define sqlite3OsThreadSpecificData sqlite3WinThreadSpecificData
#define sqlite3OsMalloc             sqlite3GenericMalloc
#define sqlite3OsRealloc            sqlite3GenericRealloc
#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"
** header file available for that interface.  Presumably the "os_other.h"
** header file contains #defines similar to those above.
*/
#if OS_OTHER

Added src/os_os2.c.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
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 */

Added src/os_os2.h.



















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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_ */