enablepsstore/src/vita_sqlite.c

234 lines
5.6 KiB
C

// This was only tested with sqlite 3.6.23.1
// Please note that this .c file does not implement thread safety for sqlite, and as such requires it to be built with -DSQLITE_THREADSAFE=0 as well
// Build flags for sqlite: -DSQLITE_OS_OTHER=1 -DSQLITE_TEMP_STORE=3 -DSQLITE_THREADSAFE=0
// It's also hacky -- no sync support, no tempdir support, access returning bs, etc... don't use in production!
// based on test_demovfs.c
#include "sqlite3.h"
#include <stdio.h>
#include <string.h>
#include <psp2/io/fcntl.h>
#include <psp2/io/stat.h>
#include <psp2/kernel/threadmgr.h>
#include <psp2/rtc.h>
#define VERBOSE 0
#if VERBOSE
#define LOG psvDebugScreenPrintf
#else
#define LOG(...)
#endif
typedef struct VitaFile {
sqlite3_file base;
unsigned fd;
} VitaFile;
// File ops
static int vita_xClose(sqlite3_file *pFile) {
VitaFile *p = (VitaFile*)pFile;
sceIoClose(p->fd);
LOG("close %x\n", p->fd);
return SQLITE_OK;
}
static int vita_xRead(sqlite3_file *pFile, void *zBuf, int iAmt, sqlite_int64 iOfst) {
VitaFile *p = (VitaFile*)pFile;
memset(zBuf, 0, iAmt);
sceIoLseek(p->fd, iOfst, SCE_SEEK_SET);
int read = sceIoRead(p->fd, zBuf, iAmt);
LOG("read %x %x %x => %x\n", p->fd, zBuf, iAmt, read);
if (read == iAmt)
return SQLITE_OK;
else if (read >= 0)
return SQLITE_IOERR_SHORT_READ;
return SQLITE_IOERR_READ;
}
static int vita_xWrite(sqlite3_file *pFile, const void *zBuf, int iAmt, sqlite_int64 iOfst) {
VitaFile *p = (VitaFile*)pFile;
int ofst = sceIoLseek(p->fd, iOfst, SCE_SEEK_SET);
LOG("seek %x %x => %x\n", p->fd, iOfst, ofst);
if (ofst != iOfst)
return SQLITE_IOERR_WRITE;
int write = sceIoWrite(p->fd, zBuf, iAmt);
LOG("write %x %x %x => %x\n", p->fd, zBuf, iAmt);
if (write != iAmt)
return SQLITE_IOERR_WRITE;
return SQLITE_OK;
}
static int vita_xTruncate(sqlite3_file *pFile, sqlite_int64 size) {
LOG("truncate\n");
return SQLITE_OK;
}
static int vita_xSync(sqlite3_file *pFile, int flags) {
return SQLITE_OK;
}
static int vita_xFileSize(sqlite3_file *pFile, sqlite_int64 *pSize) {
VitaFile *p = (VitaFile*)pFile;
SceIoStat stat = {0};
sceIoGetstatByFd(p->fd, &stat);
LOG("filesize %x => %x\n", p->fd, stat.st_size);
*pSize = stat.st_size;
return SQLITE_OK;
}
static int vita_xLock(sqlite3_file *pFile, int eLock) {
return SQLITE_OK;
}
static int vita_xUnlock(sqlite3_file *pFile, int eLock) {
return SQLITE_OK;
}
static int vita_xCheckReservedLock(sqlite3_file *pFile, int *pResOut) {
*pResOut = 0;
return SQLITE_OK;
}
static int vita_xFileControl(sqlite3_file *pFile, int op, void *pArg) {
return SQLITE_OK;
}
static int vita_xSectorSize(sqlite3_file *pFile) {
return 0;
}
static int vita_xDeviceCharacteristics(sqlite3_file *pFile) {
return 0;
}
// VFS ops
static int vita_xOpen(sqlite3_vfs *vfs, const char *name, sqlite3_file *file, int flags, int *outFlags) {
static const sqlite3_io_methods vitaio = {
1,
vita_xClose,
vita_xRead,
vita_xWrite,
vita_xTruncate,
vita_xSync,
vita_xFileSize,
vita_xLock,
vita_xUnlock,
vita_xCheckReservedLock,
vita_xFileControl,
vita_xSectorSize,
vita_xDeviceCharacteristics,
};
VitaFile *p = (VitaFile*)file;
unsigned oflags = 0;
if (flags & SQLITE_OPEN_EXCLUSIVE)
oflags |= SCE_O_EXCL;
if (flags & SQLITE_OPEN_CREATE)
oflags |= SCE_O_CREAT;
if (flags & SQLITE_OPEN_READONLY)
oflags |= SCE_O_RDONLY;
if (flags & SQLITE_OPEN_READWRITE)
oflags |= SCE_O_RDWR;
// TODO(xyz): sqlite tries to open inexistant journal and then tries to read from it, wtf?
// so force O_CREAT here
if (flags & SQLITE_OPEN_MAIN_JOURNAL && !(flags & SQLITE_OPEN_EXCLUSIVE))
oflags |= SCE_O_CREAT;
memset(p, 0, sizeof(*p));
p->fd = sceIoOpen(name, oflags, 7);
LOG("open %s %x orig flags %x => %x\n", name, oflags, flags, p->fd);
if (p->fd < 0) {
return SQLITE_CANTOPEN;
}
if (outFlags)
*outFlags = flags;
p->base.pMethods = &vitaio;
return SQLITE_OK;
}
int vita_xDelete(sqlite3_vfs *vfs, const char *name, int syncDir) {
int ret = sceIoRemove(name);
if (ret < 0)
return SQLITE_IOERR_DELETE;
return SQLITE_OK;
}
int vita_xAccess(sqlite3_vfs *vfs, const char *name, int flags, int *pResOut) {
*pResOut = 1;
return SQLITE_OK;
}
int vita_xFullPathname(sqlite3_vfs *vfs, const char *zName, int nOut, char *zOut) {
snprintf(zOut, nOut, "%s", zName);
return 0;
}
void* vita_xDlOpen(sqlite3_vfs *vfs, const char *zFilename) {
return NULL;
}
void vita_xDlError(sqlite3_vfs *vfs, int nByte, char *zErrMsg) {
}
void (*vita_xDlSym(sqlite3_vfs *vfs,void*p, const char *zSymbol))(void) {
return NULL;
}
void vita_xDlClose(sqlite3_vfs *vfs, void*p) {
}
int vita_xRandomness(sqlite3_vfs *vfs, int nByte, char *zOut) {
return SQLITE_OK;
}
int vita_xSleep(sqlite3_vfs *vfs, int microseconds) {
sceKernelDelayThread(microseconds);
return SQLITE_OK;
}
int vita_xCurrentTime(sqlite3_vfs *vfs, double *pTime) {
time_t t = 0;
SceDateTime time = {0};
sceRtcGetCurrentClock(&time, 0);
sceRtcGetTime_t(&time, &t);
*pTime = t/86400.0 + 2440587.5;
return SQLITE_OK;
}
int vita_xGetLastError(sqlite3_vfs *vfs, int e, char *err) {
return 0;
}
sqlite3_vfs vita_vfs = {
.iVersion = 1,
.szOsFile = sizeof(VitaFile),
.mxPathname = 0x100,
.pNext = NULL,
.zName = "psp2",
.pAppData = NULL,
.xOpen = vita_xOpen,
.xDelete = vita_xDelete,
.xAccess = vita_xAccess,
.xFullPathname = vita_xFullPathname,
.xDlOpen = vita_xDlOpen,
.xDlError = vita_xDlError,
.xDlSym = vita_xDlSym,
.xDlClose = vita_xDlClose,
.xRandomness = vita_xRandomness,
.xSleep = vita_xSleep,
.xCurrentTime = vita_xCurrentTime,
.xGetLastError = vita_xGetLastError,
};
int sqlite3_os_init(void) {
sqlite3_vfs_register(&vita_vfs, 1);
return 0;
}
int sqlite3_os_end(void) {
return 0;
}