Snapshot of upstream SQLite 3.43.2
[sqlcipher.git] / ext / lsm1 / lsm_unix.c
blob88952d15fc721ac19747a0cf284b7f7b28520c45
1 /*
2 ** 2011-12-03
3 **
4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
6 **
7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give.
11 *************************************************************************
13 ** Unix-specific run-time environment implementation for LSM.
16 #ifndef _WIN32
18 #if defined(__GNUC__) || defined(__TINYC__)
19 /* workaround for ftruncate() visibility on gcc. */
20 # ifndef _XOPEN_SOURCE
21 # define _XOPEN_SOURCE 500
22 # endif
23 #endif
25 #include <unistd.h>
26 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <assert.h>
31 #include <string.h>
33 #include <stdlib.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <ctype.h>
38 #include <unistd.h>
39 #include <errno.h>
41 #include <sys/mman.h>
42 #include "lsmInt.h"
44 /* There is no fdatasync() call on Android */
45 #ifdef __ANDROID__
46 # define fdatasync(x) fsync(x)
47 #endif
50 ** An open file is an instance of the following object
52 typedef struct PosixFile PosixFile;
53 struct PosixFile {
54 lsm_env *pEnv; /* The run-time environment */
55 const char *zName; /* Full path to file */
56 int fd; /* The open file descriptor */
57 int shmfd; /* Shared memory file-descriptor */
58 void *pMap; /* Pointer to mapping of file fd */
59 off_t nMap; /* Size of mapping at pMap in bytes */
60 int nShm; /* Number of entries in array apShm[] */
61 void **apShm; /* Array of 32K shared memory segments */
64 static char *posixShmFile(PosixFile *p){
65 char *zShm;
66 int nName = strlen(p->zName);
67 zShm = (char *)lsmMalloc(p->pEnv, nName+4+1);
68 if( zShm ){
69 memcpy(zShm, p->zName, nName);
70 memcpy(&zShm[nName], "-shm", 5);
72 return zShm;
75 static int lsmPosixOsOpen(
76 lsm_env *pEnv,
77 const char *zFile,
78 int flags,
79 lsm_file **ppFile
81 int rc = LSM_OK;
82 PosixFile *p;
84 p = lsm_malloc(pEnv, sizeof(PosixFile));
85 if( p==0 ){
86 rc = LSM_NOMEM;
87 }else{
88 int bReadonly = (flags & LSM_OPEN_READONLY);
89 int oflags = (bReadonly ? O_RDONLY : (O_RDWR|O_CREAT));
90 memset(p, 0, sizeof(PosixFile));
91 p->zName = zFile;
92 p->pEnv = pEnv;
93 p->fd = open(zFile, oflags, 0644);
94 if( p->fd<0 ){
95 lsm_free(pEnv, p);
96 p = 0;
97 if( errno==ENOENT ){
98 rc = lsmErrorBkpt(LSM_IOERR_NOENT);
99 }else{
100 rc = LSM_IOERR_BKPT;
105 *ppFile = (lsm_file *)p;
106 return rc;
109 static int lsmPosixOsWrite(
110 lsm_file *pFile, /* File to write to */
111 lsm_i64 iOff, /* Offset to write to */
112 void *pData, /* Write data from this buffer */
113 int nData /* Bytes of data to write */
115 int rc = LSM_OK;
116 PosixFile *p = (PosixFile *)pFile;
117 off_t offset;
119 offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
120 if( offset!=iOff ){
121 rc = LSM_IOERR_BKPT;
122 }else{
123 ssize_t prc = write(p->fd, pData, (size_t)nData);
124 if( prc<0 ) rc = LSM_IOERR_BKPT;
127 return rc;
130 static int lsmPosixOsTruncate(
131 lsm_file *pFile, /* File to write to */
132 lsm_i64 nSize /* Size to truncate file to */
134 PosixFile *p = (PosixFile *)pFile;
135 int rc = LSM_OK; /* Return code */
136 int prc; /* Posix Return Code */
137 struct stat sStat; /* Result of fstat() invocation */
139 prc = fstat(p->fd, &sStat);
140 if( prc==0 && sStat.st_size>nSize ){
141 prc = ftruncate(p->fd, (off_t)nSize);
143 if( prc<0 ) rc = LSM_IOERR_BKPT;
145 return rc;
148 static int lsmPosixOsRead(
149 lsm_file *pFile, /* File to read from */
150 lsm_i64 iOff, /* Offset to read from */
151 void *pData, /* Read data into this buffer */
152 int nData /* Bytes of data to read */
154 int rc = LSM_OK;
155 PosixFile *p = (PosixFile *)pFile;
156 off_t offset;
158 offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
159 if( offset!=iOff ){
160 rc = LSM_IOERR_BKPT;
161 }else{
162 ssize_t prc = read(p->fd, pData, (size_t)nData);
163 if( prc<0 ){
164 rc = LSM_IOERR_BKPT;
165 }else if( prc<nData ){
166 memset(&((u8 *)pData)[prc], 0, nData - prc);
171 return rc;
174 static int lsmPosixOsSync(lsm_file *pFile){
175 int rc = LSM_OK;
177 #ifndef LSM_NO_SYNC
178 PosixFile *p = (PosixFile *)pFile;
179 int prc = 0;
181 if( p->pMap ){
182 prc = msync(p->pMap, p->nMap, MS_SYNC);
184 if( prc==0 ) prc = fdatasync(p->fd);
185 if( prc<0 ) rc = LSM_IOERR_BKPT;
186 #else
187 (void)pFile;
188 #endif
190 return rc;
193 static int lsmPosixOsSectorSize(lsm_file *pFile){
194 return 512;
197 static int lsmPosixOsRemap(
198 lsm_file *pFile,
199 lsm_i64 iMin,
200 void **ppOut,
201 lsm_i64 *pnOut
203 off_t iSz;
204 int prc;
205 PosixFile *p = (PosixFile *)pFile;
206 struct stat buf;
208 /* If the file is between 0 and 2MB in size, extend it in chunks of 256K.
209 ** Thereafter, in chunks of 1MB at a time. */
210 const int aIncrSz[] = {256*1024, 1024*1024};
211 int nIncrSz = aIncrSz[iMin>(2*1024*1024)];
213 if( p->pMap ){
214 munmap(p->pMap, p->nMap);
215 *ppOut = p->pMap = 0;
216 *pnOut = p->nMap = 0;
219 if( iMin>=0 ){
220 memset(&buf, 0, sizeof(buf));
221 prc = fstat(p->fd, &buf);
222 if( prc!=0 ) return LSM_IOERR_BKPT;
223 iSz = buf.st_size;
224 if( iSz<iMin ){
225 iSz = ((iMin + nIncrSz-1) / nIncrSz) * nIncrSz;
226 prc = ftruncate(p->fd, iSz);
227 if( prc!=0 ) return LSM_IOERR_BKPT;
230 p->pMap = mmap(0, iSz, PROT_READ|PROT_WRITE, MAP_SHARED, p->fd, 0);
231 if( p->pMap==MAP_FAILED ){
232 p->pMap = 0;
233 return LSM_IOERR_BKPT;
235 p->nMap = iSz;
238 *ppOut = p->pMap;
239 *pnOut = p->nMap;
240 return LSM_OK;
243 static int lsmPosixOsFullpath(
244 lsm_env *pEnv,
245 const char *zName,
246 char *zOut,
247 int *pnOut
249 int nBuf = *pnOut;
250 int nReq;
252 if( zName[0]!='/' ){
253 char *z;
254 char *zTmp;
255 int nTmp = 512;
256 zTmp = lsmMalloc(pEnv, nTmp);
257 while( zTmp ){
258 z = getcwd(zTmp, nTmp);
259 if( z || errno!=ERANGE ) break;
260 nTmp = nTmp*2;
261 zTmp = lsmReallocOrFree(pEnv, zTmp, nTmp);
263 if( zTmp==0 ) return LSM_NOMEM_BKPT;
264 if( z==0 ) return LSM_IOERR_BKPT;
265 assert( z==zTmp );
267 nTmp = strlen(zTmp);
268 nReq = nTmp + 1 + strlen(zName) + 1;
269 if( nReq<=nBuf ){
270 memcpy(zOut, zTmp, nTmp);
271 zOut[nTmp] = '/';
272 memcpy(&zOut[nTmp+1], zName, strlen(zName)+1);
274 lsmFree(pEnv, zTmp);
275 }else{
276 nReq = strlen(zName)+1;
277 if( nReq<=nBuf ){
278 memcpy(zOut, zName, strlen(zName)+1);
282 *pnOut = nReq;
283 return LSM_OK;
286 static int lsmPosixOsFileid(
287 lsm_file *pFile,
288 void *pBuf,
289 int *pnBuf
291 int prc;
292 int nBuf;
293 int nReq;
294 PosixFile *p = (PosixFile *)pFile;
295 struct stat buf;
297 nBuf = *pnBuf;
298 nReq = (sizeof(buf.st_dev) + sizeof(buf.st_ino));
299 *pnBuf = nReq;
300 if( nReq>nBuf ) return LSM_OK;
302 memset(&buf, 0, sizeof(buf));
303 prc = fstat(p->fd, &buf);
304 if( prc!=0 ) return LSM_IOERR_BKPT;
306 memcpy(pBuf, &buf.st_dev, sizeof(buf.st_dev));
307 memcpy(&(((u8 *)pBuf)[sizeof(buf.st_dev)]), &buf.st_ino, sizeof(buf.st_ino));
308 return LSM_OK;
311 static int lsmPosixOsUnlink(lsm_env *pEnv, const char *zFile){
312 int prc = unlink(zFile);
313 return prc ? LSM_IOERR_BKPT : LSM_OK;
316 static int lsmPosixOsLock(lsm_file *pFile, int iLock, int eType){
317 int rc = LSM_OK;
318 PosixFile *p = (PosixFile *)pFile;
319 static const short aType[3] = { F_UNLCK, F_RDLCK, F_WRLCK };
320 struct flock lock;
322 assert( aType[LSM_LOCK_UNLOCK]==F_UNLCK );
323 assert( aType[LSM_LOCK_SHARED]==F_RDLCK );
324 assert( aType[LSM_LOCK_EXCL]==F_WRLCK );
325 assert( eType>=0 && eType<array_size(aType) );
326 assert( iLock>0 && iLock<=32 );
328 memset(&lock, 0, sizeof(lock));
329 lock.l_whence = SEEK_SET;
330 lock.l_len = 1;
331 lock.l_type = aType[eType];
332 lock.l_start = (4096-iLock);
334 if( fcntl(p->fd, F_SETLK, &lock) ){
335 int e = errno;
336 if( e==EACCES || e==EAGAIN ){
337 rc = LSM_BUSY;
338 }else{
339 rc = LSM_IOERR_BKPT;
343 return rc;
346 static int lsmPosixOsTestLock(lsm_file *pFile, int iLock, int nLock, int eType){
347 int rc = LSM_OK;
348 PosixFile *p = (PosixFile *)pFile;
349 static const short aType[3] = { 0, F_RDLCK, F_WRLCK };
350 struct flock lock;
352 assert( eType==LSM_LOCK_SHARED || eType==LSM_LOCK_EXCL );
353 assert( aType[LSM_LOCK_SHARED]==F_RDLCK );
354 assert( aType[LSM_LOCK_EXCL]==F_WRLCK );
355 assert( eType>=0 && eType<array_size(aType) );
356 assert( iLock>0 && iLock<=32 );
358 memset(&lock, 0, sizeof(lock));
359 lock.l_whence = SEEK_SET;
360 lock.l_len = nLock;
361 lock.l_type = aType[eType];
362 lock.l_start = (4096-iLock-nLock+1);
364 if( fcntl(p->fd, F_GETLK, &lock) ){
365 rc = LSM_IOERR_BKPT;
366 }else if( lock.l_type!=F_UNLCK ){
367 rc = LSM_BUSY;
370 return rc;
373 static int lsmPosixOsShmMap(lsm_file *pFile, int iChunk, int sz, void **ppShm){
374 PosixFile *p = (PosixFile *)pFile;
376 *ppShm = 0;
377 assert( sz==LSM_SHM_CHUNK_SIZE );
378 if( iChunk>=p->nShm ){
379 int i;
380 void **apNew;
381 int nNew = iChunk+1;
382 off_t nReq = nNew * LSM_SHM_CHUNK_SIZE;
383 struct stat sStat;
385 /* If the shared-memory file has not been opened, open it now. */
386 if( p->shmfd<=0 ){
387 char *zShm = posixShmFile(p);
388 if( !zShm ) return LSM_NOMEM_BKPT;
389 p->shmfd = open(zShm, O_RDWR|O_CREAT, 0644);
390 lsmFree(p->pEnv, zShm);
391 if( p->shmfd<0 ){
392 return LSM_IOERR_BKPT;
396 /* If the shared-memory file is not large enough to contain the
397 ** requested chunk, cause it to grow. */
398 if( fstat(p->shmfd, &sStat) ){
399 return LSM_IOERR_BKPT;
401 if( sStat.st_size<nReq ){
402 if( ftruncate(p->shmfd, nReq) ){
403 return LSM_IOERR_BKPT;
407 apNew = (void **)lsmRealloc(p->pEnv, p->apShm, sizeof(void *) * nNew);
408 if( !apNew ) return LSM_NOMEM_BKPT;
409 for(i=p->nShm; i<nNew; i++){
410 apNew[i] = 0;
412 p->apShm = apNew;
413 p->nShm = nNew;
416 if( p->apShm[iChunk]==0 ){
417 p->apShm[iChunk] = mmap(0, LSM_SHM_CHUNK_SIZE,
418 PROT_READ|PROT_WRITE, MAP_SHARED, p->shmfd, iChunk*LSM_SHM_CHUNK_SIZE
420 if( p->apShm[iChunk]==MAP_FAILED ){
421 p->apShm[iChunk] = 0;
422 return LSM_IOERR_BKPT;
426 *ppShm = p->apShm[iChunk];
427 return LSM_OK;
430 static void lsmPosixOsShmBarrier(void){
433 static int lsmPosixOsShmUnmap(lsm_file *pFile, int bDelete){
434 PosixFile *p = (PosixFile *)pFile;
435 if( p->shmfd>0 ){
436 int i;
437 for(i=0; i<p->nShm; i++){
438 if( p->apShm[i] ){
439 munmap(p->apShm[i], LSM_SHM_CHUNK_SIZE);
440 p->apShm[i] = 0;
443 close(p->shmfd);
444 p->shmfd = 0;
445 if( bDelete ){
446 char *zShm = posixShmFile(p);
447 if( zShm ) unlink(zShm);
448 lsmFree(p->pEnv, zShm);
451 return LSM_OK;
455 static int lsmPosixOsClose(lsm_file *pFile){
456 PosixFile *p = (PosixFile *)pFile;
457 lsmPosixOsShmUnmap(pFile, 0);
458 if( p->pMap ) munmap(p->pMap, p->nMap);
459 close(p->fd);
460 lsm_free(p->pEnv, p->apShm);
461 lsm_free(p->pEnv, p);
462 return LSM_OK;
465 static int lsmPosixOsSleep(lsm_env *pEnv, int us){
466 #if 0
467 /* Apparently on Android usleep() returns void */
468 if( usleep(us) ) return LSM_IOERR;
469 #endif
470 usleep(us);
471 return LSM_OK;
474 /****************************************************************************
475 ** Memory allocation routines.
477 #define BLOCK_HDR_SIZE ROUND8( sizeof(size_t) )
479 static void *lsmPosixOsMalloc(lsm_env *pEnv, size_t N){
480 unsigned char * m;
481 N += BLOCK_HDR_SIZE;
482 m = (unsigned char *)malloc(N);
483 *((size_t*)m) = N;
484 return m + BLOCK_HDR_SIZE;
487 static void lsmPosixOsFree(lsm_env *pEnv, void *p){
488 if(p){
489 free( ((unsigned char *)p) - BLOCK_HDR_SIZE );
493 static void *lsmPosixOsRealloc(lsm_env *pEnv, void *p, size_t N){
494 unsigned char * m = (unsigned char *)p;
495 if(1>N){
496 lsmPosixOsFree( pEnv, p );
497 return NULL;
498 }else if(NULL==p){
499 return lsmPosixOsMalloc(pEnv, N);
500 }else{
501 void * re = NULL;
502 m -= BLOCK_HDR_SIZE;
503 #if 0 /* arguable: don't shrink */
504 size_t * sz = (size_t*)m;
505 if(*sz >= (size_t)N){
506 return p;
508 #endif
509 re = realloc( m, N + BLOCK_HDR_SIZE );
510 if(re){
511 m = (unsigned char *)re;
512 *((size_t*)m) = N;
513 return m + BLOCK_HDR_SIZE;
514 }else{
515 return NULL;
520 static size_t lsmPosixOsMSize(lsm_env *pEnv, void *p){
521 unsigned char * m = (unsigned char *)p;
522 return *((size_t*)(m-BLOCK_HDR_SIZE));
524 #undef BLOCK_HDR_SIZE
527 #ifdef LSM_MUTEX_PTHREADS
528 /*************************************************************************
529 ** Mutex methods for pthreads based systems. If LSM_MUTEX_PTHREADS is
530 ** missing then a no-op implementation of mutexes found in lsm_mutex.c
531 ** will be used instead.
533 #include <pthread.h>
535 typedef struct PthreadMutex PthreadMutex;
536 struct PthreadMutex {
537 lsm_env *pEnv;
538 pthread_mutex_t mutex;
539 #ifdef LSM_DEBUG
540 pthread_t owner;
541 #endif
544 #ifdef LSM_DEBUG
545 # define LSM_PTHREAD_STATIC_MUTEX { 0, PTHREAD_MUTEX_INITIALIZER, 0 }
546 #else
547 # define LSM_PTHREAD_STATIC_MUTEX { 0, PTHREAD_MUTEX_INITIALIZER }
548 #endif
550 static int lsmPosixOsMutexStatic(
551 lsm_env *pEnv,
552 int iMutex,
553 lsm_mutex **ppStatic
555 static PthreadMutex sMutex[2] = {
556 LSM_PTHREAD_STATIC_MUTEX,
557 LSM_PTHREAD_STATIC_MUTEX
560 assert( iMutex==LSM_MUTEX_GLOBAL || iMutex==LSM_MUTEX_HEAP );
561 assert( LSM_MUTEX_GLOBAL==1 && LSM_MUTEX_HEAP==2 );
563 *ppStatic = (lsm_mutex *)&sMutex[iMutex-1];
564 return LSM_OK;
567 static int lsmPosixOsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
568 PthreadMutex *pMutex; /* Pointer to new mutex */
569 pthread_mutexattr_t attr; /* Attributes object */
571 pMutex = (PthreadMutex *)lsmMallocZero(pEnv, sizeof(PthreadMutex));
572 if( !pMutex ) return LSM_NOMEM_BKPT;
574 pMutex->pEnv = pEnv;
575 pthread_mutexattr_init(&attr);
576 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
577 pthread_mutex_init(&pMutex->mutex, &attr);
578 pthread_mutexattr_destroy(&attr);
580 *ppNew = (lsm_mutex *)pMutex;
581 return LSM_OK;
584 static void lsmPosixOsMutexDel(lsm_mutex *p){
585 PthreadMutex *pMutex = (PthreadMutex *)p;
586 pthread_mutex_destroy(&pMutex->mutex);
587 lsmFree(pMutex->pEnv, pMutex);
590 static void lsmPosixOsMutexEnter(lsm_mutex *p){
591 PthreadMutex *pMutex = (PthreadMutex *)p;
592 pthread_mutex_lock(&pMutex->mutex);
594 #ifdef LSM_DEBUG
595 assert( !pthread_equal(pMutex->owner, pthread_self()) );
596 pMutex->owner = pthread_self();
597 assert( pthread_equal(pMutex->owner, pthread_self()) );
598 #endif
601 static int lsmPosixOsMutexTry(lsm_mutex *p){
602 int ret;
603 PthreadMutex *pMutex = (PthreadMutex *)p;
604 ret = pthread_mutex_trylock(&pMutex->mutex);
605 #ifdef LSM_DEBUG
606 if( ret==0 ){
607 assert( !pthread_equal(pMutex->owner, pthread_self()) );
608 pMutex->owner = pthread_self();
609 assert( pthread_equal(pMutex->owner, pthread_self()) );
611 #endif
612 return ret;
615 static void lsmPosixOsMutexLeave(lsm_mutex *p){
616 PthreadMutex *pMutex = (PthreadMutex *)p;
617 #ifdef LSM_DEBUG
618 assert( pthread_equal(pMutex->owner, pthread_self()) );
619 pMutex->owner = 0;
620 assert( !pthread_equal(pMutex->owner, pthread_self()) );
621 #endif
622 pthread_mutex_unlock(&pMutex->mutex);
625 #ifdef LSM_DEBUG
626 static int lsmPosixOsMutexHeld(lsm_mutex *p){
627 PthreadMutex *pMutex = (PthreadMutex *)p;
628 return pMutex ? pthread_equal(pMutex->owner, pthread_self()) : 1;
630 static int lsmPosixOsMutexNotHeld(lsm_mutex *p){
631 PthreadMutex *pMutex = (PthreadMutex *)p;
632 return pMutex ? !pthread_equal(pMutex->owner, pthread_self()) : 1;
634 #endif
636 ** End of pthreads mutex implementation.
637 *************************************************************************/
638 #else
639 /*************************************************************************
640 ** Noop mutex implementation
642 typedef struct NoopMutex NoopMutex;
643 struct NoopMutex {
644 lsm_env *pEnv; /* Environment handle (for xFree()) */
645 int bHeld; /* True if mutex is held */
646 int bStatic; /* True for a static mutex */
648 static NoopMutex aStaticNoopMutex[2] = {
649 {0, 0, 1},
650 {0, 0, 1},
653 static int lsmPosixOsMutexStatic(
654 lsm_env *pEnv,
655 int iMutex,
656 lsm_mutex **ppStatic
658 assert( iMutex>=1 && iMutex<=(int)array_size(aStaticNoopMutex) );
659 *ppStatic = (lsm_mutex *)&aStaticNoopMutex[iMutex-1];
660 return LSM_OK;
662 static int lsmPosixOsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
663 NoopMutex *p;
664 p = (NoopMutex *)lsmMallocZero(pEnv, sizeof(NoopMutex));
665 if( p ) p->pEnv = pEnv;
666 *ppNew = (lsm_mutex *)p;
667 return (p ? LSM_OK : LSM_NOMEM_BKPT);
669 static void lsmPosixOsMutexDel(lsm_mutex *pMutex) {
670 NoopMutex *p = (NoopMutex *)pMutex;
671 assert( p->bStatic==0 && p->pEnv );
672 lsmFree(p->pEnv, p);
674 static void lsmPosixOsMutexEnter(lsm_mutex *pMutex){
675 NoopMutex *p = (NoopMutex *)pMutex;
676 assert( p->bHeld==0 );
677 p->bHeld = 1;
679 static int lsmPosixOsMutexTry(lsm_mutex *pMutex){
680 NoopMutex *p = (NoopMutex *)pMutex;
681 assert( p->bHeld==0 );
682 p->bHeld = 1;
683 return 0;
685 static void lsmPosixOsMutexLeave(lsm_mutex *pMutex){
686 NoopMutex *p = (NoopMutex *)pMutex;
687 assert( p->bHeld==1 );
688 p->bHeld = 0;
690 #ifdef LSM_DEBUG
691 static int lsmPosixOsMutexHeld(lsm_mutex *pMutex){
692 NoopMutex *p = (NoopMutex *)pMutex;
693 return p ? p->bHeld : 1;
695 static int lsmPosixOsMutexNotHeld(lsm_mutex *pMutex){
696 NoopMutex *p = (NoopMutex *)pMutex;
697 return p ? !p->bHeld : 1;
699 #endif
700 /***************************************************************************/
701 #endif /* else LSM_MUTEX_NONE */
703 /* Without LSM_DEBUG, the MutexHeld tests are never called */
704 #ifndef LSM_DEBUG
705 # define lsmPosixOsMutexHeld 0
706 # define lsmPosixOsMutexNotHeld 0
707 #endif
709 lsm_env *lsm_default_env(void){
710 static lsm_env posix_env = {
711 sizeof(lsm_env), /* nByte */
712 1, /* iVersion */
713 /***** file i/o ******************/
714 0, /* pVfsCtx */
715 lsmPosixOsFullpath, /* xFullpath */
716 lsmPosixOsOpen, /* xOpen */
717 lsmPosixOsRead, /* xRead */
718 lsmPosixOsWrite, /* xWrite */
719 lsmPosixOsTruncate, /* xTruncate */
720 lsmPosixOsSync, /* xSync */
721 lsmPosixOsSectorSize, /* xSectorSize */
722 lsmPosixOsRemap, /* xRemap */
723 lsmPosixOsFileid, /* xFileid */
724 lsmPosixOsClose, /* xClose */
725 lsmPosixOsUnlink, /* xUnlink */
726 lsmPosixOsLock, /* xLock */
727 lsmPosixOsTestLock, /* xTestLock */
728 lsmPosixOsShmMap, /* xShmMap */
729 lsmPosixOsShmBarrier, /* xShmBarrier */
730 lsmPosixOsShmUnmap, /* xShmUnmap */
731 /***** memory allocation *********/
732 0, /* pMemCtx */
733 lsmPosixOsMalloc, /* xMalloc */
734 lsmPosixOsRealloc, /* xRealloc */
735 lsmPosixOsFree, /* xFree */
736 lsmPosixOsMSize, /* xSize */
737 /***** mutexes *********************/
738 0, /* pMutexCtx */
739 lsmPosixOsMutexStatic, /* xMutexStatic */
740 lsmPosixOsMutexNew, /* xMutexNew */
741 lsmPosixOsMutexDel, /* xMutexDel */
742 lsmPosixOsMutexEnter, /* xMutexEnter */
743 lsmPosixOsMutexTry, /* xMutexTry */
744 lsmPosixOsMutexLeave, /* xMutexLeave */
745 lsmPosixOsMutexHeld, /* xMutexHeld */
746 lsmPosixOsMutexNotHeld, /* xMutexNotHeld */
747 /***** other *********************/
748 lsmPosixOsSleep, /* xSleep */
750 return &posix_env;
753 #endif