// Code generated by modernc.org/undup from the per-target sqlite_*.go files; DO NOT EDIT.

//go:build (netbsd && amd64) || (openbsd && amd64) || (openbsd && arm64)

package sqlite3

import (
	"unsafe"

	"modernc.org/libc"
)

const CHAR_BIT = 8

const CLOCKS_PER_SEC = 100

const CLOCK_MONOTONIC = 3

const DL_GETERRNO = 1

const DL_LAZY = 1

const INT_MAX = 2147483647

const INT_MIN = -2147483648

const IOCPARM_MAX = 0

const LLONG_MAX = 9223372036854775807

const LLONG_MIN = -9223372036854775808

const LONG_BIT = 64

const LONG_MAX = 9223372036854775807

const LONG_MIN = -9223372036854775808

const MADV_FREE = 6

const MADV_SPACEAVAIL = 5

const MAP_INHERIT_COPY = 1

const MAP_INHERIT_NONE = 2

const MAP_INHERIT_SHARE = 0

const QUAD_MAX = 9223372036854775807

const QUAD_MIN = -9223372036854775808

const SCHAR_MAX = 127

const SCHAR_MIN = -128

const SHRT_MAX = 32767

const SHRT_MIN = -32768

const SIZE_T_MAX = 18446744073709551615

const STRIPDISC = 6

const TIOCFLAG_CLOCAL = 2

const TIOCFLAG_CRTSCTS = 4

const TIOCFLAG_MDMBUF = 8

const TIOCFLAG_SOFTCAR = 1

type Tcpuid_t = uint64

type Tqdiv_t = struct {
	Fquot Tquad_t
	Frem  Tquad_t
}

type Ttimer_t = int32

type Tunchar = uint8

// C documentation
//
//	/*
//	** The unixFile structure is subclass of sqlite3_file specific to the unix
//	** VFS implementations.
//	*/
type TunixFile = struct {
	FpMethod               uintptr
	FpVfs                  uintptr
	FpInode                uintptr
	Fh                     int32
	FeFileLock             uint8
	FctrlFlags             uint16
	FlastErrno             int32
	FlockingContext        uintptr
	FpPreallocatedUnused   uintptr
	FzPath                 uintptr
	FpShm                  uintptr
	FszChunk               int32
	FsectorSize            int32
	FdeviceCharacteristics int32
}

const UCHAR_MAX = 255

const UINT_MAX = 4294967295

const ULLONG_MAX = 18446744073709551615

const ULONG_MAX = 18446744073709551615

const UQUAD_MAX = 18446744073709551615

const USHRT_MAX = 65535

const WORD_BIT = 32

const _BIG_ENDIAN = 4321

const _LITTLE_ENDIAN = 1234

const _SC_FSYNC = 29

const _SC_PAGESIZE = 28

const _SC_PAGE_SIZE = 28

const _SC_XOPEN_SHM = 30

const __BEGIN_DECLS = 0

const __BEGIN_HIDDEN_DECLS = 0

const __BEGIN_PUBLIC_DECLS = 0

const __END_DECLS = 0

const __END_HIDDEN_DECLS = 0

const __END_PUBLIC_DECLS = 0

// C documentation
//
//	/*
//	** This function performs the parts of the "close file" operation
//	** common to all locking schemes. It closes the directory and file
//	** handles, if they are valid, and sets all fields of the unixFile
//	** structure to 0.
//	**
//	** It is *not* necessary to hold the mutex when this routine is called,
//	** even on VxWorks.  A mutex will be acquired on VxWorks by the
//	** vxworksReleaseFileId() routine.
//	*/
func _closeUnixFile(tls *libc.TLS, id uintptr) (r int32) {
	var pFile uintptr
	_ = pFile
	pFile = id
	if (*TunixFile)(unsafe.Pointer(pFile)).Fh >= 0 {
		_robust_close(tls, pFile, (*TunixFile)(unsafe.Pointer(pFile)).Fh, int32(42499))
		(*TunixFile)(unsafe.Pointer(pFile)).Fh = -int32(1)
	}
	Xsqlite3_free(tls, (*TunixFile)(unsafe.Pointer(pFile)).FpPreallocatedUnused)
	libc.Xmemset(tls, pFile, 0, uint64(88))
	return SQLITE_OK
}

// C documentation
//
//	/*
//	** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
//	** 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.
//	**
//	** When the locking level reaches NO_LOCK, delete the lock file.
//	*/
func _dotlockUnlock(tls *libc.TLS, id uintptr, eFileLock int32) (r int32) {
	var pFile, zLockFile uintptr
	var rc, tErrno int32
	_, _, _, _ = pFile, rc, tErrno, zLockFile
	pFile = id
	zLockFile = (*TunixFile)(unsafe.Pointer(pFile)).FlockingContext
	/* no-op if possible */
	if libc.Int32FromUint8((*TunixFile)(unsafe.Pointer(pFile)).FeFileLock) == eFileLock {
		return SQLITE_OK
	}
	/* To downgrade to shared, simply update our internal notion of the
	 ** lock state.  No need to mess with the file on disk.
	 */
	if eFileLock == int32(SHARED_LOCK) {
		(*TunixFile)(unsafe.Pointer(pFile)).FeFileLock = uint8(SHARED_LOCK)
		return SQLITE_OK
	}
	/* To fully unlock the database, delete the lock file */
	rc = (*(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(19)].FpCurrent})))(tls, zLockFile)
	if rc < 0 {
		tErrno = **(**int32)(__ccgo_up(libc.X__errno(tls)))
		if tErrno == int32(ENOENT) {
			rc = SQLITE_OK
		} else {
			rc = libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(8)<<libc.Int32FromInt32(8)
			_storeLastErrno(tls, pFile, tErrno)
		}
		return rc
	}
	(*TunixFile)(unsafe.Pointer(pFile)).FeFileLock = uint8(NO_LOCK)
	return SQLITE_OK
}

