/ Check-in [30a0132a]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Work toward cleaning up and refactoring the os_unix.c VFS module. Change IS_VXWORKS to OS_VXWORKS. The VxWorks implementation can now be built and tested on Linux using -DOS_VXWORKS=1 -Dsem_t=int -DPATH_MAX=512 -DNO_GETTOD=1. (CVS 5942)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 30a0132a83ce95d45f106fce1439e7509fdc64d1
User & Date: drh 2008-11-21 20:32:34
Context
2008-11-21
22:21
Factor out and simplify the canonical pathname logic in the VxWorks OS interface. (CVS 5943) check-in: adb0aafa user: drh tags: trunk
20:32
Work toward cleaning up and refactoring the os_unix.c VFS module. Change IS_VXWORKS to OS_VXWORKS. The VxWorks implementation can now be built and tested on Linux using -DOS_VXWORKS=1 -Dsem_t=int -DPATH_MAX=512 -DNO_GETTOD=1. (CVS 5942) check-in: 30a0132a user: drh tags: trunk
16:58
Fix the OOM handling for explain statements so that it is the same as for regular statements if the OOM error occurs from within a call to sqlite3_column_text() or text16(). (CVS 5941) check-in: 891b14e1 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
37
38
39
40
41
42
43
44
45
46

47
48
49
50

51
52
53
54
55
56
57
..
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
...
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
...
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
...
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
...
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
...
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
...
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
...
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
...
662
663
664
665
666
667
668























































669

























































































670
671
672
673
674
675
676
...
753
754
755
756
757
758
759




















































































































760
761
762
763
764
765
766
...
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
...
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
...
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
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
....
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
....
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
....
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
....
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
....
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
....
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
....
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
....
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
....
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
....
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
....
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
....
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
....
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
....
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
....
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
....
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
....
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
....
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
....
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
....
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
....
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
....
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
....
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
....
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
....
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
....
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
....
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
....
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
....
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
....
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
....
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
....
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
....
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
....
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
....
4282
4283
4284
4285
4286
4287
4288




4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
....
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
**    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 Unix systems.
**
** $Id: os_unix.c,v 1.218 2008/11/21 00:24:42 drh Exp $
*/
#include "sqliteInt.h"
#if SQLITE_OS_UNIX              /* This file is used on unix only */

/*
** If SQLITE_ENABLE_LOCKING_STYLE is defined and is non-zero, then several
** alternative locking implementations are provided:
................................................................................
#    define SQLITE_ENABLE_LOCKING_STYLE 1
#  else
#    define SQLITE_ENABLE_LOCKING_STYLE 0
#  endif
#endif

/*
** Define the IS_VXWORKS pre-processor macro to 1 if building on 
** vxworks, or 0 otherwise.
*/

#if defined(__RTP__) || defined(_WRS_KERNEL)
#  define IS_VXWORKS 1
#else
#  define IS_VXWORKS 0

#endif

/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it.  If the OS lacks
** large file support, these should be no-ops.
**
................................................................................
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>

#if SQLITE_ENABLE_LOCKING_STYLE
# include <sys/ioctl.h>
# if IS_VXWORKS
#  define lstat stat
#  include <semaphore.h>
#  include <limits.h>
# else
#  include <sys/param.h>
#  include <sys/mount.h>
# endif
................................................................................
/*
** The unixFile structure is subclass of sqlite3_file specific for the unix
** protability layer.
*/
typedef struct unixFile unixFile;
struct unixFile {
  sqlite3_io_methods const *pMethod;  /* Always the first entry */

















#ifdef SQLITE_TEST
  /* In test mode, increase the size of this structure a bit so that 
  ** it is larger than the struct CrashFile defined in test6.c.
  */
  char aPadding[32];
#endif
  struct openCnt *pOpen;    /* Info about all open fd's on this inode */
  struct lockInfo *pLock;   /* Info about locks on this inode */
#if SQLITE_ENABLE_LOCKING_STYLE
  void *lockingContext;     /* Locking style specific state */
#endif
  int h;                    /* The file descriptor */
  unsigned char locktype;   /* The type of lock held on this fd */
  int dirfd;                /* File descriptor for the directory */
#if SQLITE_THREADSAFE
  pthread_t tid;            /* The thread that "owns" this unixFile */
#endif
  int lastErrno;            /* The unix errno from the last I/O error */
#if IS_VXWORKS
  int isDelete;             /* Delete on close if true */
  char *zRealpath;
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
  int oflags;               /* The flags specified at open */
#endif
};

/*
** Include code that is common to all os_*.c files
*/
#include "os_common.h"

................................................................................
*/
#if SQLITE_THREADSAFE
#define threadid pthread_self()
#else
#define threadid 0
#endif

/*
** Set or check the unixFile.tid field.  This field is set when an unixFile
** is first opened.  All subsequent uses of the unixFile verify that the
** same thread is operating on the unixFile.  Some operating systems do
** not allow locks to be overridden by other threads and that restriction
** means that sqlite3* database handles cannot be moved from one thread
** to another.  This logic makes sure a user does not try to do that
** by mistake.
**
** Version 3.3.1 (2006-01-15):  unixFile can be moved from one thread to
** another as long as we are running on a system that supports threads
** overriding each others locks (which now the most common behavior)
** or if no locks are held.  But the unixFile.pLock field needs to be
** recomputed because its key includes the thread-id.  See the 
** transferOwnership() function below for additional information
*/
#if SQLITE_THREADSAFE
# define SET_THREADID(X)   (X)->tid = pthread_self()
# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \
                            !pthread_equal((X)->tid, pthread_self()))
#else
# define SET_THREADID(X)
# define CHECK_THREADID(X) 0
#endif




/*
** Here is the dirt on POSIX advisory locks:  ANSI STD 1003.1 (1996)
** section 6.5.2.2 lines 483 through 490 specify that when a process
** sets or clears a lock, that operation overrides any prior locks set
** by the same process.  It does not explicitly say so, but this implies
** that it overrides locks set by the same process using a different
** file descriptor.  Consider this test case:


**       int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
**
** Suppose ./file1 and ./file2 are really the same file (because
** one is a hard or symbolic link to the other) then if you set
** an exclusive lock on fd1, then try to get an exclusive lock
** on fd2, it works.  I would have expected the second lock to
** fail since there was already a lock on the file due to fd1.
................................................................................
** More recent discoveries about POSIX advisory locks.  (The more
** I discover, the more I realize the a POSIX advisory locks are
** an abomination.)
**
** If you close a file descriptor that points to a file that has locks,
** all locks on that file that are owned by the current process are
** released.  To work around this problem, each unixFile structure contains
** a pointer to an openCnt structure.  There is one openCnt structure
** per open inode, which means that multiple unixFile can point to a single
** openCnt.  When an attempt is made to close an unixFile, if there are
** other unixFile open on the same inode that are holding locks, the call
** to close() the file descriptor is deferred until all of the locks clear.
** The openCnt structure keeps a list of file descriptors that need to
** be closed and that list is walked (and cleared) when the last lock
** clears.
**
** First, under Linux threads, because each thread has a separate
** process ID, lock operations in one thread do not override locks
** to the same file in other threads.  Linux threads behave like
** separate processes in this respect.  But, if you close a file
** descriptor in linux threads, all locks are cleared, even locks
** on other threads and even though the other threads have different
** process IDs.  Linux threads is inconsistent in this respect.
** (I'm beginning to think that linux threads is an abomination too.)
** The consequence of this all is that the hash table for the lockInfo
** structure has to include the process id as part of its key because
** locks in different threads are treated as distinct.  But the 
** openCnt structure should not include the process id in its
** key because close() clears lock on all threads, not just the current
** thread.  Were it not for this goofiness in linux threads, we could
** combine the lockInfo and openCnt structures into a single structure.
**
** 2004-Jun-28:
** On some versions of linux, threads can override each others locks.
** On others not.  Sometimes you can change the behavior on the same
** system by setting the LD_ASSUME_KERNEL environment variable.  The
** POSIX standard is silent as to which behavior is correct, as far
** as I can tell, so other versions of unix might show the same
................................................................................
** To work around the inconsistencies, we have to test at runtime 
** whether or not threads can override each others locks.  This test
** is run once, the first time any lock is attempted.  A static 
** variable is set to record the results of this test for future
** use.
*/

/*

























** An instance of the following structure serves as the key used














** to locate a particular lockInfo structure given its inode.
**
** If threads cannot override each others locks, then we set the
** lockKey.tid field to the thread ID.  If threads can override
** each others locks then tid is always set to zero.  tid is omitted
** if we compile without threading support.
*/
struct lockKey {
  dev_t dev;       /* Device number */
#if IS_VXWORKS
  void *rnam;      /* Realname since inode unusable */
#else
  ino_t ino;       /* Inode number */
#endif
#if SQLITE_THREADSAFE
  pthread_t tid;   /* Thread ID or zero if threads can override each other */
#endif
};

/*
** An instance of the following structure is allocated for each open
** inode on each thread with a different process ID.  (Threads have
** different process IDs on linux, but not on most other unixes.)
**
** A single inode can have multiple file descriptors, so each unixFile
** structure contains a pointer to an instance of this object and this
** object keeps a count of the number of unixFile pointing to it.
*/
struct lockInfo {
  struct lockKey key;  /* The lookup key */
  int cnt;             /* Number of SHARED locks held */
  int locktype;        /* One of SHARED_LOCK, RESERVED_LOCK etc. */
  int nRef;            /* Number of pointers to this structure */
  struct lockInfo *pNext, *pPrev;   /* List of all lockInfo objects */
};

/*
** An instance of the following structure serves as the key used
** to locate a particular openCnt structure given its inode.  This
** is the same as the lockKey except that the thread ID is omitted.
*/
struct openKey {
  dev_t dev;   /* Device number */
#if IS_VXWORKS
  void *rnam;  /* Realname since inode unusable */
#else
  ino_t ino;   /* Inode number */
#endif
};

/*
** An instance of the following structure is allocated for each open
** inode.  This structure keeps track of the number of locks on that
** inode.  If a close is attempted against an inode that is holding
** locks, the close is deferred until all locks clear by adding the
** file descriptor to be closed to the pending list.
*/
struct openCnt {
  struct openKey key;   /* The lookup key */
  int nRef;             /* Number of pointers to this structure */
  int nLock;            /* Number of outstanding locks */
  int nPending;         /* Number of pending close() operations */
  int *aPending;        /* Malloced space holding fd's awaiting a close() */
#if IS_VXWORKS
  sem_t *pSem;          /* Named POSIX semaphore */
  char aSemName[MAX_PATHNAME+1];   /* Name of that semaphore */
#endif
  struct openCnt *pNext, *pPrev;   /* List of all openCnt objects */
};

/*
** List of all lockInfo and openCnt objects.  This used to be a hash
** table.  But the number of objects is rarely more than a dozen and
** never exceeds a few thousand.  And lookup is not on a critical
** path oo a simple linked list will suffice.
*/
static struct lockInfo *lockList = 0;
static struct openCnt *openList = 0;

#ifdef SQLITE_TEST
/* simulate multiple hosts by creating unique hostid file paths */
int sqlite3_hostid_num = 0;
#endif


#if IS_VXWORKS
/*
** This hash table is used to bind the canonical file name to a
** unixFile structure and use the hash key (= canonical name)
** instead of the Inode number of the file to find the matching
** lockInfo and openCnt structures. It also helps to make the
** name of the semaphore when LOCKING_STYLE_NAMEDSEM is used
** for the file.
*/
static Hash nameHash;
#endif

/*
** The locking styles are associated with the different file locking
** capabilities supported by different file systems.  
**
** POSIX locking style fully supports shared and exclusive byte-range locks 
** AFP locking only supports exclusive byte-range locks
** FLOCK only supports a single file-global exclusive lock
** DOTLOCK isn't a true locking style, it refers to the use of a special
**   file named the same as the database file with a '.lock' extension, this
**   can be used on file systems that do not offer any reliable file locking
** NONE locking means that no locking will be attempted, this is only used for
**   read-only file systems currently
** NAMEDSEM is similar to DOTLOCK but uses a named semaphore instead of an
**   indicator file.
** PROXY uses a second file to represent the lock state of the database file
**   which is never actually locked, a third file controls access to the proxy
** UNSUPPORTED means that no locking will be attempted, this is only used for
**   file systems that are known to be unsupported
*/
#define LOCKING_STYLE_POSIX        1
#define LOCKING_STYLE_NONE         2
#define LOCKING_STYLE_DOTFILE      3
#define LOCKING_STYLE_FLOCK        4
#define LOCKING_STYLE_AFP          5
#define LOCKING_STYLE_NAMEDSEM     6
#define LOCKING_STYLE_PROXY        7

