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

//go:build (darwin && amd64) || (darwin && arm64) || (freebsd && 386) || (freebsd && amd64) || (freebsd && arm) || (freebsd && arm64) || (linux && 386) || (linux && amd64) || (linux && arm) || (linux && arm64) || (linux && loong64) || (linux && ppc64le) || (linux && riscv64) || (linux && s390x)

package sqlite3

import (
	"unsafe"

	"modernc.org/libc"
)

// 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 (*TPager)(unsafe.Pointer(pPager)).FbUseFetch != 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
//
//	/*
//	** 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) {
	var nEofBuffer, rc int32
	var pFd uintptr
	_, _, _ = nEofBuffer, pFd, rc
	pFd = fd /* The underlying database file */
	**(**uintptr)(__ccgo_up(pp)) = uintptr(0)
	if (*TunixFile)(unsafe.Pointer(pFd)).FmmapSizeMax > 0 {
		/* Ensure that there is always at least a 256 byte buffer of addressable
		 ** memory following the returned page. If the database is corrupt,
		 ** SQLite may overread the page slightly (in practice only a few bytes,
		 ** but 256 is safe, round, number).  */
		nEofBuffer = int32(256)
		if (*TunixFile)(unsafe.Pointer(pFd)).FpMapRegion == uintptr(0) {
			rc = _unixMapfile(tls, pFd, int64(-int32(1)))
			if rc != SQLITE_OK {
				return rc
			}
		}
		if (*TunixFile)(unsafe.Pointer(pFd)).FmmapSize >= iOff+int64(nAmt)+int64(nEofBuffer) {
			**(**uintptr)(__ccgo_up(pp)) = (*TunixFile)(unsafe.Pointer(pFd)).FpMapRegion + uintptr(iOff)
			(*TunixFile)(unsafe.Pointer(pFd)).FnFetchOut = (*TunixFile)(unsafe.Pointer(pFd)).FnFetchOut + 1
		}
	}
	return SQLITE_OK
}

// 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) {
	var pFd uintptr
	_ = pFd
	pFd = fd /* The underlying database file */
	_ = iOff
	/* If p==0 (unmap the entire file) then there must be no outstanding
	 ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
	 ** then there must be at least one outstanding.  */
	/* If p!=0, it must match the iOff value. */
	if p != 0 {
		(*TunixFile)(unsafe.Pointer(pFd)).FnFetchOut = (*TunixFile)(unsafe.Pointer(pFd)).FnFetchOut - 1
	} else {
		_unixUnmapfile(tls, pFd)
	}
	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.
 */

type fd_mask = Tfd_mask