// C documentation
//
//	/*
//	** Begin a read transaction on the WAL.
//	**
//	** This routine used to be called "pagerOpenSnapshot()" because it essentially
//	** makes a snapshot of the database at the current point in time and preserves
//	** that snapshot for use by the reader in spite of concurrently changes by
//	** other writers or checkpointers.
//	*/
func _pagerBeginReadTransaction(tls *libc.TLS, pPager uintptr) (r int32) {
	bp := tls.Alloc(16)
	defer tls.Free(16)
	var rc int32
	var _ /* changed at bp+0 */ int32
	_ = rc                         /* Return code */
	**(**int32)(__ccgo_up(bp)) = 0 /* True if cache must be reset */
	/* sqlite3WalEndReadTransaction() was not called for the previous
	 ** transaction in locking_mode=EXCLUSIVE.  So call it now.  If we
	 ** are in locking_mode=NORMAL and EndRead() was previously called,
	 ** the duplicate call is harmless.
	 */
	_sqlite3WalEndReadTransaction(tls, (*TPager)(unsafe.Pointer(pPager)).FpWal)
	rc = _sqlite3WalBeginReadTransaction(tls, (*TPager)(unsafe.Pointer(pPager)).FpWal, bp)
	if rc != SQLITE_OK || **(**int32)(__ccgo_up(bp)) != 0 {
		_pager_reset(tls, pPager)
		if 0 != 0 {
			_sqlite3OsUnfetch(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd, 0, uintptr(0))
		}
	}
	return rc
}

// C documentation
//
//	/*
//	** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap.
//	*/
func _pagerFixMaplimit(tls *libc.TLS, pPager uintptr) {
}

// C documentation
//
//	/*
//	** This function is a no-op if the pager is in exclusive mode and not
//	** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN
//	** state.
//	**
//	** If the pager is not in exclusive-access mode, the database file is
//	** completely unlocked. If the file is unlocked and the file-system does
//	** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is
//	** closed (if it is open).
//	**
//	** If the pager is in ERROR state when this function is called, the
//	** contents of the pager cache are discarded before switching back to
//	** the OPEN state. Regardless of whether the pager is in exclusive-mode
//	** or not, any journal file left in the file-system will be treated
//	** as a hot-journal and rolled back the next time a read-transaction
//	** is opened (by this or by any other connection).
//	*/
func _pager_unlock(tls *libc.TLS, pPager uintptr) {
	var iDc, rc, v1 int32
	_, _, _ = iDc, rc, v1
	_sqlite3BitvecDestroy(tls, (*TPager)(unsafe.Pointer(pPager)).FpInJournal)
	(*TPager)(unsafe.Pointer(pPager)).FpInJournal = uintptr(0)
	_releaseAllSavepoints(tls, pPager)
	if (*TPager)(unsafe.Pointer(pPager)).FpWal != uintptr(0) {
		if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) == int32(PAGER_ERROR) {
			/* If an IO error occurs in wal.c while attempting to wrap the wal file,
			 ** then the Wal object may be holding a write-lock but no read-lock.
			 ** This call ensures that the write-lock is dropped as well. We cannot
			 ** have sqlite3WalEndReadTransaction() drop the write-lock, as it once
			 ** did, because this would break "BEGIN EXCLUSIVE" handling for
			 ** SQLITE_ENABLE_SETLK_TIMEOUT builds.  */
			_sqlite3WalEndWriteTransaction(tls, (*TPager)(unsafe.Pointer(pPager)).FpWal)
		}
		_sqlite3WalEndReadTransaction(tls, (*TPager)(unsafe.Pointer(pPager)).FpWal)
		(*TPager)(unsafe.Pointer(pPager)).FeState = uint8(PAGER_OPEN)
	} else {
		if !((*TPager)(unsafe.Pointer(pPager)).FexclusiveMode != 0) {
			if (*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Ffd)).FpMethods != uintptr(0) {
				v1 = _sqlite3OsDeviceCharacteristics(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd)
			} else {
				v1 = 0
			} /* Error code returned by pagerUnlockDb() */
			iDc = v1
			/* If the operating system support deletion of open files, then
			 ** close the journal file when dropping the database lock.  Otherwise
			 ** another connection with journal_mode=delete might delete the file
			 ** out from under us.
			 */
			if 0 == iDc&int32(SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN) || int32(1) != libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode)&int32(5) {
				_sqlite3OsClose(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd)
			}
			/* If the pager is in the ERROR state and the call to unlock the database
			 ** file fails, set the current lock to UNKNOWN_LOCK. See the comment
			 ** above the #define for UNKNOWN_LOCK for an explanation of why this
			 ** is necessary.
			 */
			rc = _pagerUnlockDb(tls, pPager, NO_LOCK)
			if rc != SQLITE_OK && libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) == int32(PAGER_ERROR) {
				(*TPager)(unsafe.Pointer(pPager)).FeLock = libc.Uint8FromInt32(libc.Int32FromInt32(EXCLUSIVE_LOCK) + libc.Int32FromInt32(1))
			}
			/* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here
			 ** without clearing the error code. This is intentional - the error
			 ** code is cleared and the cache reset in the block below.
			 */
			(*TPager)(unsafe.Pointer(pPager)).FeState = uint8(PAGER_OPEN)
		}
	}
	/* If Pager.errCode is set, the contents of the pager cache cannot be
	 ** trusted. Now that there are no outstanding references to the pager,
	 ** it can safely move back to PAGER_OPEN state. This happens in both
	 ** normal and exclusive-locking mode.
	 */
	if (*TPager)(unsafe.Pointer(pPager)).FerrCode != 0 {
		if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FtempFile) == 0 {
			_pager_reset(tls, pPager)
			(*TPager)(unsafe.Pointer(pPager)).FchangeCountDone = uint8(0)
			(*TPager)(unsafe.Pointer(pPager)).FeState = uint8(PAGER_OPEN)
		} else {
			if (*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Fjfd)).FpMethods != uintptr(0) {
				v1 = PAGER_OPEN
			} else {
				v1 = int32(PAGER_READER)
			}
			(*TPager)(unsafe.Pointer(pPager)).FeState = libc.Uint8FromInt32(v1)
		}
		if 0 != 0 {
			_sqlite3OsUnfetch(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd, 0, uintptr(0))
		}
		(*TPager)(unsafe.Pointer(pPager)).FerrCode = SQLITE_OK
		_setGetterMethod(tls, pPager)
	}
	(*TPager)(unsafe.Pointer(pPager)).FjournalOff = 0
	(*TPager)(unsafe.Pointer(pPager)).FjournalHdr = 0
	(*TPager)(unsafe.Pointer(pPager)).FsetSuper = uint8(0)
}

// C documentation
//
//	/*
//	** Set the Pager.xGet method for the appropriate routine used to fetch
//	** content from the pager.
//	*/
func _setGetterMethod(tls *libc.TLS, pPager uintptr) {
	if (*TPager)(unsafe.Pointer(pPager)).FerrCode != 0 {
		(*TPager)(unsafe.Pointer(pPager)).FxGet = __ccgo_fp(_getPageError)
	} else {
		(*TPager)(unsafe.Pointer(pPager)).FxGet = __ccgo_fp(_getPageNormal)
	}
}

