/ Check-in [92c91a6c]
Login

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

Overview
Comment:In os_unix.c, use "IS_VXWORKS" instead of "defined(__RTP__) || defined(_WRS_KERNEL)". Purely because it's easier on the eyes. (CVS 5925)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:92c91a6cd7bcbe79206bdf7708fe9049a7b7fdd6
User & Date: danielk1977 2008-11-19 13:52:30
Context
2008-11-19
14:35
Fix a few more compiler warnings. (CVS 5926) check-in: 70b2f683 user: danielk1977 tags: trunk
13:52
In os_unix.c, use "IS_VXWORKS" instead of "defined(__RTP__) || defined(_WRS_KERNEL)". Purely because it's easier on the eyes. (CVS 5925) check-in: 92c91a6c user: danielk1977 tags: trunk
12:43
Version number to 3.6.6. (CVS 5924) check-in: 8cc120fb user: drh 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
..
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
...
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
...
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
...
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
...
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
...
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769
770
771
772
773
774
775
...
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
...
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
...
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
...
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
...
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
....
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
....
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
....
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
....
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
....
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
....
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504

2505
2506
2507
2508
2509
2510
2511
....
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
....
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
....
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
....
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
....
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
....
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
....
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
....
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
....
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
....
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
....
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
....
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
**    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.213 2008/11/19 11:35:40 danielk1977 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:
................................................................................
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>

#if SQLITE_ENABLE_LOCKING_STYLE
#include <sys/ioctl.h>
#if defined(__RTP__) || defined(_WRS_KERNEL)
#define lstat stat
#include <semaphore.h>
#include <limits.h>
#else
#include <sys/param.h>
#include <sys/mount.h>
#endif
#endif /* SQLITE_ENABLE_LOCKING_STYLE */

/*
** If we are to be thread-safe, include the pthreads header and define
** the SQLITE_UNIX_THREADS macro.
*/
#if SQLITE_THREADSAFE
................................................................................
  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 defined(__RTP__) || defined(_WRS_KERNEL)
  int isDelete;             /* Delete on close if true */
  char *zRealpath;
#endif
};

/*
** Include code that is common to all os_*.c files
................................................................................
** 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 defined(__RTP__) || defined(_WRS_KERNEL)
  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 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 defined(__RTP__) || defined(_WRS_KERNEL)
  void *rnam;  /* Realname since inode unusable */
#else
  ino_t ino;   /* Inode number */
#endif
};

/*
................................................................................
*/
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 defined(__RTP__) || defined(_WRS_KERNEL)
  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 */
};

/*
................................................................................
** 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;

#if defined(__RTP__) || defined(_WRS_KERNEL)
/*
** 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.
................................................................................
      }
      sqlite3_free(pOpen->aPending);
      sqlite3_free(pOpen);
    }
  }
}

#if defined(__RTP__) || defined(_WRS_KERNEL)
/*
** 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)
................................................................................
  lockInfo.l_whence = SEEK_SET;
  lockInfo.l_type = F_RDLCK;
  if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) {
    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.

  */
#if defined(__RTP__) || defined(_WRS_KERNEL)  
  return LOCKING_STYLE_NAMEDSEM;
#else
  return LOCKING_STYLE_DOTFILE;
#endif
}
#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 defined(__RTP__) || defined(_WRS_KERNEL)
  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 defined(__RTP__) || defined(_WRS_KERNEL) */
  return LOCKING_STYLE_POSIX;
}
#else
  #define detectLockingStyle(x,y,z) LOCKING_STYLE_POSIX
#endif /* ifdef SQLITE_ENABLE_LOCKING_STYLE */

/*
................................................................................
** 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(
  int fd,                      /* The file descriptor used in the key */
#if defined(__RTP__) || defined(_WRS_KERNEL)
  void *rnam,                  /* vxWorks realname */
#endif
  struct lockInfo **ppLock,    /* Return the lockInfo structure here */
  struct openCnt **ppOpen      /* Return the openCnt structure here */
){
  int rc;
  struct lockKey key1;
................................................................................
    if( rc!=0 ){
      return SQLITE_IOERR;
    }
  }

  memset(&key1, 0, sizeof(key1));
  key1.dev = statbuf.st_dev;