/*
** Only set the lastErrno if the error code is a real error and not 
** a normal expected return code of SQLITE_BUSY or SQLITE_OK
*/
#define IS_LOCK_ERROR(x)  ((x != SQLITE_OK) && (x != SQLITE_BUSY))

/*
** Helper functions to obtain and relinquish the global mutex.
*/
static void enterMutex(void){
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
static void leaveMutex(void){
  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}

#if SQLITE_THREADSAFE
/*
** This variable records whether or not threads can override each others
** locks.
**
**    0:  No.  Threads cannot override each others locks.
**    1:  Yes.  Threads can override each others locks.
**   -1:  We don't know yet.
................................................................................
*/
struct threadTestData {
  int fd;                /* File to be locked */
  struct flock lock;     /* The locking operation */
  int result;            /* Result of the locking operation */
};

#ifdef SQLITE_LOCK_TRACE
/*
** Print out information about all locking operations.
**
** This routine is used for troubleshooting locks on multithreaded
** platforms.  Enable by compiling with the -DSQLITE_LOCK_TRACE
** command-line option on the compiler.  This code is normally
** turned off.
*/
static int lockTrace(int fd, int op, struct flock *p){
  char *zOpName, *zType;
  int s;
  int savedErrno;
  if( op==F_GETLK ){
    zOpName = "GETLK";
  }else if( op==F_SETLK ){
    zOpName = "SETLK";
  }else{
    s = fcntl(fd, op, p);
    sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
    return s;
  }
  if( p->l_type==F_RDLCK ){
    zType = "RDLCK";
  }else if( p->l_type==F_WRLCK ){
    zType = "WRLCK";
  }else if( p->l_type==F_UNLCK ){
    zType = "UNLCK";
  }else{
    assert( 0 );
  }
  assert( p->l_whence==SEEK_SET );
  s = fcntl(fd, op, p);
  savedErrno = errno;
  sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
     threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
     (int)p->l_pid, s);
  if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
    struct flock l2;
    l2 = *p;
    fcntl(fd, F_GETLK, &l2);
    if( l2.l_type==F_RDLCK ){
      zType = "RDLCK";
    }else if( l2.l_type==F_WRLCK ){
      zType = "WRLCK";
    }else if( l2.l_type==F_UNLCK ){
      zType = "UNLCK";
    }else{
      assert( 0 );
    }
    sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
       zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
  }
  errno = savedErrno;
  return s;
}
#define fcntl lockTrace
#endif /* SQLITE_LOCK_TRACE */

#ifdef __linux__
/*
** This function is used as the main routine for a thread launched by
** testThreadLockingBehavior(). It tests whether the shared-lock obtained
** by the main thread in testThreadLockingBehavior() conflicts with a
** hypothetical write-lock obtained by this thread on the same file.
**
** The write-lock is not actually acquired, as this is not possible if 
................................................................................
** the file is open in read-only mode (see ticket #3472).
*/ 
static void *threadLockingTest(void *pArg){
  struct threadTestData *pData = (struct threadTestData*)pArg;
  pData->result = fcntl(pData->fd, F_GETLK, &pData->lock);
  return pArg;
}




/*
** This procedure attempts to determine whether or not threads
** can override each others locks then sets the 
** threadsOverrideEachOthersLocks variable appropriately.
*/
static void testThreadLockingBehavior(int fd_orig){
  int fd;
................................................................................
  d.lock.l_type = F_WRLCK;
  pthread_create(&t, 0, threadLockingTest, &d);
  pthread_join(t, 0);
  close(fd);
  if( d.result!=0 ) return;
  threadsOverrideEachOthersLocks = (d.lock.l_type==F_UNLCK);
}
#else
/*
** On anything other than linux, assume threads override each others locks.
*/
static void testThreadLockingBehavior(int fd_orig){

  threadsOverrideEachOthersLocks = 1;
}
#endif /* __linux__ */


















































#endif /* SQLITE_THREADSAFE */


/*
** Release a lockInfo structure previously allocated by findLockInfo().
*/
static void releaseLockInfo(struct lockInfo *pLock){
  if( pLock ){
    pLock->nRef--;
    if( pLock->nRef==0 ){
      if( pLock->pPrev ){
        assert( pLock->pPrev->pNext==pLock );
        pLock->pPrev->pNext = pLock->pNext;
      }else{
................................................................................
      }
      sqlite3_free(pLock);
    }
  }
}

/*
** Release a openCnt structure previously allocated by findLockInfo().
*/
static void releaseOpenCnt(struct openCnt *pOpen){
  if( pOpen ){
    pOpen->nRef--;
    if( pOpen->nRef==0 ){
      if( pOpen->pPrev ){
        assert( pOpen->pPrev->pNext==pOpen );
        pOpen->pPrev->pNext = pOpen->pNext;
      }else{
................................................................................
      }
      sqlite3_free(pOpen->aPending);
      sqlite3_free(pOpen);
    }
  }
}
























































#if IS_VXWORKS

























































































/*
** Implementation of a realpath() like function for vxWorks
** to determine canonical path name from given name. It does
** not support symlinks. Neither does it handle volume prefixes.
*/
char *
vxrealpath(const char *pathname, int dostat)
................................................................................
    }
    strcpy(workpath, namebuf);
  }
  strcpy(result, workpath);
  return result;
}
#endif





















































































































#if SQLITE_ENABLE_LOCKING_STYLE
/*
** The proxyLockingContext has the path and file structures for the remote 
** and local proxy files in it
*/
typedef struct proxyLockingContext proxyLockingContext;
................................................................................
    return LOCKING_STYLE_POSIX;
  }
  
  /* Testing for flock() can give false positives.  So if if the above 
  ** test fails, then we fall back to using dot-file style locking (or
  ** named-semaphore locking on vxworks).
  */
  return (IS_VXWORKS ? LOCKING_STYLE_NAMEDSEM : LOCKING_STYLE_DOTFILE);
}
#endif

/* 
** If SQLITE_ENABLE_LOCKING_STYLE is defined, this function Examines the 
** f_fstypename entry in the statfs structure as returned by stat() for 
** the file system hosting the database file and selects  the appropriate
................................................................................
*/
#if SQLITE_ENABLE_LOCKING_STYLE
static int detectLockingStyle(
  sqlite3_vfs *pVfs,
  const char *filePath, 
  int fd
){
#if IS_VXWORKS
  if( !filePath ){
    return LOCKING_STYLE_NONE;
  }
  if( pVfs->pAppData ){
    return SQLITE_PTR_TO_INT(pVfs->pAppData);
  }
  if (access(filePath, 0) != -1){
................................................................................
        return aMap[i].eLockingStyle;
      }
    }
  }

  /* Default case. Handles, amongst others, "nfs". */
  return testLockingStyle(fd);  
#endif /* if IS_VXWORKS */
  return LOCKING_STYLE_POSIX;
}
#else
  #define detectLockingStyle(x,y,z) LOCKING_STYLE_POSIX
#endif /* if SQLITE_ENABLE_LOCKING_STYLE */

/*
** Given a file descriptor, locate lockInfo and openCnt structures that
** describes that file descriptor.  Create new ones if necessary.  The
** return values might be uninitialized if an error occurs.
**
** Return an appropriate error code.
*/
static int findLockInfo(
  unixFile *pFile,             /* Unix file with file desc used in the key */
#if IS_VXWORKS
  void *rnam,                  /* vxWorks realname */
#endif
  struct lockInfo **ppLock,    /* Return the lockInfo structure here */
  struct openCnt **ppOpen      /* Return the openCnt structure here */
){
  int rc;
  int fd;
  struct lockKey key1;
  struct openKey key2;
  struct stat statbuf;
  struct lockInfo *pLock;
  struct openCnt *pOpen;
  fd = pFile->h;
  rc = fstat(fd, &statbuf);
  if( rc!=0 ){
    pFile->lastErrno = errno;
#ifdef EOVERFLOW
    if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
#endif
    return SQLITE_IOERR;
  }

  /* On OS X on an msdos filesystem, the inode number is reported
  ** incorrectly for zero-size files.  See ticket #3260.  To work
  ** around this problem (we consider it a bug in OS X, not SQLite)
  ** we always increase the file size to 1 by writing a single byte
  ** prior to accessing the inode number.  The one byte written is
  ** an ASCII 'S' character which also happens to be the first byte
  ** in the header of every SQLite database.  In this way, if there
  ** is a race condition such that another thread has already populated
  ** the first page of the database, no damage is done.
  */
  if( statbuf.st_size==0 ){
    write(fd, "S", 1);
    rc = fstat(fd, &statbuf);
    if( rc!=0 ){
      pFile->lastErrno = errno;
      return SQLITE_IOERR;
    }
  }

  memset(&key1, 0, sizeof(key1));
  key1.dev = statbuf.st_dev;
#if IS_VXWORKS
  key1.rnam = rnam;
#else
  key1.ino = statbuf.st_ino;
#endif
#if SQLITE_THREADSAFE
  if( threadsOverrideEachOthersLocks<0 ){
    testThreadLockingBehavior(fd);
  }
  key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self();
#endif
  memset(&key2, 0, sizeof(key2));
  key2.dev = statbuf.st_dev;
#if IS_VXWORKS
  key2.rnam = rnam;
#else
  key2.ino = statbuf.st_ino;
#endif
  if( ppLock!=0 ){
    pLock = lockList;
    while( pLock && memcmp(&key1, &pLock->key, sizeof(key1)) ){
      pLock = pLock->pNext;
    }
    if( pLock==0 ){
      pLock = sqlite3_malloc( sizeof(*pLock) );
      if( pLock==0 ){
        rc = SQLITE_NOMEM;
        goto exit_findlockinfo;
      }
      pLock->key = key1;
      pLock->nRef = 1;
      pLock->cnt = 0;
      pLock->locktype = 0;
      pLock->pNext = lockList;
      pLock->pPrev = 0;
      if( lockList ) lockList->pPrev = pLock;
      lockList = pLock;
    }else{
      pLock->nRef++;
    }
    *ppLock = pLock;
  }
  if( ppOpen!=0 ){
    pOpen = openList;
    while( pOpen && memcmp(&key2, &pOpen->key, sizeof(key2)) ){
      pOpen = pOpen->pNext;
    }
    if( pOpen==0 ){
      pOpen = sqlite3_malloc( sizeof(*pOpen) );
      if( pOpen==0 ){
        releaseLockInfo(pLock);
        rc = SQLITE_NOMEM;
        goto exit_findlockinfo;
      }
      pOpen->key = key2;
      pOpen->nRef = 1;
      pOpen->nLock = 0;
      pOpen->nPending = 0;
      pOpen->aPending = 0;
      pOpen->pNext = openList;
      pOpen->pPrev = 0;
      if( openList ) openList->pPrev = pOpen;
      openList = pOpen;
#if IS_VXWORKS
      pOpen->pSem = NULL;
      pOpen->aSemName[0] = '\0';
#endif
    }else{
      pOpen->nRef++;
    }
    *ppOpen = pOpen;
  }

exit_findlockinfo:
  return rc;
}

#ifdef SQLITE_DEBUG
/*
** Helper function for printing out trace information from debugging
** binaries. This returns the string represetation of the supplied
** integer lock-type.
*/
static const char *locktypeName(int locktype){
................................................................................
  case PENDING_LOCK: return "PENDING";
  case EXCLUSIVE_LOCK: return "EXCLUSIVE";
  }
  return "ERROR";
}
#endif