// C documentation
//
//	/*
//	** The following singleton contains the global configuration for
//	** the SQLite library.
//	*/
var _sqlite3Config = TSqlite3Config{
	FbCoreMutex:          uint8(1),
	FbFullMutex:          libc.BoolUint8(true),
	FbUseCis:             uint8(SQLITE_ALLOW_COVERING_INDEX_SCAN),
	FbExtraSchemaChecks:  uint8(1),
	FmxStrlen:            int32(0x7ffffffe),
	FszLookaside:         int32(1200),
	FnLookaside:          int32(40),
	FnStmtSpill:          libc.Int32FromInt32(64) * libc.Int32FromInt32(1024),
	FnPage:               int32(SQLITE_DEFAULT_PCACHE_INITSZ),
	FszPma:               uint32(SQLITE_SORTER_PMASZ),
	FmxMemdbSize:         int64(SQLITE_MEMDB_DEFAULT_MAXSIZE),
	FiOnceResetThreshold: int32(0x7ffffffe),
	FszSorterRef:         uint32(SQLITE_DEFAULT_SORTERREF_SIZE),
}

// C documentation
//
//	/* No-op stubs to use when memory-mapped I/O is disabled */
func _sqlite3OsFetch(tls *libc.TLS, id uintptr, iOff Ti64, iAmt int32, pp uintptr) (r int32) {
	**(**uintptr)(__ccgo_up(pp)) = uintptr(0)
	return SQLITE_OK
}

func _sqlite3OsUnfetch(tls *libc.TLS, id uintptr, iOff Ti64, p uintptr) (r int32) {
	return SQLITE_OK
}

// C documentation
//
//	/*
//	** This routine checks if there is a RESERVED lock held on the specified
//	** file by this or any other process. If such a lock is held, set *pResOut
//	** to a non-zero value otherwise *pResOut is set to zero.  The return value
//	** is set to SQLITE_OK unless an I/O error occurs during lock checking.
//	*/
func _unixCheckReservedLock(tls *libc.TLS, id uintptr, pResOut uintptr) (r int32) {
	bp := tls.Alloc(48)
	defer tls.Free(48)
	var pFile uintptr
	var rc, reserved int32
	var _ /* lock at bp+0 */ Tflock
	_, _, _ = pFile, rc, reserved
	rc = SQLITE_OK
	reserved = 0
	pFile = id
	Xsqlite3_mutex_enter(tls, (*TunixInodeInfo)(unsafe.Pointer((*TunixFile)(unsafe.Pointer(pFile)).FpInode)).FpLockMutex)
	/* Check if a thread in this process holds such a lock */
	if libc.Int32FromUint8((*TunixInodeInfo)(unsafe.Pointer((*TunixFile)(unsafe.Pointer(pFile)).FpInode)).FeFileLock) > int32(SHARED_LOCK) {
		reserved = int32(1)
	}
	/* Otherwise see if some other process holds it.
	 */
	if !(reserved != 0) && !((*TunixInodeInfo)(unsafe.Pointer((*TunixFile)(unsafe.Pointer(pFile)).FpInode)).FbProcessLock != 0) {
		(**(**Tflock)(__ccgo_up(bp))).Fl_whence = SEEK_SET
		(**(**Tflock)(__ccgo_up(bp))).Fl_start = int64(_sqlite3PendingByte + libc.Int32FromInt32(1))
		(**(**Tflock)(__ccgo_up(bp))).Fl_len = int64(1)
		(**(**Tflock)(__ccgo_up(bp))).Fl_type = int16(F_WRLCK)
		if (*(*func(*libc.TLS, int32, int32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(7)].FpCurrent})))(tls, (*TunixFile)(unsafe.Pointer(pFile)).Fh, int32(F_GETLK), libc.VaList(bp+32, bp)) != 0 {
			rc = libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(14)<<libc.Int32FromInt32(8)
			_storeLastErrno(tls, pFile, **(**int32)(__ccgo_up(libc.X__errno(tls))))
		} else {
			if int32((**(**Tflock)(__ccgo_up(bp))).Fl_type) != int32(F_UNLCK) {
				reserved = int32(1)
			}
		}
	}
	Xsqlite3_mutex_leave(tls, (*TunixInodeInfo)(unsafe.Pointer((*TunixFile)(unsafe.Pointer(pFile)).FpInode)).FpLockMutex)
	**(**int32)(__ccgo_up(pResOut)) = reserved
	return rc
}

/*
** Set a posix-advisory-lock.
**
** There are two versions of this routine.  If compiled with
** SQLITE_ENABLE_SETLK_TIMEOUT then the routine has an extra parameter
** which is a pointer to a unixFile.  If the unixFile->iBusyTimeout
** value is set, then it is the number of milliseconds to wait before
** failing the lock.  The iBusyTimeout value is always reset back to
** zero on each call.
**
** If SQLITE_ENABLE_SETLK_TIMEOUT is not defined, then do a non-blocking
** attempt to set the lock.
 */

// C documentation
//
//	/*
//	** Use F_GETLK to check whether or not there are any readers with open
//	** wal-mode transactions in other processes on database file pFile. If
//	** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are
//	** such transactions, or 0 otherwise. If an error occurs, return an
//	** SQLite error code. The final value of *piOut is undefined in this
//	** case.
//	*/
func _unixFcntlExternalReader(tls *libc.TLS, pFile uintptr, piOut uintptr) (r int32) {
	bp := tls.Alloc(48)
	defer tls.Free(48)
	var pShmNode uintptr
	var rc int32
	var _ /* f at bp+0 */ Tflock
	_, _ = pShmNode, rc
	rc = SQLITE_OK
	**(**int32)(__ccgo_up(piOut)) = 0
	if (*TunixFile)(unsafe.Pointer(pFile)).FpShm != 0 {
		pShmNode = (*TunixShm)(unsafe.Pointer((*TunixFile)(unsafe.Pointer(pFile)).FpShm)).FpShmNode
		libc.Xmemset(tls, bp, 0, uint64(24))
		(**(**Tflock)(__ccgo_up(bp))).Fl_type = int16(F_WRLCK)
		(**(**Tflock)(__ccgo_up(bp))).Fl_whence = SEEK_SET
		(**(**Tflock)(__ccgo_up(bp))).Fl_start = int64((libc.Int32FromInt32(22)+libc.Int32FromInt32(SQLITE_SHM_NLOCK))*libc.Int32FromInt32(4) + libc.Int32FromInt32(3))
		(**(**Tflock)(__ccgo_up(bp))).Fl_len = int64(libc.Int32FromInt32(SQLITE_SHM_NLOCK) - libc.Int32FromInt32(3))
		Xsqlite3_mutex_enter(tls, (*TunixShmNode)(unsafe.Pointer(pShmNode)).FpShmMutex)
		if (*(*func(*libc.TLS, int32, int32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(7)].FpCurrent})))(tls, (*TunixShmNode)(unsafe.Pointer(pShmNode)).FhShm, int32(F_GETLK), libc.VaList(bp+32, bp)) < 0 {
			rc = libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(15)<<libc.Int32FromInt32(8)
		} else {
			**(**int32)(__ccgo_up(piOut)) = libc.BoolInt32(int32((**(**Tflock)(__ccgo_up(bp))).Fl_type) != int32(F_UNLCK))
		}
		Xsqlite3_mutex_leave(tls, (*TunixShmNode)(unsafe.Pointer(pShmNode)).FpShmMutex)
	}
	return rc
}

