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

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

package sqlite3

import (
	"unsafe"

	"modernc.org/libc"
)

type Tfd_mask = uint64

const __LONG_MAX = 9223372036854775807

// 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
	_unixUnmapfile(tls, pFile)
	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(120))
	return SQLITE_OK
}

// C documentation
//
//	/*
//	** Obtain a reference to a memory mapped page object for page number pgno.
//	** The new object will use the pointer pData, obtained from xFetch().
//	** If successful, set *ppPage to point to the new page reference
//	** and return SQLITE_OK. Otherwise, return an SQLite error code and set
//	** *ppPage to zero.
//	**
//	** Page references obtained by calling this function should be released
//	** by calling pagerReleaseMapPage().
//	*/
func _pagerAcquireMapPage(tls *libc.TLS, pPager uintptr, pgno TPgno, pData uintptr, ppPage uintptr) (r int32) {
	var p, v1 uintptr
	_, _ = p, v1 /* Memory mapped page to return */
	if (*TPager)(unsafe.Pointer(pPager)).FpMmapFreelist != 0 {
		v1 = (*TPager)(unsafe.Pointer(pPager)).FpMmapFreelist
		p = v1
		**(**uintptr)(__ccgo_up(ppPage)) = v1
		(*TPager)(unsafe.Pointer(pPager)).FpMmapFreelist = (*TPgHdr)(unsafe.Pointer(p)).FpDirty
		(*TPgHdr)(unsafe.Pointer(p)).FpDirty = uintptr(0)
		libc.Xmemset(tls, (*TPgHdr)(unsafe.Pointer(p)).FpExtra, 0, uint64(8))
	} else {
		v1 = _sqlite3MallocZero(tls, uint64(80)+uint64((*TPager)(unsafe.Pointer(pPager)).FnExtra))
		p = v1
		**(**uintptr)(__ccgo_up(ppPage)) = v1
		if p == uintptr(0) {
			_sqlite3OsUnfetch(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd, libc.Int64FromUint32(pgno-libc.Uint32FromInt32(1))*(*TPager)(unsafe.Pointer(pPager)).FpageSize, pData)
			return int32(SQLITE_NOMEM)
		}
		(*TPgHdr)(unsafe.Pointer(p)).FpExtra = p + 1*80
		(*TPgHdr)(unsafe.Pointer(p)).Fflags = uint16(PGHDR_MMAP)
		(*TPgHdr)(unsafe.Pointer(p)).FnRef = int64(1)
		(*TPgHdr)(unsafe.Pointer(p)).FpPager = pPager
	}
	(*TPgHdr)(unsafe.Pointer(p)).Fpgno = pgno
	(*TPgHdr)(unsafe.Pointer(p)).FpData = pData
	(*TPager)(unsafe.Pointer(pPager)).FnMmapOut = (*TPager)(unsafe.Pointer(pPager)).FnMmapOut + 1
	return SQLITE_OK
}

// C documentation
//
//	/*
//	** Find the current time (in Universal Coordinated Time).  Write into *piNow
//	** the current time and date as a Julian Day number times 86_400_000.  In
//	** other words, write into *piNow the number of milliseconds since the Julian
//	** epoch of noon in Greenwich on November 24, 4714 B.C according to the
//	** proleptic Gregorian calendar.
//	**
//	** On success, return SQLITE_OK.  Return SQLITE_ERROR if the time and date
//	** cannot be found.
//	*/
func _unixCurrentTimeInt64(tls *libc.TLS, NotUsed uintptr, piNow uintptr) (r int32) {
	bp := tls.Alloc(16)
	defer tls.Free(16)
	var rc int32
	var _ /* sNow at bp+0 */ Ttimeval
	_ = rc
	rc = SQLITE_OK
	libc.Xgettimeofday(tls, bp, uintptr(0)) /* Cannot fail given valid arguments */
	**(**Tsqlite3_int64)(__ccgo_up(piNow)) = _unixEpoch + int64(1000)*int64((**(**Ttimeval)(__ccgo_up(bp))).Ftv_sec) + int64((**(**Ttimeval)(__ccgo_up(bp))).Ftv_usec/int64(1000))
	_ = NotUsed
	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, nCopy int32
	var pFile uintptr
	_, _, _ = got, nCopy, 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. */
	/* Deal with as much of this read request as possible by transferring
	 ** data from the memory mapping using memcpy().  */
	if offset < (*TunixFile)(unsafe.Pointer(pFile)).FmmapSize {
		if offset+int64(amt) <= (*TunixFile)(unsafe.Pointer(pFile)).FmmapSize {
			libc.Xmemcpy(tls, pBuf, (*TunixFile)(unsafe.Pointer(pFile)).FpMapRegion+uintptr(offset), libc.Uint64FromInt32(amt))
			return SQLITE_OK
		} else {
			nCopy = int32((*TunixFile)(unsafe.Pointer(pFile)).FmmapSize - offset)
			libc.Xmemcpy(tls, pBuf, (*TunixFile)(unsafe.Pointer(pFile)).FpMapRegion+uintptr(offset), libc.Uint64FromInt32(nCopy))
			pBuf = pBuf + uintptr(nCopy)
			amt = amt - nCopy
			offset = offset + int64(nCopy)
		}
	}
	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
//
//	/*
//	** 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 {
		_vdbeSorterExtendFile(tls, db, (*TSortSubtask)(unsafe.Pointer(pTask)).Ffile.FpFd, (*TSortSubtask)(unsafe.Pointer(pTask)).Ffile.FiEof+(*TSorterList)(unsafe.Pointer(pList)).FszPMA+int64(9))
	}
	/* 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
}
