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

//go:build (linux && arm64) || (linux && loong64) || (linux && riscv64)

package sqlite3

import (
	"unsafe"

	"modernc.org/libc"
)

type Tstat = struct {
	Fst_dev     Tdev_t
	Fst_ino     Tino_t
	Fst_mode    Tmode_t
	Fst_nlink   Tnlink_t
	Fst_uid     Tuid_t
	Fst_gid     Tgid_t
	Fst_rdev    Tdev_t
	F__pad      uint64
	Fst_size    Toff_t
	Fst_blksize Tblksize_t
	F__pad2     int32
	Fst_blocks  Tblkcnt_t
	Fst_atim    Ttimespec
	Fst_mtim    Ttimespec
	Fst_ctim    Ttimespec
	F__unused   [2]uint32
}

// C documentation
//
//	/*
//	** Return TRUE if pFile has been renamed or unlinked since it was first opened.
//	*/
func _fileHasMoved(tls *libc.TLS, pFile uintptr) (r int32) {
	bp := tls.Alloc(128)
	defer tls.Free(128)
	var _ /* buf at bp+0 */ Tstat
	return libc.BoolInt32((*TunixFile)(unsafe.Pointer(pFile)).FpInode != uintptr(0) && ((*(*func(*libc.TLS, uintptr, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(4)].FpCurrent})))(tls, (*TunixFile)(unsafe.Pointer(pFile)).FzPath, bp) != 0 || uint64((**(**Tstat)(__ccgo_up(bp))).Fst_ino) != (*TunixInodeInfo)(unsafe.Pointer((*TunixFile)(unsafe.Pointer(pFile)).FpInode)).FfileId.Fino))
}