// C documentation
//
//	/*
//	** If possible, return a pointer to a mapping of file fd starting at offset
//	** iOff. The mapping must be valid for at least nAmt bytes.
//	**
//	** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
//	** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
//	** Finally, if an error does occur, return an SQLite error code. The final
//	** value of *pp is undefined in this case.
//	**
//	** If this function does return a pointer, the caller must eventually
//	** release the reference by calling unixUnfetch().
//	*/
func _unixFetch(tls *libc.TLS, fd uintptr, iOff Ti64, nAmt int32, pp uintptr) (r int32) {
	**(**uintptr)(__ccgo_up(pp)) = uintptr(0)
	return SQLITE_OK
}

// C documentation
//
//	/*
//	** The xGetLastError() method is designed to return a better
//	** low-level error message when operating-system problems come up
//	** during SQLite operation.  Only the integer return code is currently
//	** used.
//	*/
func _unixGetLastError(tls *libc.TLS, NotUsed uintptr, NotUsed2 int32, NotUsed3 uintptr) (r int32) {
	_ = NotUsed
	_ = NotUsed2
	_ = NotUsed3
	return **(**int32)(__ccgo_up(libc.X__errno(tls)))
}

/*
************************ End of sqlite3_vfs methods ***************************
******************************************************************************/

/******************************************************************************
************************** Begin Proxy Locking ********************************
**
** Proxy locking is a "uber-locking-method" in this sense:  It uses the
** other locking methods on secondary lock files.  Proxy locking is a
** meta-layer over top of the primitive locking implemented above.  For
** this reason, the division that implements of proxy locking is deferred
** until late in the file (here) after all of the other I/O methods have
** been defined - so that the primitive locking methods are available
** as services to help with the implementation of proxy locking.
**
****
**
** The default locking schemes in SQLite use byte-range locks on the
** database file to coordinate safe, concurrent access by multiple readers
** and writers [http://sqlite.org/lockingv3.html].  The five file locking
** states (UNLOCKED, PENDING, SHARED, RESERVED, EXCLUSIVE) are implemented
** as POSIX read & write locks over fixed set of locations (via fsctl),
** on AFP and SMB only exclusive byte-range locks are available via fsctl
** with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states.
** To simulate a F_RDLCK on the shared range, on AFP a randomly selected
** address in the shared range is taken for a SHARED lock, the entire
** shared range is taken for an EXCLUSIVE lock):
**
**      PENDING_BYTE        0x40000000
**      RESERVED_BYTE       0x40000001
**      SHARED_RANGE        0x40000002 -> 0x40000200
**
** This works well on the local file system, but shows a nearly 100x
** slowdown in read performance on AFP because the AFP client disables
** the read cache when byte-range locks are present.  Enabling the read
** cache exposes a cache coherency problem that is present on all OS X
** supported network file systems.  NFS and AFP both observe the
** close-to-open semantics for ensuring cache coherency
** [http://nfs.sourceforge.net/#faq_a8], which does not effectively
** address the requirements for concurrent database access by multiple
** readers and writers
** [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html].
**
** To address the performance and cache coherency issues, proxy file locking
** changes the way database access is controlled by limiting access to a
** single host at a time and moving file locks off of the database file
** and onto a proxy file on the local file system.
**
**
** Using proxy locks
** -----------------
**
** C APIs
**
**  sqlite3_file_control(db, dbname, SQLITE_FCNTL_SET_LOCKPROXYFILE,
**                       <proxy_path> | ":auto:");
**  sqlite3_file_control(db, dbname, SQLITE_FCNTL_GET_LOCKPROXYFILE,
**                       &<proxy_path>);
**
**
** SQL pragmas
**
**  PRAGMA [database.]lock_proxy_file=<proxy_path> | :auto:
**  PRAGMA [database.]lock_proxy_file
**
** Specifying ":auto:" means that if there is a conch file with a matching
** host ID in it, the proxy path in the conch file will be used, otherwise
** a proxy path based on the user's temp dir
** (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the
** actual proxy file name is generated from the name and path of the
** database file.  For example:
**
**       For database path "/Users/me/foo.db"
**       The lock path will be "<tmpdir>/sqliteplocks/_Users_me_foo.db:auto:")
**
** Once a lock proxy is configured for a database connection, it can not
** be removed, however it may be switched to a different proxy path via
** the above APIs (assuming the conch file is not being held by another
** connection or process).
**
**
** How proxy locking works
** -----------------------
**
** Proxy file locking relies primarily on two new supporting files:
**
**   *  conch file to limit access to the database file to a single host
**      at a time
**
**   *  proxy file to act as a proxy for the advisory locks normally
**      taken on the database
**
** The conch file - to use a proxy file, sqlite must first "hold the conch"
** by taking an sqlite-style shared lock on the conch file, reading the
** contents and comparing the host's unique host ID (see below) and lock
** proxy path against the values stored in the conch.  The conch file is
** stored in the same directory as the database file and the file name
** is patterned after the database file name as ".<databasename>-conch".
** If the conch file does not exist, or its contents do not match the
** host ID and/or proxy path, then the lock is escalated to an exclusive
** lock and the conch file contents is updated with the host ID and proxy
** path and the lock is downgraded to a shared lock again.  If the conch
** is held by another process (with a shared lock), the exclusive lock
** will fail and SQLITE_BUSY is returned.
**
** The proxy file - a single-byte file used for all advisory file locks
** normally taken on the database file.   This allows for safe sharing
** of the database file for multiple readers and writers on the same
** host (the conch ensures that they all use the same local lock file).
**
** Requesting the lock proxy does not immediately take the conch, it is
** only taken when the first request to lock database file is made.
** This matches the semantics of the traditional locking behavior, where
** opening a connection to a database file does not take a lock on it.
** The shared lock and an open file descriptor are maintained until
** the connection to the database is closed.
**
** The proxy file and the lock file are never deleted so they only need
** to be created the first time they are used.
**
** Configuration options
** ---------------------
**
**  SQLITE_PREFER_PROXY_LOCKING
**
**       Database files accessed on non-local file systems are
**       automatically configured for proxy locking, lock files are
**       named automatically using the same logic as
**       PRAGMA lock_proxy_file=":auto:"
**
**  SQLITE_PROXY_DEBUG
**
**       Enables the logging of error messages during host id file
**       retrieval and creation
**
**  LOCKPROXYDIR
**
**       Overrides the default directory used for lock proxy files that
**       are named automatically via the ":auto:" setting
**
**  SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
**
**       Permissions to use when creating a directory for storing the
**       lock proxy files, only used when LOCKPROXYDIR is not set.
**
**
** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING,
** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
** force proxy locking to be used for every database file opened, and 0
** will force automatic proxy locking to be disabled for all database
** files (explicitly calling the SQLITE_FCNTL_SET_LOCKPROXYFILE pragma or
** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
 */

