From d28cca785fb68805e038440f69065224eeabe842 Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Wed, 23 Sep 2015 10:42:20 -0400 Subject: [PATCH] More NaCl support. We need to emulate listdirectory(). --- filematch.c | 26 ++++++++++---- fs.c | 102 +++++++++++++++++++++++++++++++++++----------------- fs.h | 1 + makefile | 10 +++--- sys_sdl.c | 4 +-- zone.c | 2 ++ 6 files changed, 99 insertions(+), 46 deletions(-) diff --git a/filematch.c b/filematch.c index 754d362c..ae51599b 100644 --- a/filematch.c +++ b/filematch.c @@ -192,14 +192,24 @@ void listdirectory(stringlist_t *list, const char *basepath, const char *path) char fullpath[MAX_OSPATH]; DIR *dir; struct dirent *ent; - dpsnprintf(fullpath, sizeof(fullpath), "%s%s", basepath, *path ? path : "./"); - dir = opendir(fullpath); - if (!dir) + dpsnprintf(fullpath, sizeof(fullpath), "%s%s", basepath, path); #ifdef __native_client__ + // In NaCl, only html5fs supports readdir. And attempting to readdir a + // directory before opening a file in it will actually mark the + // directory as a file for httpfs, leading to files inside becoming + // inaccessible. So our only solution is to read text files as a virtual + // directory listing. Create using "ls > .ls.txt" in any httpfs + // directory you want to support. + if (strncmp(basepath, "/.", 2)) { char listpath[MAX_OSPATH]; + qfile_t *listfile; dpsnprintf(listpath, sizeof(listpath), "%s.ls.txt", fullpath); - char *buf = (char *) FS_LoadFile(listpath, tempmempool, true, NULL); + listfile = FS_SysOpen(listpath, "rb", false); + if (!listfile) + return; + char *buf = (char *) FS_LoadQFile(listfile, tempmempool, true, NULL); + FS_Close(listfile); if (!buf) return; char *p = buf; @@ -209,14 +219,18 @@ void listdirectory(stringlist_t *list, const char *basepath, const char *path) if (q == NULL) break; *q = 0; + Con_Printf("Got file: %s\n", p); adddirentry(list, path, p); p = q + 1; } Mem_Free(buf); - } -#else return; + } #endif + dir = opendir(fullpath); + if (!dir) + return; + while ((ent = readdir(dir))) adddirentry(list, path, ent->d_name); closedir(dir); diff --git a/fs.c b/fs.c index e682f6fa..550503cb 100644 --- a/fs.c +++ b/fs.c @@ -226,7 +226,7 @@ struct qfile_s const unsigned char *data; ///< For data files. - const char *filename; ///< Kept around for QFILE_FLAG_REMOVE, unused otherwise + const char *filename; ///< Kept around for QFILE_FLAG_REMOVE and logging, unused otherwise }; @@ -339,7 +339,11 @@ const char *const fs_checkgamedir_missing = "missing"; #define MAX_FILES_IN_PACK 65536 char fs_userdir[MAX_OSPATH]; +char fs_cachedir[MAX_OSPATH]; + char fs_gamedir[MAX_OSPATH]; +char fs_gamecachedir[MAX_OSPATH]; + char fs_basedir[MAX_OSPATH]; static pack_t *fs_selfpack = NULL; @@ -1230,13 +1234,16 @@ Sets fs_gamedir, adds the directory to the head of the path, then loads and adds pak1.pak pak2.pak ... ================ */ -static void FS_AddGameDirectory (const char *dir) +static void FS_AddGameDirectory (const char *dir, qboolean iscache) { int i; stringlist_t list; searchpath_t *search; - strlcpy (fs_gamedir, dir, sizeof (fs_gamedir)); + if (iscache) + strlcpy (fs_gamedir, dir, sizeof (fs_gamedir)); + else + strlcpy (fs_gamecachedir, dir, sizeof (fs_gamedir)); stringlistinit(&list); listdirectory(&list, "", dir); @@ -1280,10 +1287,12 @@ static void FS_AddGameHierarchy (const char *dir) { char vabuf[1024]; // Add the common game directory - FS_AddGameDirectory (va(vabuf, sizeof(vabuf), "%s%s/", fs_basedir, dir)); + FS_AddGameDirectory (va(vabuf, sizeof(vabuf), "%s%s/", fs_basedir, dir), false); + if (*fs_cachedir) + FS_AddGameDirectory(va(vabuf, sizeof(vabuf), "%s%s/", fs_cachedir, dir), true); if (*fs_userdir) - FS_AddGameDirectory(va(vabuf, sizeof(vabuf), "%s%s/", fs_userdir, dir)); + FS_AddGameDirectory(va(vabuf, sizeof(vabuf), "%s%s/", fs_userdir, dir), false); } @@ -1779,14 +1788,26 @@ void FS_Init_SelfPack (void) } } -static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t userdirsize) +static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t userdirsize, char *cachedir, size_t cachedirsize) { + *userdir = 0; + *cachedir = 0; + #if defined(__IPHONEOS__) if (userdirmode == USERDIRMODE_HOME) { // fs_basedir is "" by default, to utilize this you can simply add your gamedir to the Resources in xcode // fs_userdir stores configurations to the Documents folder of the app - strlcpy(userdir, "../Documents/", MAX_OSPATH); + strlcpy(userdir, "../Documents/", userdirsize); + return 1; + } + return -1; + +#elif defined(__native_client__) + if (userdirmode == USERDIRMODE_HOME) + { + dpsnprintf(userdir, userdirsize, "/.config/%s/", gameuserdirname); + dpsnprintf(cachedir, cachedirsize, "/.cache/%s/", gameuserdirname); return 1; } return -1; @@ -1915,7 +1936,7 @@ static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t use #endif -#if !defined(__IPHONEOS__) +#if !defined(__IPHONEOS__) && !defined(__native_client__) #ifdef WIN32 // historical behavior... @@ -1962,7 +1983,9 @@ void FS_Init (void) *fs_basedir = 0; *fs_userdir = 0; + *fs_cachedir = 0; *fs_gamedir = 0; + *fs_gamecachedir = 0; // -basedir // Overrides the system supplied base directory (under GAMENAME) @@ -2043,7 +2066,7 @@ void FS_Init (void) // gather the status of the possible userdirs for (dirmode = 0;dirmode < USERDIRMODE_COUNT;dirmode++) { - userdirstatus[dirmode] = FS_ChooseUserDir((userdirmode_t)dirmode, fs_userdir, sizeof(fs_userdir)); + userdirstatus[dirmode] = FS_ChooseUserDir((userdirmode_t)dirmode, fs_userdir, sizeof(fs_userdir), fs_cachedir, sizeof(fs_cachedir)); if (userdirstatus[dirmode] == 1) Con_DPrintf("userdir %i = %s (writable)\n", dirmode, fs_userdir); else if (userdirstatus[dirmode] == 0) @@ -2065,7 +2088,7 @@ void FS_Init (void) if (userdirstatus[dirmode] >= 0) break; // and finally, we picked one... - FS_ChooseUserDir((userdirmode_t)dirmode, fs_userdir, sizeof(fs_userdir)); + FS_ChooseUserDir((userdirmode_t)dirmode, fs_userdir, sizeof(fs_userdir), fs_cachedir, sizeof(fs_cachedir)); Con_DPrintf("userdir %i is the winner\n", dirmode); } @@ -2642,7 +2665,10 @@ qfile_t* FS_OpenRealFile (const char* filepath, const char* mode, qboolean quiet return NULL; } - dpsnprintf (real_path, sizeof (real_path), "%s/%s", fs_gamedir, filepath); // this is never a vpack + if (!strncmp(filepath, "dlcache/", 8)) + dpsnprintf (real_path, sizeof (real_path), "%s/%s", fs_gamecachedir, filepath); // this is never a vpack + else + dpsnprintf (real_path, sizeof (real_path), "%s/%s", fs_gamedir, filepath); // this is never a vpack // If the file is opened in "write", "append", or "read/write" mode, // create directories up to the file. @@ -3226,6 +3252,31 @@ void FS_Purge (qfile_t* file) } +/* +============ +FS_LoadQFile + +Loads a file content from a qfile_t. +============ +*/ +unsigned char *FS_LoadQFile (qfile_t *file, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer) +{ + unsigned char *buf; + fs_offset_t filesize = file->real_length; + if(filesize < 0) + { + Con_Printf("FS_LoadQFile(\"%s\", pool, %s, filesizepointer): trying to open a non-regular file\n", file->filename, quiet ? "true" : "false"); + return NULL; + } + buf = (unsigned char *)Mem_Alloc (pool, filesize + 1); + buf[filesize] = '\0'; + FS_Read (file, buf, filesize); + if (filesizepointer) + *filesizepointer = filesize; + return buf; +} + + /* ============ FS_LoadFile @@ -3238,29 +3289,14 @@ unsigned char *FS_LoadFile (const char *path, mempool_t *pool, qboolean quiet, f { qfile_t *file; unsigned char *buf = NULL; - fs_offset_t filesize = 0; - file = FS_OpenVirtualFile(path, quiet); - if (file) - { - filesize = file->real_length; - if(filesize < 0) - { - Con_Printf("FS_LoadFile(\"%s\", pool, %s, filesizepointer): trying to open a non-regular file\n", path, quiet ? "true" : "false"); - FS_Close(file); - return NULL; - } - - buf = (unsigned char *)Mem_Alloc (pool, filesize + 1); - buf[filesize] = '\0'; - FS_Read (file, buf, filesize); - FS_Close (file); - if (developer_loadfile.integer) - Con_Printf("loaded file \"%s\" (%u bytes)\n", path, (unsigned int)filesize); - } - - if (filesizepointer) - *filesizepointer = filesize; + if (!file) + return NULL; + buf = FS_LoadQFile(file, pool, quiet, filesizepointer); + if (buf == NULL) + return NULL; + if (developer_loadfile.integer) + Con_Printf("loaded file \"%s\"\n", path); return buf; } diff --git a/fs.h b/fs.h index 657f6440..e3dbfa10 100644 --- a/fs.h +++ b/fs.h @@ -110,6 +110,7 @@ fssearch_t; fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet); void FS_FreeSearch(fssearch_t *search); +unsigned char *FS_LoadQFile (qfile_t *file, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer); unsigned char *FS_LoadFile (const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer); qboolean FS_WriteFileInBlocks (const char *filename, const void *const *data, const fs_offset_t *len, size_t count); qboolean FS_WriteFile (const char *filename, const void *data, fs_offset_t len); diff --git a/makefile b/makefile index 97f428b1..9d74a8d8 100644 --- a/makefile +++ b/makefile @@ -125,9 +125,9 @@ ifeq ($(DP_MAKE_TARGET), pnacl) LDFLAGS_CL=BRLOGENSHFEGLE # TODO is there a better way to get this path? - LDFLAGS_SV=$(LDFLAGS_UNIXCOMMON) -L$(HOME)/nacl_sdk/pepper_44/lib/pnacl/Release + LDFLAGS_SV=$(LDFLAGS_UNIXCOMMON) -L$(HOME)/nacl_sdk/pepper_44/lib/pnacl/Release -L$(HOME)/nacl_sdk/pepper_44/ports/lib/newlib_pnacl/Release # TODO is there a better way to get this path? - LDFLAGS_SDL=$(LDFLAGS_UNIXSDL) -L$(HOME)/nacl_sdk/pepper_44/lib/pnacl/Release + LDFLAGS_SDL=$(LDFLAGS_UNIXCOMMON) $(LDFLAGS_UNIXSDL) -L$(HOME)/nacl_sdk/pepper_44/lib/pnacl/Release -L$(HOME)/nacl_sdk/pepper_44/ports/lib/newlib_pnacl/Release SDLCONFIG_CFLAGS=$(SDLCONFIG_UNIXCFLAGS) SDLCONFIG_LIBS=$(SDLCONFIG_STATICLIBS) @@ -141,15 +141,15 @@ ifeq ($(DP_MAKE_TARGET), pnacl) EXE_SVNEXUIZ=$(EXE_UNIXSVNEXUIZ) EXE_SDLNEXUIZ=$(EXE_UNIXSDLNEXUIZ) - DP_LINK_ZLIB?=dlopen - DP_LINK_JPEG?=dlopen + DP_LINK_ZLIB?=shared + DP_LINK_JPEG?=shared DP_LINK_ODE?=dlopen DP_LINK_CRYPTO?=dlopen DP_LINK_CRYPTO_RIJNDAEL?=dlopen # TODO is there a better way to get this path? # TODO is net/if.h really missing? - CFLAGS_EXTRA=-I$(HOME)/nacl_sdk/pepper_44/include -I$(HOME)/nacl_sdk/pepper_44/include/pnacl $(SDLCONFIG_CFLAGS) -DNOSUPPORTIPV6 + CFLAGS_EXTRA=-I$(HOME)/nacl_sdk/pepper_44/include -I$(HOME)/nacl_sdk/pepper_44/include/pnacl -I$(HOME)/nacl_sdk/pepper_44/ports/include $(SDLCONFIG_CFLAGS) -DNOSUPPORTIPV6 CFLAGS_SSE= CFLAGS_SSE2= diff --git a/sys_sdl.c b/sys_sdl.c index 54651b44..9d261de4 100644 --- a/sys_sdl.c +++ b/sys_sdl.c @@ -206,8 +206,8 @@ void Sys_InitConsole (void) static void NaCl_Init(void) { mount("", "/dev", "dev", 0, ""); - mount("", "/.persistentfs", "html5fs", 0, "type=PERSISTENT,expected_size=8388608"); - mount("", "/.tempfs", "html5fs", 0, "type=TEMPORARY,expected_size=1073741824"); + mount("", "/.config", "html5fs", 0, "type=PERSISTENT,expected_size=8388608"); + mount("", "/.cache", "html5fs", 0, "type=TEMPORARY,expected_size=1073741824"); int fd = open("/dev/console0", O_WRONLY, 0644); outfd = fd; } diff --git a/zone.c b/zone.c index fe80693c..b7cc5b8f 100644 --- a/zone.c +++ b/zone.c @@ -953,6 +953,7 @@ void Memory_Init_Commands (void) // first guess Cvar_SetValueQuick(&sys_memsize_virtual, (sizeof(void*) == 4) ? 2048 : 268435456); // then improve +#ifndef __native_client__ { // Linux, and BSD with linprocfs mounted FILE *f = fopen("/proc/meminfo", "r"); @@ -980,6 +981,7 @@ void Memory_Init_Commands (void) fclose(f); } } +#endif } #endif } -- 2.39.2