// C documentation
//
//	/*
//	** Given a file descriptor, locate the unixInodeInfo object that
//	** describes that file descriptor.  Create a new one if necessary.  The
//	** return value might be uninitialized if an error occurs.
//	**
//	** The global mutex must held when calling this routine.
//	**
//	** Return an appropriate error code.
//	*/
func _findInodeInfo(tls *libc.TLS, pFile uintptr, ppInode uintptr) (r int32) {
	bp := tls.Alloc(144)
	defer tls.Free(144)
	var fd, rc int32
	var pInode uintptr
	var _ /* fileId at bp+0 */ TunixFileId
	var _ /* statbuf at bp+16 */ Tstat
	_, _, _ = fd, pInode, rc /* Low-level file information */
	pInode = uintptr(0)      /* Candidate unixInodeInfo object */
	/* Get low-level information about the file that we can used to
	 ** create a unique name for the file.
	 */
	fd = (*TunixFile)(unsafe.Pointer(pFile)).Fh
	rc = (*(*func(*libc.TLS, int32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(5)].FpCurrent})))(tls, fd, bp+16)
	if rc != 0 {
		_storeLastErrno(tls, pFile, **(**int32)(__ccgo_up(libc.X__errno_location(tls))))
		return int32(SQLITE_IOERR)
	}
	libc.Xmemset(tls, bp, 0, uint64(16))
	(**(**TunixFileId)(__ccgo_up(bp))).Fdev = (**(**Tstat)(__ccgo_up(bp + 16))).Fst_dev
	(**(**TunixFileId)(__ccgo_up(bp))).Fino = uint64((**(**Tstat)(__ccgo_up(bp + 16))).Fst_ino)
	pInode = _inodeList
	for pInode != 0 && libc.Xmemcmp(tls, bp, pInode, uint64(16)) != 0 {
		pInode = (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpNext
	}
	if pInode == uintptr(0) {
		pInode = Xsqlite3_malloc64(tls, uint64(80))
		if pInode == uintptr(0) {
			return int32(SQLITE_NOMEM)
		}
		libc.Xmemset(tls, pInode, 0, uint64(80))
		libc.Xmemcpy(tls, pInode, bp, uint64(16))
		if _sqlite3Config.FbCoreMutex != 0 {
			(*TunixInodeInfo)(unsafe.Pointer(pInode)).FpLockMutex = Xsqlite3_mutex_alloc(tls, SQLITE_MUTEX_FAST)
			if (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpLockMutex == uintptr(0) {
				Xsqlite3_free(tls, pInode)
				return int32(SQLITE_NOMEM)
			}
		}
		(*TunixInodeInfo)(unsafe.Pointer(pInode)).FnRef = int32(1)
		(*TunixInodeInfo)(unsafe.Pointer(pInode)).FpNext = _inodeList
		(*TunixInodeInfo)(unsafe.Pointer(pInode)).FpPrev = uintptr(0)
		if _inodeList != 0 {
			(*TunixInodeInfo)(unsafe.Pointer(_inodeList)).FpPrev = pInode
		}
		_inodeList = pInode
	} else {
		(*TunixInodeInfo)(unsafe.Pointer(pInode)).FnRef = (*TunixInodeInfo)(unsafe.Pointer(pInode)).FnRef + 1
	}
	**(**uintptr)(__ccgo_up(ppInode)) = pInode
	return SQLITE_OK
}

// C documentation
//
//	/*
//	** Search for an unused file descriptor that was opened on the database
//	** file (not a journal or super-journal file) identified by pathname
//	** zPath with SQLITE_OPEN_XXX flags matching those passed as the second
//	** argument to this function.
//	**
//	** Such a file descriptor may exist if a database connection was closed
//	** but the associated file descriptor could not be closed because some
//	** other file descriptor open on the same file is holding a file-lock.
//	** Refer to comments in the unixClose() function and the lengthy comment
//	** describing "Posix Advisory Locking" at the start of this file for
//	** further details. Also, ticket #4018.
//	**
//	** If a suitable file descriptor is found, then it is returned. If no
//	** such file descriptor is located, -1 is returned.
//	*/
func _findReusableFd(tls *libc.TLS, zPath uintptr, flags int32) (r uintptr) {
	bp := tls.Alloc(128)
	defer tls.Free(128)
	var pInode, pUnused, pp uintptr
	var _ /* sStat at bp+0 */ Tstat
	_, _, _ = pInode, pUnused, pp
	pUnused = uintptr(0) /* Results of stat() call */
	_unixEnterMutex(tls)
	/* A stat() call may fail for various reasons. If this happens, it is
	 ** almost certain that an open() call on the same path will also fail.
	 ** For this reason, if an error occurs in the stat() call here, it is
	 ** ignored and -1 is returned. The caller will try to open a new file
	 ** descriptor on the same path, fail, and return an error to SQLite.
	 **
	 ** Even if a subsequent open() call does succeed, the consequences of
	 ** not searching for a reusable file descriptor are not dire.  */
	if _inodeList != uintptr(0) && 0 == (*(*func(*libc.TLS, uintptr, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(4)].FpCurrent})))(tls, zPath, bp) {
		pInode = _inodeList
		for pInode != 0 && ((*TunixInodeInfo)(unsafe.Pointer(pInode)).FfileId.Fdev != (**(**Tstat)(__ccgo_up(bp))).Fst_dev || (*TunixInodeInfo)(unsafe.Pointer(pInode)).FfileId.Fino != uint64((**(**Tstat)(__ccgo_up(bp))).Fst_ino)) {
			pInode = (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpNext
		}
		if pInode != 0 {
			Xsqlite3_mutex_enter(tls, (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpLockMutex)
			flags = flags & (libc.Int32FromInt32(SQLITE_OPEN_READONLY) | libc.Int32FromInt32(SQLITE_OPEN_READWRITE))
			pp = pInode + 40
			for {
				if !(**(**uintptr)(__ccgo_up(pp)) != 0 && (*TUnixUnusedFd)(unsafe.Pointer(**(**uintptr)(__ccgo_up(pp)))).Fflags != flags) {
					break
				}
				goto _1
			_1:
				;
				pp = **(**uintptr)(__ccgo_up(pp)) + 8
			}
			pUnused = **(**uintptr)(__ccgo_up(pp))
			if pUnused != 0 {
				**(**uintptr)(__ccgo_up(pp)) = (*TUnixUnusedFd)(unsafe.Pointer(pUnused)).FpNext
			}
			Xsqlite3_mutex_leave(tls, (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpLockMutex)
		}
	}
	_unixLeaveMutex(tls)
	return pUnused
}

// C documentation
//
//	/*
//	** Test the existence of or access permissions of file zPath. The
//	** test performed depends on the value of flags:
//	**
//	**     SQLITE_ACCESS_EXISTS: Return 1 if the file exists
//	**     SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable.
//	**     SQLITE_ACCESS_READONLY: Return 1 if the file is readable.
//	**
//	** Otherwise return 0.
//	*/
func _unixAccess(tls *libc.TLS, NotUsed uintptr, zPath uintptr, flags int32, pResOut uintptr) (r int32) {
	bp := tls.Alloc(128)
	defer tls.Free(128)
	var _ /* buf at bp+0 */ Tstat
	_ = NotUsed
	/* The spec says there are three possible values for flags.  But only
	 ** two of them are actually used */
	if flags == SQLITE_ACCESS_EXISTS {
		**(**int32)(__ccgo_up(pResOut)) = libc.BoolInt32(0 == (*(*func(*libc.TLS, uintptr, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(4)].FpCurrent})))(tls, zPath, bp) && (!((**(**Tstat)(__ccgo_up(bp))).Fst_mode&libc.Uint32FromInt32(S_IFMT) == libc.Uint32FromInt32(S_IFREG)) || (**(**Tstat)(__ccgo_up(bp))).Fst_size > 0))
	} else {
		**(**int32)(__ccgo_up(pResOut)) = libc.BoolInt32((*(*func(*libc.TLS, uintptr, int32) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(2)].FpCurrent})))(tls, zPath, libc.Int32FromInt32(W_OK)|libc.Int32FromInt32(R_OK)) == 0)
	}
	return SQLITE_OK
}