/*
** Proxy locking is only available on MacOSX
 */
/*
** The proxy locking style is intended for use with AFP filesystems.
** And since AFP is only supported on MacOSX, the proxy locking is also
** restricted to MacOSX.
**
**
******************* End of the proxy lock implementation **********************
******************************************************************************/

// C documentation
//
//	/*
//	** If pFile has a -shm file open and it is sharing that file with some
//	** other connection, either in the same process or in a separate process,
//	** then return true.  Return false if either pFile does not have a -shm
//	** file open or if it is the only connection to that -shm file across the
//	** entire system.
//	**
//	** This routine is not required for correct operation.  It can always return
//	** false and SQLite will continue to operate according to spec.  However,
//	** when this routine does its job, it adds extra robustness in cases
//	** where database file locks have been erroneously deleted in a WAL-mode
//	** database by doing close(open(DATABASE_PATHNAME)) or similar.
//	**
//	** With false negatives, SQLite still operates to spec, though with less
//	** robustness.  With false positives, the last database connection on a
//	** WAL-mode database will fail to unlink the -wal and -shm files, which
//	** is annoying but harmless.  False positives will also prevent a database
//	** connection from running "PRAGMA journal_mode=DELETE" in order to take
//	** the database out of WAL mode, which is perhaps more serious, but is
//	** still not a disaster.
//	*/
func _unixIsSharingShmNode(tls *libc.TLS, pFile uintptr) (r int32) {
	bp := tls.Alloc(48)
	defer tls.Free(48)
	var pShmNode uintptr
	var _ /* lock at bp+0 */ Tflock
	_ = pShmNode
	if (*TunixFile)(unsafe.Pointer(pFile)).FpShm == uintptr(0) {
		return 0
	}
	if libc.Int32FromUint16((*TunixFile)(unsafe.Pointer(pFile)).FctrlFlags)&int32(UNIXFILE_EXCL) != 0 {
		return 0
	}
	pShmNode = (*TunixShm)(unsafe.Pointer((*TunixFile)(unsafe.Pointer(pFile)).FpShm)).FpShmNode
	libc.Xmemset(tls, bp, 0, uint64(24))
	(**(**Tflock)(__ccgo_up(bp))).Fl_whence = SEEK_SET
	(**(**Tflock)(__ccgo_up(bp))).Fl_start = int64((libc.Int32FromInt32(22)+libc.Int32FromInt32(SQLITE_SHM_NLOCK))*libc.Int32FromInt32(4) + libc.Int32FromInt32(SQLITE_SHM_NLOCK))
	(**(**Tflock)(__ccgo_up(bp))).Fl_len = int64(1)
	(**(**Tflock)(__ccgo_up(bp))).Fl_type = int16(F_WRLCK)
	(*(*func(*libc.TLS, int32, int32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(7)].FpCurrent})))(tls, (*TunixShmNode)(unsafe.Pointer(pShmNode)).FhShm, int32(F_GETLK), libc.VaList(bp+32, bp))
	return libc.BoolInt32(int32((**(**Tflock)(__ccgo_up(bp))).Fl_type) != int32(F_UNLCK))
}

