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;
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);
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
};
#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;
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);
{
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);
}
}
}
-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;
#endif
-#if !defined(__IPHONEOS__)
+#if !defined(__IPHONEOS__) && !defined(__native_client__)
#ifdef WIN32
// historical behavior...
*fs_basedir = 0;
*fs_userdir = 0;
+ *fs_cachedir = 0;
*fs_gamedir = 0;
+ *fs_gamecachedir = 0;
// -basedir <path>
// Overrides the system supplied base directory (under GAMENAME)
// 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)
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);
}
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.
}
+/*
+============
+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
{
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;
}