// C documentation
//
//	/*
//	** Determine the current size of a file in bytes
//	*/
func _unixFileSize(tls *libc.TLS, id uintptr, pSize uintptr) (r int32) {
	bp := tls.Alloc(128)
	defer tls.Free(128)
	var rc int32
	var _ /* buf at bp+0 */ Tstat
	_ = rc
	rc = (*(*func(*libc.TLS, int32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(5)].FpCurrent})))(tls, (*TunixFile)(unsafe.Pointer(id)).Fh, bp)
	if rc != 0 {
		_storeLastErrno(tls, id, **(**int32)(__ccgo_up(libc.X__errno_location(tls))))
		return libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(7)<<libc.Int32FromInt32(8)
	}
	**(**Ti64)(__ccgo_up(pSize)) = int64((**(**Tstat)(__ccgo_up(bp))).Fst_size)
	/* When opening a zero-size database, the findInodeInfo() procedure
	 ** writes a single byte into that file in order to work around a bug
	 ** in the OS-X msdos filesystem.  In order to avoid problems with upper
	 ** layers, we need to report this file size as zero even though it is
	 ** really 1.   Ticket #3260.
	 */
	if **(**Ti64)(__ccgo_up(pSize)) == int64(1) {
		**(**Ti64)(__ccgo_up(pSize)) = 0
	}
	return SQLITE_OK
}

// C documentation
//
//	/*
//	** Memory map or remap the file opened by file-descriptor pFd (if the file
//	** is already mapped, the existing mapping is replaced by the new). Or, if
//	** there already exists a mapping for this file, and there are still
//	** outstanding xFetch() references to it, this function is a no-op.
//	**
//	** If parameter nByte is non-negative, then it is the requested size of
//	** the mapping to create. Otherwise, if nByte is less than zero, then the
//	** requested size is the size of the file on disk. The actual size of the
//	** created mapping is either the requested size or the value configured
//	** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
//	**
//	** SQLITE_OK is returned if no error occurs (even if the mapping is not
//	** recreated as a result of outstanding references) or an SQLite error
//	** code otherwise.
//	*/
func _unixMapfile(tls *libc.TLS, pFd uintptr, nMap Ti64) (r int32) {
	bp := tls.Alloc(128)
	defer tls.Free(128)
	var _ /* statbuf at bp+0 */ Tstat
	if (*TunixFile)(unsafe.Pointer(pFd)).FnFetchOut > 0 {
		return SQLITE_OK
	}
	if nMap < 0 { /* Low-level file information */
		if (*(*func(*libc.TLS, int32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(5)].FpCurrent})))(tls, (*TunixFile)(unsafe.Pointer(pFd)).Fh, bp) != 0 {
			return libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(7)<<libc.Int32FromInt32(8)
		}
		nMap = int64((**(**Tstat)(__ccgo_up(bp))).Fst_size)
	}
	if nMap > (*TunixFile)(unsafe.Pointer(pFd)).FmmapSizeMax {
		nMap = (*TunixFile)(unsafe.Pointer(pFd)).FmmapSizeMax
	}
	if nMap != (*TunixFile)(unsafe.Pointer(pFd)).FmmapSize {
		_unixRemapfile(tls, pFd, nMap)
	}
	return SQLITE_OK
}

// C documentation
//
//	/*
//	** Return the name of a directory in which to put temporary files.
//	** If no suitable temporary file directory can be found, return NULL.
//	*/
func _unixTempFileDir(tls *libc.TLS) (r uintptr) {
	bp := tls.Alloc(128)
	defer tls.Free(128)
	var i, v1 uint32
	var zDir uintptr
	var _ /* buf at bp+0 */ Tstat
	_, _, _ = i, zDir, v1
	i = uint32(0)
	zDir = Xsqlite3_temp_directory
	for int32(1) != 0 {
		if zDir != uintptr(0) && (*(*func(*libc.TLS, uintptr, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(4)].FpCurrent})))(tls, zDir, bp) == 0 && (**(**Tstat)(__ccgo_up(bp))).Fst_mode&uint32(S_IFMT) == uint32(S_IFDIR) && (*(*func(*libc.TLS, uintptr, int32) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(2)].FpCurrent})))(tls, zDir, int32(03)) == 0 {
			return zDir
		}
		if uint64(i) >= libc.Uint64FromInt64(48)/libc.Uint64FromInt64(8) {
			break
		}
		v1 = i
		i = i + 1
		zDir = _azTempDirs[v1]
	}
	return uintptr(0)
}