// C documentation
//
//	/*
//	** Lock the file with the lock specified by parameter eFileLock - one
//	** of the following:
//	**
//	**     (1) SHARED_LOCK
//	**     (2) RESERVED_LOCK
//	**     (3) PENDING_LOCK
//	**     (4) EXCLUSIVE_LOCK
//	**
//	** Sometimes when requesting one lock state, additional lock states
//	** are inserted in between.  The locking might fail on one of the later
//	** transitions leaving the lock state different from what it started but
//	** still short of its goal.  The following chart shows the allowed
//	** transitions and the inserted intermediate states:
//	**
//	**    UNLOCKED -> SHARED
//	**    SHARED -> RESERVED
//	**    SHARED -> EXCLUSIVE
//	**    RESERVED -> (PENDING) -> EXCLUSIVE
//	**    PENDING -> EXCLUSIVE
//	**
//	** This routine will only increase a lock.  Use the sqlite3OsUnlock()
//	** routine to lower a locking level.
//	*/
func _unixLock(tls *libc.TLS, id uintptr, eFileLock int32) (r int32) {
	bp := tls.Alloc(32)
	defer tls.Free(32)
	var pFile, pInode uintptr
	var rc, tErrno, v1 int32
	var _ /* lock at bp+0 */ Tflock
	_, _, _, _, _ = pFile, pInode, rc, tErrno, v1
	/* The following describes the implementation of the various locks and
	 ** lock transitions in terms of the POSIX advisory shared and exclusive
	 ** lock primitives (called read-locks and write-locks below, to avoid
	 ** confusion with SQLite lock names). The algorithms are complicated
	 ** slightly in order to be compatible with Windows95 systems simultaneously
	 ** accessing the same database file, in case that is ever required.
	 **
	 ** Symbols defined in os.h identify the 'pending byte' and the 'reserved
	 ** byte', each single bytes at well known offsets, and the 'shared byte
	 ** range', a range of 510 bytes at a well known offset.
	 **
	 ** To obtain a SHARED lock, a read-lock is obtained on the 'pending
	 ** byte'.  If this is successful, 'shared byte range' is read-locked
	 ** and the lock on the 'pending byte' released.  (Legacy note:  When
	 ** SQLite was first developed, Windows95 systems were still very common,
	 ** and Windows95 lacks a shared-lock capability.  So on Windows95, a
	 ** single randomly selected by from the 'shared byte range' is locked.
	 ** Windows95 is now pretty much extinct, but this work-around for the
	 ** lack of shared-locks on Windows95 lives on, for backwards
	 ** compatibility.)
	 **
	 ** A process may only obtain a RESERVED lock after it has a SHARED lock.
	 ** A RESERVED lock is implemented by grabbing a write-lock on the
	 ** 'reserved byte'.
	 **
	 ** An EXCLUSIVE lock may only be requested after either a SHARED or
	 ** RESERVED lock is held. An EXCLUSIVE lock is implemented by obtaining
	 ** a write-lock on the entire 'shared byte range'. Since all other locks
	 ** require a read-lock on one of the bytes within this range, this ensures
	 ** that no other locks are held on the database.
	 **
	 ** If a process that holds a RESERVED lock requests an EXCLUSIVE, then
	 ** a PENDING lock is obtained first. A PENDING lock is implemented by
	 ** obtaining a write-lock on the 'pending byte'. This ensures that no new
	 ** SHARED locks can be obtained, but existing SHARED locks are allowed to
	 ** persist. If the call to this function fails to obtain the EXCLUSIVE
	 ** lock in this case, it holds the PENDING lock instead. The client may
	 ** then re-attempt the EXCLUSIVE lock later on, after existing SHARED
	 ** locks have cleared.
	 */
	rc = SQLITE_OK
	pFile = id
	tErrno = 0
	/* 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 libc.Int32FromUint8((*TunixFile)(unsafe.Pointer(pFile)).FeFileLock) >= eFileLock {
		return SQLITE_OK
	}
	/* Make sure the locking sequence is correct.
	 **  (1) We never move from unlocked to anything higher than shared lock.
	 **  (2) SQLite never explicitly requests a pending lock.
	 **  (3) A shared lock is always held when a reserve lock is requested.
	 */
	/* This mutex is needed because pFile->pInode is shared across threads
	 */
	pInode = (*TunixFile)(unsafe.Pointer(pFile)).FpInode
	Xsqlite3_mutex_enter(tls, (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpLockMutex)
	/* If some thread using this PID has a lock via a different unixFile*
	 ** handle that precludes the requested lock, return BUSY.
	 */
	if libc.Int32FromUint8((*TunixFile)(unsafe.Pointer(pFile)).FeFileLock) != libc.Int32FromUint8((*TunixInodeInfo)(unsafe.Pointer(pInode)).FeFileLock) && (libc.Int32FromUint8((*TunixInodeInfo)(unsafe.Pointer(pInode)).FeFileLock) >= int32(PENDING_LOCK) || eFileLock > int32(SHARED_LOCK)) {
		rc = int32(SQLITE_BUSY)
		goto end_lock
	}
	/* If a SHARED lock is requested, and some thread using this PID already
	 ** has a SHARED or RESERVED lock, then increment reference counts and
	 ** return SQLITE_OK.
	 */
	if eFileLock == int32(SHARED_LOCK) && (libc.Int32FromUint8((*TunixInodeInfo)(unsafe.Pointer(pInode)).FeFileLock) == int32(SHARED_LOCK) || libc.Int32FromUint8((*TunixInodeInfo)(unsafe.Pointer(pInode)).FeFileLock) == int32(RESERVED_LOCK)) {
		(*TunixFile)(unsafe.Pointer(pFile)).FeFileLock = uint8(SHARED_LOCK)
		(*TunixInodeInfo)(unsafe.Pointer(pInode)).FnShared = (*TunixInodeInfo)(unsafe.Pointer(pInode)).FnShared + 1
		(*TunixInodeInfo)(unsafe.Pointer(pInode)).FnLock = (*TunixInodeInfo)(unsafe.Pointer(pInode)).FnLock + 1
		goto end_lock
	}
	/* 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.
	 */
	(**(**Tflock)(__ccgo_up(bp))).Fl_len = int64(1)
	(**(**Tflock)(__ccgo_up(bp))).Fl_whence = SEEK_SET
	if eFileLock == int32(SHARED_LOCK) || eFileLock == int32(EXCLUSIVE_LOCK) && libc.Int32FromUint8((*TunixFile)(unsafe.Pointer(pFile)).FeFileLock) == int32(RESERVED_LOCK) {
		if eFileLock == int32(SHARED_LOCK) {
			v1 = int32(F_RDLCK)
		} else {
			v1 = int32(F_WRLCK)
		}
		(**(**Tflock)(__ccgo_up(bp))).Fl_type = int16(v1)
		(**(**Tflock)(__ccgo_up(bp))).Fl_start = int64(_sqlite3PendingByte)
		if _unixFileLock(tls, pFile, bp) != 0 {
			tErrno = **(**int32)(__ccgo_up(libc.X__errno(tls)))
			rc = _sqliteErrorFromPosixError(tls, tErrno, libc.Int32FromInt32(SQLITE_IOERR)|libc.Int32FromInt32(15)<<libc.Int32FromInt32(8))
			if rc != int32(SQLITE_BUSY) {
				_storeLastErrno(tls, pFile, tErrno)
			}
			goto end_lock
		} else {
			if eFileLock == int32(EXCLUSIVE_LOCK) {
				(*TunixFile)(unsafe.Pointer(pFile)).FeFileLock = uint8(PENDING_LOCK)
				(*TunixInodeInfo)(unsafe.Pointer(pInode)).FeFileLock = uint8(PENDING_LOCK)
			}
		}
	}
	/* If control gets to this point, then actually go ahead and make
	 ** operating system calls for the specified lock.
	 */
	if eFileLock == int32(SHARED_LOCK) {
		/* Now get the read-lock */
		(**(**Tflock)(__ccgo_up(bp))).Fl_start = int64(_sqlite3PendingByte + libc.Int32FromInt32(2))
		(**(**Tflock)(__ccgo_up(bp))).Fl_len = int64(SHARED_SIZE)
		if _unixFileLock(tls, pFile, bp) != 0 {
			tErrno = **(**int32)(__ccgo_up(libc.X__errno(tls)))
			rc = _sqliteErrorFromPosixError(tls, tErrno, libc.Int32FromInt32(SQLITE_IOERR)|libc.Int32FromInt32(15)<<libc.Int32FromInt32(8))
		}
		/* Drop the temporary PENDING lock */
		(**(**Tflock)(__ccgo_up(bp))).Fl_start = int64(_sqlite3PendingByte)
		(**(**Tflock)(__ccgo_up(bp))).Fl_len = int64(1)
		(**(**Tflock)(__ccgo_up(bp))).Fl_type = int16(F_UNLCK)
		if _unixFileLock(tls, pFile, bp) != 0 && rc == SQLITE_OK {
			/* This could happen with a network mount */
			tErrno = **(**int32)(__ccgo_up(libc.X__errno(tls)))
			rc = libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(8)<<libc.Int32FromInt32(8)
		}
		if rc != 0 {
			if rc != int32(SQLITE_BUSY) {
				_storeLastErrno(tls, pFile, tErrno)
			}
			goto end_lock
		} else {
			(*TunixFile)(unsafe.Pointer(pFile)).FeFileLock = uint8(SHARED_LOCK)
			(*TunixInodeInfo)(unsafe.Pointer(pInode)).FnLock = (*TunixInodeInfo)(unsafe.Pointer(pInode)).FnLock + 1
			(*TunixInodeInfo)(unsafe.Pointer(pInode)).FnShared = int32(1)
		}
	} else {
		if eFileLock == int32(EXCLUSIVE_LOCK) && (*TunixInodeInfo)(unsafe.Pointer(pInode)).FnShared > int32(1) {
			/* We are trying for an exclusive lock but another thread in this
			 ** same process is still holding a shared lock. */
			rc = int32(SQLITE_BUSY)
		} else {
			if _unixIsSharingShmNode(tls, pFile) != 0 {
				/* We are in WAL mode and attempting to delete the SHM and WAL
				 ** files due to closing the connection or changing out of WAL mode,
				 ** but another process still holds locks on the SHM file, thus
				 ** indicating that database locks have been broken, perhaps due
				 ** to a rogue close(open(dbFile)) or similar.
				 */
				rc = int32(SQLITE_BUSY)
			} else {
				/* The request was for a RESERVED or EXCLUSIVE lock.  It is
				 ** assumed that there is a SHARED or greater lock on the file
				 ** already.
				 */
				(**(**Tflock)(__ccgo_up(bp))).Fl_type = int16(F_WRLCK)
				if eFileLock == int32(RESERVED_LOCK) {
					(**(**Tflock)(__ccgo_up(bp))).Fl_start = int64(_sqlite3PendingByte + libc.Int32FromInt32(1))
					(**(**Tflock)(__ccgo_up(bp))).Fl_len = int64(1)
				} else {
					(**(**Tflock)(__ccgo_up(bp))).Fl_start = int64(_sqlite3PendingByte + libc.Int32FromInt32(2))
					(**(**Tflock)(__ccgo_up(bp))).Fl_len = int64(SHARED_SIZE)
				}
				if _unixFileLock(tls, pFile, bp) != 0 {
					tErrno = **(**int32)(__ccgo_up(libc.X__errno(tls)))
					rc = _sqliteErrorFromPosixError(tls, tErrno, libc.Int32FromInt32(SQLITE_IOERR)|libc.Int32FromInt32(15)<<libc.Int32FromInt32(8))
					if rc != int32(SQLITE_BUSY) {
						_storeLastErrno(tls, pFile, tErrno)
					}
				}
			}
		}
	}
	if rc == SQLITE_OK {
		(*TunixFile)(unsafe.Pointer(pFile)).FeFileLock = libc.Uint8FromInt32(eFileLock)
		(*TunixInodeInfo)(unsafe.Pointer(pInode)).FeFileLock = libc.Uint8FromInt32(eFileLock)
	}
	goto end_lock
end_lock:
	;
	Xsqlite3_mutex_leave(tls, (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpLockMutex)
	return rc
}

// C documentation
//
//	/*
//	** Read data from a file into a buffer.  Return SQLITE_OK if all
//	** bytes were read successfully and SQLITE_IOERR if anything goes
//	** wrong.
//	*/
func _unixRead(tls *libc.TLS, id uintptr, pBuf uintptr, amt int32, offset Tsqlite3_int64) (r int32) {
	var got int32
	var pFile uintptr
	_, _ = got, pFile
	pFile = id
	/* If this is a database file (not a journal, super-journal or temp
	 ** file), the bytes in the locking range should never be read or written. */
	got = _seekAndRead(tls, pFile, offset, pBuf, amt)
	if got == amt {
		return SQLITE_OK
	} else {
		if got < 0 {
			/* pFile->lastErrno has been set by seekAndRead().
			 ** Usually we return SQLITE_IOERR_READ here, though for some
			 ** kinds of errors we return SQLITE_IOERR_CORRUPTFS.  The
			 ** SQLITE_IOERR_CORRUPTFS will be converted into SQLITE_CORRUPT
			 ** prior to returning to the application by the sqlite3ApiExit()
			 ** routine.
			 */
			switch (*TunixFile)(unsafe.Pointer(pFile)).FlastErrno {
			case int32(ERANGE):
				fallthrough
			case int32(EIO):
				fallthrough
			case int32(ENXIO):
				return libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(33)<<libc.Int32FromInt32(8)
			}
			return libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(1)<<libc.Int32FromInt32(8)
		} else {
			_storeLastErrno(tls, pFile, 0) /* not a system error */
			/* Unread parts of the buffer must be zero-filled */
			libc.Xmemset(tls, pBuf+uintptr(got), 0, libc.Uint64FromInt32(amt-got))
			return libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(2)<<libc.Int32FromInt32(8)
		}
	}
	return r
}

// C documentation
//
//	/*
//	** If the third argument is non-NULL, then this function releases a
//	** reference obtained by an earlier call to unixFetch(). The second
//	** argument passed to this function must be the same as the corresponding
//	** argument that was passed to the unixFetch() invocation.
//	**
//	** Or, if the third argument is NULL, then this function is being called
//	** to inform the VFS layer that, according to POSIX, any existing mapping
//	** may now be invalid and should be unmapped.
//	*/
func _unixUnfetch(tls *libc.TLS, fd uintptr, iOff Ti64, p uintptr) (r int32) {
	_ = fd
	_ = p
	_ = iOff
	return SQLITE_OK
}

/*
** Here ends the implementation of all sqlite3_file methods.
**
********************** End sqlite3_file Methods *******************************
******************************************************************************/

/*
** This division contains definitions of sqlite3_io_methods objects that
** implement various file locking strategies.  It also contains definitions
** of "finder" functions.  A finder-function is used to locate the appropriate
** sqlite3_io_methods object for a particular database file.  The pAppData
** field of the sqlite3_vfs VFS objects are initialized to be pointers to
** the correct finder-function for that VFS.
**
** Most finder functions return a pointer to a fixed sqlite3_io_methods
** object.  The only interesting finder-function is autolockIoFinder, which
** looks at the filesystem type and tries to guess the best locking
** strategy from that.
**
** For finder-function F, two objects are created:
**
**    (1) The real finder-function named "FImpt()".
**
**    (2) A constant pointer to this function named just "F".
**
**
** A pointer to the F pointer is used as the pAppData value for VFS
** objects.  We have to do this instead of letting pAppData point
** directly at the finder-function since C90 rules prevent a void*
** from be cast into a function pointer.
**
**
** Each instance of this macro generates two objects:
**
**   *  A constant sqlite3_io_methods object call METHOD that has locking
**      methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
**
**   *  An I/O method finder function called FINDER that returns a pointer
**      to the METHOD object in the previous bullet.
 */

// C documentation
//
//	/*
//	** Write the current contents of in-memory linked-list pList to a level-0
//	** PMA in the temp file belonging to sub-task pTask. Return SQLITE_OK if
//	** successful, or an SQLite error code otherwise.
//	**
//	** The format of a PMA is:
//	**
//	**     * A varint. This varint contains the total number of bytes of content
//	**       in the PMA (not including the varint itself).
//	**
//	**     * One or more records packed end-to-end in order of ascending keys.
//	**       Each record consists of a varint followed by a blob of data (the
//	**       key). The varint is the number of bytes in the blob of data.
//	*/
func _vdbeSorterListToPMA(tls *libc.TLS, pTask uintptr, pList uintptr) (r int32) {
	bp := tls.Alloc(64)
	defer tls.Free(64)
	var db, p, pNext uintptr
	var rc int32
	var _ /* writer at bp+0 */ TPmaWriter
	_, _, _, _ = db, p, pNext, rc
	db = (*TVdbeSorter)(unsafe.Pointer((*TSortSubtask)(unsafe.Pointer(pTask)).FpSorter)).Fdb
	rc = SQLITE_OK /* Object used to write to the file */
	libc.Xmemset(tls, bp, 0, uint64(56))
	/* If the first temporary PMA file has not been opened, open it now. */
	if (*TSortSubtask)(unsafe.Pointer(pTask)).Ffile.FpFd == uintptr(0) {
		rc = _vdbeSorterOpenTempFile(tls, db, 0, pTask+64)
	}
	/* Try to get the file to memory map */
	if rc == SQLITE_OK {
	}
	/* Sort the list */
	if rc == SQLITE_OK {
		rc = _vdbeSorterSort(tls, pTask, pList)
	}
	if rc == SQLITE_OK {
		pNext = uintptr(0)
		_vdbePmaWriterInit(tls, (*TSortSubtask)(unsafe.Pointer(pTask)).Ffile.FpFd, bp, (*TVdbeSorter)(unsafe.Pointer((*TSortSubtask)(unsafe.Pointer(pTask)).FpSorter)).Fpgsz, (*TSortSubtask)(unsafe.Pointer(pTask)).Ffile.FiEof)
		(*TSortSubtask)(unsafe.Pointer(pTask)).FnPMA = (*TSortSubtask)(unsafe.Pointer(pTask)).FnPMA + 1
		_vdbePmaWriteVarint(tls, bp, libc.Uint64FromInt64((*TSorterList)(unsafe.Pointer(pList)).FszPMA))
		p = (*TSorterList)(unsafe.Pointer(pList)).FpList
		for {
			if !(p != 0) {
				break
			}
			pNext = *(*uintptr)(unsafe.Pointer(p + 8))
			_vdbePmaWriteVarint(tls, bp, libc.Uint64FromInt32((*TSorterRecord)(unsafe.Pointer(p)).FnVal))
			_vdbePmaWriteBlob(tls, bp, p+libc.UintptrFromInt32(1)*16, (*TSorterRecord)(unsafe.Pointer(p)).FnVal)
			if (*TSorterList)(unsafe.Pointer(pList)).FaMemory == uintptr(0) {
				Xsqlite3_free(tls, p)
			}
			goto _1
		_1:
			;
			p = pNext
		}
		(*TSorterList)(unsafe.Pointer(pList)).FpList = p
		rc = _vdbePmaWriterFinish(tls, bp, pTask+64+8, pTask+96)
	}
	return rc
}

type cpuid_t = Tcpuid_t

const fd_mask = 0

type max_align_t = Tmax_align_t

/*
** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY.
** This allows better measurements of where memcpy() is used when running
** cachegrind.  But this macro version of memcpy() is very slow so it
** should not be used in production.  This is a performance measurement
** hack only.
 */

/*
** If compiling for a processor that lacks floating point support,
** substitute integer for floating-point
 */

/*
** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0
** afterward. Having this macro allows us to cause the C compiler
** to omit code used by TEMP tables without messy #ifndef statements.
 */

/*
** The "file format" number is an integer that is incremented whenever
** the VDBE-level file format changes.  The following macros define the
** the default file format for new databases and the maximum file format
** that the library can read.
 */

/*
** Determine whether triggers are recursive by default.  This can be
** changed at run-time using a pragma.
 */

/*
** Provide a default value for SQLITE_TEMP_STORE in case it is not specified
** on the command-line
 */

/*
** If no value has been provided for SQLITE_MAX_WORKER_THREADS, or if
** SQLITE_TEMP_STORE is set to 3 (never use temporary files), set it
** to zero.
 */

/*
** The default initial allocation for the pagecache when using separate
** pagecaches for each database connection.  A positive number is the
** number of pages.  A negative number N translations means that a buffer
** of -1024*N bytes is allocated and used for as many pages as it will hold.
**
** The default value of "20" was chosen to minimize the run-time of the
** speedtest1 test program with options: --shrink-memory --reprepare
 */

/*
** Default value for the SQLITE_CONFIG_SORTERREF_SIZE option.
 */

/*
** The compile-time options SQLITE_MMAP_READWRITE and
** SQLITE_ENABLE_BATCH_ATOMIC_WRITE are not compatible with one another.
** You must choose one or the other (or neither) but not both.
 */

/*
** GCC does not define the offsetof() macro so we'll have to do it
** ourselves.
 */

/*
** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
** to avoid complaints from -fsanitize=strict-bounds.
 */

/*
** Macros to compute minimum and maximum of two numbers.
 */

/*
** Swap two objects of type TYPE.
 */

/*
** Check to see if this machine uses EBCDIC.  (Yes, believe it or
** not, there are still machines out there that use EBCDIC.)
 */

type qdiv_t = Tqdiv_t

type t__in_addr_t = uint32

type t__in_port_t = uint16

type t__mode_t = uint32

type t__wctrans_t = uintptr

type t__wctype_t = uintptr

type unchar = Tunchar