/*
** If we are currently in a different thread than the thread that the
** unixFile argument belongs to, then transfer ownership of the unixFile
** over to the current thread.
**
** A unixFile is only owned by a thread on systems where one thread is
** unable to override locks created by a different thread.  RedHat9 is
** an example of such a system.
**
** Ownership transfer is only allowed if the unixFile is currently unlocked.
** If the unixFile is locked and an ownership is wrong, then return
** SQLITE_MISUSE.  SQLITE_OK is returned if everything works.
*/
#if SQLITE_THREADSAFE
static int transferOwnership(unixFile *pFile){
  int rc;
  pthread_t hSelf;
  if( threadsOverrideEachOthersLocks ){
    /* Ownership transfers not needed on this system */
    return SQLITE_OK;
  }
  hSelf = pthread_self();
  if( pthread_equal(pFile->tid, hSelf) ){
    /* We are still in the same thread */
    OSTRACE1("No-transfer, same thread\n");
    return SQLITE_OK;
  }
  if( pFile->locktype!=NO_LOCK ){
    /* We cannot change ownership while we are holding a lock! */
    return SQLITE_MISUSE;
  }
  OSTRACE4("Transfer ownership of %d from %d to %d\n",
            pFile->h, pFile->tid, hSelf);
  pFile->tid = hSelf;
  if (pFile->pLock != NULL) {
    releaseLockInfo(pFile->pLock);
#if IS_VXWORKS
    rc = findLockInfo(pFile, pFile->zRealpath, &pFile->pLock, 0);
#else
    rc = findLockInfo(pFile, &pFile->pLock, 0);
#endif
    OSTRACE5("LOCK    %d is now %s(%s,%d)\n", pFile->h,
           locktypeName(pFile->locktype),
           locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
    return rc;
  } else {
    return SQLITE_OK;
  }
}
#else
  /* On single-threaded builds, ownership transfer is a no-op */
# define transferOwnership(X) SQLITE_OK
#endif

/*
** Seek to the offset passed as the second argument, then read cnt 
** bytes into pBuf. Return the number of bytes actually read.
**
** NB:  If you define USE_PREAD or USE_PREAD64, then it might also
** be necessary to define _XOPEN_SOURCE to be 500.  This varies from
** one system to another.  Since SQLite does not define USE_PREAD
................................................................................
   * the fcntl call every time sync is called.
   */
  if( rc ) rc = fsync(fd);

#else 
  if( dataOnly ){
    rc = fdatasync(fd);
    if( IS_VXWORKS && rc==-1 && errno==ENOTSUP ){
      rc = fsync(fd);
    }
  }else{
    rc = fsync(fd);
  }
#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */

  if( IS_VXWORKS && rc!= -1 ){
    rc = 0;
  }
  return rc;
}

/*
** Make sure all writes to a particular file are committed to disk.
................................................................................
  int rc = SQLITE_OK;
  int reserved = 0;
  unixFile *pFile = (unixFile*)id;

  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );

  assert( pFile );
  enterMutex(); /* Because pFile->pLock is shared across threads */

  /* Check if a thread in this process holds such a lock */
  if( pFile->pLock->locktype>SHARED_LOCK ){
    reserved = 1;
  }

  /* Otherwise see if some other process holds it.
................................................................................
      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
      pFile->lastErrno = tErrno;
    } else if( lock.l_type!=F_UNLCK ){
      reserved = 1;
    }
  }
  
  leaveMutex();
  OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);

  *pResOut = reserved;
  return rc;
}

/*
................................................................................
  ** The reason a single byte cannot be used instead of the 'shared byte
  ** range' is that some versions of windows do not support read-locks. By
  ** locking a random byte from a range, concurrent SHARED locks may exist
  ** even if the locking primitive used is always a write-lock.
  */
  int rc = SQLITE_OK;
  unixFile *pFile = (unixFile*)id;
  struct lockInfo *pLock = pFile->pLock;
  struct flock lock;
  int s;

  assert( pFile );
  OSTRACE7("LOCK    %d %s was %s(%s,%d) pid=%d\n", pFile->h,
      locktypeName(locktype), locktypeName(pFile->locktype),
      locktypeName(pLock->locktype), pLock->cnt , getpid());

  /* If there is already a lock of this type or more restrictive on the
  ** unixFile, do nothing. Don't use the end_lock: exit path, as
  ** enterMutex() hasn't been called yet.
  */
  if( pFile->locktype>=locktype ){
    OSTRACE3("LOCK    %d %s ok (already held)\n", pFile->h,
            locktypeName(locktype));
    return SQLITE_OK;
  }

................................................................................
  */
  assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
  assert( locktype!=PENDING_LOCK );
  assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );

  /* This mutex is needed because pFile->pLock is shared across threads
  */
  enterMutex();

  /* Make sure the current thread owns the pFile.
  */
  rc = transferOwnership(pFile);
  if( rc!=SQLITE_OK ){
    leaveMutex();
    return rc;
  }
  pLock = pFile->pLock;

  /* If some thread using this PID has a lock via a different unixFile*
  ** handle that precludes the requested lock, return BUSY.
  */
................................................................................
    pLock->locktype = locktype;
  }else if( locktype==EXCLUSIVE_LOCK ){
    pFile->locktype = PENDING_LOCK;
    pLock->locktype = PENDING_LOCK;
  }

end_lock:
  leaveMutex();
  OSTRACE4("LOCK    %d %s %s\n", pFile->h, locktypeName(locktype), 
      rc==SQLITE_OK ? "ok" : "failed");
  return rc;
}

/*
** Lower the locking level on file descriptor pFile 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.
*/
static int unixUnlock(sqlite3_file *id, int locktype){
  struct lockInfo *pLock;
  struct flock lock;
  int rc = SQLITE_OK;
  unixFile *pFile = (unixFile*)id;
  int h;

  assert( pFile );
  OSTRACE7("UNLOCK  %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype,
................................................................................
  assert( locktype<=SHARED_LOCK );
  if( pFile->locktype<=locktype ){
    return SQLITE_OK;
  }
  if( CHECK_THREADID(pFile) ){
    return SQLITE_MISUSE;
  }
  enterMutex();
  h = pFile->h;
  pLock = pFile->pLock;
  assert( pLock->cnt!=0 );
  if( pFile->locktype>SHARED_LOCK ){
    assert( pLock->locktype==pFile->locktype );
    SimulateIOErrorBenign(1);
    SimulateIOError( h=(-1) )
................................................................................
      if( IS_LOCK_ERROR(rc) ){
        pFile->lastErrno = tErrno;
      }
			goto end_unlock;
    }
  }
  if( locktype==NO_LOCK ){
    struct openCnt *pOpen;

    /* Decrement the shared lock counter.  Release the lock using an
    ** OS call only when all threads in this same process have released
    ** the lock.
    */
    pLock->cnt--;
    if( pLock->cnt==0 ){
................................................................................
          pOpen->aPending = 0;
        }
      }
    }
  }
	
end_unlock:
  leaveMutex();
  if( rc==SQLITE_OK ) pFile->locktype = locktype;
  return rc;
}

/*
** This function performs the parts of the "close file" operation 
** common to all locking schemes. It closes the directory and file
................................................................................
    if( pFile->h>=0 ){
      int err = close(pFile->h);
      if( err ){
        pFile->lastErrno = errno;
        return SQLITE_IOERR_CLOSE;
      }
    }
#if IS_VXWORKS
    if( pFile->isDelete && pFile->zRealpath ){
      unlink(pFile->zRealpath);
    }
    if( pFile->zRealpath ){
      HashElem *pElem;
      int n = strlen(pFile->zRealpath) + 1;
      pElem = sqlite3HashFindElem(&nameHash, pFile->zRealpath, n);
      if( pElem ){
        long cnt = (long)pElem->data;
        cnt--;
        if( cnt==0 ){
          sqlite3HashInsert(&nameHash, pFile->zRealpath, n, 0);
        }else{
          pElem->data = (void*)cnt;
        }
      }
    }
#endif
    OSTRACE2("CLOSE   %-3d\n", pFile->h);
................................................................................
** Close a file.
*/
static int unixClose(sqlite3_file *id){
  int rc = SQLITE_OK;
  if( id ){
    unixFile *pFile = (unixFile *)id;
    unixUnlock(id, NO_LOCK);
    enterMutex();
    if( pFile->pOpen && pFile->pOpen->nLock ){
      /* If there are outstanding locks, do not actually close the file just
      ** yet because that would clear those locks.  Instead, add the file
      ** descriptor to pOpen->aPending.  It will be automatically closed when
      ** the last lock is cleared.
      */
      int *aNew;
      struct openCnt *pOpen = pFile->pOpen;
      aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
      if( aNew==0 ){
        /* If a malloc fails, just leak the file descriptor */
      }else{
        pOpen->aPending = aNew;
        pOpen->aPending[pOpen->nPending] = pFile->h;
        pOpen->nPending++;
        pFile->h = -1;
      }
    }
    releaseLockInfo(pFile->pLock);
    releaseOpenCnt(pFile->pOpen);
    rc = closeUnixFile(id);
    leaveMutex();
  }
  return rc;
}


#if SQLITE_ENABLE_LOCKING_STYLE
#if !IS_VXWORKS
#pragma mark AFP support

/*
 ** The afpLockingContext structure contains all afp lock specific state
 */
typedef struct afpLockingContext afpLockingContext;
struct afpLockingContext {
................................................................................
  
  assert( pFile );
  OSTRACE5("LOCK    %d %s was %s pid=%d\n", pFile->h,
         locktypeName(locktype), locktypeName(pFile->locktype), getpid());

  /* If there is already a lock of this type or more restrictive on the
  ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
  ** enterMutex() hasn't been called yet.
  */
  if( pFile->locktype>=locktype ){
    OSTRACE3("LOCK    %d %s ok (already held)\n", pFile->h,
           locktypeName(locktype));
    return SQLITE_OK;
  }

................................................................................
  */
  assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
  assert( locktype!=PENDING_LOCK );
  assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
  
  /* This mutex is needed because pFile->pLock is shared across threads
  */
  enterMutex();

  /* Make sure the current thread owns the pFile.
  */
  rc = transferOwnership(pFile);
  if( rc!=SQLITE_OK ){
    leaveMutex();
    return rc;
  }
    
  /* A PENDING lock is needed before acquiring a SHARED lock and before
  ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
  ** be released.
  */
................................................................................
  if( rc==SQLITE_OK ){
    pFile->locktype = locktype;
  }else if( locktype==EXCLUSIVE_LOCK ){
    pFile->locktype = PENDING_LOCK;
  }
  
afp_end_lock:
  leaveMutex();
  OSTRACE4("LOCK    %d %s %s\n", pFile->h, locktypeName(locktype), 
         rc==SQLITE_OK ? "ok" : "failed");
  return rc;
}

/*
** Lower the locking level on file descriptor pFile to locktype.  locktype
................................................................................
  assert( locktype<=SHARED_LOCK );
  if( pFile->locktype<=locktype ){
    return SQLITE_OK;
  }
  if( CHECK_THREADID(pFile) ){
    return SQLITE_MISUSE;
  }
  enterMutex();
  if( pFile->locktype>SHARED_LOCK ){
    
    if( pFile->locktype==EXCLUSIVE_LOCK ){
      rc = _AFPFSSetLock(pCtx->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
      if( rc==SQLITE_OK && locktype==SHARED_LOCK ){
        /* only re-establish the shared lock if necessary */
        int sharedLockByte = SHARED_FIRST+pCtx->sharedByte;
................................................................................
    /* clear the shared lock */
    int sharedLockByte = SHARED_FIRST+pCtx->sharedByte;
    rc = _AFPFSSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 0);
  }

  if( rc==SQLITE_OK ){
    if( locktype==NO_LOCK ){
      struct openCnt *pOpen = pFile->pOpen;
      pOpen->nLock--;
      assert( pOpen->nLock>=0 );
      if( pOpen->nLock==0 && pOpen->nPending>0 ){
        int i;
        for(i=0; i<pOpen->nPending; i++){
          if( pOpen->aPending[i] < 0 ) continue;
          if( close(pOpen->aPending[i]) ){
................................................................................
          pOpen->nPending = 0;
          pOpen->aPending = 0;
        }
      }
    }
  }
end_afpunlock:
  leaveMutex();
  if( rc==SQLITE_OK ) pFile->locktype = locktype;
  return rc;
}

/*
** Close a file & cleanup AFP specific locking context 
*/
static int afpClose(sqlite3_file *id) {
  if( id ){
    unixFile *pFile = (unixFile*)id;
    afpUnlock(id, NO_LOCK);
    enterMutex();
    if( pFile->pOpen && pFile->pOpen->nLock ){
      /* If there are outstanding locks, do not actually close the file just
       ** yet because that would clear those locks.  Instead, add the file
       ** descriptor to pOpen->aPending.  It will be automatically closed when
       ** the last lock is cleared.
       */
      int *aNew;
      struct openCnt *pOpen = pFile->pOpen;
      aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
      if( aNew==0 ){
        /* If a malloc fails, just leak the file descriptor */
      }else{
        pOpen->aPending = aNew;
        pOpen->aPending[pOpen->nPending] = pFile->h;
        pOpen->nPending++;
        pFile->h = -1;
      }
    }
    releaseOpenCnt(pFile->pOpen);
    sqlite3_free(pFile->lockingContext);
    closeUnixFile(id);
    leaveMutex();
  }
  return SQLITE_OK;
}


