mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Split up os.c into separate files, one for each platform. (CVS 1441)
FossilOrigin-Name: 5c61be1c47ac960fba2a642e69a98436ce1cd725
This commit is contained in:
307
main.mk
307
main.mk
@@ -54,13 +54,10 @@ TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src
|
||||
|
||||
# Object files for the SQLite library.
|
||||
#
|
||||
# LIBOBJ = btree.o hash.o os.o pager.o random.o \
|
||||
# util.o tclsqlite.o utf.o
|
||||
|
||||
|
||||
LIBOBJ = attach.o auth.o btree.o build.o copy.o date.o delete.o \
|
||||
expr.o func.o hash.o insert.o \
|
||||
main.o opcodes.o os.o pager.o parse.o pragma.o printf.o random.o \
|
||||
main.o opcodes.o os_mac.o os_unix.o os_win.o \
|
||||
pager.o parse.o pragma.o printf.o random.o \
|
||||
select.o table.o tokenize.o trigger.o update.o util.o \
|
||||
vacuum.o vdbe.o vdbeaux.o where.o tclsqlite.o utf.o
|
||||
|
||||
@@ -82,7 +79,9 @@ SRC = \
|
||||
$(TOP)/src/hash.h \
|
||||
$(TOP)/src/insert.c \
|
||||
$(TOP)/src/main.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os_mac.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/pager.c \
|
||||
$(TOP)/src/pager.h \
|
||||
$(TOP)/src/parse.y \
|
||||
@@ -109,19 +108,12 @@ SRC = \
|
||||
|
||||
# Source code to the test files.
|
||||
#
|
||||
TESTSRC_SUBSET = \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/pager.c \
|
||||
$(TOP)/src/test1.c \
|
||||
$(TOP)/src/test2.c \
|
||||
$(TOP)/src/test3.c \
|
||||
$(TOP)/src/test5.c \
|
||||
$(TOP)/src/md5.c
|
||||
|
||||
TESTSRC = \
|
||||
$(TOP)/src/btree.c \
|
||||
$(TOP)/src/func.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os_mac.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/pager.c \
|
||||
$(TOP)/src/test1.c \
|
||||
$(TOP)/src/test2.c \
|
||||
@@ -140,6 +132,9 @@ HDR = \
|
||||
$(TOP)/src/hash.h \
|
||||
opcodes.h \
|
||||
$(TOP)/src/os.h \
|
||||
$(TOP)/src/os_mac.h \
|
||||
$(TOP)/src/os_unix.h \
|
||||
$(TOP)/src/os_win.h \
|
||||
$(TOP)/src/sqliteInt.h \
|
||||
$(TOP)/src/vdbe.h \
|
||||
parse.h
|
||||
@@ -191,49 +186,20 @@ lemon: $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
|
||||
$(BCC) -o lemon $(TOP)/tool/lemon.c
|
||||
cp $(TOP)/tool/lempar.c .
|
||||
|
||||
# Rules to build individual files
|
||||
#
|
||||
attach.o: $(TOP)/src/attach.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/attach.c
|
||||
|
||||
auth.o: $(TOP)/src/auth.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/auth.c
|
||||
|
||||
btree.o: $(TOP)/src/btree.c $(HDR) $(TOP)/src/pager.h
|
||||
$(TCCX) -c $(TOP)/src/btree.c
|
||||
|
||||
btree_rb.o: $(TOP)/src/btree_rb.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/btree_rb.c
|
||||
|
||||
build.o: $(TOP)/src/build.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/build.c
|
||||
|
||||
main.o: $(TOP)/src/main.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/main.c
|
||||
|
||||
pager.o: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h
|
||||
$(TCCX) -c $(TOP)/src/pager.c
|
||||
|
||||
opcodes.o: opcodes.c
|
||||
$(TCCX) -c opcodes.c
|
||||
|
||||
opcodes.c: $(TOP)/src/vdbe.c
|
||||
echo '/* Automatically generated file. Do not edit */' >opcodes.c
|
||||
echo 'char *sqlite3OpcodeNames[] = { "???", ' >>opcodes.c
|
||||
grep '^case OP_' $(TOP)/src/vdbe.c | \
|
||||
sed -e 's/^.*OP_/ "/' -e 's/:.*$$/", /' >>opcodes.c
|
||||
echo '};' >>opcodes.c
|
||||
|
||||
opcodes.h: $(TOP)/src/vdbe.h
|
||||
echo '/* Automatically generated file. Do not edit */' >opcodes.h
|
||||
grep '^case OP_' $(TOP)/src/vdbe.c | \
|
||||
sed -e 's/://' | \
|
||||
awk '{printf "#define %-30s %3d\n", $$2, ++cnt}' >>opcodes.h
|
||||
|
||||
os.o: $(TOP)/src/os.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/os.c
|
||||
|
||||
parse.o: parse.c $(HDR)
|
||||
$(TCCX) -c parse.c
|
||||
|
||||
parse.h: parse.c
|
||||
|
||||
parse.c: $(TOP)/src/parse.y lemon
|
||||
cp $(TOP)/src/parse.y .
|
||||
./lemon parse.y
|
||||
|
||||
# The config.h file will contain a single #define that tells us how
|
||||
# many bytes are in a pointer. This only works if a pointer is the
|
||||
# same size on the host as it is on the target. If you are cross-compiling
|
||||
@@ -250,35 +216,6 @@ config.h:
|
||||
echo >>config.h
|
||||
rm -f temp.c temp
|
||||
|
||||
sqlite.h: $(TOP)/src/sqlite.h.in
|
||||
sed -e s/--VERS--/`cat ${TOP}/VERSION`/ \
|
||||
-e s/--ENCODING--/$(ENCODING)/ \
|
||||
$(TOP)/src/sqlite.h.in >sqlite.h
|
||||
|
||||
tokenize.o: $(TOP)/src/tokenize.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/tokenize.c
|
||||
|
||||
trigger.o: $(TOP)/src/trigger.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/trigger.c
|
||||
|
||||
utf.o: $(TOP)/src/utf.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/utf.c
|
||||
|
||||
util.o: $(TOP)/src/util.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/util.c
|
||||
|
||||
vacuum.o: $(TOP)/src/vacuum.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/vacuum.c
|
||||
|
||||
vdbe.o: $(TOP)/src/vdbe.c $(VDBEHDR)
|
||||
$(TCCX) -c $(TOP)/src/vdbe.c
|
||||
|
||||
vdbeaux.o: $(TOP)/src/vdbeaux.c $(VDBEHDR)
|
||||
$(TCCX) -c $(TOP)/src/vdbeaux.c
|
||||
|
||||
where.o: $(TOP)/src/where.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/where.c
|
||||
|
||||
copy.o: $(TOP)/src/copy.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/copy.c
|
||||
|
||||
@@ -303,20 +240,46 @@ hash.o: $(TOP)/src/hash.c $(HDR)
|
||||
insert.o: $(TOP)/src/insert.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/insert.c
|
||||
|
||||
random.o: $(TOP)/src/random.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/random.c
|
||||
|
||||
select.o: $(TOP)/src/select.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/select.c
|
||||
main.o: $(TOP)/src/main.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/main.c
|
||||
|
||||
table.o: $(TOP)/src/table.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/table.c
|
||||
pager.o: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h
|
||||
$(TCCX) -c $(TOP)/src/pager.c
|
||||
|
||||
update.o: $(TOP)/src/update.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/update.c
|
||||
opcodes.o: opcodes.c
|
||||
$(TCCX) -c opcodes.c
|
||||
|
||||
tclsqlite.o: $(TOP)/src/tclsqlite.c $(HDR)
|
||||
$(TCCX) $(TCL_FLAGS) -c $(TOP)/src/tclsqlite.c
|
||||
opcodes.c: $(TOP)/src/vdbe.c
|
||||
echo '/* Automatically generated file. Do not edit */' >opcodes.c
|
||||
echo 'char *sqlite3OpcodeNames[] = { "???", ' >>opcodes.c
|
||||
grep '^case OP_' $(TOP)/src/vdbe.c | \
|
||||
sed -e 's/^.*OP_/ "/' -e 's/:.*$$/", /' >>opcodes.c
|
||||
echo '};' >>opcodes.c
|
||||
|
||||
opcodes.h: $(TOP)/src/vdbe.h
|
||||
echo '/* Automatically generated file. Do not edit */' >opcodes.h
|
||||
grep '^case OP_' $(TOP)/src/vdbe.c | \
|
||||
sed -e 's/://' | \
|
||||
awk '{printf "#define %-30s %3d\n", $$2, ++cnt}' >>opcodes.h
|
||||
|
||||
os_mac.o: $(TOP)/src/os_mac.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/os_mac.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
|
||||
|
||||
parse.o: parse.c $(HDR)
|
||||
$(TCCX) -c parse.c
|
||||
|
||||
parse.h: parse.c
|
||||
|
||||
parse.c: $(TOP)/src/parse.y lemon
|
||||
cp $(TOP)/src/parse.y .
|
||||
./lemon parse.y
|
||||
|
||||
pragma.o: $(TOP)/src/pragma.c $(HDR)
|
||||
$(TCCX) $(TCL_FLAGS) -c $(TOP)/src/pragma.c
|
||||
@@ -324,12 +287,52 @@ pragma.o: $(TOP)/src/pragma.c $(HDR)
|
||||
printf.o: $(TOP)/src/printf.c $(HDR)
|
||||
$(TCCX) $(TCL_FLAGS) -c $(TOP)/src/printf.c
|
||||
|
||||
attach.o: $(TOP)/src/attach.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/attach.c
|
||||
random.o: $(TOP)/src/random.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/random.c
|
||||
|
||||
auth.o: $(TOP)/src/auth.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/auth.c
|
||||
select.o: $(TOP)/src/select.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/select.c
|
||||
|
||||
sqlite.h: $(TOP)/src/sqlite.h.in
|
||||
sed -e s/--VERS--/`cat ${TOP}/VERSION`/ \
|
||||
-e s/--ENCODING--/$(ENCODING)/ \
|
||||
$(TOP)/src/sqlite.h.in >sqlite.h
|
||||
|
||||
table.o: $(TOP)/src/table.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/table.c
|
||||
|
||||
tclsqlite.o: $(TOP)/src/tclsqlite.c $(HDR)
|
||||
$(TCCX) $(TCL_FLAGS) -c $(TOP)/src/tclsqlite.c
|
||||
|
||||
tokenize.o: $(TOP)/src/tokenize.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/tokenize.c
|
||||
|
||||
trigger.o: $(TOP)/src/trigger.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/trigger.c
|
||||
|
||||
update.o: $(TOP)/src/update.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/update.c
|
||||
|
||||
utf.o: $(TOP)/src/utf.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/utf.c
|
||||
|
||||
util.o: $(TOP)/src/util.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/util.c
|
||||
|
||||
vacuum.o: $(TOP)/src/vacuum.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/vacuum.c
|
||||
|
||||
vdbe.o: $(TOP)/src/vdbe.c $(VDBEHDR)
|
||||
$(TCCX) -c $(TOP)/src/vdbe.c
|
||||
|
||||
vdbeaux.o: $(TOP)/src/vdbeaux.c $(VDBEHDR)
|
||||
$(TCCX) -c $(TOP)/src/vdbeaux.c
|
||||
|
||||
where.o: $(TOP)/src/where.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/where.c
|
||||
|
||||
# Rules for building test programs and for running tests
|
||||
#
|
||||
tclsqlite: $(TOP)/src/tclsqlite.c libsqlite.a
|
||||
$(TCCX) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite \
|
||||
$(TOP)/src/tclsqlite.c libsqlite.a $(LIBTCL)
|
||||
@@ -345,11 +348,13 @@ fulltest: testfixture$(EXE) sqlite$(EXE)
|
||||
test: testfixture$(EXE) sqlite$(EXE)
|
||||
./testfixture$(EXE) $(TOP)/test/quick.test
|
||||
|
||||
index.html: $(TOP)/www/index.tcl last_change
|
||||
tclsh $(TOP)/www/index.tcl `cat $(TOP)/VERSION` >index.html
|
||||
# Rules used to build documentation
|
||||
#
|
||||
arch.html: $(TOP)/www/arch.tcl
|
||||
tclsh $(TOP)/www/arch.tcl >arch.html
|
||||
|
||||
sqlite.html: $(TOP)/www/sqlite.tcl
|
||||
tclsh $(TOP)/www/sqlite.tcl >sqlite.html
|
||||
arch.png: $(TOP)/www/arch.png
|
||||
cp $(TOP)/www/arch.png .
|
||||
|
||||
c_interface.html: $(TOP)/www/c_interface.tcl
|
||||
tclsh $(TOP)/www/c_interface.tcl >c_interface.html
|
||||
@@ -357,17 +362,32 @@ c_interface.html: $(TOP)/www/c_interface.tcl
|
||||
changes.html: $(TOP)/www/changes.tcl
|
||||
tclsh $(TOP)/www/changes.tcl >changes.html
|
||||
|
||||
conflict.html: $(TOP)/www/conflict.tcl
|
||||
tclsh $(TOP)/www/conflict.tcl >conflict.html
|
||||
|
||||
datatypes.html: $(TOP)/www/datatypes.tcl
|
||||
tclsh $(TOP)/www/datatypes.tcl >datatypes.html
|
||||
|
||||
download.html: $(TOP)/www/download.tcl
|
||||
tclsh $(TOP)/www/download.tcl >download.html
|
||||
|
||||
faq.html: $(TOP)/www/faq.tcl
|
||||
tclsh $(TOP)/www/faq.tcl >faq.html
|
||||
|
||||
fileformat.html: $(TOP)/www/fileformat.tcl
|
||||
tclsh $(TOP)/www/fileformat.tcl >fileformat.html
|
||||
|
||||
formatchng.html: $(TOP)/www/formatchng.tcl
|
||||
tclsh $(TOP)/www/formatchng.tcl >formatchng.html
|
||||
|
||||
index.html: $(TOP)/www/index.tcl last_change
|
||||
tclsh $(TOP)/www/index.tcl `cat $(TOP)/VERSION` >index.html
|
||||
|
||||
lang.html: $(TOP)/www/lang.tcl
|
||||
tclsh $(TOP)/www/lang.tcl >lang.html
|
||||
|
||||
vdbe.html: $(TOP)/www/vdbe.tcl
|
||||
tclsh $(TOP)/www/vdbe.tcl >vdbe.html
|
||||
|
||||
arch.html: $(TOP)/www/arch.tcl
|
||||
tclsh $(TOP)/www/arch.tcl >arch.html
|
||||
|
||||
arch.png: $(TOP)/www/arch.png
|
||||
cp $(TOP)/www/arch.png .
|
||||
omitted.html: $(TOP)/www/omitted.tcl
|
||||
tclsh $(TOP)/www/omitted.tcl >omitted.html
|
||||
|
||||
opcode.html: $(TOP)/www/opcode.tcl $(TOP)/src/vdbe.c
|
||||
tclsh $(TOP)/www/opcode.tcl $(TOP)/src/vdbe.c >opcode.html
|
||||
@@ -375,69 +395,56 @@ opcode.html: $(TOP)/www/opcode.tcl $(TOP)/src/vdbe.c
|
||||
mingw.html: $(TOP)/www/mingw.tcl
|
||||
tclsh $(TOP)/www/mingw.tcl >mingw.html
|
||||
|
||||
tclsqlite.html: $(TOP)/www/tclsqlite.tcl
|
||||
tclsh $(TOP)/www/tclsqlite.tcl >tclsqlite.html
|
||||
|
||||
speed.html: $(TOP)/www/speed.tcl
|
||||
tclsh $(TOP)/www/speed.tcl >speed.html
|
||||
|
||||
faq.html: $(TOP)/www/faq.tcl
|
||||
tclsh $(TOP)/www/faq.tcl >faq.html
|
||||
|
||||
formatchng.html: $(TOP)/www/formatchng.tcl
|
||||
tclsh $(TOP)/www/formatchng.tcl >formatchng.html
|
||||
|
||||
conflict.html: $(TOP)/www/conflict.tcl
|
||||
tclsh $(TOP)/www/conflict.tcl >conflict.html
|
||||
|
||||
download.html: $(TOP)/www/download.tcl
|
||||
tclsh $(TOP)/www/download.tcl >download.html
|
||||
|
||||
omitted.html: $(TOP)/www/omitted.tcl
|
||||
tclsh $(TOP)/www/omitted.tcl >omitted.html
|
||||
|
||||
datatypes.html: $(TOP)/www/datatypes.tcl
|
||||
tclsh $(TOP)/www/datatypes.tcl >datatypes.html
|
||||
nulls.html: $(TOP)/www/nulls.tcl
|
||||
tclsh $(TOP)/www/nulls.tcl >nulls.html
|
||||
|
||||
quickstart.html: $(TOP)/www/quickstart.tcl
|
||||
tclsh $(TOP)/www/quickstart.tcl >quickstart.html
|
||||
|
||||
fileformat.html: $(TOP)/www/fileformat.tcl
|
||||
tclsh $(TOP)/www/fileformat.tcl >fileformat.html
|
||||
speed.html: $(TOP)/www/speed.tcl
|
||||
tclsh $(TOP)/www/speed.tcl >speed.html
|
||||
|
||||
nulls.html: $(TOP)/www/nulls.tcl
|
||||
tclsh $(TOP)/www/nulls.tcl >nulls.html
|
||||
sqlite.html: $(TOP)/www/sqlite.tcl
|
||||
tclsh $(TOP)/www/sqlite.tcl >sqlite.html
|
||||
|
||||
tclsqlite.html: $(TOP)/www/tclsqlite.tcl
|
||||
tclsh $(TOP)/www/tclsqlite.tcl >tclsqlite.html
|
||||
|
||||
vdbe.html: $(TOP)/www/vdbe.tcl
|
||||
tclsh $(TOP)/www/vdbe.tcl >vdbe.html
|
||||
|
||||
|
||||
# Files to be published on the website.
|
||||
#
|
||||
DOC = \
|
||||
index.html \
|
||||
sqlite.html \
|
||||
changes.html \
|
||||
lang.html \
|
||||
opcode.html \
|
||||
arch.html \
|
||||
arch.png \
|
||||
vdbe.html \
|
||||
changes.html \
|
||||
c_interface.html \
|
||||
mingw.html \
|
||||
tclsqlite.html \
|
||||
download.html \
|
||||
speed.html \
|
||||
faq.html \
|
||||
formatchng.html \
|
||||
conflict.html \
|
||||
omitted.html \
|
||||
datatypes.html \
|
||||
quickstart.html \
|
||||
download.html \
|
||||
faq.html \
|
||||
fileformat.html \
|
||||
nulls.html
|
||||
formatchng.html \
|
||||
index.html \
|
||||
lang.html \
|
||||
mingw.html \
|
||||
nulls.html \
|
||||
omitted.html \
|
||||
opcode.html \
|
||||
quickstart.html \
|
||||
speed.html \
|
||||
sqlite.html \
|
||||
tclsqlite.html \
|
||||
vdbe.html
|
||||
|
||||
doc: $(DOC)
|
||||
mkdir -p doc
|
||||
mv $(DOC) doc
|
||||
|
||||
# Standard install and cleanup targets
|
||||
#
|
||||
install: sqlite libsqlite.a sqlite.h
|
||||
mv sqlite /usr/bin
|
||||
mv libsqlite.a /usr/lib
|
||||
|
28
manifest
28
manifest
@@ -1,5 +1,5 @@
|
||||
C Bug\sfix\sin\svdbe.c\s-\svariable\sdeclarations\smust\scome\sbefore\scode\sin\sANSI\sC.\s(CVS\s1440)
|
||||
D 2004-05-22T11:09:30
|
||||
C Split\sup\sos.c\sinto\sseparate\sfiles,\sone\sfor\seach\splatform.\s(CVS\s1441)
|
||||
D 2004-05-22T17:41:59
|
||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
@@ -16,7 +16,7 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
|
||||
F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
||||
F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
|
||||
F main.mk fbc906044c1b891be4bd9e48a74a9fd5bcd5fc81
|
||||
F main.mk a56ffbc29258e373614da28baa568f173d80d0d7
|
||||
F publish.sh 1cd5c982388560fa91eedf6a338e210f713b35c8
|
||||
F spec.template a38492f1c1dd349fc24cb0565e08afc53045304b
|
||||
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
|
||||
@@ -37,10 +37,16 @@ F src/func.c cfbb7096efb58e2857e3b312a8958a12774b625a
|
||||
F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f
|
||||
F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
|
||||
F src/insert.c e510d62d23b4de4d901e7ccbbe7833b7fb3b9570
|
||||
F src/main.c 6b59eda1481376df6c8e2b5fa2f24b4c101ffd72
|
||||
F src/main.c 289e05cf20d74c0b393055745591e6ea8568faee
|
||||
F src/md5.c 8e39fdae6d8776b87558e91dcc94740c9b635a9c
|
||||
F src/os.c ddcda92f7fd71b4513c57c1ec797917f206d504e
|
||||
F src/os.h 6e446a17cbeb6c2ce470683a0bb8d9c63abe8607
|
||||
F src/os.h ab42f4a7c4c716f26b988e759b6e12085a3bfc67
|
||||
F src/os_common.h 744286a27de55c52f1b18921e8d17abbf7fafc0f
|
||||
F src/os_mac.c b823874690615ace0dd520d3ad1fe8bfd864b7e0
|
||||
F src/os_mac.h 51d2445f47e182ed32d3bd6937f81070c6fd9bd4
|
||||
F src/os_unix.c e93a6858b4ab880ce91cbc95af14975ef53b6369
|
||||
F src/os_unix.h 426e1480f0847a7f8ba22aa9ac5115520875610b
|
||||
F src/os_win.c 92b51a38437b98d8aa3ac05b57c71e1d1092e5be
|
||||
F src/os_win.h 5d41af24caaef6c13a2d8e2399caa1c57d45c84d
|
||||
F src/pager.c 6ff6b906427d4824099140776cb8768f922f3dc5
|
||||
F src/pager.h 78a00ac280899bcba1a89dc51585dcae6b7b3253
|
||||
F src/parse.y 567718866b94d58a6c7681cc45ba7987771d583a
|
||||
@@ -50,7 +56,7 @@ F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
||||
F src/select.c 7d77a8bed7eeac23216d42fc1be006fb4352fcdc
|
||||
F src/shell.c 657623c2a3df126538d41842c2146cadbd52b154
|
||||
F src/sqlite.h.in 9a4c374f4030cde181593166d71bf376274ca45c
|
||||
F src/sqliteInt.h 4b45892cb082f4883efb58c5e13328c42cbc7642
|
||||
F src/sqliteInt.h 2d7b2c7e734f95c4e21513224cb7815adea86e2a
|
||||
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
|
||||
F src/tclsqlite.c f241854328ee2b06006efded270d84799159f760
|
||||
F src/test1.c b5f2f9f9d866c8a586b8d47c5999d2cbefaac686
|
||||
@@ -61,7 +67,7 @@ F src/test5.c 9a1f15133f6955f067c5246e564723b5f23ff221
|
||||
F src/tokenize.c e7536dd31205d5afb76c1bdc832dea009c7a3847
|
||||
F src/trigger.c 11afe9abfba13a2ba142944c797c952e162d117f
|
||||
F src/update.c 1a5e9182596f3ea8c7a141e308a3d2a7e5689fee
|
||||
F src/utf.c 537e1c98cddc623628d44497ec02c2246cf66dea
|
||||
F src/utf.c a4640c6a1530b43b651495246349ee0a6eca3038
|
||||
F src/util.c 5cbeb452da09cfc7248de9948c15b14d840723f7
|
||||
F src/vacuum.c 8734f89742f246abd91dbd3e087fc153bddbfbad
|
||||
F src/vdbe.c c1846f4b2938d11250f532b068d7856fd8decd6c
|
||||
@@ -197,7 +203,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
||||
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||
P 891be63a92097384e1b00993d35f002048c4b42e
|
||||
R 543ddb60688125b3fffe05e3e9ef31d2
|
||||
P c36203de22f673691783529e06ce5a58bcebeedc
|
||||
R 2c92275d417e436955c48e131db4f92e
|
||||
U drh
|
||||
Z 735268b125ff8e5769b42e78ffc4dd1e
|
||||
Z f6cdae699efac8ed1a9148f3d6e06cad
|
||||
|
@@ -1 +1 @@
|
||||
c36203de22f673691783529e06ce5a58bcebeedc
|
||||
5c61be1c47ac960fba2a642e69a98436ce1cd725
|
@@ -14,7 +14,7 @@
|
||||
** other files are for internal use by SQLite and should not be
|
||||
** accessed by users of the library.
|
||||
**
|
||||
** $Id: main.c,v 1.184 2004/05/22 09:21:21 danielk1977 Exp $
|
||||
** $Id: main.c,v 1.185 2004/05/22 17:41:59 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -29,6 +29,12 @@ typedef struct {
|
||||
char **pzErrMsg; /* Error message stored here */
|
||||
} InitData;
|
||||
|
||||
/*
|
||||
** The following constant value is used by the SQLITE3_BIGENDIAN and
|
||||
** SQLITE3_LITTLEENDIAN macros.
|
||||
*/
|
||||
const int sqlite3one = 1;
|
||||
|
||||
/*
|
||||
** Fill the InitData structure with an error message that indicates
|
||||
** that the database is corrupt.
|
||||
@@ -1335,4 +1341,3 @@ int sqlite3_reset_new(sqlite3_stmt *pStmt){
|
||||
sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
123
src/os.h
123
src/os.h
@@ -17,47 +17,6 @@
|
||||
#ifndef _SQLITE_OS_H_
|
||||
#define _SQLITE_OS_H_
|
||||
|
||||
/*
|
||||
** Helpful hint: To get this to compile on HP/UX, add -D_INCLUDE_POSIX_SOURCE
|
||||
** to the compiler command line.
|
||||
*/
|
||||
|
||||
/*
|
||||
** These #defines should enable >2GB file support on Posix if the
|
||||
** underlying operating system supports it. If the OS lacks
|
||||
** large file support, or if the OS is windows, these should be no-ops.
|
||||
**
|
||||
** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
|
||||
** on the compiler command line. This is necessary if you are compiling
|
||||
** on a recent machine (ex: RedHat 7.2) but you want your code to work
|
||||
** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
|
||||
** without this option, LFS is enable. But LFS does not exist in the kernel
|
||||
** in RedHat 6.0, so the code won't work. Hence, for maximum binary
|
||||
** portability you should omit LFS.
|
||||
**
|
||||
** Similar is true for MacOS. LFS is only supported on MacOS 9 and later.
|
||||
*/
|
||||
#ifndef SQLITE_DISABLE_LFS
|
||||
# define _LARGE_FILE 1
|
||||
# ifndef _FILE_OFFSET_BITS
|
||||
# define _FILE_OFFSET_BITS 64
|
||||
# endif
|
||||
# define _LARGEFILE_SOURCE 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Temporary files are named starting with this prefix followed by 16 random
|
||||
** alphanumeric characters, and no file extension. They are stored in the
|
||||
** OS's standard temporary file directory, and are deleted prior to exit.
|
||||
** If sqlite is being embedded in another program, you may wish to change the
|
||||
** prefix to reflect your program's name, so that if your program exits
|
||||
** prematurely, old temporary files can be easily identified. This can be done
|
||||
** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line.
|
||||
*/
|
||||
#ifndef TEMP_FILE_PREFIX
|
||||
# define TEMP_FILE_PREFIX "sqlite_"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Figure out if we are dealing with Unix, Windows or MacOS.
|
||||
**
|
||||
@@ -96,78 +55,31 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
** A handle for an open file is stored in an OsFile object.
|
||||
** Invoke the appropriate operating-system specific header file.
|
||||
*/
|
||||
#if OS_UNIX
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <fcntl.h>
|
||||
# include <unistd.h>
|
||||
typedef struct OsFile OsFile;
|
||||
struct OsFile {
|
||||
struct openCnt *pOpen; /* Info about all open fd's on this inode */
|
||||
struct lockInfo *pLock; /* Info about locks on this inode */
|
||||
int fd; /* The file descriptor */
|
||||
int locked; /* True if this instance holds the lock */
|
||||
int dirfd; /* File descriptor for the directory */
|
||||
};
|
||||
# define SQLITE_TEMPNAME_SIZE 200
|
||||
# if defined(HAVE_USLEEP) && HAVE_USLEEP
|
||||
# define SQLITE_MIN_SLEEP_MS 1
|
||||
# else
|
||||
# define SQLITE_MIN_SLEEP_MS 1000
|
||||
# endif
|
||||
# include "os_unix.h"
|
||||
#endif
|
||||
|
||||
#if OS_WIN
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
typedef struct OsFile OsFile;
|
||||
struct OsFile {
|
||||
HANDLE h; /* Handle for accessing the file */
|
||||
int locked; /* 0: unlocked, <0: write lock, >0: read lock */
|
||||
};
|
||||
# if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef __int64 off_t;
|
||||
# else
|
||||
# if !defined(_CYGWIN_TYPES_H)
|
||||
typedef long long off_t;
|
||||
# if defined(__MINGW32__)
|
||||
# define _OFF_T_
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
|
||||
# define SQLITE_MIN_SLEEP_MS 1
|
||||
# include "os_win.h"
|
||||
#endif
|
||||
|
||||
#if OS_MAC
|
||||
# include <unistd.h>
|
||||
# include <Files.h>
|
||||
typedef struct OsFile OsFile;
|
||||
struct OsFile {
|
||||
SInt16 refNum; /* Data fork/file reference number */
|
||||
SInt16 refNumRF; /* Resource fork reference number (for locking) */
|
||||
int locked; /* 0: unlocked, <0: write lock, >0: read lock */
|
||||
int delOnClose; /* True if file is to be deleted on close */
|
||||
char *pathToDel; /* Name of file to delete on close */
|
||||
};
|
||||
# ifdef _LARGE_FILE
|
||||
typedef SInt64 off_t;
|
||||
# else
|
||||
typedef SInt32 off_t;
|
||||
# endif
|
||||
# define SQLITE_TEMPNAME_SIZE _MAX_PATH
|
||||
# define SQLITE_MIN_SLEEP_MS 17
|
||||
# include "os_mac.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Macros to determine whether the machine is big or little endian,
|
||||
** evaluated at runtime.
|
||||
** Temporary files are named starting with this prefix followed by 16 random
|
||||
** alphanumeric characters, and no file extension. They are stored in the
|
||||
** OS's standard temporary file directory, and are deleted prior to exit.
|
||||
** If sqlite is being embedded in another program, you may wish to change the
|
||||
** prefix to reflect your program's name, so that if your program exits
|
||||
** prematurely, old temporary files can be easily identified. This can be done
|
||||
** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line.
|
||||
*/
|
||||
static const int sqlite3_one = 1;
|
||||
#define SQLITE3_BIGENDIAN (*(char *)(&sqlite3_one)==0)
|
||||
#define SQLITE3_LITTLEENDIAN (*(char *)(&sqlite3_one)==1)
|
||||
#ifndef TEMP_FILE_PREFIX
|
||||
# define TEMP_FILE_PREFIX "sqlite_"
|
||||
#endif
|
||||
|
||||
|
||||
int sqlite3OsDelete(const char*);
|
||||
int sqlite3OsFileExists(const char*);
|
||||
@@ -194,9 +106,4 @@ void sqlite3OsEnterMutex(void);
|
||||
void sqlite3OsLeaveMutex(void);
|
||||
char *sqlite3OsFullPathname(const char*);
|
||||
|
||||
|
||||
|
||||
#endif /* _SQLITE_OS_H_ */
|
||||
|
||||
|
||||
|
||||
|
82
src/os_common.h
Normal file
82
src/os_common.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
** 2004 May 22
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This file contains macros and a little bit of code that is common to
|
||||
** all of the platform-specific files (os_*.c) and is #included into those
|
||||
** files.
|
||||
**
|
||||
** This file should be #included by the os_*.c files only. It is not a
|
||||
** general purpose header file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** Macros for performance tracing. Normally turned off. Only works
|
||||
** on i486 hardware.
|
||||
*/
|
||||
#if 0
|
||||
static int last_page = 0;
|
||||
__inline__ unsigned long long int hwtime(void){
|
||||
unsigned long long int x;
|
||||
__asm__("rdtsc\n\t"
|
||||
"mov %%edx, %%ecx\n\t"
|
||||
:"=A" (x));
|
||||
return x;
|
||||
}
|
||||
static unsigned long long int g_start;
|
||||
static unsigned int elapse;
|
||||
#define TIMER_START g_start=hwtime()
|
||||
#define TIMER_END elapse=hwtime()-g_start
|
||||
#define SEEK(X) last_page=(X)
|
||||
#define TRACE1(X) fprintf(stderr,X)
|
||||
#define TRACE2(X,Y) fprintf(stderr,X,Y)
|
||||
#define TRACE3(X,Y,Z) fprintf(stderr,X,Y,Z)
|
||||
#define TRACE4(X,Y,Z,A) fprintf(stderr,X,Y,Z,A)
|
||||
#define TRACE5(X,Y,Z,A,B) fprintf(stderr,X,Y,Z,A,B)
|
||||
#else
|
||||
#define TIMER_START
|
||||
#define TIMER_END
|
||||
#define SEEK(X)
|
||||
#define TRACE1(X)
|
||||
#define TRACE2(X,Y)
|
||||
#define TRACE3(X,Y,Z)
|
||||
#define TRACE4(X,Y,Z,A)
|
||||
#define TRACE5(X,Y,Z,A,B)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** If we compile with the SQLITE_TEST macro set, then the following block
|
||||
** of code will give us the ability to simulate a disk I/O error. This
|
||||
** is used for testing the I/O recovery logic.
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3_io_error_pending = 0;
|
||||
#define SimulateIOError(A) \
|
||||
if( sqlite3_io_error_pending ) \
|
||||
if( sqlite3_io_error_pending-- == 1 ){ local_ioerr(); return A; }
|
||||
static void local_ioerr(){
|
||||
sqlite3_io_error_pending = 0; /* Really just a place to set a breakpoint */
|
||||
}
|
||||
#else
|
||||
#define SimulateIOError(A)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** When testing, keep a count of the number of open files.
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3_open_file_count = 0;
|
||||
#define OpenCounter(X) sqlite3_open_file_count+=(X)
|
||||
#else
|
||||
#define OpenCounter(X)
|
||||
#endif
|
729
src/os_mac.c
Normal file
729
src/os_mac.c
Normal file
@@ -0,0 +1,729 @@
|
||||
/*
|
||||
** 2004 May 22
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This file contains code that is specific classic mac. Mac OS X
|
||||
** uses the os_unix.c file, not this one.
|
||||
*/
|
||||
#include "os.h" /* Must be first to enable large file support */
|
||||
#if OS_MAC /* This file used on classic mac only */
|
||||
#include "sqliteInt.h"
|
||||
|
||||
#include <extras.h>
|
||||
#include <path2fss.h>
|
||||
#include <TextUtils.h>
|
||||
#include <FinderRegistry.h>
|
||||
#include <Folders.h>
|
||||
#include <Timer.h>
|
||||
#include <OSUtils.h>
|
||||
|
||||
/*
|
||||
** Macros used to determine whether or not to use threads.
|
||||
*/
|
||||
#if defined(THREADSAFE) && THREADSAFE
|
||||
# include <Multiprocessing.h>
|
||||
# define SQLITE_MACOS_MULTITASKING 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Include code that is common to all os_*.c files
|
||||
*/
|
||||
#include "os_common.h"
|
||||
|
||||
/*
|
||||
** Delete the named file
|
||||
*/
|
||||
int sqlite3OsDelete(const char *zFilename){
|
||||
unlink(zFilename);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the named file exists.
|
||||
*/
|
||||
int sqlite3OsFileExists(const char *zFilename){
|
||||
return access(zFilename, 0)==0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to open a file for both reading and writing. If that
|
||||
** fails, try opening it read-only. If the file does not exist,
|
||||
** try to create it.
|
||||
**
|
||||
** On success, a handle for the open file is written to *id
|
||||
** and *pReadonly is set to 0 if the file was opened for reading and
|
||||
** writing or 1 if the file was opened read-only. The function returns
|
||||
** SQLITE_OK.
|
||||
**
|
||||
** On failure, the function returns SQLITE_CANTOPEN and leaves
|
||||
** *id and *pReadonly unchanged.
|
||||
*/
|
||||
int sqlite3OsOpenReadWrite(
|
||||
const char *zFilename,
|
||||
OsFile *id,
|
||||
int *pReadonly
|
||||
){
|
||||
FSSpec fsSpec;
|
||||
# ifdef _LARGE_FILE
|
||||
HFSUniStr255 dfName;
|
||||
FSRef fsRef;
|
||||
if( __path2fss(zFilename, &fsSpec) != noErr ){
|
||||
if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
FSGetDataForkName(&dfName);
|
||||
if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
|
||||
fsRdWrShPerm, &(id->refNum)) != noErr ){
|
||||
if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
|
||||
fsRdWrPerm, &(id->refNum)) != noErr ){
|
||||
if (FSOpenFork(&fsRef, dfName.length, dfName.unicode,
|
||||
fsRdPerm, &(id->refNum)) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
else
|
||||
*pReadonly = 1;
|
||||
} else
|
||||
*pReadonly = 0;
|
||||
} else
|
||||
*pReadonly = 0;
|
||||
# else
|
||||
__path2fss(zFilename, &fsSpec);
|
||||
if( !sqlite3OsFileExists(zFilename) ){
|
||||
if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNum)) != noErr ){
|
||||
if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr ){
|
||||
if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
else
|
||||
*pReadonly = 1;
|
||||
} else
|
||||
*pReadonly = 0;
|
||||
} else
|
||||
*pReadonly = 0;
|
||||
# endif
|
||||
if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){
|
||||
id->refNumRF = -1;
|
||||
}
|
||||
id->locked = 0;
|
||||
id->delOnClose = 0;
|
||||
OpenCounter(+1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Attempt to open a new file for exclusive access by this process.
|
||||
** The file will be opened for both reading and writing. To avoid
|
||||
** a potential security problem, we do not allow the file to have
|
||||
** previously existed. Nor do we allow the file to be a symbolic
|
||||
** link.
|
||||
**
|
||||
** If delFlag is true, then make arrangements to automatically delete
|
||||
** the file when it is closed.
|
||||
**
|
||||
** On success, write the file handle into *id and return SQLITE_OK.
|
||||
**
|
||||
** On failure, return SQLITE_CANTOPEN.
|
||||
*/
|
||||
int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
|
||||
FSSpec fsSpec;
|
||||
# ifdef _LARGE_FILE
|
||||
HFSUniStr255 dfName;
|
||||
FSRef fsRef;
|
||||
__path2fss(zFilename, &fsSpec);
|
||||
if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
FSGetDataForkName(&dfName);
|
||||
if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
|
||||
fsRdWrPerm, &(id->refNum)) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
# else
|
||||
__path2fss(zFilename, &fsSpec);
|
||||
if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
# endif
|
||||
id->refNumRF = -1;
|
||||
id->locked = 0;
|
||||
id->delOnClose = delFlag;
|
||||
if (delFlag)
|
||||
id->pathToDel = sqlite3OsFullPathname(zFilename);
|
||||
OpenCounter(+1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to open a new file for read-only access.
|
||||
**
|
||||
** On success, write the file handle into *id and return SQLITE_OK.
|
||||
**
|
||||
** On failure, return SQLITE_CANTOPEN.
|
||||
*/
|
||||
int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){
|
||||
FSSpec fsSpec;
|
||||
# ifdef _LARGE_FILE
|
||||
HFSUniStr255 dfName;
|
||||
FSRef fsRef;
|
||||
if( __path2fss(zFilename, &fsSpec) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
FSGetDataForkName(&dfName);
|
||||
if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
|
||||
fsRdPerm, &(id->refNum)) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
# else
|
||||
__path2fss(zFilename, &fsSpec);
|
||||
if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr )
|
||||
return SQLITE_CANTOPEN;
|
||||
# endif
|
||||
if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){
|
||||
id->refNumRF = -1;
|
||||
}
|
||||
id->locked = 0;
|
||||
id->delOnClose = 0;
|
||||
OpenCounter(+1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to open a file descriptor for the directory that contains a
|
||||
** file. This file descriptor can be used to fsync() the directory
|
||||
** in order to make sure the creation of a new file is actually written
|
||||
** to disk.
|
||||
**
|
||||
** This routine is only meaningful for Unix. It is a no-op under
|
||||
** windows since windows does not support hard links.
|
||||
**
|
||||
** On success, a handle for a previously open file is at *id is
|
||||
** updated with the new directory file descriptor and SQLITE_OK is
|
||||
** returned.
|
||||
**
|
||||
** On failure, the function returns SQLITE_CANTOPEN and leaves
|
||||
** *id unchanged.
|
||||
*/
|
||||
int sqlite3OsOpenDirectory(
|
||||
const char *zDirname,
|
||||
OsFile *id
|
||||
){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a temporary file name in zBuf. zBuf must be big enough to
|
||||
** hold at least SQLITE_TEMPNAME_SIZE characters.
|
||||
*/
|
||||
int sqlite3OsTempFileName(char *zBuf){
|
||||
static char zChars[] =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
int i, j;
|
||||
char zTempPath[SQLITE_TEMPNAME_SIZE];
|
||||
char zdirName[32];
|
||||
CInfoPBRec infoRec;
|
||||
Str31 dirName;
|
||||
memset(&infoRec, 0, sizeof(infoRec));
|
||||
memset(zTempPath, 0, SQLITE_TEMPNAME_SIZE);
|
||||
if( FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder,
|
||||
&(infoRec.dirInfo.ioVRefNum), &(infoRec.dirInfo.ioDrParID)) == noErr ){
|
||||
infoRec.dirInfo.ioNamePtr = dirName;
|
||||
do{
|
||||
infoRec.dirInfo.ioFDirIndex = -1;
|
||||
infoRec.dirInfo.ioDrDirID = infoRec.dirInfo.ioDrParID;
|
||||
if( PBGetCatInfoSync(&infoRec) == noErr ){
|
||||
CopyPascalStringToC(dirName, zdirName);
|
||||
i = strlen(zdirName);
|
||||
memmove(&(zTempPath[i+1]), zTempPath, strlen(zTempPath));
|
||||
strcpy(zTempPath, zdirName);
|
||||
zTempPath[i] = ':';
|
||||
}else{
|
||||
*zTempPath = 0;
|
||||
break;
|
||||
}
|
||||
} while( infoRec.dirInfo.ioDrDirID != fsRtDirID );
|
||||
}
|
||||
if( *zTempPath == 0 )
|
||||
getcwd(zTempPath, SQLITE_TEMPNAME_SIZE-24);
|
||||
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;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close a file.
|
||||
*/
|
||||
int sqlite3OsClose(OsFile *id){
|
||||
if( id->refNumRF!=-1 )
|
||||
FSClose(id->refNumRF);
|
||||
# ifdef _LARGE_FILE
|
||||
FSCloseFork(id->refNum);
|
||||
# else
|
||||
FSClose(id->refNum);
|
||||
# endif
|
||||
if( id->delOnClose ){
|
||||
unlink(id->pathToDel);
|
||||
sqliteFree(id->pathToDel);
|
||||
}
|
||||
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 sqlite3OsRead(OsFile *id, void *pBuf, int amt){
|
||||
int got;
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
TRACE2("READ %d\n", last_page);
|
||||
# ifdef _LARGE_FILE
|
||||
FSReadFork(id->refNum, fsAtMark, 0, (ByteCount)amt, pBuf, (ByteCount*)&got);
|
||||
# else
|
||||
got = amt;
|
||||
FSRead(id->refNum, &got, pBuf);
|
||||
# endif
|
||||
if( got==amt ){
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Write data from a buffer into a file. Return SQLITE_OK on success
|
||||
** or some other error code on failure.
|
||||
*/
|
||||
int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
|
||||
OSErr oserr;
|
||||
int wrote = 0;
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
TRACE2("WRITE %d\n", last_page);
|
||||
while( amt>0 ){
|
||||
# ifdef _LARGE_FILE
|
||||
oserr = FSWriteFork(id->refNum, fsAtMark, 0,
|
||||
(ByteCount)amt, pBuf, (ByteCount*)&wrote);
|
||||
# else
|
||||
wrote = amt;
|
||||
oserr = FSWrite(id->refNum, &wrote, pBuf);
|
||||
# endif
|
||||
if( wrote == 0 || oserr != noErr)
|
||||
break;
|
||||
amt -= wrote;
|
||||
pBuf = &((char*)pBuf)[wrote];
|
||||
}
|
||||
if( oserr != noErr || amt>wrote ){
|
||||
return SQLITE_FULL;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Move the read/write pointer in a file.
|
||||
*/
|
||||
int sqlite3OsSeek(OsFile *id, off_t offset){
|
||||
off_t curSize;
|
||||
SEEK(offset/1024 + 1);
|
||||
if( sqlite3OsFileSize(id, &curSize) != SQLITE_OK ){
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
if( offset >= curSize ){
|
||||
if( sqlite3OsTruncate(id, offset+1) != SQLITE_OK ){
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
}
|
||||
# ifdef _LARGE_FILE
|
||||
if( FSSetForkPosition(id->refNum, fsFromStart, offset) != noErr ){
|
||||
# else
|
||||
if( SetFPos(id->refNum, fsFromStart, offset) != noErr ){
|
||||
# endif
|
||||
return SQLITE_IOERR;
|
||||
}else{
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Make sure all writes to a particular file are committed to disk.
|
||||
**
|
||||
** Under Unix, also make sure that the directory entry for the file
|
||||
** has been created by fsync-ing the directory that contains the file.
|
||||
** If we do not do this and we encounter a power failure, the directory
|
||||
** entry for the journal might not exist after we reboot. The next
|
||||
** SQLite to access the file will not know that the journal exists (because
|
||||
** the directory entry for the journal was never created) and the transaction
|
||||
** will not roll back - possibly leading to database corruption.
|
||||
*/
|
||||
int sqlite3OsSync(OsFile *id){
|
||||
# ifdef _LARGE_FILE
|
||||
if( FSFlushFork(id->refNum) != noErr ){
|
||||
# else
|
||||
ParamBlockRec params;
|
||||
memset(¶ms, 0, sizeof(ParamBlockRec));
|
||||
params.ioParam.ioRefNum = id->refNum;
|
||||
if( PBFlushFileSync(¶ms) != noErr ){
|
||||
# endif
|
||||
return SQLITE_IOERR;
|
||||
}else{
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Truncate an open file to a specified size
|
||||
*/
|
||||
int sqlite3OsTruncate(OsFile *id, off_t nByte){
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
# ifdef _LARGE_FILE
|
||||
if( FSSetForkSize(id->refNum, fsFromStart, nByte) != noErr){
|
||||
# else
|
||||
if( SetEOF(id->refNum, nByte) != noErr ){
|
||||
# endif
|
||||
return SQLITE_IOERR;
|
||||
}else{
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Determine the current size of a file in bytes
|
||||
*/
|
||||
int sqlite3OsFileSize(OsFile *id, off_t *pSize){
|
||||
# ifdef _LARGE_FILE
|
||||
if( FSGetForkSize(id->refNum, pSize) != noErr){
|
||||
# else
|
||||
if( GetEOF(id->refNum, pSize) != noErr ){
|
||||
# endif
|
||||
return SQLITE_IOERR;
|
||||
}else{
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Windows file locking notes: [similar issues apply to MacOS]
|
||||
**
|
||||
** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
|
||||
** those functions are not available. So we use only LockFile() and
|
||||
** UnlockFile().
|
||||
**
|
||||
** LockFile() prevents not just writing but also reading by other processes.
|
||||
** (This is a design error on the part of Windows, but there is nothing
|
||||
** we can do about that.) So the region used for locking is at the
|
||||
** end of the file where it is unlikely to ever interfere with an
|
||||
** actual read attempt.
|
||||
**
|
||||
** A database read lock is obtained by locking a single randomly-chosen
|
||||
** byte out of a specific range of bytes. The lock byte is obtained at
|
||||
** random so two separate readers can probably access the file at the
|
||||
** same time, unless they are unlucky and choose the same lock byte.
|
||||
** A database write lock is obtained by locking all bytes in the range.
|
||||
** There can only be one writer.
|
||||
**
|
||||
** A lock is obtained on the first byte of the lock range before acquiring
|
||||
** either a read lock or a write lock. This prevents two processes from
|
||||
** attempting to get a lock at a same time. The semantics of
|
||||
** sqlite3OsReadLock() require that if there is already a write lock, that
|
||||
** lock is converted into a read lock atomically. The lock on the first
|
||||
** byte allows us to drop the old write lock and get the read lock without
|
||||
** another process jumping into the middle and messing us up. The same
|
||||
** argument applies to sqlite3OsWriteLock().
|
||||
**
|
||||
** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
|
||||
** which means we can use reader/writer locks. When reader writer locks
|
||||
** are used, the lock is placed on the same range of bytes that is used
|
||||
** for probabilistic locking in Win95/98/ME. Hence, the locking scheme
|
||||
** will support two or more Win95 readers or two or more WinNT readers.
|
||||
** But a single Win95 reader will lock out all WinNT readers and a single
|
||||
** WinNT reader will lock out all other Win95 readers.
|
||||
**
|
||||
** Note: On MacOS we use the resource fork for locking.
|
||||
**
|
||||
** The following #defines specify the range of bytes used for locking.
|
||||
** N_LOCKBYTE is the number of bytes available for doing the locking.
|
||||
** The first byte used to hold the lock while the lock is changing does
|
||||
** not count toward this number. FIRST_LOCKBYTE is the address of
|
||||
** the first byte in the range of bytes used for locking.
|
||||
*/
|
||||
#define N_LOCKBYTE 10239
|
||||
#define FIRST_LOCKBYTE (0x000fffff - N_LOCKBYTE)
|
||||
|
||||
/*
|
||||
** Change the status of the lock on the file "id" to be a readlock.
|
||||
** If the file was write locked, then this reduces the lock to a read.
|
||||
** If the file was read locked, then this acquires a new read lock.
|
||||
**
|
||||
** Return SQLITE_OK on success and SQLITE_BUSY on failure. If this
|
||||
** library was compiled with large file support (LFS) but LFS is not
|
||||
** available on the host, then an SQLITE_NOLFS is returned.
|
||||
*/
|
||||
int sqlite3OsReadLock(OsFile *id){
|
||||
int rc;
|
||||
if( id->locked>0 || id->refNumRF == -1 ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
int lk;
|
||||
OSErr res;
|
||||
int cnt = 5;
|
||||
ParamBlockRec params;
|
||||
sqlite3Randomness(sizeof(lk), &lk);
|
||||
lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.ioParam.ioRefNum = id->refNumRF;
|
||||
params.ioParam.ioPosMode = fsFromStart;
|
||||
params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
|
||||
params.ioParam.ioReqCount = 1;
|
||||
while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){
|
||||
UInt32 finalTicks;
|
||||
Delay(1, &finalTicks); /* 1/60 sec */
|
||||
}
|
||||
if( res == noErr ){
|
||||
params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
|
||||
params.ioParam.ioReqCount = N_LOCKBYTE;
|
||||
PBUnlockRangeSync(¶ms);
|
||||
params.ioParam.ioPosOffset = FIRST_LOCKBYTE+lk;
|
||||
params.ioParam.ioReqCount = 1;
|
||||
res = PBLockRangeSync(¶ms);
|
||||
params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
|
||||
params.ioParam.ioReqCount = 1;
|
||||
PBUnlockRangeSync(¶ms);
|
||||
}
|
||||
if( res == noErr ){
|
||||
id->locked = lk;
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
rc = SQLITE_BUSY;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the lock status to be an exclusive or write lock. Return
|
||||
** SQLITE_OK on success and SQLITE_BUSY on a failure. If this
|
||||
** library was compiled with large file support (LFS) but LFS is not
|
||||
** available on the host, then an SQLITE_NOLFS is returned.
|
||||
*/
|
||||
int sqlite3OsWriteLock(OsFile *id){
|
||||
int rc;
|
||||
if( id->locked<0 || id->refNumRF == -1 ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
OSErr res;
|
||||
int cnt = 5;
|
||||
ParamBlockRec params;
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.ioParam.ioRefNum = id->refNumRF;
|
||||
params.ioParam.ioPosMode = fsFromStart;
|
||||
params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
|
||||
params.ioParam.ioReqCount = 1;
|
||||
while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){
|
||||
UInt32 finalTicks;
|
||||
Delay(1, &finalTicks); /* 1/60 sec */
|
||||
}
|
||||
if( res == noErr ){
|
||||
params.ioParam.ioPosOffset = FIRST_LOCKBYTE + id->locked;
|
||||
params.ioParam.ioReqCount = 1;
|
||||
if( id->locked==0
|
||||
|| PBUnlockRangeSync(¶ms)==noErr ){
|
||||
params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
|
||||
params.ioParam.ioReqCount = N_LOCKBYTE;
|
||||
res = PBLockRangeSync(¶ms);
|
||||
}else{
|
||||
res = afpRangeNotLocked;
|
||||
}
|
||||
params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
|
||||
params.ioParam.ioReqCount = 1;
|
||||
PBUnlockRangeSync(¶ms);
|
||||
}
|
||||
if( res == noErr ){
|
||||
id->locked = -1;
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
rc = SQLITE_BUSY;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Unlock the given file descriptor. If the file descriptor was
|
||||
** not previously locked, then this routine is a no-op. If this
|
||||
** library was compiled with large file support (LFS) but LFS is not
|
||||
** available on the host, then an SQLITE_NOLFS is returned.
|
||||
*/
|
||||
int sqlite3OsUnlock(OsFile *id){
|
||||
int rc;
|
||||
ParamBlockRec params;
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.ioParam.ioRefNum = id->refNumRF;
|
||||
params.ioParam.ioPosMode = fsFromStart;
|
||||
if( id->locked==0 || id->refNumRF == -1 ){
|
||||
rc = SQLITE_OK;
|
||||
}else if( id->locked<0 ){
|
||||
params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
|
||||
params.ioParam.ioReqCount = N_LOCKBYTE;
|
||||
PBUnlockRangeSync(¶ms);
|
||||
rc = SQLITE_OK;
|
||||
id->locked = 0;
|
||||
}else{
|
||||
params.ioParam.ioPosOffset = FIRST_LOCKBYTE+id->locked;
|
||||
params.ioParam.ioReqCount = 1;
|
||||
PBUnlockRangeSync(¶ms);
|
||||
rc = SQLITE_OK;
|
||||
id->locked = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Get information to seed the random number generator. The seed
|
||||
** is written into the buffer zBuf[256]. The calling function must
|
||||
** supply a sufficiently large buffer.
|
||||
*/
|
||||
int sqlite3OsRandomSeed(char *zBuf){
|
||||
/* We have to initialize zBuf to prevent valgrind from reporting
|
||||
** errors. The reports issued by valgrind are incorrect - we would
|
||||
** prefer that the randomness be increased by making use of the
|
||||
** uninitialized space in zBuf - but valgrind errors tend to worry
|
||||
** some users. Rather than argue, it seems easier just to initialize
|
||||
** the whole array and silence valgrind, even if that means less randomness
|
||||
** in the random seed.
|
||||
**
|
||||
** When testing, initializing zBuf[] to zero is all we do. That means
|
||||
** that we always use the same random number sequence.* This makes the
|
||||
** tests repeatable.
|
||||
*/
|
||||
memset(zBuf, 0, 256);
|
||||
#if !defined(SQLITE_TEST)
|
||||
{
|
||||
int pid;
|
||||
Microseconds((UnsignedWide*)zBuf);
|
||||
pid = getpid();
|
||||
memcpy(&zBuf[sizeof(UnsignedWide)], &pid, sizeof(pid));
|
||||
}
|
||||
#endif
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sleep for a little while. Return the amount of time slept.
|
||||
*/
|
||||
int sqlite3OsSleep(int ms){
|
||||
UInt32 finalTicks;
|
||||
UInt32 ticks = (((UInt32)ms+16)*3)/50; /* 1/60 sec per tick */
|
||||
Delay(ticks, &finalTicks);
|
||||
return (int)((ticks*50)/3);
|
||||
}
|
||||
|
||||
/*
|
||||
** Static variables used for thread synchronization
|
||||
*/
|
||||
static int inMutex = 0;
|
||||
#ifdef SQLITE_MACOS_MULTITASKING
|
||||
static MPCriticalRegionID criticalRegion;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The following pair of routine implement mutual exclusion for
|
||||
** multi-threaded processes. Only a single thread is allowed to
|
||||
** executed code that is surrounded by EnterMutex() and LeaveMutex().
|
||||
**
|
||||
** SQLite uses only a single Mutex. There is not much critical
|
||||
** code and what little there is executes quickly and without blocking.
|
||||
*/
|
||||
void sqlite3OsEnterMutex(){
|
||||
#ifdef SQLITE_MACOS_MULTITASKING
|
||||
static volatile int notInit = 1;
|
||||
if( notInit ){
|
||||
if( notInit == 2 ) /* as close as you can get to thread safe init */
|
||||
MPYield();
|
||||
else{
|
||||
notInit = 2;
|
||||
MPCreateCriticalRegion(&criticalRegion);
|
||||
notInit = 0;
|
||||
}
|
||||
}
|
||||
MPEnterCriticalRegion(criticalRegion, kDurationForever);
|
||||
#endif
|
||||
assert( !inMutex );
|
||||
inMutex = 1;
|
||||
}
|
||||
void sqlite3OsLeaveMutex(){
|
||||
assert( inMutex );
|
||||
inMutex = 0;
|
||||
#ifdef SQLITE_MACOS_MULTITASKING
|
||||
MPExitCriticalRegion(criticalRegion);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Turn a relative pathname into a full pathname. Return a pointer
|
||||
** to the full pathname stored in space obtained from sqliteMalloc().
|
||||
** The calling function is responsible for freeing this space once it
|
||||
** is no longer needed.
|
||||
*/
|
||||
char *sqlite3OsFullPathname(const char *zRelative){
|
||||
char *zFull = 0;
|
||||
if( zRelative[0]==':' ){
|
||||
char zBuf[_MAX_PATH+1];
|
||||
sqlite3SetString(&zFull, getcwd(zBuf, sizeof(zBuf)), &(zRelative[1]),
|
||||
(char*)0);
|
||||
}else{
|
||||
if( strchr(zRelative, ':') ){
|
||||
sqlite3SetString(&zFull, zRelative, (char*)0);
|
||||
}else{
|
||||
char zBuf[_MAX_PATH+1];
|
||||
sqlite3SetString(&zFull, getcwd(zBuf, sizeof(zBuf)), zRelative, (char*)0);
|
||||
}
|
||||
}
|
||||
return zFull;
|
||||
}
|
||||
|
||||
/*
|
||||
** The following variable, if set to a non-zero value, becomes the result
|
||||
** returned from sqlite3OsCurrentTime(). This is used for testing.
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3_current_time = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Find the current time (in Universal Coordinated Time). Write the
|
||||
** current time and date as a Julian Day number into *prNow and
|
||||
** return 0. Return 1 if the time and date cannot be found.
|
||||
*/
|
||||
int sqlite3OsCurrentTime(double *prNow){
|
||||
*prNow = 0.0; /**** FIX ME *****/
|
||||
#ifdef SQLITE_TEST
|
||||
if( sqlite3_current_time ){
|
||||
*prNow = sqlite3_current_time/86400.0 + 2440587.5;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* OS_MAC */
|
46
src/os_mac.h
Normal file
46
src/os_mac.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
** 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 defines OS-specific features of classic Mac.
|
||||
** OS X uses the os_unix.h file, not this one.
|
||||
*/
|
||||
#ifndef _SQLITE_OS_MAC_H_
|
||||
#define _SQLITE_OS_MAC_H_
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <Files.h>
|
||||
#ifdef _LARGE_FILE
|
||||
typedef SInt64 off_t;
|
||||
#else
|
||||
typedef SInt32 off_t;
|
||||
#endif
|
||||
#define SQLITE_TEMPNAME_SIZE _MAX_PATH
|
||||
#define SQLITE_MIN_SLEEP_MS 17
|
||||
|
||||
/*
|
||||
** 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 class Mac.
|
||||
*/
|
||||
typedef struct OsFile OsFile;
|
||||
struct OsFile {
|
||||
SInt16 refNum; /* Data fork/file reference number */
|
||||
SInt16 refNumRF; /* Resource fork reference number (for locking) */
|
||||
int locked; /* 0: unlocked, <0: write lock, >0: read lock */
|
||||
int delOnClose; /* True if file is to be deleted on close */
|
||||
char *pathToDel; /* Name of file to delete on close */
|
||||
};
|
||||
|
||||
|
||||
#endif /* _SQLITE_OS_MAC_H_ */
|
File diff suppressed because it is too large
Load Diff
84
src/os_unix.h
Normal file
84
src/os_unix.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
** 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 Unix.
|
||||
*/
|
||||
#ifndef _SQLITE_OS_UNIX_H_
|
||||
#define _SQLITE_OS_UNIX_H_
|
||||
|
||||
/*
|
||||
** Helpful hint: To get this to compile on HP/UX, add -D_INCLUDE_POSIX_SOURCE
|
||||
** to the compiler command line.
|
||||
*/
|
||||
|
||||
/*
|
||||
** These #defines should enable >2GB file support on Posix if the
|
||||
** underlying operating system supports it. If the OS lacks
|
||||
** large file support, or if the OS is windows, these should be no-ops.
|
||||
**
|
||||
** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
|
||||
** on the compiler command line. This is necessary if you are compiling
|
||||
** on a recent machine (ex: RedHat 7.2) but you want your code to work
|
||||
** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
|
||||
** without this option, LFS is enable. But LFS does not exist in the kernel
|
||||
** in RedHat 6.0, so the code won't work. Hence, for maximum binary
|
||||
** portability you should omit LFS.
|
||||
**
|
||||
** Similar is true for MacOS. LFS is only supported on MacOS 9 and later.
|
||||
*/
|
||||
#ifndef SQLITE_DISABLE_LFS
|
||||
# define _LARGE_FILE 1
|
||||
# ifndef _FILE_OFFSET_BITS
|
||||
# define _FILE_OFFSET_BITS 64
|
||||
# endif
|
||||
# define _LARGEFILE_SOURCE 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** standard include files.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
** 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.
|
||||
*/
|
||||
typedef struct OsFile OsFile;
|
||||
struct OsFile {
|
||||
struct openCnt *pOpen; /* Info about all open fd's on this inode */
|
||||
struct lockInfo *pLock; /* Info about locks on this inode */
|
||||
int fd; /* The file descriptor */
|
||||
int locked; /* True if this instance holds the lock */
|
||||
int dirfd; /* File descriptor for the directory */
|
||||
};
|
||||
|
||||
/*
|
||||
** Maximum number of characters in a temporary file name
|
||||
*/
|
||||
#define SQLITE_TEMPNAME_SIZE 200
|
||||
|
||||
/*
|
||||
** Minimum interval supported by sqlite3OsSleep().
|
||||
*/
|
||||
#if defined(HAVE_USLEEP) && HAVE_USLEEP
|
||||
# define SQLITE_MIN_SLEEP_MS 1
|
||||
#else
|
||||
# define SQLITE_MIN_SLEEP_MS 1000
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _SQLITE_OS_UNIX_H_ */
|
601
src/os_win.c
Normal file
601
src/os_win.c
Normal file
@@ -0,0 +1,601 @@
|
||||
/*
|
||||
** 2004 May 22
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This file contains code that is specific to windows.
|
||||
*/
|
||||
#include "os.h" /* Must be first to enable large file support */
|
||||
#if OS_WIN /* This file is used for windows only */
|
||||
#include "sqliteInt.h"
|
||||
|
||||
#include <winbase.h>
|
||||
|
||||
/*
|
||||
** Macros used to determine whether or not to use threads.
|
||||
*/
|
||||
#if defined(THREADSAFE) && THREADSAFE
|
||||
# define SQLITE_W32_THREADS 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Include code that is common to all os_*.c files
|
||||
*/
|
||||
#include "os_common.h"
|
||||
|
||||
/*
|
||||
** Delete the named file
|
||||
*/
|
||||
int sqlite3OsDelete(const char *zFilename){
|
||||
DeleteFile(zFilename);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the named file exists.
|
||||
*/
|
||||
int sqlite3OsFileExists(const char *zFilename){
|
||||
return GetFileAttributes(zFilename) != 0xffffffff;
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to open a file for both reading and writing. If that
|
||||
** fails, try opening it read-only. If the file does not exist,
|
||||
** try to create it.
|
||||
**
|
||||
** On success, a handle for the open file is written to *id
|
||||
** and *pReadonly is set to 0 if the file was opened for reading and
|
||||
** writing or 1 if the file was opened read-only. The function returns
|
||||
** SQLITE_OK.
|
||||
**
|
||||
** On failure, the function returns SQLITE_CANTOPEN and leaves
|
||||
** *id and *pReadonly unchanged.
|
||||
*/
|
||||
int sqlite3OsOpenReadWrite(
|
||||
const char *zFilename,
|
||||
OsFile *id,
|
||||
int *pReadonly
|
||||
){
|
||||
HANDLE h = CreateFile(zFilename,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
||||
NULL
|
||||
);
|
||||
if( h==INVALID_HANDLE_VALUE ){
|
||||
h = CreateFile(zFilename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
||||
NULL
|
||||
);
|
||||
if( h==INVALID_HANDLE_VALUE ){
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
*pReadonly = 1;
|
||||
}else{
|
||||
*pReadonly = 0;
|
||||
}
|
||||
id->h = h;
|
||||
id->locked = 0;
|
||||
OpenCounter(+1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Attempt to open a new file for exclusive access by this process.
|
||||
** The file will be opened for both reading and writing. To avoid
|
||||
** a potential security problem, we do not allow the file to have
|
||||
** previously existed. Nor do we allow the file to be a symbolic
|
||||
** link.
|
||||
**
|
||||
** If delFlag is true, then make arrangements to automatically delete
|
||||
** the file when it is closed.
|
||||
**
|
||||
** On success, write the file handle into *id and return SQLITE_OK.
|
||||
**
|
||||
** On failure, return SQLITE_CANTOPEN.
|
||||
*/
|
||||
int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
|
||||
HANDLE h;
|
||||
int fileflags;
|
||||
if( delFlag ){
|
||||
fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS
|
||||
| FILE_FLAG_DELETE_ON_CLOSE;
|
||||
}else{
|
||||
fileflags = FILE_FLAG_RANDOM_ACCESS;
|
||||
}
|
||||
h = CreateFile(zFilename,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
fileflags,
|
||||
NULL
|
||||
);
|
||||
if( h==INVALID_HANDLE_VALUE ){
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
id->h = h;
|
||||
id->locked = 0;
|
||||
OpenCounter(+1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to open a new file for read-only access.
|
||||
**
|
||||
** On success, write the file handle into *id and return SQLITE_OK.
|
||||
**
|
||||
** On failure, return SQLITE_CANTOPEN.
|
||||
*/
|
||||
int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){
|
||||
HANDLE h = CreateFile(zFilename,
|
||||
GENERIC_READ,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
||||
NULL
|
||||
);
|
||||
if( h==INVALID_HANDLE_VALUE ){
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
id->h = h;
|
||||
id->locked = 0;
|
||||
OpenCounter(+1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to open a file descriptor for the directory that contains a
|
||||
** file. This file descriptor can be used to fsync() the directory
|
||||
** in order to make sure the creation of a new file is actually written
|
||||
** to disk.
|
||||
**
|
||||
** This routine is only meaningful for Unix. It is a no-op under
|
||||
** windows since windows does not support hard links.
|
||||
**
|
||||
** On success, a handle for a previously open file is at *id is
|
||||
** updated with the new directory file descriptor and SQLITE_OK is
|
||||
** returned.
|
||||
**
|
||||
** On failure, the function returns SQLITE_CANTOPEN and leaves
|
||||
** *id unchanged.
|
||||
*/
|
||||
int sqlite3OsOpenDirectory(
|
||||
const char *zDirname,
|
||||
OsFile *id
|
||||
){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a temporary file name in zBuf. zBuf must be big enough to
|
||||
** hold at least SQLITE_TEMPNAME_SIZE characters.
|
||||
*/
|
||||
int sqlite3OsTempFileName(char *zBuf){
|
||||
static char zChars[] =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
int i, j;
|
||||
char zTempPath[SQLITE_TEMPNAME_SIZE];
|
||||
GetTempPath(SQLITE_TEMPNAME_SIZE-30, zTempPath);
|
||||
for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
|
||||
zTempPath[i] = 0;
|
||||
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;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close a file.
|
||||
*/
|
||||
int sqlite3OsClose(OsFile *id){
|
||||
CloseHandle(id->h);
|
||||
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 sqlite3OsRead(OsFile *id, void *pBuf, int amt){
|
||||
DWORD got;
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
TRACE2("READ %d\n", last_page);
|
||||
if( !ReadFile(id->h, pBuf, amt, &got, 0) ){
|
||||
got = 0;
|
||||
}
|
||||
if( got==(DWORD)amt ){
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Write data from a buffer into a file. Return SQLITE_OK on success
|
||||
** or some other error code on failure.
|
||||
*/
|
||||
int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
|
||||
int rc;
|
||||
DWORD wrote;
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
TRACE2("WRITE %d\n", last_page);
|
||||
while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){
|
||||
amt -= wrote;
|
||||
pBuf = &((char*)pBuf)[wrote];
|
||||
}
|
||||
if( !rc || amt>(int)wrote ){
|
||||
return SQLITE_FULL;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Move the read/write pointer in a file.
|
||||
*/
|
||||
int sqlite3OsSeek(OsFile *id, off_t offset){
|
||||
LONG upperBits = offset>>32;
|
||||
LONG lowerBits = offset & 0xffffffff;
|
||||
DWORD rc;
|
||||
SEEK(offset/1024 + 1);
|
||||
rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN);
|
||||
/* TRACE3("SEEK rc=0x%x upper=0x%x\n", rc, upperBits); */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Make sure all writes to a particular file are committed to disk.
|
||||
*/
|
||||
int sqlite3OsSync(OsFile *id){
|
||||
if( FlushFileBuffers(id->h) ){
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Truncate an open file to a specified size
|
||||
*/
|
||||
int sqlite3OsTruncate(OsFile *id, off_t nByte){
|
||||
LONG upperBits = nByte>>32;
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN);
|
||||
SetEndOfFile(id->h);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Determine the current size of a file in bytes
|
||||
*/
|
||||
int sqlite3OsFileSize(OsFile *id, off_t *pSize){
|
||||
DWORD upperBits, lowerBits;
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
lowerBits = GetFileSize(id->h, &upperBits);
|
||||
*pSize = (((off_t)upperBits)<<32) + lowerBits;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.
|
||||
** Return false (zero) for Win95, Win98, or WinME.
|
||||
**
|
||||
** Here is an interesting observation: Win95, Win98, and WinME lack
|
||||
** the LockFileEx() API. But we can still statically link against that
|
||||
** API as long as we don't call it win running Win95/98/ME. A call to
|
||||
** this routine is used to determine if the host is Win95/98/ME or
|
||||
** WinNT/2K/XP so that we will know whether or not we can safely call
|
||||
** the LockFileEx() API.
|
||||
*/
|
||||
int isNT(void){
|
||||
static int osType = 0; /* 0=unknown 1=win95 2=winNT */
|
||||
if( osType==0 ){
|
||||
OSVERSIONINFO sInfo;
|
||||
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
||||
GetVersionEx(&sInfo);
|
||||
osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
|
||||
}
|
||||
return osType==2;
|
||||
}
|
||||
|
||||
/*
|
||||
** Windows file locking notes:
|
||||
**
|
||||
** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
|
||||
** those functions are not available. So we use only LockFile() and
|
||||
** UnlockFile().
|
||||
**
|
||||
** LockFile() prevents not just writing but also reading by other processes.
|
||||
** (This is a design error on the part of Windows, but there is nothing
|
||||
** we can do about that.) So the region used for locking is at the
|
||||
** end of the file where it is unlikely to ever interfere with an
|
||||
** actual read attempt.
|
||||
**
|
||||
** A database read lock is obtained by locking a single randomly-chosen
|
||||
** byte out of a specific range of bytes. The lock byte is obtained at
|
||||
** random so two separate readers can probably access the file at the
|
||||
** same time, unless they are unlucky and choose the same lock byte.
|
||||
** A database write lock is obtained by locking all bytes in the range.
|
||||
** There can only be one writer.
|
||||
**
|
||||
** A lock is obtained on the first byte of the lock range before acquiring
|
||||
** either a read lock or a write lock. This prevents two processes from
|
||||
** attempting to get a lock at a same time. The semantics of
|
||||
** sqlite3OsReadLock() require that if there is already a write lock, that
|
||||
** lock is converted into a read lock atomically. The lock on the first
|
||||
** byte allows us to drop the old write lock and get the read lock without
|
||||
** another process jumping into the middle and messing us up. The same
|
||||
** argument applies to sqlite3OsWriteLock().
|
||||
**
|
||||
** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
|
||||
** which means we can use reader/writer locks. When reader writer locks
|
||||
** are used, the lock is placed on the same range of bytes that is used
|
||||
** for probabilistic locking in Win95/98/ME. Hence, the locking scheme
|
||||
** will support two or more Win95 readers or two or more WinNT readers.
|
||||
** But a single Win95 reader will lock out all WinNT readers and a single
|
||||
** WinNT reader will lock out all other Win95 readers.
|
||||
**
|
||||
** The following #defines specify the range of bytes used for locking.
|
||||
** N_LOCKBYTE is the number of bytes available for doing the locking.
|
||||
** The first byte used to hold the lock while the lock is changing does
|
||||
** not count toward this number. FIRST_LOCKBYTE is the address of
|
||||
** the first byte in the range of bytes used for locking.
|
||||
*/
|
||||
#define N_LOCKBYTE 10239
|
||||
#define FIRST_LOCKBYTE (0xffffffff - N_LOCKBYTE)
|
||||
|
||||
/*
|
||||
** Change the status of the lock on the file "id" to be a readlock.
|
||||
** If the file was write locked, then this reduces the lock to a read.
|
||||
** If the file was read locked, then this acquires a new read lock.
|
||||
**
|
||||
** Return SQLITE_OK on success and SQLITE_BUSY on failure. If this
|
||||
** library was compiled with large file support (LFS) but LFS is not
|
||||
** available on the host, then an SQLITE_NOLFS is returned.
|
||||
*/
|
||||
int sqlite3OsReadLock(OsFile *id){
|
||||
int rc;
|
||||
if( id->locked>0 ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
int lk;
|
||||
int res;
|
||||
int cnt = 100;
|
||||
sqlite3Randomness(sizeof(lk), &lk);
|
||||
lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;
|
||||
while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
|
||||
Sleep(1);
|
||||
}
|
||||
if( res ){
|
||||
UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
|
||||
if( isNT() ){
|
||||
OVERLAPPED ovlp;
|
||||
ovlp.Offset = FIRST_LOCKBYTE+1;
|
||||
ovlp.OffsetHigh = 0;
|
||||
ovlp.hEvent = 0;
|
||||
res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY,
|
||||
0, N_LOCKBYTE, 0, &ovlp);
|
||||
}else{
|
||||
res = LockFile(id->h, FIRST_LOCKBYTE+lk, 0, 1, 0);
|
||||
}
|
||||
UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
|
||||
}
|
||||
if( res ){
|
||||
id->locked = lk;
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
rc = SQLITE_BUSY;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the lock status to be an exclusive or write lock. Return
|
||||
** SQLITE_OK on success and SQLITE_BUSY on a failure. If this
|
||||
** library was compiled with large file support (LFS) but LFS is not
|
||||
** available on the host, then an SQLITE_NOLFS is returned.
|
||||
*/
|
||||
int sqlite3OsWriteLock(OsFile *id){
|
||||
int rc;
|
||||
if( id->locked<0 ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
int res;
|
||||
int cnt = 100;
|
||||
while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
|
||||
Sleep(1);
|
||||
}
|
||||
if( res ){
|
||||
if( id->locked>0 ){
|
||||
if( isNT() ){
|
||||
UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
|
||||
}else{
|
||||
res = UnlockFile(id->h, FIRST_LOCKBYTE + id->locked, 0, 1, 0);
|
||||
}
|
||||
}
|
||||
if( res ){
|
||||
res = LockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
|
||||
}else{
|
||||
res = 0;
|
||||
}
|
||||
UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
|
||||
}
|
||||
if( res ){
|
||||
id->locked = -1;
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
rc = SQLITE_BUSY;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Unlock the given file descriptor. If the file descriptor was
|
||||
** not previously locked, then this routine is a no-op. If this
|
||||
** library was compiled with large file support (LFS) but LFS is not
|
||||
** available on the host, then an SQLITE_NOLFS is returned.
|
||||
*/
|
||||
int sqlite3OsUnlock(OsFile *id){
|
||||
int rc;
|
||||
if( id->locked==0 ){
|
||||
rc = SQLITE_OK;
|
||||
}else if( isNT() || id->locked<0 ){
|
||||
UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
|
||||
rc = SQLITE_OK;
|
||||
id->locked = 0;
|
||||
}else{
|
||||
UnlockFile(id->h, FIRST_LOCKBYTE+id->locked, 0, 1, 0);
|
||||
rc = SQLITE_OK;
|
||||
id->locked = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Get information to seed the random number generator. The seed
|
||||
** is written into the buffer zBuf[256]. The calling function must
|
||||
** supply a sufficiently large buffer.
|
||||
*/
|
||||
int sqlite3OsRandomSeed(char *zBuf){
|
||||
/* We have to initialize zBuf to prevent valgrind from reporting
|
||||
** errors. The reports issued by valgrind are incorrect - we would
|
||||
** prefer that the randomness be increased by making use of the
|
||||
** uninitialized space in zBuf - but valgrind errors tend to worry
|
||||
** some users. Rather than argue, it seems easier just to initialize
|
||||
** the whole array and silence valgrind, even if that means less randomness
|
||||
** in the random seed.
|
||||
**
|
||||
** When testing, initializing zBuf[] to zero is all we do. That means
|
||||
** that we always use the same random number sequence.* This makes the
|
||||
** tests repeatable.
|
||||
*/
|
||||
memset(zBuf, 0, 256);
|
||||
GetSystemTime((LPSYSTEMTIME)zBuf);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sleep for a little while. Return the amount of time slept.
|
||||
*/
|
||||
int sqlite3OsSleep(int ms){
|
||||
Sleep(ms);
|
||||
return ms;
|
||||
}
|
||||
|
||||
/*
|
||||
** Static variables used for thread synchronization
|
||||
*/
|
||||
static int inMutex = 0;
|
||||
#ifdef SQLITE_W32_THREADS
|
||||
static CRITICAL_SECTION cs;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The following pair of routine implement mutual exclusion for
|
||||
** multi-threaded processes. Only a single thread is allowed to
|
||||
** executed code that is surrounded by EnterMutex() and LeaveMutex().
|
||||
**
|
||||
** SQLite uses only a single Mutex. There is not much critical
|
||||
** code and what little there is executes quickly and without blocking.
|
||||
*/
|
||||
void sqlite3OsEnterMutex(){
|
||||
#ifdef SQLITE_W32_THREADS
|
||||
static int isInit = 0;
|
||||
while( !isInit ){
|
||||
static long lock = 0;
|
||||
if( InterlockedIncrement(&lock)==1 ){
|
||||
InitializeCriticalSection(&cs);
|
||||
isInit = 1;
|
||||
}else{
|
||||
Sleep(1);
|
||||
}
|
||||
}
|
||||
EnterCriticalSection(&cs);
|
||||
#endif
|
||||
assert( !inMutex );
|
||||
inMutex = 1;
|
||||
}
|
||||
void sqlite3OsLeaveMutex(){
|
||||
assert( inMutex );
|
||||
inMutex = 0;
|
||||
#ifdef SQLITE_W32_THREADS
|
||||
LeaveCriticalSection(&cs);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Turn a relative pathname into a full pathname. Return a pointer
|
||||
** to the full pathname stored in space obtained from sqliteMalloc().
|
||||
** The calling function is responsible for freeing this space once it
|
||||
** is no longer needed.
|
||||
*/
|
||||
char *sqlite3OsFullPathname(const char *zRelative){
|
||||
char *zNotUsed;
|
||||
char *zFull;
|
||||
int nByte;
|
||||
nByte = GetFullPathName(zRelative, 0, 0, &zNotUsed) + 1;
|
||||
zFull = sqliteMalloc( nByte );
|
||||
if( zFull==0 ) return 0;
|
||||
GetFullPathName(zRelative, nByte, zFull, &zNotUsed);
|
||||
return zFull;
|
||||
}
|
||||
|
||||
/*
|
||||
** The following variable, if set to a non-zero value, becomes the result
|
||||
** returned from sqlite3OsCurrentTime(). This is used for testing.
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3_current_time = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Find the current time (in Universal Coordinated Time). Write the
|
||||
** current time and date as a Julian Day number into *prNow and
|
||||
** return 0. Return 1 if the time and date cannot be found.
|
||||
*/
|
||||
int sqlite3OsCurrentTime(double *prNow){
|
||||
FILETIME ft;
|
||||
/* FILETIME structure is a 64-bit value representing the number of
|
||||
100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
|
||||
*/
|
||||
double now;
|
||||
GetSystemTimeAsFileTime( &ft );
|
||||
now = ((double)ft.dwHighDateTime) * 4294967296.0;
|
||||
*prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;
|
||||
#ifdef SQLITE_TEST
|
||||
if( sqlite3_current_time ){
|
||||
*prNow = sqlite3_current_time/86400.0 + 2440587.5;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* OS_WIN */
|
49
src/os_win.h
Normal file
49
src/os_win.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
** 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 defines OS-specific features for Win32
|
||||
*/
|
||||
#ifndef _SQLITE_OS_WIN_H_
|
||||
#define _SQLITE_OS_WIN_H_
|
||||
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef __int64 off_t;
|
||||
#else
|
||||
# if !defined(_CYGWIN_TYPES_H)
|
||||
typedef long long off_t;
|
||||
# if defined(__MINGW32__)
|
||||
# define _OFF_T_
|
||||
# endif
|
||||
# endif
|
||||
#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 Win32.
|
||||
*/
|
||||
typedef struct OsFile OsFile;
|
||||
struct OsFile {
|
||||
HANDLE h; /* Handle for accessing the file */
|
||||
int locked; /* 0: unlocked, <0: write lock, >0: read lock */
|
||||
};
|
||||
|
||||
|
||||
#define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
|
||||
#define SQLITE_MIN_SLEEP_MS 1
|
||||
|
||||
|
||||
#endif /* _SQLITE_OS_WIN_H_ */
|
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.245 2004/05/22 03:05:34 danielk1977 Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.246 2004/05/22 17:41:59 drh Exp $
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "sqlite.h"
|
||||
@@ -129,6 +129,14 @@ typedef UINT8_TYPE i8; /* 1-byte signed integer */
|
||||
typedef INTPTR_TYPE ptr; /* Big enough to hold a pointer */
|
||||
typedef unsigned INTPTR_TYPE uptr; /* Big enough to hold a pointer */
|
||||
|
||||
/*
|
||||
** Macros to determine whether the machine is big or little endian,
|
||||
** evaluated at runtime.
|
||||
*/
|
||||
extern const int sqlite3one;
|
||||
#define SQLITE3_BIGENDIAN (*(char *)(&sqlite3one)==0)
|
||||
#define SQLITE3_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
|
||||
|
||||
/*
|
||||
** Defer sourcing vdbe.h until after the "u8" typedef is defined.
|
||||
*/
|
||||
|
@@ -12,7 +12,7 @@
|
||||
** This file contains routines used to translate between UTF-8,
|
||||
** UTF-16, UTF-16BE, and UTF-16LE.
|
||||
**
|
||||
** $Id: utf.c,v 1.7 2004/05/22 03:05:34 danielk1977 Exp $
|
||||
** $Id: utf.c,v 1.8 2004/05/22 17:41:59 drh Exp $
|
||||
**
|
||||
** Notes on UTF-8:
|
||||
**
|
||||
@@ -49,11 +49,8 @@
|
||||
** replacement character U+FFFD for each pair of bytes that cannot be
|
||||
** interpeted as part of a valid unicode character.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
|
||||
typedef struct UtfString UtfString;
|
||||
struct UtfString {
|
||||
@@ -590,5 +587,3 @@ int sqlite3utfTranslate(
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user