#if defined(__RTP__) || defined(_WRS_KERNEL)
  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 defined(__RTP__) || defined(_WRS_KERNEL)
  key2.rnam = rnam;
#else
  key2.ino = statbuf.st_ino;
#endif
  pLock = lockList;
  while( pLock && memcmp(&key1, &pLock->key, sizeof(key1)) ){
    pLock = pLock->pNext;
................................................................................
      pOpen->nLock = 0;
      pOpen->nPending = 0;
      pOpen->aPending = 0;
      pOpen->pNext = openList;
      pOpen->pPrev = 0;
      if( openList ) openList->pPrev = pOpen;
      openList = pOpen;
#if defined(__RTP__) || defined(_WRS_KERNEL)
      pOpen->pSem = NULL;
      pOpen->aSemName[0] = '\0';
#endif
    }else{
      pOpen->nRef++;
    }
    *ppOpen = pOpen;
................................................................................
    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 defined(__RTP__) || defined(_WRS_KERNEL)
    rc = findLockInfo(pFile->h, pFile->zRealpath, &pFile->pLock, 0);
#else
    rc = findLockInfo(pFile->h, &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);
................................................................................
  if( pFile ){
    if( pFile->dirfd>=0 ){
      close(pFile->dirfd);
    }
    if( pFile->h>=0 ){
      close(pFile->h);
    }
#if defined(__RTP__) || defined(_WRS_KERNEL)
    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);
................................................................................
  }
  return SQLITE_OK;
}


#if SQLITE_ENABLE_LOCKING_STYLE

#if !defined(__RTP__) && !defined(_WRS_KERNEL)
#pragma mark AFP Support

/*
 ** The afpLockingContext structure contains all afp lock specific state
 */
typedef struct afpLockingContext afpLockingContext;
struct afpLockingContext {
................................................................................
static int flockClose(sqlite3_file *id) {
  if( id ){
    flockUnlock(id, NO_LOCK);
  }
  return closeUnixFile(id);
}

#endif /* !defined(__RTP__) && !defined(_WRS_KERNEL) */

#pragma mark Old-School .lock file based locking

/* Dotlock-style reserved lock checking following the behavior of 
** unixCheckReservedLock, see the unixCheckReservedLock function comments */
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
  int rc = SQLITE_OK;
................................................................................
  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 !defined(__RTP__) && !defined(_WRS_KERNEL)    
    /* Always update the timestamp on the old file */
    utimes(zLockFile, NULL);
#endif
    rc = SQLITE_OK;
    goto dotlock_end_lock;
  }
  
................................................................................
  return SQLITE_OK;
}

/*
 ** Close a file.
 */
static int dotlockClose(sqlite3_file *id) {
#if defined(__RTP__) || defined(_WRS_KERNEL)
  int rc;
#endif
  if( id ){
    unixFile *pFile = (unixFile*)id;
    dotlockUnlock(id, NO_LOCK);
    sqlite3_free(pFile->lockingContext);
  }
#if defined(__RTP__) || defined(_WRS_KERNEL)
  enterMutex();
  rc = closeUnixFile(id);
  leaveMutex();
  return rc;
#else
  return closeUnixFile(id);
#endif
}

#if defined(__RTP__) || defined(_WRS_KERNEL)


#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;
................................................................................
    releaseOpenCnt(pFile->pOpen);
    closeUnixFile(id);
    leaveMutex();
  }
  return SQLITE_OK;
}

#endif /* defined(__RTP__) || defined(_WRS_KERNEL) */

#endif /* SQLITE_ENABLE_LOCKING_STYLE */

/*
** The nolockLockingContext is void
*/
typedef void nolockLockingContext;
................................................................................
    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 defined(__RTP__) || defined(_WRS_KERNEL)
   ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
   ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
   ,IOMETHODS(namedsemClose, namedsemLock, namedsemUnlock, namedsemCheckReservedLock)
#else
   ,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock)
   ,IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock)
   ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