#pragma mark flock() style locking

................................................................................
static int flockClose(sqlite3_file *id) {
  if( id ){
    flockUnlock(id, NO_LOCK);
  }
  return closeUnixFile(id);
}

#endif /* !IS_VXWORKS */

#pragma mark Old-School .lock file based locking
#define DOTLOCK_SUFFIX ".lock"

/* Dotlock-style reserved lock checking following the behavior of 
** unixCheckReservedLock, see the unixCheckReservedLock function comments */
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
................................................................................
  char *zLockFile = (char *)pFile->lockingContext;
  int rc=SQLITE_OK;

  /* if we already have a lock, it is exclusive.  
  ** Just adjust level and punt on outta here. */
  if (pFile->locktype > NO_LOCK) {
    pFile->locktype = locktype;
#if !IS_VXWORKS
    /* Always update the timestamp on the old file */
    utimes(zLockFile, NULL);
#endif
    rc = SQLITE_OK;
    goto dotlock_end_lock;
  }
  
................................................................................
static int dotlockClose(sqlite3_file *id) {
  int rc;
  if( id ){
    unixFile *pFile = (unixFile*)id;
    dotlockUnlock(id, NO_LOCK);
    sqlite3_free(pFile->lockingContext);
  }
  if( IS_VXWORKS ) enterMutex();
  rc = closeUnixFile(id);
  if( IS_VXWORKS ) leaveMutex();
  return rc;
}

#if IS_VXWORKS

#pragma mark POSIX/vxWorks named semaphore based locking

/* Namedsem-style reserved lock checking following the behavior of 
** unixCheckReservedLock, see the unixCheckReservedLock function comments */
static int namedsemCheckReservedLock(sqlite3_file *id, int *pResOut) {
  int rc = SQLITE_OK;
................................................................................
 ** Close a file.
 */
static int namedsemClose(sqlite3_file *id) {
  if( id ){
    unixFile *pFile = (unixFile*)id;
    namedsemUnlock(id, NO_LOCK);
    assert( pFile );
    enterMutex();
    releaseLockInfo(pFile->pLock);
    releaseOpenCnt(pFile->pOpen);
    closeUnixFile(id);
    leaveMutex();
  }
  return SQLITE_OK;
}

#endif /* IS_VXWORKS */

#pragma mark Proxy locking support

static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
  unixFile *pFile = (unixFile*)id;
  int rc = takeConch(pFile);
  if( rc==SQLITE_OK ){
................................................................................
}

/*
** Close a file.
*/
static int nolockClose(sqlite3_file *id) {
  int rc;
  if( IS_VXWORKS ) enterMutex();
  rc = closeUnixFile(id);
  if( IS_VXWORKS ) leaveMutex();
  return rc;
}


/*
** Information and control of an open file handle.
*/
................................................................................
unixDeviceCharacteristics   /* xDeviceCapabilities */                \
}
static sqlite3_io_methods aIoMethod[] = {
IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock) 
,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
#if SQLITE_ENABLE_LOCKING_STYLE
,IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock)
#if IS_VXWORKS
  ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
  ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
  ,IOMETHODS(namedsemClose, namedsemLock, namedsemUnlock, namedsemCheckReservedLock)
  ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
#else
  ,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock)
  ,IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock)
................................................................................
  assert( pNew->pLock==NULL );
  assert( pNew->pOpen==NULL );

  /* Parameter isDelete is only used on vxworks. Parameter pVfs is only
  ** used if ENABLE_LOCKING_STYLE is defined. Express this explicitly 
  ** here to prevent compiler warnings about unused parameters.
  */
  if( !IS_VXWORKS ) UNUSED_PARAMETER(isDelete);
  if( !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(pVfs);
  if( !IS_VXWORKS && !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(zFilename);

  OSTRACE3("OPEN    %-3d %s\n", h, zFilename);    
  pNew->h = h;
  pNew->dirfd = dirfd;
  SET_THREADID(pNew);

#if IS_VXWORKS
  {
    HashElem *pElem;
    char *zRealname = vxrealpath(zFilename, 1);
    int n;
    pNew->zRealpath = 0;
    if( !zRealname ){
      rc = SQLITE_NOMEM;
      eLockingStyle = LOCKING_STYLE_NONE;
    }else{
      n = strlen(zRealname) + 1;
      enterMutex();
      pElem = sqlite3HashFindElem(&nameHash, zRealname, n);
      if( pElem ){
        long cnt = (long)pElem->data;
        cnt++;
        pNew->zRealpath = pElem->pKey;
        pElem->data = (void*)cnt;
      }else{
        if( sqlite3HashInsert(&nameHash, zRealname, n, (void*)1)==0 ){
          pElem = sqlite3HashFindElem(&nameHash, zRealname, n);
          if( pElem ){
            pNew->zRealpath = pElem->pKey;
          }else{
            sqlite3HashInsert(&nameHash, zRealname, n, 0);
            rc = SQLITE_NOMEM;
            eLockingStyle = LOCKING_STYLE_NONE;
          }
        }
      }
      leaveMutex();
      sqlite3_free(zRealname);
    }
  }
#endif

  if( noLock ){
    eLockingStyle = LOCKING_STYLE_NONE;
................................................................................
  assert(LOCKING_STYLE_AFP==5);
  assert(LOCKING_STYLE_NAMEDSEM==6);
  assert(LOCKING_STYLE_PROXY==7);
    
  switch( eLockingStyle ){

    case LOCKING_STYLE_POSIX: {
      enterMutex();
#if IS_VXWORKS
      rc = findLockInfo(pNew, pNew->zRealpath, &pNew->pLock, &pNew->pOpen);
#else
      rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
#endif
      leaveMutex();
      break;
    }

#if SQLITE_ENABLE_LOCKING_STYLE

#if !IS_VXWORKS
    case LOCKING_STYLE_AFP: {
      /* AFP locking uses the file path so it needs to be included in
      ** the afpLockingContext.
      */
      afpLockingContext *pCtx;
      pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
      if( pCtx==0 ){
................................................................................
        rc = SQLITE_NOMEM;
      }else{
        /* NB: zFilename exists and remains valid until the file is closed
        ** according to requirement F11141.  So we do not need to make a
        ** copy of the filename. */
        pCtx->dbPath = zFilename;
        srandomdev();
        enterMutex();
        rc = findLockInfo(pNew, NULL, &pNew->pOpen);
        leaveMutex();        
      }
      break;
    }
#endif

    case LOCKING_STYLE_DOTFILE: {
      /* Dotfile locking uses the file path so it needs to be included in
................................................................................
      }else{
        sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
      }
      pNew->lockingContext = zLockFile;
      break;
    }

#if IS_VXWORKS
    case LOCKING_STYLE_NAMEDSEM: {
      /* Named semaphore locking uses the file path so it needs to be
       ** included in the namedsemLockingContext
       */
      enterMutex();
      rc = findLockInfo(h, pNew->zRealpath, &pNew->pLock, &pNew->pOpen);
      if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){
        char *zSemName = pNew->pOpen->aSemName;
        int n;
        sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem", pNew->zRealpath);
        for( n=0; zSemName[n]; n++ )
          if( zSemName[n]=='/' ) zSemName[n] = '_';
        pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
        if( pNew->pOpen->pSem == SEM_FAILED ){
          rc = SQLITE_NOMEM;
          pNew->pOpen->aSemName[0] = '\0';
        }
      }
      leaveMutex();
      break;
    }
#endif

    case LOCKING_STYLE_FLOCK: 
    case LOCKING_STYLE_NONE: 
      break;
#endif
  }
  
  pNew->lastErrno = 0;
#if IS_VXWORKS
  if( rc!=SQLITE_OK ){
    unlink(zFilename);
    isDelete = 0;
  }
  pNew->isDelete = isDelete;
#endif
  if( rc!=SQLITE_OK ){
................................................................................
    flags |= SQLITE_OPEN_READONLY;
    return unixOpen(pVfs, zPath, pFile, flags, pOutFlags);
  }
  if( fd<0 ){
    return SQLITE_CANTOPEN;
  }
  if( isDelete ){
#if IS_VXWORKS
    zPath = zName;
#else
    unlink(zName);
#endif
  }
#if SQLITE_ENABLE_LOCKING_STYLE
  else{
................................................................................
  SimulateIOError(return SQLITE_IOERR_DELETE);
  unlink(zPath);
#ifndef SQLITE_DISABLE_DIRSYNC
  if( dirSync ){
    int fd;
    rc = openDirectory(zPath, &fd);
    if( rc==SQLITE_OK ){
#if IS_VXWORKS
      if( fsync(fd)==-1 )
#else
      if( fsync(fd) )
#endif
      {
        rc = SQLITE_IOERR_DIR_FSYNC;
      }
................................................................................
  ** current working directly has been unlinked.
  */
  SimulateIOError( return SQLITE_ERROR );

  assert( pVfs->mxPathname==MAX_PATHNAME );
  UNUSED_PARAMETER(pVfs);

#if IS_VXWORKS
  {
    char *zRealname = vxrealpath(zPath, 0);
    zOut[0] = '\0';
    if( !zRealname ){
      return SQLITE_CANTOPEN;
    }
    sqlite3_snprintf(nOut, zOut, "%s", zRealname);
................................................................................
        }
      }
      zFull[j++] = zFull[i];
    }
    zFull[j] = 0;
  }
#endif
#endif /* #if IS_VXWORKS */
}


#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** Interfaces for opening a shared library, finding entry points
** within the shared library, and closing the shared library.
................................................................................
** message is available, it is written to zBufOut. If no error message
** is available, zBufOut is left unmodified and SQLite uses a default
** error message.
*/
static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
  char *zErr;
  UNUSED_PARAMETER(NotUsed);
  enterMutex();
  zErr = dlerror();
  if( zErr ){
    sqlite3_snprintf(nBuf, zBufOut, "%s", zErr);
  }
  leaveMutex();
}
static void *unixDlSym(sqlite3_vfs *NotUsed, void *pHandle, const char*zSymbol){
  UNUSED_PARAMETER(NotUsed);
  return dlsym(pHandle, zSymbol);
}
static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){
  UNUSED_PARAMETER(NotUsed);
................................................................................
** The argument is the number of microseconds we want to sleep.
** The return value is the number of microseconds of sleep actually
** requested from the underlying operating system, a number which
** might be greater than or equal to the argument, but not less
** than the argument.
*/
static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
#if IS_VXWORKS
  struct timespec sp;

  sp.tv_sec = microseconds / 1000000;
  sp.tv_nsec = (microseconds % 1000000) * 1000;
  nanosleep(&sp, NULL);
  return microseconds;
#elif defined(HAVE_USLEEP) && HAVE_USLEEP
................................................................................

/*
** 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.
*/
static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){




#if IS_VXWORKS
  struct timespec sNow;
  clock_gettime(CLOCK_REALTIME, &sNow);
  *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_nsec/86400000000000.0;
#elif defined(NO_GETTOD)
  time_t t;
  time(&t);
  *prNow = t/86400.0 + 2440587.5;
#else
  struct timeval sNow;
  gettimeofday(&sNow, 0);
  *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_usec/86400000000.0;
#endif

#ifdef SQLITE_TEST
................................................................................
    UNIXVFS("unix-namedsem",LOCKING_STYLE_NAMEDSEM),
    UNIXVFS("unix-proxy",   LOCKING_STYLE_PROXY)
  };
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
    sqlite3_vfs_register(&aVfs[i], 0);
  }
#endif
#if IS_VXWORKS
  sqlite3HashInit(&nameHash, 1);
#endif
  sqlite3_vfs_register(&unixVfs, 1);
  return SQLITE_OK; 
}

/*
** Shutdown the operating system interface. This is a no-op for unix.
*/
int sqlite3_os_end(void){ 
  return SQLITE_OK; 
}
 
#endif /* SQLITE_OS_UNIX */







|







 







|


>
|
|
|
|
>







 







|







 







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






<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

>
>
>
|






>
>







 







|

|


|











|


|


|







 








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

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


|



|
|
<
<
<
<
<

|












|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<









|
|
|
|
|
|
|
|


|



|


|

|
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







>

>
>







 







|




>


<
>

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


>

|

|







 







|

|







 







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







 







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







 







|







 







|







 







|






<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







|







 







|







 







|







 







|










|







 







|





|







 







|













|







 







|







 







|







 







|







 







|
|
|

|

|
|




|







 







|







|













|






|







 







|







 







