/************************************************************************* * * * 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 * @date Thu Nov 19 10:53:20 2015 * * @brief File Aliases * * */ #include #include "sysbits.h" // for native asset manager #include #if __ANDROID__ static AAssetManager * getMgr(struct vfs *me) { return me->priv[0].mgr; } void Java_pt_up_yap_app_YAPDroid_load(JNIEnv *env, jobject assetManager) { AAssetManager *mgr = AAssetManager_fromJava(env, assetManager); if (mgr == NULL) { return; } VFS_t *me = GLOBAL_VFS; while ( strcmp(me->name, "/assets") == 0) me = me->next; me->priv[0].mgr = mgr; } static bool open_asset(struct vfs *me, struct stream_desc *st, const char *fname, const char *io_mode) { AAssetManager *mgr; int mode; const void *buf; if (strstr(fname,"/assets") == fname) { // we're in mgr = getMgr(me); if (mgr == NULL) { return PlIOError(PERMISSION_ERROR_OPEN_SOURCE_SINK, TermNil, "asset manager", fname); } if (strchr(io_mode, 'w') || strchr(io_mode, 'a')) { return PlIOError(PERMISSION_ERROR_OPEN_SOURCE_SINK, TermNil, "%s: no writing but flags are %s", fname, io_mode); } if (strchr(io_mode, 'B')) mode = AASSET_MODE_BUFFER; else { mode = AASSET_MODE_UNKNOWN; } AAsset *a = AAssetManager_open(mgr , fname, mode); // try not to use it as an asset off64_t sz = AAsset_getLength64(a), sz0 = 0; int fd; if ((fd = AAsset_openFileDescriptor64(a, &sz0, &sz)) >= 0) { // can use it as red-only file st->file = fdopen( fd, "r"); st->vfs = me; st->vfs_handle = a; return true; } else if ((buf = AAsset_getBuffer(a)) ) { // copy to memory bool rc = Yap_set_stream_to_buf(st, buf, sz); AAsset_close(a); return rc; } // should be done, but if not st->vfs_handle = a; st->vfs = me; return true; } if (me->next) { return me->next->open(me->next, st, fname, io_mode); } return NULL; } static bool close_asset(struct stream_desc *st) { AAsset_close(st->vfs_handle); return true; } static int64_t seek64(struct stream_desc *st, int64_t offset, int whence) { return AAsset_seek64(st->vfs_handle, offset, whence); } static int getc_asset(struct stream_desc *st) { int ch; if ( AAsset_read (st->vfs_handle, &ch, 1) ) return ch; return -1; } static void *opendir_a(struct vfs *me, const char *dirName) { return (void *)AAssetManager_openDir (getMgr(me), dirName); } static const char *readdir_a(void *dirHandle) { return AAssetDir_getNextFileName ((AAssetDir *)dirHandle); } static bool closedir_a(void *dirHandle) { AAssetDir_close ((AAssetDir *)dirHandle); return true; } static bool stat_a(struct vfs *me, const char *fname, vfs_stat *out) { struct stat64 bf; if (stat64( "/assets", &bf)) { out->st_dev = bf.st_dev; out->st_uid = bf.st_uid; out->st_gid = bf.st_gid; memcpy(&out->st_atimespec, (const void *)&out->st_atimespec, sizeof(struct timespec)); memcpy(&out->st_mtimespec,(const void *) &out->st_mtimespec, sizeof(struct timespec)); memcpy(&out->st_ctimespec, (const void *)&out->st_ctimespec, sizeof(struct timespec)); memcpy(&out->st_birthtimespec, (const void *)&out->st_birthtimespec, sizeof(struct timespec)); } AAssetManager *mgr = getMgr(me); AAsset *a = AAssetManager_open(mgr , fname, AASSET_MODE_UNKNOWN); // try not to use it as an asset out->st_size = AAsset_getLength64(a); AAsset_close(a); return true; } static bool is_dir_a(struct vfs *me, const char *dirName) { bool rc; // try not to use it as an asset AAssetDir *d = AAssetManager_openDir (getMgr(me), dirName); if (d == NULL) return false; rc = (AAssetDir_getNextFileName(d) != NULL); AAssetDir_close(d); return rc; } static bool exists_a(struct vfs *me, const char *dirName) { // try not to use it as an asset AAsset *d = AAssetManager_open (getMgr(me), dirName, AASSET_MODE_UNKNOWN); if (d == NULL) return false; AAsset_close(d); return true; } static bool set_cwd (struct vfs *me, const char *dirName) { chdir("/assets"); if (me->virtual_cwd) free(me->virtual_cwd); me->virtual_cwd = malloc( sizeof(dirName) + 1 ); return me!= NULL; } #endif /* create a new alias arg for stream sno */ VFS_t * Yap_InitAssetManager(void) { #if __ANDROID__ VFS_t *me; /* init standard VFS */ me = (VFS_t *)Yap_AllocCodeSpace(sizeof(struct vfs)); me->name = "/assets"; me->vflags = VFS_CAN_EXEC|VFS_CAN_SEEK|VFS_HAS_PREFIX; /// the main flags describing the operation of the Fs. me->prefix = "/assets"; /** operations */ me->open = open_asset; /// open an object in this space me->close= close_asset; /// close the object me->get_char = getc_asset; /// get an octet to the stream me->putc = 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; LOCK(BGL); me-> next = GLOBAL_VFS; GLOBAL_VFS = me; return me; UNLOCK(BGL); return me; #else return NULL; #endif }