This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/os/assets.c

270 lines
8.0 KiB
C
Raw Normal View History

2016-07-31 16:28:05 +01:00
/*************************************************************************
* *
* YAP Prolog *
* *
* Yap Prolog was developed at NCCUP - Universidade do Porto *
* *
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
* *
**************************************************************************
* *
* File: assets.c *
* Last rev: 5/2/88 *
* mods: *
* comments: Asset Support in ANDROID *
* *
*************************************************************************/
#ifdef SCCSA
static char SccsId[] = "%W% %G%";
#endif
/**
* @file assets.c
* @author VITOR SANTOS COSTA <vsc@VITORs-MBP.lan>
* @date Thu Nov 19 10:53:20 2015
*
* @brief File Aliases
*
*
*/
#include <stdbool.h>
#include "sysbits.h"
// for native asset manager
#include <sys/types.h>
2017-11-21 15:44:43 +00:00
#if __ANDROID__
2017-11-29 13:47:57 +00:00
2018-02-14 00:13:13 +00:00
#include <jni.h>
2017-11-21 15:44:43 +00:00
#include <android/asset_manager.h>
#include <android/native_activity.h>
2016-07-31 16:28:05 +01:00
2018-02-21 17:41:00 +00:00
2018-03-19 15:41:06 +00:00
extern X_API void
Java_pt_up_yap_yapdroid_YAPDroid_loadAssetManager(JNIEnv *env, jclass clazz, jobject assetManager);
2018-02-21 17:41:00 +00:00
2018-02-14 00:13:13 +00:00
jobject *Yap_aref;
JNIEnv *Yap_env;
AAssetManager *Yap_assetManager(void)
{
return AAssetManager_fromJava(Yap_env, Yap_aref);
}
2016-07-31 16:28:05 +01:00
2018-03-19 15:41:06 +00:00
X_API void
Java_pt_up_yap_yapdroid_YAPDroid_loadAssetManager(JNIEnv *env, jclass clazz, jobject assetManager) {
2018-02-14 00:13:13 +00:00
Yap_aref = (*env)->NewGlobalRef(env,assetManager);
Yap_env = env;
2016-07-31 16:28:05 +01:00
}
2018-02-14 00:13:13 +00:00
2017-11-21 15:44:43 +00:00
static void *
2018-03-26 15:01:21 +01:00
open_asset(VFS_t *me, const char *fname, const char *io_mode, int sno) {
2017-11-29 13:47:57 +00:00
int mode;
const void *buf;
2018-02-14 00:13:13 +00:00
AAsset *am = NULL;
2018-06-25 13:44:09 +01:00
//__android_log_print(ANDROID_LOG_INFO, "YAPDroid", "open %s-%s <%s>", fname, me->prefix,io_mode);
2018-03-26 15:01:21 +01:00
if (strchr(io_mode, 'B')) {
2017-11-29 13:47:57 +00:00
mode = AASSET_MODE_BUFFER;
2018-03-26 23:12:48 +01:00
} else {
2017-11-29 13:47:57 +00:00
mode = AASSET_MODE_UNKNOWN;
}
2018-02-14 00:13:13 +00:00
GLOBAL_Stream[sno].name = Yap_LookupAtom(fname);
fname += strlen(me->prefix)+1;
// strcpy(dir, fname);
// AAssetDir *dp = AAssetManager_openDir( Yap_assetManager(), dirname(dir) );
// strcpy(dir, fname);
// char *d = basename(dir);
2019-01-09 09:32:09 +00:00
am = AAssetManager_open(Yap_assetManager(), fname, AASSET_MODE_UNKNOWN);
2018-06-25 13:44:09 +01:00
//if (am==NULL)
// __android_log_print(ANDROID_LOG_INFO, "YAPDroid", "failed open %s <%s>", fname, strerror(errno) );
2018-12-14 10:29:12 +00:00
__android_log_print(ANDROID_LOG_INFO, "YAPDroid", "open %s <%s>", fname, io_mode);
2018-02-14 00:13:13 +00:00
// while (dp) {
// char *f = AAssetDir_getNextFileName(dp);
2018-12-14 10:29:12 +00:00
// __android_log_print(ANDROID_LOG_INFO, "YAPDroid", "open %s <%s>", fname, mode);
2018-02-14 00:13:13 +00:00
// if (f && strcasecmp(d,f) == 0) {
//
// }
// }
2018-02-21 17:41:00 +00:00
if (!am) {
2018-12-14 10:29:12 +00:00
__android_log_print(ANDROID_LOG_INFO, "YAPDroid", "failed %s <%s>", fname, io_mode);
2017-11-29 13:47:57 +00:00
return NULL;
2018-02-21 17:41:00 +00:00
}
2017-11-29 13:47:57 +00:00
// try not to use it as an asset
2018-02-14 00:13:13 +00:00
off64_t sz = AAsset_getLength64(am), sz0 = 0;
2017-11-29 13:47:57 +00:00
int fd;
StreamDesc *st = GLOBAL_Stream + sno;
2018-02-14 00:13:13 +00:00
if ((buf = AAsset_getBuffer(am))) {
2017-11-29 13:47:57 +00:00
// copy to memory
2018-02-14 00:13:13 +00:00
char *bf = malloc(sz);
2018-06-30 14:33:32 +01:00
memmove(bf, buf, sz);
2018-02-14 00:13:13 +00:00
bool rc = Yap_set_stream_to_buf(st, bf, sz);
if (rc) AAsset_close(am);
2017-11-29 13:47:57 +00:00
st->vfs = NULL;
st->vfs_handle = NULL;
2018-07-03 00:08:19 +01:00
st->status = InMemory_Stream_f|Seekable_Stream_f|Input_Stream_f;
2017-11-29 13:47:57 +00:00
return st;
2018-02-14 00:13:13 +00:00
} else if ((fd = AAsset_openFileDescriptor64(am, &sz0, &sz)) >= 0) {
2017-11-29 13:47:57 +00:00
// can use it as read-only file
st->file = fdopen(fd, "r");
st->vfs = NULL;
st->vfs_handle = NULL;
st->status = Seekable_Stream_f|Input_Stream_f;
2018-12-14 10:29:12 +00:00
return st->file;
2017-11-29 13:47:57 +00:00
} else {
// should be done, but if not
2018-02-14 00:13:13 +00:00
GLOBAL_Stream[sno].vfs_handle = am;
2017-11-29 13:47:57 +00:00
st->vfs = me;
st->status = Input_Stream_f;
2018-02-14 00:13:13 +00:00
return am;
2017-11-29 13:47:57 +00:00
}
2016-07-31 16:28:05 +01:00
}
static bool
2017-11-29 13:47:57 +00:00
close_asset(int sno) {
AAsset_close(GLOBAL_Stream[sno].vfs_handle);
return true;
2016-07-31 16:28:05 +01:00
}
2017-11-29 13:47:57 +00:00
static int64_t seek64(int sno, int64_t offset, int whence) {
return AAsset_seek64(GLOBAL_Stream[sno].vfs_handle, offset, whence);
2016-07-31 16:28:05 +01:00
}
2017-11-29 13:47:57 +00:00
static int getc_asset(int sno) {
int ch;
if (AAsset_read(GLOBAL_Stream[sno].vfs_handle, &ch, 1))
return ch;
return -1;
2016-07-31 16:28:05 +01:00
}
2017-11-29 13:47:57 +00:00
static void *opendir_a(VFS_t *me, const char *dirName) {
dirName += strlen(me->prefix) + 1;
2018-02-14 00:13:13 +00:00
return (void *) AAssetManager_openDir(Yap_assetManager(), dirName);
2016-07-31 16:28:05 +01:00
}
2017-11-29 13:47:57 +00:00
static const char *readdir_a(void *dirHandle) {
return AAssetDir_getNextFileName((AAssetDir *) dirHandle);
2016-07-31 16:28:05 +01:00
}
2017-11-29 13:47:57 +00:00
static bool closedir_a(void *dirHandle) {
AAssetDir_close((AAssetDir *) dirHandle);
return true;
2016-07-31 16:28:05 +01:00
}
2017-11-29 13:47:57 +00:00
static bool stat_a(VFS_t *me, const char *fname, vfs_stat *out) {
struct stat bf;
fname += strlen(me->prefix) + 1;
if (stat("/assets", &bf)) {
2018-02-14 14:17:57 +00:00
out->st_mode = me ->vflags ;
2017-11-29 13:47:57 +00:00
out->st_dev = bf.st_dev;
out->st_uid = bf.st_uid;
out->st_gid = bf.st_gid;
2018-06-30 14:33:32 +01:00
memmove(&out->st_atimespec, (const void *) &bf.st_atim, sizeof(struct timespec));
memmove(&out->st_mtimespec, (const void *) &bf.st_mtim, sizeof(struct timespec));
memmove(&out->st_ctimespec, (const void *) &bf.st_ctim, sizeof(struct timespec));
memmove(&out->st_birthtimespec, (const void *) &bf.st_ctim,
2017-11-29 13:47:57 +00:00
sizeof(struct timespec));
}
2018-02-14 00:13:13 +00:00
AAsset *a = AAssetManager_open(Yap_assetManager(), fname, AASSET_MODE_UNKNOWN);
2016-07-31 16:28:05 +01:00
// try not to use it as an asset
2018-02-14 14:17:57 +00:00
if (!a)
return false;
2017-11-29 13:47:57 +00:00
out->st_size = AAsset_getLength64(a);
AAsset_close(a);
return true;
2016-07-31 16:28:05 +01:00
}
static
2017-11-29 13:47:57 +00:00
bool is_dir_a(VFS_t *me, const char *dirName) {
2018-02-14 14:17:57 +00:00
dirName += strlen(me->prefix)+1;
2018-02-14 00:13:13 +00:00
if (dirName[0] == '\0')
2018-02-14 14:17:57 +00:00
return true;
2016-07-31 16:28:05 +01:00
// try not to use it as an asset
2018-02-14 00:13:13 +00:00
AAssetDir *d = AAssetManager_openDir(Yap_assetManager(), dirName);
2018-02-14 14:17:57 +00:00
if (d == NULL || AAssetDir_getNextFileName(d) == NULL)
2017-11-29 13:47:57 +00:00
return false;
2018-02-14 00:13:13 +00:00
(AAssetDir_close(d));
2018-06-25 13:44:09 +01:00
//__android_log_print(ANDROID_LOG_INFO, "YAPDroid", "isdir %s <%p>", dirName, d);
2018-02-14 00:13:13 +00:00
return true;
2016-07-31 16:28:05 +01:00
}
static
2017-11-29 13:47:57 +00:00
bool exists_a(VFS_t *me, const char *dirName) {
dirName += strlen(me->prefix) + 1;
2016-07-31 16:28:05 +01:00
// try not to use it as an asset
2018-02-14 00:13:13 +00:00
AAsset *d = AAssetManager_open(Yap_assetManager(), dirName, AASSET_MODE_UNKNOWN);
2018-06-25 13:44:09 +01:00
//__android_log_print(ANDROID_LOG_INFO, "YAPDroid", "exists %s <%p>", dirName, d);
2016-07-31 16:28:05 +01:00
if (d == NULL)
2017-11-29 13:47:57 +00:00
return false;
AAsset_close(d);
return true;
2016-07-31 16:28:05 +01:00
}
2018-02-21 17:41:00 +00:00
char *virtual_cwd;
2017-11-30 01:14:26 +00:00
2017-11-29 13:47:57 +00:00
static bool set_cwd(VFS_t *me, const char *dirName) {
2016-07-31 16:28:05 +01:00
chdir("/assets");
2018-02-22 08:18:45 +00:00
if (GLOBAL_cwd) {
free(GLOBAL_cwd);
2018-02-21 17:41:00 +00:00
}
2018-06-22 23:55:50 +01:00
if (!is_dir_a(me,dirName))
dirName = dirname(dirName);
2018-02-22 08:18:45 +00:00
GLOBAL_cwd = malloc(strlen(dirName)+1);
strcpy(GLOBAL_cwd, dirName);
2018-06-25 13:44:09 +01:00
//__android_log_print(ANDROID_LOG_INFO, "YAPDroid", "chdir %s", GLOBAL_cwd);
2018-02-14 00:13:13 +00:00
return true;
2016-07-31 16:28:05 +01:00
}
#endif
VFS_t *
2017-11-29 13:47:57 +00:00
Yap_InitAssetManager(void) {
2016-07-31 16:28:05 +01:00
2017-11-21 15:44:43 +00:00
#if __ANDROID__
2016-07-31 16:28:05 +01:00
VFS_t *me;
2017-11-29 13:47:57 +00:00
/* init standard VFS */
me = (VFS_t *) Yap_AllocCodeSpace(sizeof(struct vfs));
me->name = "/assets";
2018-02-14 14:17:57 +00:00
me->vflags = VFS_CAN_EXEC | VFS_CAN_SEEK | VFS_CAN_READ |
2017-11-29 13:47:57 +00:00
VFS_HAS_PREFIX; /// the main flags describing the operation of the Fs.
me->prefix = "/assets";
/** operations */
2018-02-14 00:13:13 +00:00
me->open = open_asset; /// open an object in this space
2017-11-29 13:47:57 +00:00
me->close = close_asset; /// close the object
me->get_char = getc_asset; /// get an octet to the stream
me->put_char = NULL; /// output an octet to the stream
me->seek = seek64; /// jump around the stream
me->opendir = opendir_a; /// open a directory object, if one exists
me->nextdir = readdir_a; /// open a directory object, if one exists
me->closedir = closedir_a; /// close access a directory object
me->stat = stat_a; /// obtain size, age, permissions of a file.
me->isdir = is_dir_a; /// obtain size, age, permissions of a file.
me->exists = exists_a; /// obtain size, age, permissions of a file.
me->chdir = set_cwd; /// chnage working directory.
me->enc = ENC_ISO_UTF8; /// how the file is encoded.
me->parsers = NULL; /// a set of parsers that can read the stream and generate a term
me->writers = NULL;
2018-02-22 08:18:45 +00:00
GLOBAL_cwd = NULL;
2017-11-29 13:47:57 +00:00
LOCK(BGL);
me->next = GLOBAL_VFS;
GLOBAL_VFS = me;
return me;
UNLOCK(BGL);
return me;
2016-07-31 16:28:05 +01:00
#else
return NULL;
#endif
}