|





|







 







|







 







|







 







|







 







|











|







|













|







 







|







 







|







 







|

|



|







 







|



|




|







 







|

|







 







|







 







|

|






|




|





|
|



|


|
|

|

|





|







 







|
<
<
<

<
|





|







 







|

|







 







|




|
|



|








|











|







 







|







 







|







 







|







 







|







 







|




|







 







|







 







>
>
>
>
|



<
<
<
<







 







|
|













8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
...
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
...
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
...
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
...
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
...
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
...
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
...
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
...
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
...
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
...
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
....
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
....
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080


































































































































1081
1082
1083
1084
1085
1086
1087
....
1092
1093
1094
1095
1096
1097
1098






















































1099
1100
1101
1102
1103
1104
1105
....
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
....
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
....
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
....
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
....
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
....
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
....
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
....
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
....
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
....
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
....
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
....
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
....
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
....
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
....
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
....
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
....
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
....
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
....
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
....
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
....
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
....
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
....
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
....
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
....
3626
3627
3628
3629
3630
3631
3632
3633



3634

3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
....
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
....
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
....
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
....
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
....
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
....
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
....
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
....
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
....
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302




4303
4304
4305
4306
4307
4308
4309
....
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
**    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 Unix systems.
**
** $Id: os_unix.c,v 1.219 2008/11/21 20:32:34 drh Exp $
*/
#include "sqliteInt.h"
#if SQLITE_OS_UNIX              /* This file is used on unix only */

/*
** If SQLITE_ENABLE_LOCKING_STYLE is defined and is non-zero, then several
** alternative locking implementations are provided:
................................................................................
#    define SQLITE_ENABLE_LOCKING_STYLE 1
#  else
#    define SQLITE_ENABLE_LOCKING_STYLE 0
#  endif
#endif

/*
** Define the OS_VXWORKS pre-processor macro to 1 if building on 
** vxworks, or 0 otherwise.
*/
#ifndef OS_VXWORKS
#  if defined(__RTP__) || defined(_WRS_KERNEL)
#    define OS_VXWORKS 1
#  else
#    define OS_VXWORKS 0
#  endif
#endif

/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it.  If the OS lacks
** large file support, these should be no-ops.
**
................................................................................
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>

#if SQLITE_ENABLE_LOCKING_STYLE
# include <sys/ioctl.h>
# if OS_VXWORKS
#  define lstat stat
#  include <semaphore.h>
#  include <limits.h>
# else
#  include <sys/param.h>
#  include <sys/mount.h>
# endif
................................................................................
/*
** The unixFile structure is subclass of sqlite3_file specific for the unix
** protability layer.
*/
typedef struct unixFile unixFile;
struct unixFile {
  sqlite3_io_methods const *pMethod;  /* Always the first entry */
  struct unixOpenCnt *pOpen;       /* Info about all open fd's on this inode */
  struct unixLockInfo *pLock;      /* Info about locks on this inode */
  int h;                           /* The file descriptor */
  int dirfd;                       /* File descriptor for the directory */
  unsigned char locktype;          /* The type of lock held on this fd */
  int lastErrno;                   /* The unix errno from the last I/O error */
#if SQLITE_ENABLE_LOCKING_STYLE
  void *lockingContext;            /* Locking style specific state */
  int oflags;                      /* The flags specified at open */
#endif
#if SQLITE_THREADSAFE
  pthread_t tid;                   /* The thread that "owns" this unixFile */
#endif
#if OS_VXWORKS
  int isDelete;                    /* Delete on close if true */
  char *zVxworksPath;              /* Canonical pathname of the file */
#endif
#ifdef SQLITE_TEST
  /* In test mode, increase the size of this structure a bit so that 
  ** it is larger than the struct CrashFile defined in test6.c.
  */
  char aPadding[32];
#endif



















};

/*
** Include code that is common to all os_*.c files
*/
#include "os_common.h"

................................................................................
*/
#if SQLITE_THREADSAFE
#define threadid pthread_self()
#else
#define threadid 0
#endif


























/************************************************************************
*********** Posix Advisory Locking And Thread Interaction ***************
*************************************************************************
**
** Here is the dirt on POSIX advisory locks:  ANSI STD 1003.1 (1996)
** section 6.5.2.2 lines 483 through 490 specify that when a process
** sets or clears a lock, that operation overrides any prior locks set
** by the same process.  It does not explicitly say so, but this implies
** that it overrides locks set by the same process using a different
** file descriptor.  Consider this test case:
**
**       int fd1 = open("./file1", O_RDWR|O_CREAT, 0644);
**       int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
**
** Suppose ./file1 and ./file2 are really the same file (because
** one is a hard or symbolic link to the other) then if you set
** an exclusive lock on fd1, then try to get an exclusive lock
** on fd2, it works.  I would have expected the second lock to
** fail since there was already a lock on the file due to fd1.
................................................................................
** More recent discoveries about POSIX advisory locks.  (The more
** I discover, the more I realize the a POSIX advisory locks are
** an abomination.)
**
** If you close a file descriptor that points to a file that has locks,
** all locks on that file that are owned by the current process are
** released.  To work around this problem, each unixFile structure contains
** a pointer to an unixOpenCnt structure.  There is one unixOpenCnt structure
** per open inode, which means that multiple unixFile can point to a single
** unixOpenCnt.  When an attempt is made to close an unixFile, if there are
** other unixFile open on the same inode that are holding locks, the call
** to close() the file descriptor is deferred until all of the locks clear.
** The unixOpenCnt structure keeps a list of file descriptors that need to
** be closed and that list is walked (and cleared) when the last lock
** clears.
**
** First, under Linux threads, because each thread has a separate
** process ID, lock operations in one thread do not override locks
** to the same file in other threads.  Linux threads behave like
** separate processes in this respect.  But, if you close a file
** descriptor in linux threads, all locks are cleared, even locks
** on other threads and even though the other threads have different
** process IDs.  Linux threads is inconsistent in this respect.
** (I'm beginning to think that linux threads is an abomination too.)
** The consequence of this all is that the hash table for the unixLockInfo
** structure has to include the process id as part of its key because
** locks in different threads are treated as distinct.  But the 
** unixOpenCnt structure should not include the process id in its
** key because close() clears lock on all threads, not just the current
** thread.  Were it not for this goofiness in linux threads, we could
** combine the unixLockInfo and unixOpenCnt structures into a single structure.
**
** 2004-Jun-28:
** On some versions of linux, threads can override each others locks.
** On others not.  Sometimes you can change the behavior on the same
** system by setting the LD_ASSUME_KERNEL environment variable.  The
** POSIX standard is silent as to which behavior is correct, as far
** as I can tell, so other versions of unix might show the same
................................................................................
** To work around the inconsistencies, we have to test at runtime 
** whether or not threads can override each others locks.  This test
** is run once, the first time any lock is attempted.  A static 
** variable is set to record the results of this test for future
** use.
*/

/*
** Set or check the unixFile.tid field.  This field is set when an unixFile
** is first opened.  All subsequent uses of the unixFile verify that the
** same thread is operating on the unixFile.  Some operating systems do
** not allow locks to be overridden by other threads and that restriction
** means that sqlite3* database handles cannot be moved from one thread
** to another.  This logic makes sure a user does not try to do that
** by mistake.
**
** Version 3.3.1 (2006-01-15):  unixFile can be moved from one thread to
** another as long as we are running on a system that supports threads
** overriding each others locks (which now the most common behavior)
** or if no locks are held.  But the unixFile.pLock field needs to be
** recomputed because its key includes the thread-id.  See the 
** transferOwnership() function below for additional information
*/
#if SQLITE_THREADSAFE
# define SET_THREADID(X)   (X)->tid = pthread_self()
# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \
                            !pthread_equal((X)->tid, pthread_self()))
#else
# define SET_THREADID(X)
# define CHECK_THREADID(X) 0
#endif

/*
** An instance of the following structure serves as the key used
** to locate a particular unixOpenCnt structure given its inode.  This
** is the same as the unixLockKey except that the thread ID is omitted.
*/
struct unixFileId {
  dev_t dev;      /* Device number */
#if OS_VXWORKS
  void *pNameId;  /* Key of canonical filename entry in vxworksFilenameHash */
#else
  ino_t ino;      /* Inode number */
#endif
};

/*
** An instance of the following structure serves as the key used
** to locate a particular unixLockInfo structure given its inode.
**
** If threads cannot override each others locks, then we set the
** unixLockKey.tid field to the thread ID.  If threads can override
** each others locks then tid is always set to zero.  tid is omitted
** if we compile without threading support.
*/
struct unixLockKey {
  struct unixFileId fid;  /* Unique identifier for the file */





#if SQLITE_THREADSAFE
  pthread_t tid;      /* Thread ID or zero if threads can override each other */
#endif
};

/*
** An instance of the following structure is allocated for each open
** inode on each thread with a different process ID.  (Threads have
** different process IDs on linux, but not on most other unixes.)
**
** A single inode can have multiple file descriptors, so each unixFile
** structure contains a pointer to an instance of this object and this
** object keeps a count of the number of unixFile pointing to it.
*/
struct unixLockInfo {
  struct unixLockKey lockKey;       /* The lookup key */
  int cnt;                          /* Number of SHARED locks held */
  int locktype;                     /* One of SHARED_LOCK, RESERVED_LOCK etc. */
  int nRef;                         /* Number of pointers to this structure */
  struct unixLockInfo *pNext;       /* List of all unixLockInfo objects */
  struct unixLockInfo *pPrev;       /*    .... doubly linked */













};

/*
** An instance of the following structure is allocated for each open
** inode.  This structure keeps track of the number of locks on that
** inode.  If a close is attempted against an inode that is holding
** locks, the close is deferred until all locks clear by adding the
** file descriptor to be closed to the pending list.
*/
struct unixOpenCnt {
  struct unixFileId fileId;   /* The lookup key */
  int nRef;                   /* Number of pointers to this structure */
  int nLock;                  /* Number of outstanding locks */
  int nPending;               /* Number of pending close() operations */
  int *aPending;            /* Malloced space holding fd's awaiting a close() */
#if OS_VXWORKS
  sem_t *pSem;                     /* Named POSIX semaphore */
  char aSemName[MAX_PATHNAME+1];   /* Name of that semaphore */
#endif
  struct unixOpenCnt *pNext, *pPrev;   /* List of all unixOpenCnt objects */
};

/*
** List of all unixLockInfo and unixOpenCnt objects.  This used to be a hash
** table.  But the number of objects is rarely more than a dozen and
** never exceeds a few thousand.  And lookup is not on a critical
** path so a simple linked list will suffice.
*/
static struct unixLockInfo *lockList = 0;
static struct unixOpenCnt *openList = 0;































































/*
** This variable records whether or not threads can override each others
** locks.
**
**    0:  No.  Threads cannot override each others locks.
**    1:  Yes.  Threads can override each others locks.
**   -1:  We don't know yet.
................................................................................
*/
struct threadTestData {
  int fd;                /* File to be locked */
  struct flock lock;     /* The locking operation */
  int result;            /* Result of the locking operation */
};

#if SQLITE_THREADSAFE && defined(__linux__)



























































/*
** This function is used as the main routine for a thread launched by
** testThreadLockingBehavior(). It tests whether the shared-lock obtained
** by the main thread in testThreadLockingBehavior() conflicts with a
** hypothetical write-lock obtained by this thread on the same file.
**
** The write-lock is not actually acquired, as this is not possible if 
................................................................................
** the file is open in read-only mode (see ticket #3472).
*/ 
static void *threadLockingTest(void *pArg){
  struct threadTestData *pData = (struct threadTestData*)pArg;
  pData->result = fcntl(pData->fd, F_GETLK, &pData->lock);
  return pArg;
}
#endif /* SQLITE_THREADSAFE && defined(__linux__) */


#if SQLITE_THREADSAFE && defined(__linux__)
/*
** This procedure attempts to determine whether or not threads
** can override each others locks then sets the 
** threadsOverrideEachOthersLocks variable appropriately.
*/
static void testThreadLockingBehavior(int fd_orig){
  int fd;
................................................................................
  d.lock.l_type = F_WRLCK;
  pthread_create(&t, 0, threadLockingTest, &d);
  pthread_join(t, 0);
  close(fd);
  if( d.result!=0 ) return;
  threadsOverrideEachOthersLocks = (d.lock.l_type==F_UNLCK);
}
#else  /* if !SQLITE_THREADSAFE || !defined(__linux__) */
/*
** On anything other than linux, assume threads override each others locks.
*/
static void testThreadLockingBehavior(int fd_orig){
  UNUSED_PARAMETER(fd_orig);
  threadsOverrideEachOthersLocks = 1;
}

