/* quakefs.h quake virtual filesystem definitions Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 1999,2000 contributors of the QuakeForge project Please see the file "AUTHORS" for a list of contributors This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to: Free Software Foundation, Inc. 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA */ #ifndef __QF_quakefs_h #define __QF_quakefs_h /** \defgroup quakefs Quake Filesystem \ingroup utils */ ///@{ #include "QF/qtypes.h" #include "QF/quakeio.h" //============================================================================ /** Simple list for file searches. */ typedef struct filelist_s { char **list; ///< the actual list of files int count; ///< the number of files in the list int size; ///< the number of files that can be in the ///< list before reallocation is required. } filelist_t; /** Cached information about the current game directory. \see \ref dirconf. */ typedef struct gamedir_s { const char *name; ///< the tag name built from game and gamedir const char *gamedir; ///< the actual game dir const char *path; ///< colon separated list of search paths const char *gamecode; ///< name of file to load for gamecode const char *hudtype; ///< name of the hud type struct { const char *def; ///< directory to which to write other files const char *skins; ///< directory to which to write skins const char *models; ///< directory to which to write models const char *sound; ///< directory to which to write sounds const char *maps; ///< directory to which to write maps const char *shots; ///< directory to which to write screenshots } dir; } gamedir_t; typedef struct vpath_s vpath_t; typedef struct findfile_s { const vpath_t *vpath; ///< vpath in which file was found qboolean in_pak; ///< if true, path refers to a pak file rather ///< than a directory const char *realname; ///< the name of the file as found (may have ///< .gz appended, or .ogg substituded for ///< .wav) does not include the path } findfile_t; /** Cached information about the current game directory. \see \ref dirconf. */ extern gamedir_t *qfs_gamedir; /** Function type of callback called on gamedir change. \param phase 0 = before Cache_Flush(), 1 = after Cache_Flush() */ typedef void gamedir_callback_t (int phase, void *data); /** Base of the QFS user directory tree. The QFS functions, except for QFS_FOpenFile() and _QFS_FOpenFile(), will never access a file outside of this tree. Set via the \c fs_userpath directory. */ extern const char *qfs_userpath; /** Gives information about the last file opened by the FOpenFile functions. Set by QFS_FOpenFile() and _QFS_FOpenFile(). */ extern findfile_t qfs_foundfile; /** The size of the file found via QFS_FOpenFile() or _QFS_FOpenFile(). Set by QFS_FOpenFile() and _QFS_FOpenFile(). */ extern int qfs_filesize; struct cache_user_s; struct dstring_s; struct memhunk_s; /** Initialize the Quake Filesystem. This function initializes the \c fs_sharepath, \c fs_userpath and \c fs_dirconf Cvars. It then loads the \ref dirconf and parses the \c -game command line option. \param hunk Memory pool to use for hunk-based allocations. \param game The game type used for searching the directory configuration. Currently, this is \"qw\" for quakeworld clients and servers, and one of \"nq\", \"hexen\", \"rogue\" or \"abyss\" for the netquake clients and servers. */ void QFS_Init (struct memhunk_s *hunk, const char *game); /** Change the current game directory. The configuration for the game directory is taken from \ref dirconf. Sets the fields in ::qfs_gamedir. Can be called at any time (and is, by the quakeworld clients and servers). \param gamedir The directory to which the game directory will be set. */ void QFS_Gamedir (const char *gamedir); /** Search for a file in the quake file-system. The search will begin in the \a start vpath and end in the \a end vpath. If \a start is null, the search will begin in the vpath specified by qfs_vpaths (ie, the first directory in the \c Path attribute (\ref dirconf)). If \a end is null, the search will continue to the end of the list of vpaths. If \a start and \a end are the same (and non-null), then only the one vpath will be searched. \note All search paths in a vpath will be searched. This keeps \QF's directory system transparent. \note It is a fatal error for \a end to be non-null but not in the list of vpaths. \warning The returned pointer is to a static instance of findfile_t and thus will be overwritten on the next call to any of the search functions (QFS_FindFile, QFS_FOpenFile, _QFS_FOpenFile) \param fname The name of the file to be searched for. \param start The first vpath (gamedir) to search. \param end The last vpath (gamedir) to search. \return Pointer to the findfile_t record indicating the location of the file, or null if the file was not found. */ findfile_t *QFS_FindFile (const char *fname, const vpath_t *start, const vpath_t *end); /** Open a file from within the user directory. If \a path attempts to leave the user directory, this function sets errno to EACCESS and returns NULL. If \a mode indicates a write operation, then this function will make sure that any directories leading to the file exist. \param path Path name of file to open, relative to ::qfs_userpath. \param mode Mode in which to open the file. Passed through as-is to Qopen (). \return The file handle as returned by Qopen or NULL on error. \note This function cannot be used to access files within a pak file. For pak file support, use QFS_FOpenFile(). */ QFile *QFS_Open (const char *path, const char *mode); /** Open a file for writing. This is a convenience wrapper for QFS_Open(). If \a zip is true, then the file will be written uzing gzip compression if QuakeForge was built with zlib support, otherwise the file will be written uncompressed. \param path Path name of file to open, relative to ::qfs_userpath. \param zip Compression control. \return The file handle as returned by Qopen or NULL on error. */ QFile *QFS_WOpen (const char *path, int zip); /** Write a block of data to a file. This is a convenience wrapper for QFS_Open(). \param filename Path name of file to open, relative to ::qfs_userpath. \param data Pointer to the block of data to be written. \param len The size of the block of data, in bytes. \note If an error occurs, this function will call Sys_Error(), aborting the program. */ void QFS_WriteFile (const char *filename, const void *data, int len); QFile *_QFS_VOpenFile (const char *filename, int zip, const vpath_t *start, const vpath_t *end); QFile *QFS_VOpenFile (const char *filename, const vpath_t *start, const vpath_t *end); /** Open a file for reading. The file will be searched for through all the subdirectories given in the \c Path attribute (\ref dirconf). For each directory in \c Path, this function will check \c \${fs_userpath}/${dir} then \${fs_sharepath}/${dir}. In each location, pak files are checked before external files. pak files will be searched in reverse order (pak10.pak, pak9.pak, ... pak2.pak,pak1.pak,pak0.pak). However, any file ending in .pak will be checked whether it is a pak file. Does name mangling for files with .gz extention and .wav-.ogg substitution. \param filename The name of the file to open. \param zip If true and the file has been compressed with gzip, the file will be opened such that it decompresses on the fly. Otherwise, the file will be read as-is. \return The file handle or NULL if there is an error. */ QFile *_QFS_FOpenFile (const char *filename, int zip); /** Open a file for reading. This is a convenience wrapper for _QFS_FOpenFile(). The file will always be opened with decompression enabled. See the documentation for _QFS_FOpenFile() for more details. \param filename The name of the file to open. \return The file handle pointer, or NULL if there is an error. */ QFile *QFS_FOpenFile (const char *filename); /** Load a file into memory. The file will be loaded into memory allocated from the location indicated by \a usehunk. \param file The handle of the file to load. \param usehunk The location from which to allocate memory for the file's data. Use 0. \return Pointer to the file's data, or NULL on error. \todo remove \a usehunk */ byte *QFS_LoadFile (QFile *file, int usehunk); /** Load a file into memeory. The file is loaded into memory allocated from the hunk. */ byte *QFS_LoadHunkFile (QFile *file); /** Load a file into memeory. This is a wrapper for QFS_LoadFile(). \deprecated This should go away soon. */ void QFS_LoadCacheFile (QFile *file, struct cache_user_s *cu); /** Rename a file. \param old_path The file to rename. \param new_path The new name for the file. \return 0 for success, -1 for failure. \note The file and destination must both be within \c qfs_userpath. */ int QFS_Rename (const char *old_path, const char *new_path); /** Delete a file. \param path The file to delete. \return 0 for success, -1 for failure. \note The file must be within \c qfs_userpath. */ int QFS_Remove (const char *path); /** Find available filename. The filename will be of the form \c prefixXXXX.ext where \c XXXX is a zero padded number from 0 to 9999. Should there already be 10000 files of such a pattern, then extra digits will be added. \param filename This will be set to the available filename. \param prefix The part of the filename preceeding the numers. \param ext The extension to add to the filename. \return NULL for failure (with an error message in \a filename) or a quakeio file handle. \note \a prefix is relative to \c qfc_userpath, as is the generated filename. */ QFile *QFS_NextFile (struct dstring_s *filename, const char *prefix, const char *ext); /** Extract the non-extension part of the file name from the path. \param in The path from which the name will be extracted. \return The extracted name. \note It is the caller's responsibility to free the extracted name. */ char *QFS_FileBase (const char *in); /** Set the file extention if not already present. If the file already has an extension, do nothing. \param path The path to which the extension will be added. \param extension The extension to add. */ void QFS_DefaultExtension (struct dstring_s *path, const char *extension); /** Set the file extention. If the file already has an extension, it will be replaced. \param path The path to which the extension will be set. \param extension The extension to set. */ void QFS_SetExtension (struct dstring_s *path, const char *extension); /** Remove any extension from the path. \param in The path from which to strip the extension. \param out The destination of the stripped path. May be the same as \a in. \note No size checking is done on \a out. It use the caller's responsibility to ensure out is large enough to hold the stripped path. However, the stripped path will never be longer than the original path. */ void QFS_StripExtension (const char *in, char *out); /** Create a canonical path. Convert all \c \\ to \c /, remove all \c . elements from the path and resolve all \c foo/.. pairs. \param pth The path to make canonical \return The canonical path. \note It is the caller's responsibility to free the canonical path. */ char *QFS_CompressPath (const char *pth); /** Return a pointer to the start of the filename part of the path. \param pathname The path withing which to find the filename. \return Pointer to the beginning of the filename. This points inside \a pathname. */ const char *QFS_SkipPath (const char *pathname) __attribute__((pure)); /** Return a pointer to the start of the extention part of the path. \param in The path withing which to find the extention. \return Pointer to the beginning of the extention. This points inside \a in at all times. If the path has no extension, the returned pointer will point to the terminating nul of the path. */ const char *QFS_FileExtension (const char *in) __attribute__((pure)); /** Register a callback function for when the gamedir changes. The callbacks will be called in order of registration, in two passes. The first pass (\c phase is 0) is before the cache has been flushed. The second pass (\c phase is 1) is after the cache has been flushed. \param func The function to call every time the gamedir changes via QFS_Gamedir(). \param data Opaque data pointer passed to the callback. */ void QFS_GamedirCallback (gamedir_callback_t *func, void *data); /** Create a new file list. \return Pointer to the new file list. */ filelist_t *QFS_FilelistNew (void); /** Add a single file to the file list. If the extension of the file matches \a ext, it will be trimmed off the file name befor the file is added to the list. \param filelist The list to which the file is to be added. \param fname The file which is to be added to the file list. \param ext The extention to be stripped from the file. \todo Should the extension stripping be done by the caller? */ void QFS_FilelistAdd (filelist_t *filelist, const char *fname, const char *ext); /** Add files from the gamedir within the specified path. All files from the specified path in the gamedir with the given extension will be added to the list after possibly stripping their extension. \param list The list to which the files are to be added. \param path The path withing the gamedir from which files are to be added to the list. \param ext The extension of the files to be added. \param strip If true, the extension of the files will be stripped. \bug can escape the quake file system */ void QFS_FilelistFill (filelist_t *list, const char *path, const char *ext, int strip); /** Free a file list. \param list The list to be freed. */ void QFS_FilelistFree (filelist_t *list); ///@} #endif//__QF_quakefs_h