................................................................................
  assert( pNew->pOpen==NULL );

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

#if defined(__RTP__) || defined(_WRS_KERNEL)
  {
    HashElem *pElem;
    char *zRealname = vxrealpath(zFilename, 1);
    int n;
    pNew->zRealpath = 0;
    if( !zRealname ){
      rc = SQLITE_NOMEM;
................................................................................
    eLockingStyle = detectLockingStyle(pVfs, zFilename, h);
  }

  switch( eLockingStyle ){

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

#if SQLITE_ENABLE_LOCKING_STYLE

#if !defined(__RTP__) && !defined(_WRS_KERNEL)
    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 ){
................................................................................
      }else{
        sqlite3_snprintf(nFilename, zLockFile, "%s.lock", zFilename);
      }
      pNew->lockingContext = zLockFile;
      break;
    }

#if defined(__RTP__) || defined(_WRS_KERNEL)
    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) ){
................................................................................
        }
      }
      leaveMutex();
      break;
    }
#endif

#if !defined(__RTP__) && !defined(_WRS_KERNEL)
    case LOCKING_STYLE_FLOCK: 
#endif
    case LOCKING_STYLE_NONE: 
      break;
#endif
  }
  
  pNew->lastErrno = 0;
#if defined(__RTP__) || defined(_WRS_KERNEL)
  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 defined(__RTP__) || defined(_WRS_KERNEL)
    zPath = zName;
#else
    unlink(zName);
#endif
  }
  if( pOutFlags ){
    *pOutFlags = flags;
................................................................................
  SimulateIOError(return SQLITE_IOERR_DELETE);
  unlink(zPath);
#ifndef SQLITE_DISABLE_DIRSYNC
  if( dirSync ){
    int fd;
    rc = openDirectory(zPath, &fd);
    if( rc==SQLITE_OK ){
#if defined(__RTP__) || defined(_WRS_KERNEL)
      if( fsync(fd)==-1 )
#else
      if( fsync(fd) )
#endif
      {
        rc = SQLITE_IOERR_DIR_FSYNC;
      }
................................................................................
  ** function failing. This function could fail if, for example, the
  ** current working directly has been unlinked.
  */
  SimulateIOError( return SQLITE_ERROR );

  assert( pVfs->mxPathname==MAX_PATHNAME );

#if defined(__RTP__) || defined(_WRS_KERNEL)
  {
    char *zRealname = vxrealpath(zPath, 0);
    zOut[0] = '\0';
    if( !zRealname ){
      return SQLITE_CANTOPEN;
    }
    sqlite3_snprintf(nOut, zOut, "%s", zRealname);
................................................................................
** 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 defined(__RTP__) || defined(_WRS_KERNEL)
  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(__RTP__) || defined(_WRS_KERNEL)
  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;
................................................................................
    UNIXVFS("unix-none",    LOCKING_STYLE_NONE),
    UNIXVFS("unix-namedsem",LOCKING_STYLE_NAMEDSEM),
  };
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
    sqlite3_vfs_register(&aVfs[i], 0);
  }
#endif
#if defined(__RTP__) || defined(_WRS_KERNEL)
  sqlite3HashInit(&nameHash, 1);
#endif
  sqlite3_vfs_register(&unixVfs, 1);
  return SQLITE_OK; 
}

/*







|







 







|
|
|
|
|
|
|
|
|







 







|







 







|







 







|







 







|







 







|







 







|







 







|
>

<
|
<
<
<







 







|







 







|







 







|







 







|












|







 







|







 







|







 







|







 







|







 







|







 







|







 







<

<





<
|

|

<
<
<


<
>







 







|







 







|







 







|







 







|










|







 







|







 







|








|







 







|







 







|







 







|







 







|







 







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
...
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
...
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
...
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
...
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
...
755
756
757
758
759
760
761
762
763
764

765



766
767
768
769
770
771
772
...
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
...
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
...
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
...
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
...
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
....
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
....
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
....
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
....
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
....
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
....
2476
2477
2478
2479
2480
2481
2482

2483

2484
2485
2486
2487
2488

2489
2490
2491
2492



2493
2494

2495
2496
2497
2498
2499
2500
2501
2502
....
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
....
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
....
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
....
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
....
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
....
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
....
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
....
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
....
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
....
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
....
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
....
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
**    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.214 2008/11/19 13:52:30 danielk1977 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:
................................................................................
#include <fcntl.h>
#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
#endif /* SQLITE_ENABLE_LOCKING_STYLE */

/*
** If we are to be thread-safe, include the pthreads header and define
** the SQLITE_UNIX_THREADS macro.
*/
#if SQLITE_THREADSAFE
................................................................................
  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
};