#endif /* SQLITE_THERADSAFE && defined(__linux__) */

/*
** If we are currently in a different thread than the thread that the
** unixFile argument belongs to, then transfer ownership of the unixFile
** over to the current thread.
**
** A unixFile is only owned by a thread on systems where one thread is
** unable to override locks created by a different thread.  RedHat9 is
** an example of such a system.
**
** Ownership transfer is only allowed if the unixFile is currently unlocked.
** If the unixFile is locked and an ownership is wrong, then return
** SQLITE_MISUSE.  SQLITE_OK is returned if everything works.
*/
#if SQLITE_THREADSAFE
static int transferOwnership(unixFile *pFile){
  int rc;
  pthread_t hSelf;
  if( threadsOverrideEachOthersLocks ){
    /* Ownership transfers not needed on this system */
    return SQLITE_OK;
  }
  hSelf = pthread_self();
  if( pthread_equal(pFile->tid, hSelf) ){
    /* We are still in the same thread */
    OSTRACE1("No-transfer, same thread\n");
    return SQLITE_OK;
  }
  if( pFile->locktype!=NO_LOCK ){
    /* We cannot change ownership while we are holding a lock! */
    return SQLITE_MISUSE;
  }
  OSTRACE4("Transfer ownership of %d from %d to %d\n",
            pFile->h, pFile->tid, hSelf);
  pFile->tid = hSelf;
  if (pFile->pLock != NULL) {
    releaseLockInfo(pFile->pLock);
    rc = findLockInfo(pFile, &pFile->pLock, 0);
    OSTRACE5("LOCK    %d is now %s(%s,%d)\n", pFile->h,
           locktypeName(pFile->locktype),
           locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
    return rc;
  } else {
    return SQLITE_OK;
  }
}
#else  /* if not SQLITE_THREADSAFE */
  /* On single-threaded builds, ownership transfer is a no-op */
# define transferOwnership(X) SQLITE_OK
#endif /* SQLITE_THREADSAFE */


/*
** Release a unixLockInfo structure previously allocated by findLockInfo().
*/
static void releaseLockInfo(struct unixLockInfo *pLock){
  if( pLock ){
    pLock->nRef--;
    if( pLock->nRef==0 ){
      if( pLock->pPrev ){
        assert( pLock->pPrev->pNext==pLock );
        pLock->pPrev->pNext = pLock->pNext;
      }else{
................................................................................
      }
      sqlite3_free(pLock);
    }
  }
}

/*
** Release a unixOpenCnt structure previously allocated by findLockInfo().
*/
static void releaseOpenCnt(struct unixOpenCnt *pOpen){
  if( pOpen ){
    pOpen->nRef--;
    if( pOpen->nRef==0 ){
      if( pOpen->pPrev ){
        assert( pOpen->pPrev->pNext==pOpen );
        pOpen->pPrev->pNext = pOpen->pNext;
      }else{
................................................................................
      }
      sqlite3_free(pOpen->aPending);
      sqlite3_free(pOpen);
    }
  }
}


/*
** Given a file descriptor, locate unixLockInfo and unixOpenCnt structures that
** describes that file descriptor.  Create new ones if necessary.  The
** return values might be uninitialized if an error occurs.
**
** Return an appropriate error code.
*/
static int findLockInfo(
  unixFile *pFile,               /* Unix file with file desc used in the key */
  struct unixLockInfo **ppLock,  /* Return the unixLockInfo structure here */
  struct unixOpenCnt **ppOpen    /* Return the unixOpenCnt structure here */
){
  int rc;                        /* System call return code */
  int fd;                        /* The file descriptor for pFile */
  struct unixLockKey lockKey;    /* Lookup key for the unixLockInfo structure */
  struct unixFileId fileId;      /* Lookup key for the unixOpenCnt struct */
  struct stat statbuf;           /* Low-level file information */
  struct unixLockInfo *pLock;    /* Candidate unixLockInfo object */
  struct unixOpenCnt *pOpen;     /* Candidate unixOpenCnt object */

  /* Get low-level information about the file that we can used to
  ** create a unique name for the file.
  */
  fd = pFile->h;
  rc = fstat(fd, &statbuf);
  if( rc!=0 ){
    pFile->lastErrno = errno;
#ifdef EOVERFLOW
    if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
#endif
    return SQLITE_IOERR;
  }

  /* On OS X on an msdos filesystem, the inode number is reported
  ** incorrectly for zero-size files.  See ticket #3260.  To work
  ** around this problem (we consider it a bug in OS X, not SQLite)
  ** we always increase the file size to 1 by writing a single byte
  ** prior to accessing the inode number.  The one byte written is
  ** an ASCII 'S' character which also happens to be the first byte
  ** in the header of every SQLite database.  In this way, if there
  ** is a race condition such that another thread has already populated
  ** the first page of the database, no damage is done.
  */
  if( statbuf.st_size==0 ){
    write(fd, "S", 1);
    rc = fstat(fd, &statbuf);
    if( rc!=0 ){
      pFile->lastErrno = errno;
      return SQLITE_IOERR;
    }
  }

  memset(&lockKey, 0, sizeof(lockKey));
  lockKey.fid.dev = statbuf.st_dev;
#if OS_VXWORKS
  /* The pFile->zVxworksPath name has been hashed into the vxworksFilenameHash
  ** hash table at this point, so safe to using pointer comparison
  ** to compare the names. */
  lockKey.fid.pNameId = pFile->zVxworksPath;
#else
  lockKey.fid.ino = statbuf.st_ino;
#endif
#if SQLITE_THREADSAFE
  if( threadsOverrideEachOthersLocks<0 ){
    testThreadLockingBehavior(fd);
  }
  lockKey.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self();
#endif
  fileId = lockKey.fid;
  if( ppLock!=0 ){
    pLock = lockList;
    while( pLock && memcmp(&lockKey, &pLock->lockKey, sizeof(lockKey)) ){
      pLock = pLock->pNext;
    }
    if( pLock==0 ){
      pLock = sqlite3_malloc( sizeof(*pLock) );
      if( pLock==0 ){
        rc = SQLITE_NOMEM;
        goto exit_findlockinfo;
      }
      pLock->lockKey = lockKey;
      pLock->nRef = 1;
      pLock->cnt = 0;
      pLock->locktype = 0;
      pLock->pNext = lockList;
      pLock->pPrev = 0;
      if( lockList ) lockList->pPrev = pLock;
      lockList = pLock;
    }else{
      pLock->nRef++;
    }
    *ppLock = pLock;
  }
  if( ppOpen!=0 ){
    pOpen = openList;
    while( pOpen && memcmp(&fileId, &pOpen->fileId, sizeof(fileId)) ){
      pOpen = pOpen->pNext;
    }
    if( pOpen==0 ){
      pOpen = sqlite3_malloc( sizeof(*pOpen) );
      if( pOpen==0 ){
        releaseLockInfo(pLock);
        rc = SQLITE_NOMEM;
        goto exit_findlockinfo;
      }
      pOpen->fileId = fileId;
      pOpen->nRef = 1;
      pOpen->nLock = 0;
      pOpen->nPending = 0;
      pOpen->aPending = 0;
      pOpen->pNext = openList;
      pOpen->pPrev = 0;
      if( openList ) openList->pPrev = pOpen;
      openList = pOpen;
#if OS_VXWORKS
      pOpen->pSem = NULL;
      pOpen->aSemName[0] = '\0';
#endif
    }else{
      pOpen->nRef++;
    }
    *ppOpen = pOpen;
  }

exit_findlockinfo:
  return rc;
}
/**************************************************************************
******************** End of the posix lock work-around ********************
**************************************************************************/

#if OS_VXWORKS
/*
** This hash table is used to bind the canonical file name to a
** unixFile structure and use the hash key (= canonical name)
** instead of the Inode number of the file to find the matching
** unixLockInfo and unixOpenCnt structures. It also helps to make the
** name of the semaphore when LOCKING_STYLE_NAMEDSEM is used
** for the file.
*/
static Hash vxworksFilenameHash;
#endif

#if OS_VXWORKS
/*
** Implementation of a realpath() like function for vxWorks
** to determine canonical path name from given name. It does
** not support symlinks. Neither does it handle volume prefixes.
*/
char *
vxrealpath(const char *pathname, int dostat)
................................................................................
    }
    strcpy(workpath, namebuf);
  }
  strcpy(result, workpath);
  return result;
}
#endif



#ifdef SQLITE_TEST
/* simulate multiple hosts by creating unique hostid file paths */
int sqlite3_hostid_num = 0;
#endif

/*
** The locking styles are associated with the different file locking
** capabilities supported by different file systems.  
**
** POSIX     support for shared and exclusive byte-range locks 
**
** AFP       support exclusive byte-range locks
**
** FLOCK     only a single file-global exclusive lock
**
** DOTLOCK   isn't a true locking style, it refers to the use of a special
**           file named the same as the database file with a '.lock'
**           extension, this can be used on file systems that do not
**           offer any reliable file locking
**
** NONE      no locking will be attempted, this is only used for
**           read-only file systems currently
**
** NAMEDSEM  similar to DOTLOCK but uses a named semaphore instead of an
**           indicator file.
**
** PROXY     uses a second file to represent the lock state of the database
**           file which is never actually locked, a third file controls
**           access to the proxy
*/
#define LOCKING_STYLE_POSIX        1
#define LOCKING_STYLE_NONE         2
#define LOCKING_STYLE_DOTFILE      3
#define LOCKING_STYLE_FLOCK        4
#define LOCKING_STYLE_AFP          5
#define LOCKING_STYLE_NAMEDSEM     6
#define LOCKING_STYLE_PROXY        7

/*
** Only set the lastErrno if the error code is a real error and not 
** a normal expected return code of SQLITE_BUSY or SQLITE_OK
*/
#define IS_LOCK_ERROR(x)  ((x != SQLITE_OK) && (x != SQLITE_BUSY))

/*
** Helper functions to obtain and relinquish the global mutex.
*/
static void unixEnterMutex(void){
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
static void unixLeaveMutex(void){
  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}

#ifdef SQLITE_LOCK_TRACE
/*
** Print out information about all locking operations.
**
** This routine is used for troubleshooting locks on multithreaded
** platforms.  Enable by compiling with the -DSQLITE_LOCK_TRACE
** command-line option on the compiler.  This code is normally
** turned off.
*/
static int lockTrace(int fd, int op, struct flock *p){
  char *zOpName, *zType;
  int s;
  int savedErrno;
  if( op==F_GETLK ){
    zOpName = "GETLK";
  }else if( op==F_SETLK ){
    zOpName = "SETLK";
  }else{
    s = fcntl(fd, op, p);
    sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
    return s;
  }
  if( p->l_type==F_RDLCK ){
    zType = "RDLCK";
  }else if( p->l_type==F_WRLCK ){
    zType = "WRLCK";
  }else if( p->l_type==F_UNLCK ){
    zType = "UNLCK";
  }else{
    assert( 0 );
  }
  assert( p->l_whence==SEEK_SET );
  s = fcntl(fd, op, p);
  savedErrno = errno;
  sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
     threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
     (int)p->l_pid, s);
  if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
    struct flock l2;
    l2 = *p;
    fcntl(fd, F_GETLK, &l2);
    if( l2.l_type==F_RDLCK ){
      zType = "RDLCK";
    }else if( l2.l_type==F_WRLCK ){
      zType = "WRLCK";
    }else if( l2.l_type==F_UNLCK ){
      zType = "UNLCK";
    }else{
      assert( 0 );
    }
    sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
       zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
  }
  errno = savedErrno;
  return s;
}
#define fcntl lockTrace
#endif /* SQLITE_LOCK_TRACE */


#if SQLITE_ENABLE_LOCKING_STYLE
/*
** The proxyLockingContext has the path and file structures for the remote 
** and local proxy files in it
*/
typedef struct proxyLockingContext proxyLockingContext;
................................................................................
    return LOCKING_STYLE_POSIX;
  }
  
  /* Testing for flock() can give false positives.  So if if the above 
  ** test fails, then we fall back to using dot-file style locking (or
  ** named-semaphore locking on vxworks).
  */
  return (OS_VXWORKS ? LOCKING_STYLE_NAMEDSEM : LOCKING_STYLE_DOTFILE);
}
#endif

