45#define MODS_DIR "mods"
50 Sys_Error(
"Filesystem call made without initialization");
58 if (
f->f !=
nullptr) {
72 return search->filename;
94 const int pos = ftell(
f->f);
97 const int end = ftell(
f->f);
104 Sys_Error(
"Couldn't get size of %s",
f->name);
123 for (
char* ofs = pathCopy + 1; *ofs; ofs++) {
166 file->
z = file->
f =
nullptr;
186 if (!strncmp(
filename, link->from, link->fromlength)) {
191 Com_Printf(
"linked file could not be opened: %s\n", netpath);
201 const pack_t* pak = search->pack;
238#define PK3_SEEK_BUFFER_SIZE 65536
253 Sys_Error(
"Negative offsets and FS_SEEK_END not implemented "
254 "for FS_Seek on pk3 file contents\n");
288 return fseek(
f->f,
offset, _origin);
311#define MAX_READ 0x10000
329 byte*
buf = (
byte*) buffer;
334 Sys_Error(
"FS_Read (zipfile): -1 bytes read");
342 int block = remaining;
345 const int read = fread(
buf, 1, block,
f->f);
348 if (read != block && feof(
f->f))
349 return (
len - remaining + read);
355 else if (failOnEmptyRead)
358 return len - remaining;
435 Com_Printf(
"Could not load '%s'\n", packfile);
440 for (
i = 0;
i <
gi.number_entry;
i++) {
441 err =
unzGetCurrentFileInfo(uf, &file_info, filenameInZip,
sizeof(filenameInZip),
nullptr, 0,
nullptr, 0);
458 for (
i = 0;
i <
gi.number_entry;
i++) {
459 err =
unzGetCurrentFileInfo(uf, &file_info, filenameInZip,
sizeof(filenameInZip),
nullptr, 0,
nullptr, 0);
469 pack->
files = newfiles;
474 Com_Printf(
"Added packfile %s (%li files)\n", packfile,
gi.number_entry);
478 Com_Printf(
"Pack file type %s unrecognized\n", extension);
483#define MAX_PACKFILES 1024
486 "pk3",
"zip",
nullptr
499 int pakfile_count = 0;
503 if (
Q_streq(search->filename, dir))
505 if (write && search->write) {
506 Com_Printf(
"change writing directory to %s\n", dir);
507 search->write =
false;
513 for (
char const*
const* extList =
pakFileExt; *extList; ++extList) {
514 Com_sprintf(pattern,
sizeof(pattern),
"%s/*.%s", dir, *extList);
516 if (dirnames !=
nullptr) {
517 for (
int i = 0;
i < ndirs - 1;
i++) {
518 if (strrchr(dirnames[
i],
'/')) {
519 Q_strncpyz(pakfile_list[pakfile_count], dirnames[
i],
sizeof(pakfile_list[pakfile_count]));
535 for (
int i = 0;
i < pakfile_count;
i++) {
543 search->
write =
false;
551 search->
write = write;
570 if (s[strlen(s) - 1] !=
'.')
589 if (s[strlen(s) - 1] !=
'.') {
590 Q_strncpyz(tempList[nfiles], s,
sizeof(tempList[nfiles]));
603 for (
int i = 0;
i < nfiles;
i++) {
619 char* prev =
nullptr;
623 if (prev &&
Q_streq(prevpath, prev))
638#elif defined (__APPLE__) || defined (MACOSX)
645 Com_Printf(
"could not find the home directory\n");
660 Q_strcat(gdir,
sizeof(gdir),
"/%s", dir);
675 char const*
const append =
"/" MODS_DIR;
676 Q_strcat(gdir,
sizeof(gdir), append);
682 char const* searchpaths[] = {
694 for (
const char** path = searchpaths; *path; path++) {
695 const char* pattern = *path;
698 if (dirnames !=
nullptr) {
699 for (
int i = 0;
i < ndirs - 1;
i++) {
713static void FS_Mod_f (
void)
734 if (snprintf(
name,
sizeof(
name),
"%s/autoexec.cfg", s->filename)) {
753static void FS_Link_f (
void)
791static void FS_Dir_f (
void)
794 const char* path =
nullptr;
806 if (dirnames !=
nullptr) {
807 for (
int i = 0;
i < ndirs - 1;
i++) {
808 char const*
const slash = strrchr(dirnames[
i],
'/');
809 Com_Printf(
"%s\n", slash ? slash + 1 : dirnames[
i]);
819static void FS_List_f (
void)
824 Com_Printf(
"Show files for '%s'\n", wildcard);
834static void FS_Info_f (
void)
840 if (search->pack ==
nullptr)
841 Com_Printf(
"...path: '%s'\n", search->filename);
843 Com_Printf(
"...pakfile: '%s' (%i files)\n", search->pack->filename, search->pack->numfiles);
850static void FS_RestartFilesystem_f (
void)
864 {
"fs_restart", FS_RestartFilesystem_f,
"Reloads the file subsystem"},
865 {
"link", FS_Link_f,
"Create file links"},
866 {
"dir", FS_Dir_f,
"Show the filesystem contents per game dir - also supports wildcarding"},
867 {
"ls", FS_List_f,
"Show the filesystem contents"},
868 {
"fs_info", FS_Info_f,
"Show information about the virtual filesystem"},
869 {
"fs_mod", FS_Mod_f,
"Show or activate mods"},
871 {
nullptr,
nullptr,
nullptr}
874static void FS_RemoveCommands (
void)
880static void FS_InitCommandsAndCvars (
void)
892 Com_Printf(
"\n---- filesystem initialization -----\n");
905 Com_sprintf(path,
sizeof(path),
"./%s", fsGameDir);
915 FS_InitCommandsAndCvars();
928typedef struct listBlock_s {
975 *anchor = block->
next;
980 anchor = &block->
next;
1000 const char* ext = strrchr(files,
'.');
1001 const pack_t* pak = search->pack;
1002 size_t l = strlen(files);
1007 l -= (strlen(ext) + 1);
1013 const char* fileNameEntry = pak->
files[
i].
name;
1014 bool matchAlsoInSubDirs = (
findname[0] ==
'*' || !strncmp(fileNameEntry,
findname, l))
1015 && (ext[0] ==
'*' || strstr(fileNameEntry, ext));
1016 if (matchAlsoInSubDirs) {
1024 Com_FilePath(fileNameEntry, pathNameEntry,
sizeof(pathNameEntry));
1025 if (
Q_streq(pathNameEntry, pathName))
1033 }
else if (strstr(files,
"**")) {
1035 const char* wildcard = strstr(files,
"**");
1036 const size_t l = strlen(files) - strlen(wildcard);
1041 if (l > 0 &&
findname[l - 1] ==
'/')
1058 if (filenames !=
nullptr) {
1059 for (
int i = 0;
i < nfiles - 1;
i++) {
1087 if (files ==
nullptr) {
1106 Com_Printf(
"FS_NextFileFromFileList: Could not create filelist for %s\n", files);
1113 if (_block != block) {
1115 listEntry = block->
files;
1118 const char* file =
nullptr;
1120 file = (
const char*)listEntry->
data;
1121 listEntry = listEntry->
next;
1140 static byte* buffer =
nullptr;
1169 Com_Printf(
"FS_GetFileData: Could not create filelist for %s\n", files);
1176 fileList = block->
files;
1179 fileList = fileList->
next;
1186 strcpy(strrchr(
filename,
'/') + 1, (
const char*)fileList->
data);
1189 return (
const char*)buffer;
1201 static byte* lBuffer;
1202 static char headerType[
MAX_VAR];
1203 static char headerName[512];
1217 if (!
Q_streq(files, lastList)) {
1219 Q_strncpyz(lastList, files,
sizeof(lastList));
1232 lFile = block->
files;
1240 if (*token ==
'{') {
1245 Q_strncpyz(headerType, token,
sizeof(headerType));
1248 Q_strncpyz(headerName, token,
sizeof(headerName));
1255 lFile = lFile->
next;
1257 while (!lFile && lBlock) {
1259 for (lBlock = lBlock->
next; lBlock; lBlock = lBlock->
next) {
1261 lFile = lBlock->
files;
1279 strcpy(strrchr(
filename,
'/') + 1, (
const char*)lFile->
data);
1284 lFile = lFile->
next;
1287 *text = (
char*)lBuffer;
1291 if (
Q_strneq (*text,
"--!usr/bin/lua", 14)) {
1293 Q_strncpyz(headerName, (
const char*)lFile->
data,
sizeof(headerName));
1295 static char luaType[] =
"lua";
1298 }
else if (!lBuffer)
1322 const char* mapStr1 = *(
const char*
const*)map1;
1323 const char* mapStr2 = *(
const char*
const*)map2;
1326 if (mapStr1[0] ==
'+')
1328 if (mapStr2[0] ==
'+')
1356 FS_Read(header,
sizeof(header), &file);
1358 for (
int i = 0;
i < 2;
i++)
1378 const char* baseMapName =
nullptr;
1397 pack_t* pak = search->pack;
1400 baseMapName = strchr(pak->
files[
i].
name,
'/');
1403 baseMapName = strchr(baseMapName + 1,
'/');
1412 Com_Printf(
"FS_GetMaps: Max maps limit hit\n");
1417 Com_Printf(
"Could not allocate memory in FS_GetMaps\n");
1436 if (dirnames !=
nullptr) {
1437 for (
int i = 0;
i < ndirs - 1;
i++) {
1443 Com_Printf(
"FS_GetMaps: Max maps limit hit\n");
1448 Com_Printf(
"Could not allocate memory in FS_GetMaps\n");
1455 Com_Printf(
"invalid mapstatus: %i (%s)\n", status, dirnames[
i]);
1465 if (dirnames !=
nullptr) {
1466 for (
int i = 0;
i < ndirs - 1;
i++) {
1470 Com_Printf(
"FS_GetMaps: Max maps limit hit\n");
1475 Com_Printf(
"Could not allocate memory in FS_GetMaps\n");
1504 const int len = fprintf(
f->f,
"%s",
buf);
1518 const byte*
buf = (
const byte*) buffer;
1520 int remaining =
len;
1523 const int block = remaining;
1524 const int written = fwrite(
buf, 1, block,
f->f);
1534 if (written == -1) {
1539 remaining -= written;
1557 if (c !=
len || lencheck !=
len) {
1631 FS_RemoveCommands();
1645 if (gamedir !=
nullptr)
1646 Com_Printf(
"restarting with gamedir set to %s\n", gamedir);
1657 Sys_Error(
"Filesystem call made without initialization");
1659 Com_Printf(
"FS_CopyFile: copy %s to %s\n", fromOSPath, toOSPath);
1666 const int len = ftell(
f);
1683 Sys_Error(
"Short write in FS_CopyFile");
1695 Sys_Error(
"Filesystem call made without initialization");
1697 Com_Printf(
"FS_RemoveFile: remove %s\n", osPath);
1715 Sys_Error(
"Filesystem call made without initialization");
const char * Cmd_Argv(int arg)
Returns a given argument.
void Cmd_TableAddList(const cmdList_t *cmdList)
void Cbuf_Execute(void)
Pulls off terminated lines of text from the command buffer and sends them through Cmd_ExecuteString...
void Cmd_TableCheck(void)
Check both the functiontable and the associated hashtable for invalid entries.
int Cmd_Argc(void)
Return the number of arguments of the current command. "command parameter" will result in a argc of 2...
void Cbuf_AddText(const char *format,...)
Adds command text at the end of the buffer.
void Cmd_TableRemoveList(const cmdList_t *cmdList)
void Com_Printf(const char *const fmt,...)
memPool_t * com_fileSysPool
definitions common between client and server, but not game lib
const char * Cvar_GetString(const char *varName)
Returns the value of cvar as string.
Defined CONSTANTS (Macros are elsewhere).
static listBlock_t * fs_blocklist
int FS_Seek(qFILE *f, long offset, int origin)
Sets the file position of the given file.
const char * FS_GetFileData(const char *files)
Returns the buffer of a file.
void FS_CreatePath(const char *path)
Creates any directories needed to store the given filename.
int FS_Read2(void *buffer, int len, qFILE *f, bool failOnEmptyRead)
Read a file into a given buffer in memory.
static int CheckBSPFile(const char *filename)
Checks for valid BSP-file.
static void _AddToListBlock(linkedList_t **fl, const char *name, bool stripPath)
Add one name to the filelist.
const char * FS_NextPath(const char *prevpath)
Allows enumerating all of the directories in the search path.
static char const *const pakFileExt[]
static bool fs_mapsInstalledInit
int FS_Printf(qFILE *f, const char *msg,...)
Can print chunks for 1024 chars into a file.
#define PK3_SEEK_BUFFER_SIZE
void FS_InitFilesystem(bool writeToHomeDir)
void FS_RemoveFile(const char *osPath)
int FS_Write(const void *buffer, int len, qFILE *f)
Properly handles partial writes.
int FS_CheckFile(const char *fmt,...)
Just returns the filelength and -1 if the file wasn't found.
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
static searchpath_t * fs_searchpaths
void FS_CopyFile(const char *fromOSPath, const char *toOSPath)
Copy a fully specified file from one place to another.
char * FS_NextScriptHeader(const char *files, const char **name, const char **text)
void FS_FreeFile(void *buffer)
int FS_GetModList(linkedList_t **mods)
Searches and builds a list of mod directories.
const char * FS_NextFileFromFileList(const char *files)
Returns the next file that is found in the virtual filesystem identified by the given file pattern.
void FS_AddHomeAsGameDirectory(const char *dir, bool write)
int FS_WriteFile(const void *buffer, size_t len, const char *filename)
static int FS_MapDefSort(const void *map1, const void *map2)
void FS_RestartFilesystem(const char *gamedir)
Restart the filesystem (reload all pk3 files).
bool FS_RenameFile(const char *from, const char *to, bool relative)
Renames a file.
char ** FS_ListFiles(const char *findname, int *numfiles, unsigned musthave, unsigned canthave)
Builds a qsorted filelist.
int FS_FileLength(qFILE *f)
Returns the size of a given file or -1 if no file is opened.
void FS_CloseFile(qFILE *f)
Closes a file handle.
static bool FS_GetHomeDirectory(char *gdir, size_t length)
const char * FS_GetCwd(void)
Return current working dir.
int FS_Read(void *buffer, int len, qFILE *f)
void FS_Shutdown(void)
Cleanup function.
void FS_CreateOpenPipeFile(const char *filename, qFILE *f)
static filelink_t * fs_links
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
void FS_NormPath(char *path)
Convert operating systems path separators to ufo virtual filesystem separators (/).
static pack_t * FS_LoadPackFile(const char *packfile)
Takes an explicit (not game tree related) path to a pak file. Adding the files at the beginning of th...
void FS_GetMaps(bool reset)
File the fs_maps array with valid maps.
const char * FS_Gamedir(void)
Called to find where to write a file (savegames, etc).
void FS_AddGameDirectory(const char *dir, bool write)
Adds the directory to the head of the search path.
int FS_BuildFileList(const char *fileList)
Build a filelist.
static int fs_openedFiles
bool FS_FileExists(const char *filename,...)
Checks whether a file exists (not in virtual filesystem).
void FS_ExecAutoexec(void)
void Sys_Error(const char *error,...)
void LIST_AddStringSorted(linkedList_t **listDest, const char *data)
void LIST_AddString(linkedList_t **listDest, const char *data)
Adds an string to a new or to an already existing linked list. The string is copied here.
void LIST_Delete(linkedList_t **list)
int LIST_Count(const linkedList_t *list)
const linkedList_t * LIST_ContainsString(const linkedList_t *list, const char *string)
Searches for the first occurrence of a given string.
#define LIST_Foreach(list, type, var)
Iterates over a linked list, it's safe to delete the returned entry from the list while looping over ...
void _Mem_Free(void *ptr, const char *fileName, const int fileLine)
#define Mem_FreePool(pool)
#define Mem_PoolAllocTypeN(type, n, pool)
#define Mem_PoolStrDup(in, pool, tagNum)
#define Mem_PoolAllocType(type, pool)
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
void Com_SkipBlock(const char **text)
Skips a block of {} in our script files.
Shared parsing functions.
Header for various formats like pak, and model formats as well as bsp format.
QGL_EXTERN GLuint GLchar GLuint * len
QGL_EXTERN GLuint GLsizei GLsizei * length
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
#define Q_strvalid(string)
#define Q_strcasecmp(a, b)
#define Q_strneq(a, b, n)
char * Q_strlwr(char *str)
Converts a string to lowercase.
void Com_StripExtension(const char *in, char *out, const size_t size)
Removes the file extension from a filename.
const char * Com_SkipPath(const char *pathname)
Returns just the filename from a given path.
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
int Q_StringSort(const void *string1, const void *string2)
Compare two strings.
void Com_FilePath(const char *in, char *out, size_t size)
Returns the path up to, but not including the last /.
int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap)
Safe (null terminating) vsnprintf implementation.
const char * Com_GetExtension(const char *path)
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Links one file onto another - like a symlink.
struct listBlock_s * next
char filename[MAX_OSPATH]
struct searchpath_s * next
char filename[MAX_OSPATH]
char * Sys_Cwd(void)
Get current working dir.
void Sys_NormPath(char *path)
Normalize path (remove all \ ).
FILE * Sys_Fopen(const char *filename, const char *mode)
int Sys_Remove(const char *filename)
int Sys_Rename(const char *oldname, const char *newname)
char * Sys_GetHomeDirectory(void)
Returns the home environment variable (which hold the path of the user's homedir).
void Sys_ListFilteredFiles(const char *basedir, const char *subdirs, const char *filter, linkedList_t **list)
char * Sys_FindFirst(const char *path, unsigned musthave, unsigned canthave)
Opens the directory and returns the first file that matches our searchrules.
void Sys_Mkdir(const char *path)
void Sys_FindClose(void)
Closes the find handle.
void Sys_Mkfifo(const char *ospath, struct qFILE_s *f)
int Sys_Access(const char *filename, int mode)
char * Sys_FindNext(unsigned musthave, unsigned canthave)
Returns the next file of the already opened directory (Sys_FindFirst) that matches our search mask.
int ZEXPORT unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity)
unzFile ZEXPORT unzOpen(const char *path)
int ZEXPORT unzGoToFirstFile(unzFile file)
int ZEXPORT unzSetCurrentFileInfoPosition(unzFile file, unsigned long pos)
int ZEXPORT unzOpenCurrentFile(unzFile file)
int ZEXPORT unzGetCurrentFileInfoPosition(unzFile file, unsigned long *pos)
int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len)
int ZEXPORT unzCloseCurrentFile(unzFile file)
int ZEXPORT unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)
int ZEXPORT unzGoToNextFile(unzFile file)
int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info)
int ZEXPORT unzClose(unzFile file)
static char findname[MAX_OSPATH]