/*
** Include code that is common to all os_*.c files
................................................................................
** 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 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
};

/*
................................................................................
*/
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 */
};

/*
................................................................................
** 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;

#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.
................................................................................
      }
      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)
................................................................................
  lockInfo.l_whence = SEEK_SET;
  lockInfo.l_type = F_RDLCK;
  if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) {
    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 /* ifdef SQLITE_ENABLE_LOCKING_STYLE */

/*
................................................................................
** 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(
  int fd,                      /* The file descriptor 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;
  struct lockKey key1;
................................................................................
    if( rc!=0 ){
      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
  pLock = lockList;
  while( pLock && memcmp(&key1, &pLock->key, sizeof(key1)) ){
    pLock = pLock->pNext;
................................................................................
      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;
................................................................................
    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->h, pFile->zRealpath, &pFile->pLock, 0);
#else
    rc = findLockInfo(pFile->h, &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);
................................................................................
  if( pFile ){
    if( pFile->dirfd>=0 ){
      close(pFile->dirfd);
    }
    if( pFile->h>=0 ){
      close(pFile->h);
    }
#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);
................................................................................
  }
  return SQLITE_OK;
}


#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 {
................................................................................
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

/* Dotlock-style reserved lock checking following the behavior of 
** unixCheckReservedLock, see the unixCheckReservedLock function comments */
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
  int rc = SQLITE_OK;
................................................................................
  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;
  }
  
................................................................................
  return SQLITE_OK;
}

/*
 ** Close a file.
 */
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;
................................................................................
    releaseOpenCnt(pFile->pOpen);
    closeUnixFile(id);
    leaveMutex();
  }
  return SQLITE_OK;
}

#endif /* IS_VXWORKS */

#endif /* SQLITE_ENABLE_LOCKING_STYLE */

/*
** The nolockLockingContext is void
*/
typedef void nolockLockingContext;
................................................................................
    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)
#else
   ,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock)
   ,IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock)
   ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
................................................................................
  assert( pNew->pOpen==NULL );

  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 = detectLockingStyle(pVfs, zFilename, h);
  }

  switch( eLockingStyle ){

    case LOCKING_STYLE_POSIX: {
      enterMutex();
#if IS_VXWORKS
      rc = findLockInfo(h, pNew->zRealpath, &pNew->pLock, &pNew->pOpen);
#else
      rc = findLockInfo(h, &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 ){
................................................................................
      }else{
        sqlite3_snprintf(nFilename, zLockFile, "%s.lock", 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) ){
................................................................................
        }
      }
      leaveMutex();
      break;
    }
#endif

#if !IS_VXWORKS
    case LOCKING_STYLE_FLOCK: 
#endif
    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( pOutFlags ){
    *pOutFlags = flags;
................................................................................
  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;
      }
................................................................................
  ** function failing. This function could fail if, for example, the
  ** current working directly has been unlinked.
  */
  SimulateIOError( return SQLITE_ERROR );

  assert( pVfs->mxPathname==MAX_PATHNAME );

#if IS_VXWORKS
  {
    char *zRealname = vxrealpath(zPath, 0);
    zOut[0] = '\0';
    if( !zRealname ){
      return SQLITE_CANTOPEN;
    }
    sqlite3_snprintf(nOut, zOut, "%s", zRealname);
................................................................................
** 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;
................................................................................
    UNIXVFS("unix-none",    LOCKING_STYLE_NONE),
    UNIXVFS("unix-namedsem",LOCKING_STYLE_NAMEDSEM),
  };
  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; 
}

/*