/* 
** If SQLITE_ENABLE_LOCKING_STYLE is defined, this function Examines the 
** f_fstypename entry in the statfs structure as returned by stat() for 
** the file system hosting the database file and selects  the appropriate
................................................................................
*/
#if SQLITE_ENABLE_LOCKING_STYLE
static int detectLockingStyle(
  sqlite3_vfs *pVfs,
  const char *filePath, 
  int fd
){
#if OS_VXWORKS
  if( !filePath ){
    return LOCKING_STYLE_NONE;
  }
  if( pVfs->pAppData ){
    return SQLITE_PTR_TO_INT(pVfs->pAppData);
  }
  if (access(filePath, 0) != -1){
................................................................................
        return aMap[i].eLockingStyle;
      }
    }
  }

  /* Default case. Handles, amongst others, "nfs". */
  return testLockingStyle(fd);  
#endif /* if OS_VXWORKS */
  return LOCKING_STYLE_POSIX;
}
#else
  #define detectLockingStyle(x,y,z) LOCKING_STYLE_POSIX
#endif /* if SQLITE_ENABLE_LOCKING_STYLE */



































































































































#ifdef SQLITE_DEBUG
/*
** Helper function for printing out trace information from debugging
** binaries. This returns the string represetation of the supplied
** integer lock-type.
*/
static const char *locktypeName(int locktype){
................................................................................
  case PENDING_LOCK: return "PENDING";
  case EXCLUSIVE_LOCK: return "EXCLUSIVE";
  }
  return "ERROR";
}
#endif























































/*
** Seek to the offset passed as the second argument, then read cnt 
** bytes into pBuf. Return the number of bytes actually read.
**
** NB:  If you define USE_PREAD or USE_PREAD64, then it might also
** be necessary to define _XOPEN_SOURCE to be 500.  This varies from
** one system to another.  Since SQLite does not define USE_PREAD
................................................................................
   * the fcntl call every time sync is called.
   */
  if( rc ) rc = fsync(fd);

#else 
  if( dataOnly ){
    rc = fdatasync(fd);
    if( OS_VXWORKS && rc==-1 && errno==ENOTSUP ){
      rc = fsync(fd);
    }
  }else{
    rc = fsync(fd);
  }
#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */

  if( OS_VXWORKS && rc!= -1 ){
    rc = 0;
  }
  return rc;
}

/*
** Make sure all writes to a particular file are committed to disk.
................................................................................
  int rc = SQLITE_OK;
  int reserved = 0;
  unixFile *pFile = (unixFile*)id;

  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );

  assert( pFile );
  unixEnterMutex(); /* Because pFile->pLock is shared across threads */

  /* Check if a thread in this process holds such a lock */
  if( pFile->pLock->locktype>SHARED_LOCK ){
    reserved = 1;
  }

  /* Otherwise see if some other process holds it.
................................................................................
      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
      pFile->lastErrno = tErrno;
    } else if( lock.l_type!=F_UNLCK ){
      reserved = 1;
    }
  }
  
  unixLeaveMutex();
  OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);

  *pResOut = reserved;
  return rc;
}

/*
................................................................................
  ** The reason a single byte cannot be used instead of the 'shared byte
  ** range' is that some versions of windows do not support read-locks. By
  ** locking a random byte from a range, concurrent SHARED locks may exist
  ** even if the locking primitive used is always a write-lock.
  */
  int rc = SQLITE_OK;
  unixFile *pFile = (unixFile*)id;
  struct unixLockInfo *pLock = pFile->pLock;
  struct flock lock;
  int s;

  assert( pFile );
  OSTRACE7("LOCK    %d %s was %s(%s,%d) pid=%d\n", pFile->h,
      locktypeName(locktype), locktypeName(pFile->locktype),
      locktypeName(pLock->locktype), pLock->cnt , getpid());

  /* If there is already a lock of this type or more restrictive on the
  ** unixFile, do nothing. Don't use the end_lock: exit path, as
  ** unixEnterMutex() hasn't been called yet.
  */
  if( pFile->locktype>=locktype ){
    OSTRACE3("LOCK    %d %s ok (already held)\n", pFile->h,
            locktypeName(locktype));
    return SQLITE_OK;
  }

................................................................................
  */
  assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
  assert( locktype!=PENDING_LOCK );
  assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );

  /* This mutex is needed because pFile->pLock is shared across threads
  */
  unixEnterMutex();

  /* Make sure the current thread owns the pFile.
  */
  rc = transferOwnership(pFile);
  if( rc!=SQLITE_OK ){
    unixLeaveMutex();
    return rc;
  }
  pLock = pFile->pLock;

  /* If some thread using this PID has a lock via a different unixFile*
  ** handle that precludes the requested lock, return BUSY.
  */
................................................................................
    pLock->locktype = locktype;
  }else if( locktype==EXCLUSIVE_LOCK ){
    pFile->locktype = PENDING_LOCK;
    pLock->locktype = PENDING_LOCK;
  }

end_lock:
  unixLeaveMutex();
  OSTRACE4("LOCK    %d %s %s\n", pFile->h, locktypeName(locktype), 
      rc==SQLITE_OK ? "ok" : "failed");
  return rc;
}

/*
** Lower the locking level on file descriptor pFile 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.
*/
static int unixUnlock(sqlite3_file *id, int locktype){
  struct unixLockInfo *pLock;
  struct flock lock;
  int rc = SQLITE_OK;
  unixFile *pFile = (unixFile*)id;
  int h;

  assert( pFile );
  OSTRACE7("UNLOCK  %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype,
................................................................................
  assert( locktype<=SHARED_LOCK );
  if( pFile->locktype<=locktype ){
    return SQLITE_OK;
  }
  if( CHECK_THREADID(pFile) ){
    return SQLITE_MISUSE;
  }
  unixEnterMutex();
  h = pFile->h;
  pLock = pFile->pLock;
  assert( pLock->cnt!=0 );
  if( pFile->locktype>SHARED_LOCK ){
    assert( pLock->locktype==pFile->locktype );
    SimulateIOErrorBenign(1);
    SimulateIOError( h=(-1) )
................................................................................
      if( IS_LOCK_ERROR(rc) ){
        pFile->lastErrno = tErrno;
      }
			goto end_unlock;
    }
  }
  if( locktype==NO_LOCK ){
    struct unixOpenCnt *pOpen;

    /* Decrement the shared lock counter.  Release the lock using an
    ** OS call only when all threads in this same process have released
    ** the lock.
    */
    pLock->cnt--;
    if( pLock->cnt==0 ){
................................................................................
          pOpen->aPending = 0;
        }
      }
    }
  }
	
end_unlock:
  unixLeaveMutex();
  if( rc==SQLITE_OK ) pFile->locktype = locktype;
  return rc;
}

/*
** This function performs the parts of the "close file" operation 
** common to all locking schemes. It closes the directory and file
................................................................................
    if( pFile->h>=0 ){
      int err = close(pFile->h);
      if( err ){
        pFile->lastErrno = errno;
        return SQLITE_IOERR_CLOSE;
      }
    }
#if OS_VXWORKS
    if( pFile->isDelete && pFile->zVxworksPath ){
      unlink(pFile->zVxworksPath);
    }
    if( pFile->zVxworksPath ){
      HashElem *pElem;
      int n = strlen(pFile->zVxworksPath) + 1;
      pElem = sqlite3HashFindElem(&vxworksFilenameHash, pFile->zVxworksPath, n);
      if( pElem ){
        long cnt = (long)pElem->data;
        cnt--;
        if( cnt==0 ){
          sqlite3HashInsert(&vxworksFilenameHash, pFile->zVxworksPath, n, 0);
        }else{
          pElem->data = (void*)cnt;
        }
      }
    }
#endif
    OSTRACE2("CLOSE   %-3d\n", pFile->h);
................................................................................
** Close a file.
*/
static int unixClose(sqlite3_file *id){
  int rc = SQLITE_OK;
  if( id ){
    unixFile *pFile = (unixFile *)id;
    unixUnlock(id, NO_LOCK);
    unixEnterMutex();
    if( pFile->pOpen && pFile->pOpen->nLock ){
      /* If there are outstanding locks, do not actually close the file just
      ** yet because that would clear those locks.  Instead, add the file
      ** descriptor to pOpen->aPending.  It will be automatically closed when
      ** the last lock is cleared.
      */
      int *aNew;
      struct unixOpenCnt *pOpen = pFile->pOpen;
      aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
      if( aNew==0 ){
        /* If a malloc fails, just leak the file descriptor */
      }else{
        pOpen->aPending = aNew;
        pOpen->aPending[pOpen->nPending] = pFile->h;
        pOpen->nPending++;
        pFile->h = -1;
      }
    }
    releaseLockInfo(pFile->pLock);
    releaseOpenCnt(pFile->pOpen);
    rc = closeUnixFile(id);
    unixLeaveMutex();
  }
  return rc;
}


#if SQLITE_ENABLE_LOCKING_STYLE
#if !OS_VXWORKS
#pragma mark AFP support

/*
 ** The afpLockingContext structure contains all afp lock specific state
 */
typedef struct afpLockingContext afpLockingContext;
struct afpLockingContext {
................................................................................
  
  assert( pFile );
  OSTRACE5("LOCK    %d %s was %s pid=%d\n", pFile->h,
         locktypeName(locktype), locktypeName(pFile->locktype), getpid());

  /* If there is already a lock of this type or more restrictive on the
  ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
  ** unixEnterMutex() hasn't been called yet.
  */
  if( pFile->locktype>=locktype ){
    OSTRACE3("LOCK    %d %s ok (already held)\n", pFile->h,
           locktypeName(locktype));
    return SQLITE_OK;
  }

................................................................................
  */
  assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
  assert( locktype!=PENDING_LOCK );
  assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
  
  /* This mutex is needed because pFile->pLock is shared across threads
  */
  unixEnterMutex();

  /* Make sure the current thread owns the pFile.
  */
  rc = transferOwnership(pFile);
  if( rc!=SQLITE_OK ){
    unixLeaveMutex();
    return rc;
  }
    
  /* A PENDING lock is needed before acquiring a SHARED lock and before
  ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
  ** be released.
  */
................................................................................
  if( rc==SQLITE_OK ){
    pFile->locktype = locktype;
  }else if( locktype==EXCLUSIVE_LOCK ){
    pFile->locktype = PENDING_LOCK;
  }
  
afp_end_lock:
  unixLeaveMutex();
  OSTRACE4("LOCK    %d %s %s\n", pFile->h, locktypeName(locktype), 
         rc==SQLITE_OK ? "ok" : "failed");
  return rc;
}

/*
** Lower the locking level on file descriptor pFile to locktype.  locktype
................................................................................
  assert( locktype<=SHARED_LOCK );
  if( pFile->locktype<=locktype ){
    return SQLITE_OK;
  }
  if( CHECK_THREADID(pFile) ){
    return SQLITE_MISUSE;
  }
  unixEnterMutex();
  if( pFile->locktype>SHARED_LOCK ){
    
    if( pFile->locktype==EXCLUSIVE_LOCK ){
      rc = _AFPFSSetLock(pCtx->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
      if( rc==SQLITE_OK && locktype==SHARED_LOCK ){
        /* only re-establish the shared lock if necessary */
        int sharedLockByte = SHARED_FIRST+pCtx->sharedByte;
................................................................................
    /* clear the shared lock */
    int sharedLockByte = SHARED_FIRST+pCtx->sharedByte;
    rc = _AFPFSSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 0);
  }

  if( rc==SQLITE_OK ){
    if( locktype==NO_LOCK ){
      struct unixOpenCnt *pOpen = pFile->pOpen;
      pOpen->nLock--;
      assert( pOpen->nLock>=0 );
      if( pOpen->nLock==0 && pOpen->nPending>0 ){
        int i;
        for(i=0; i<pOpen->nPending; i++){
          if( pOpen->aPending[i] < 0 ) continue;
          if( close(pOpen->aPending[i]) ){
................................................................................
          pOpen->nPending = 0;
          pOpen->aPending = 0;
        }
      }
    }
  }
end_afpunlock:
  unixLeaveMutex();
  if( rc==SQLITE_OK ) pFile->locktype = locktype;
  return rc;
}

/*
** Close a file & cleanup AFP specific locking context 
*/
static int afpClose(sqlite3_file *id) {
  if( id ){
    unixFile *pFile = (unixFile*)id;
    afpUnlock(id, NO_LOCK);
    unixEnterMutex();
    if( pFile->pOpen && pFile->pOpen->nLock ){
      /* If there are outstanding locks, do not actually close the file just
       ** yet because that would clear those locks.  Instead, add the file
       ** descriptor to pOpen->aPending.  It will be automatically closed when
       ** the last lock is cleared.
       */
      int *aNew;
      struct unixOpenCnt *pOpen = pFile->pOpen;
      aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
      if( aNew==0 ){
        /* If a malloc fails, just leak the file descriptor */
      }else{
        pOpen->aPending = aNew;
        pOpen->aPending[pOpen->nPending] = pFile->h;
        pOpen->nPending++;
        pFile->h = -1;
      }
    }
    releaseOpenCnt(pFile->pOpen);
    sqlite3_free(pFile->lockingContext);
    closeUnixFile(id);
    unixLeaveMutex();
  }
  return SQLITE_OK;
}


#pragma mark flock() style locking

................................................................................
static int flockClose(sqlite3_file *id) {
  if( id ){
    flockUnlock(id, NO_LOCK);
  }
  return closeUnixFile(id);
}

#endif /* !OS_VXWORKS */

#pragma mark Old-School .lock file based locking
#define DOTLOCK_SUFFIX ".lock"

/* Dotlock-style reserved lock checking following the behavior of 
** unixCheckReservedLock, see the unixCheckReservedLock function comments */
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
................................................................................
  char *zLockFile = (char *)pFile->lockingContext;
  int rc=SQLITE_OK;

  /* if we already have a lock, it is exclusive.  
  ** Just adjust level and punt on outta here. */
  if (pFile->locktype > NO_LOCK) {
    pFile->locktype = locktype;
#if !OS_VXWORKS
    /* Always update the timestamp on the old file */
    utimes(zLockFile, NULL);
#endif
    rc = SQLITE_OK;
    goto dotlock_end_lock;
  }
  
................................................................................
static int dotlockClose(sqlite3_file *id) {
  int rc;
  if( id ){
    unixFile *pFile = (unixFile*)id;
    dotlockUnlock(id, NO_LOCK);
    sqlite3_free(pFile->lockingContext);
  }
  if( OS_VXWORKS ) unixEnterMutex();
  rc = closeUnixFile(id);
  if( OS_VXWORKS ) unixLeaveMutex();
  return rc;
}

#if OS_VXWORKS

#pragma mark POSIX/vxWorks named semaphore based locking

/* Namedsem-style reserved lock checking following the behavior of 
** unixCheckReservedLock, see the unixCheckReservedLock function comments */
static int namedsemCheckReservedLock(sqlite3_file *id, int *pResOut) {
  int rc = SQLITE_OK;
................................................................................
 ** Close a file.
 */
static int namedsemClose(sqlite3_file *id) {
  if( id ){
    unixFile *pFile = (unixFile*)id;
    namedsemUnlock(id, NO_LOCK);
    assert( pFile );
    unixEnterMutex();
    releaseLockInfo(pFile->pLock);
    releaseOpenCnt(pFile->pOpen);
    closeUnixFile(id);
    unixLeaveMutex();
  }
  return SQLITE_OK;
}

#endif /* OS_VXWORKS */

#pragma mark Proxy locking support

static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
  unixFile *pFile = (unixFile*)id;
  int rc = takeConch(pFile);
  if( rc==SQLITE_OK ){
................................................................................
}

/*
** Close a file.
*/
static int nolockClose(sqlite3_file *id) {
  int rc;
  if( OS_VXWORKS ) unixEnterMutex();
  rc = closeUnixFile(id);
  if( OS_VXWORKS ) unixLeaveMutex();
  return rc;
}


/*
** Information and control of an open file handle.
*/
................................................................................
unixDeviceCharacteristics   /* xDeviceCapabilities */                \
}
static sqlite3_io_methods aIoMethod[] = {
IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock) 
,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
#if SQLITE_ENABLE_LOCKING_STYLE
,IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock)
#if OS_VXWORKS
  ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
  ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
  ,IOMETHODS(namedsemClose, namedsemLock, namedsemUnlock, namedsemCheckReservedLock)
  ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
#else
  ,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock)
  ,IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock)
................................................................................
  assert( pNew->pLock==NULL );
  assert( pNew->pOpen==NULL );

  /* Parameter isDelete is only used on vxworks. Parameter pVfs is only
  ** used if ENABLE_LOCKING_STYLE is defined. Express this explicitly 
  ** here to prevent compiler warnings about unused parameters.
  */
  if( !OS_VXWORKS ) UNUSED_PARAMETER(isDelete);
  if( !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(pVfs);
  if( !OS_VXWORKS && !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(zFilename);

  OSTRACE3("OPEN    %-3d %s\n", h, zFilename);    
  pNew->h = h;
  pNew->dirfd = dirfd;
  SET_THREADID(pNew);

#if OS_VXWORKS
  {
    HashElem *pElem;
    char *zRealname = vxrealpath(zFilename, 1);
    int n;
    pNew->zVxworksPath = 0;
    if( !zRealname ){
      rc = SQLITE_NOMEM;
      eLockingStyle = LOCKING_STYLE_NONE;
    }else{
      n = strlen(zRealname) + 1;
      unixEnterMutex();
      pElem = sqlite3HashFindElem(&vxworksFilenameHash, zRealname, n);
      if( pElem ){
        long cnt = (long)pElem->data;
        cnt++;
        pNew->zVxworksPath = pElem->pKey;
        pElem->data = (void*)cnt;
      }else{
        if( sqlite3HashInsert(&vxworksFilenameHash, zRealname, n,(void*)1)==0 ){
          pElem = sqlite3HashFindElem(&vxworksFilenameHash, zRealname, n);
          if( pElem ){
            pNew->zVxworksPath = pElem->pKey;
          }else{
            sqlite3HashInsert(&vxworksFilenameHash, zRealname, n, 0);
            rc = SQLITE_NOMEM;
            eLockingStyle = LOCKING_STYLE_NONE;
          }
        }
      }
      unixLeaveMutex();
      sqlite3_free(zRealname);
    }
  }
#endif

  if( noLock ){
    eLockingStyle = LOCKING_STYLE_NONE;
................................................................................
  assert(LOCKING_STYLE_AFP==5);
  assert(LOCKING_STYLE_NAMEDSEM==6);
  assert(LOCKING_STYLE_PROXY==7);
    
  switch( eLockingStyle ){

    case LOCKING_STYLE_POSIX: {
      unixEnterMutex();



      rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);

      unixLeaveMutex();
      break;
    }

#if SQLITE_ENABLE_LOCKING_STYLE

#if !OS_VXWORKS
    case LOCKING_STYLE_AFP: {
      /* AFP locking uses the file path so it needs to be included in
      ** the afpLockingContext.
      */
      afpLockingContext *pCtx;
      pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
      if( pCtx==0 ){
................................................................................
        rc = SQLITE_NOMEM;
      }else{
        /* NB: zFilename exists and remains valid until the file is closed
        ** according to requirement F11141.  So we do not need to make a
        ** copy of the filename. */
        pCtx->dbPath = zFilename;
        srandomdev();
        unixEnterMutex();
        rc = findLockInfo(pNew, NULL, &pNew->pOpen);
        unixLeaveMutex();        
      }
      break;
    }
#endif

    case LOCKING_STYLE_DOTFILE: {
      /* Dotfile locking uses the file path so it needs to be included in
................................................................................
      }else{
        sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
      }
      pNew->lockingContext = zLockFile;
      break;
    }

#if OS_VXWORKS
    case LOCKING_STYLE_NAMEDSEM: {
      /* Named semaphore locking uses the file path so it needs to be
       ** included in the namedsemLockingContext
       */
      unixEnterMutex();
      rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
      if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){
        char *zSemName = pNew->pOpen->aSemName;
        int n;
        sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem", pNew->zVxworksPath);
        for( n=0; zSemName[n]; n++ )
          if( zSemName[n]=='/' ) zSemName[n] = '_';
        pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
        if( pNew->pOpen->pSem == SEM_FAILED ){
          rc = SQLITE_NOMEM;
          pNew->pOpen->aSemName[0] = '\0';
        }
      }
      unixLeaveMutex();
      break;
    }
#endif

    case LOCKING_STYLE_FLOCK: 
    case LOCKING_STYLE_NONE: 
      break;
#endif
  }
  
  pNew->lastErrno = 0;
#if OS_VXWORKS
  if( rc!=SQLITE_OK ){
    unlink(zFilename);
    isDelete = 0;
  }
  pNew->isDelete = isDelete;
#endif
  if( rc!=SQLITE_OK ){
................................................................................
    flags |= SQLITE_OPEN_READONLY;
    return unixOpen(pVfs, zPath, pFile, flags, pOutFlags);
  }
  if( fd<0 ){
    return SQLITE_CANTOPEN;
  }
  if( isDelete ){
#if OS_VXWORKS
    zPath = zName;
#else
    unlink(zName);
#endif
  }
#if SQLITE_ENABLE_LOCKING_STYLE
  else{
................................................................................
  SimulateIOError(return SQLITE_IOERR_DELETE);
  unlink(zPath);
#ifndef SQLITE_DISABLE_DIRSYNC
  if( dirSync ){
    int fd;
    rc = openDirectory(zPath, &fd);
    if( rc==SQLITE_OK ){
#if OS_VXWORKS
      if( fsync(fd)==-1 )
#else
      if( fsync(fd) )
#endif
      {
        rc = SQLITE_IOERR_DIR_FSYNC;
      }
................................................................................
  ** current working directly has been unlinked.
  */
  SimulateIOError( return SQLITE_ERROR );

  assert( pVfs->mxPathname==MAX_PATHNAME );
  UNUSED_PARAMETER(pVfs);

#if OS_VXWORKS
  {
    char *zRealname = vxrealpath(zPath, 0);
    zOut[0] = '\0';
    if( !zRealname ){
      return SQLITE_CANTOPEN;
    }
    sqlite3_snprintf(nOut, zOut, "%s", zRealname);
................................................................................
        }
      }
      zFull[j++] = zFull[i];
    }
    zFull[j] = 0;
  }
#endif
#endif /* #if OS_VXWORKS */
}


#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** Interfaces for opening a shared library, finding entry points
** within the shared library, and closing the shared library.
................................................................................
** message is available, it is written to zBufOut. If no error message
** is available, zBufOut is left unmodified and SQLite uses a default
** error message.
*/
static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
  char *zErr;
  UNUSED_PARAMETER(NotUsed);
  unixEnterMutex();
  zErr = dlerror();
  if( zErr ){
    sqlite3_snprintf(nBuf, zBufOut, "%s", zErr);
  }
  unixLeaveMutex();
}
static void *unixDlSym(sqlite3_vfs *NotUsed, void *pHandle, const char*zSymbol){
  UNUSED_PARAMETER(NotUsed);
  return dlsym(pHandle, zSymbol);
}
static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){
  UNUSED_PARAMETER(NotUsed);
................................................................................
** The argument is the number of microseconds we want to sleep.
** The return value is the number of microseconds of sleep actually
** requested from the underlying operating system, a number which
** might be greater than or equal to the argument, but not less
** than the argument.
*/
static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
#if OS_VXWORKS
  struct timespec sp;

  sp.tv_sec = microseconds / 1000000;
  sp.tv_nsec = (microseconds % 1000000) * 1000;
  nanosleep(&sp, NULL);
  return microseconds;
#elif defined(HAVE_USLEEP) && HAVE_USLEEP
................................................................................

/*
** 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.
*/
static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
#if defined(NO_GETTOD)
  time_t t;
  time(&t);
  *prNow = t/86400.0 + 2440587.5;
#elif OS_VXWORKS
  struct timespec sNow;
  clock_gettime(CLOCK_REALTIME, &sNow);
  *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_nsec/86400000000000.0;




#else
  struct timeval sNow;
  gettimeofday(&sNow, 0);
  *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_usec/86400000000.0;
#endif

#ifdef SQLITE_TEST
................................................................................
    UNIXVFS("unix-namedsem",LOCKING_STYLE_NAMEDSEM),
    UNIXVFS("unix-proxy",   LOCKING_STYLE_PROXY)
  };
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
    sqlite3_vfs_register(&aVfs[i], 0);
  }
#endif
#if OS_VXWORKS
  sqlite3HashInit(&vxworksFilenameHash, 1);
#endif
  sqlite3_vfs_register(&unixVfs, 1);
  return SQLITE_OK; 
}

/*
** Shutdown the operating system interface. This is a no-op for unix.
*/
int sqlite3_os_end(void){ 
  return SQLITE_OK; 
}
 
#endif /* SQLITE_OS_UNIX */