]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - fs.c
physics: fix and refactor unsticking
[xonotic/darkplaces.git] / fs.c
diff --git a/fs.c b/fs.c
index af62b898a3b2a330be6797f80ec34c2033bd91d3..e2afcf052ca4b89b8227b7fd1f4a30b277aefea3 100644 (file)
--- a/fs.c
+++ b/fs.c
@@ -171,7 +171,7 @@ static fs_offset_t WriteAll(const filedesc_t fd, const void *const buf, const si
 
 /** \page fs File System
 
-All of Quake's data access is through a hierchal file system, but the contents
+All of Quake's data access is through a hierarchical file system, the contents
 of the file system can be transparently merged from several sources.
 
 The "base directory" is the path to the directory holding the quake.exe and
@@ -183,9 +183,8 @@ directory is only used during filesystem initialization.
 The "game directory" is the first tree on the search path and directory that
 all generated files (savegames, screenshots, demos, config files) will be
 saved to.  This can be overridden with the "-game" command line parameter.
-The game directory can never be changed while quake is executing.  This is a
-precaution against having a malicious server instruct clients to write files
-over areas they shouldn't.
+If multiple "-game <gamedir>" args are passed the last one is the "primary"
+and files will be saved there, the rest are read-only.
 
 */
 
@@ -382,7 +381,7 @@ typedef struct pack_s
        char filename [MAX_OSPATH];
        char shortname [MAX_QPATH];
        filedesc_t handle;
-       int ignorecase;  ///< PK3 ignores case
+       qbool ignorecase;  ///< PK3 ignores case
        int numfiles;
        qbool vpack;
        qbool dlcache;
@@ -412,7 +411,7 @@ void FS_Dir_f(cmd_state_t *cmd);
 void FS_Ls_f(cmd_state_t *cmd);
 void FS_Which_f(cmd_state_t *cmd);
 
-static searchpath_t *FS_FindFile (const char *name, int* index, qbool quiet);
+static searchpath_t *FS_FindFile (const char *name, int *index, const char **canonicalname, qbool quiet);
 static packfile_t* FS_AddFileToPack (const char* name, pack_t* pack,
                                                                        fs_offset_t offset, fs_offset_t packsize,
                                                                        fs_offset_t realsize, int flags);
@@ -449,6 +448,7 @@ int fs_all_gamedirs_count = 0;
 
 cvar_t scr_screenshot_name = {CF_CLIENT | CF_PERSISTENT, "scr_screenshot_name","dp", "prefix name for saved screenshots (changes based on -game commandline, as well as which game mode is running; the date is encoded using strftime escapes)"};
 cvar_t fs_empty_files_in_pack_mark_deletions = {CF_CLIENT | CF_SERVER, "fs_empty_files_in_pack_mark_deletions", "0", "if enabled, empty files in a pak/pk3 count as not existing but cancel the search in further packs, effectively allowing patch pak/pk3 files to 'delete' files"};
+cvar_t fs_unload_dlcache = {CF_CLIENT, "fs_unload_dlcache", "1", "if enabled, unload dlcache's loaded pak/pk3 files when changing server and/or map WARNING: disabling unloading can cause servers to override assets of other servers, \"memory leaking\" by dlcache assets never unloading and many more issues"};
 cvar_t cvar_fs_gamedir = {CF_CLIENT | CF_SERVER | CF_READONLY | CF_PERSISTENT, "fs_gamedir", "", "the list of currently selected gamedirs (use the 'gamedir' command to change this)"};
 
 
@@ -863,7 +863,7 @@ static pack_t *FS_LoadPackPK3FromFD (const char *packfile, filedesc_t packhandle
        // Create a package structure in memory
        pack = (pack_t *)Mem_Alloc(fs_mempool, sizeof (pack_t));
        pack->ignorecase = true; // PK3 ignores case
-       strlcpy (pack->filename, packfile, sizeof (pack->filename));
+       dp_strlcpy (pack->filename, packfile, sizeof (pack->filename));
        pack->handle = packhandle;
        pack->numfiles = eocd.nbentries;
        pack->files = (packfile_t *)Mem_Alloc(fs_mempool, eocd.nbentries * sizeof(packfile_t));
@@ -981,7 +981,7 @@ static packfile_t* FS_AddFileToPack (const char* name, pack_t* pack,
        memmove (pfile + 1, pfile, (pack->numfiles - left) * sizeof (*pfile));
        pack->numfiles++;
 
-       strlcpy (pfile->name, name, sizeof (pfile->name));
+       dp_strlcpy (pfile->name, name, sizeof (pfile->name));
        pfile->offset = offset;
        pfile->packsize = packsize;
        pfile->realsize = realsize;
@@ -1139,7 +1139,7 @@ static pack_t *FS_LoadPackPAK (const char *packfile)
 
        pack = (pack_t *)Mem_Alloc(fs_mempool, sizeof (pack_t));
        pack->ignorecase = true; // PAK is sensitive in Quake1 but insensitive in Quake2
-       strlcpy (pack->filename, packfile, sizeof (pack->filename));
+       dp_strlcpy (pack->filename, packfile, sizeof (pack->filename));
        pack->handle = packhandle;
        pack->numfiles = 0;
        pack->files = (packfile_t *)Mem_Alloc(fs_mempool, numpackfiles * sizeof(packfile_t));
@@ -1175,7 +1175,7 @@ static pack_t *FS_LoadPackVirtual (const char *dirname)
        pack = (pack_t *)Mem_Alloc(fs_mempool, sizeof (pack_t));
        pack->vpack = true;
        pack->ignorecase = false;
-       strlcpy (pack->filename, dirname, sizeof(pack->filename));
+       dp_strlcpy (pack->filename, dirname, sizeof(pack->filename));
        pack->handle = FILEDESC_INVALID;
        pack->numfiles = -1;
        pack->files = NULL;
@@ -1231,7 +1231,7 @@ static qbool FS_AddPack_Fullpath(const char *pakfile, const char *shortname, qbo
 
        if(pak)
        {
-               strlcpy(pak->shortname, shortname, sizeof(pak->shortname));
+               dp_strlcpy(pak->shortname, shortname, sizeof(pak->shortname));
 
                //Con_DPrintf("  Registered pack with short name %s\n", shortname);
                if(keep_plain_dirs)
@@ -1323,7 +1323,7 @@ qbool FS_AddPack(const char *pakfile, qbool *already_loaded, qbool keep_plain_di
                *already_loaded = false;
 
        // then find the real name...
-       search = FS_FindFile(pakfile, &index, true);
+       search = FS_FindFile(pakfile, &index, NULL, true);
        if(!search || search->pack)
        {
                Con_Printf("could not find pak \"%s\"\n", pakfile);
@@ -1350,7 +1350,7 @@ static void FS_AddGameDirectory (const char *dir)
        stringlist_t list;
        searchpath_t *search;
 
-       strlcpy (fs_gamedir, dir, sizeof (fs_gamedir));
+       dp_strlcpy (fs_gamedir, dir, sizeof (fs_gamedir));
 
        stringlistinit(&list);
        listdirectory(&list, "", dir);
@@ -1380,7 +1380,7 @@ static void FS_AddGameDirectory (const char *dir)
        // Add the directory to the search path
        // (unpacked files have the priority over packed files)
        search = (searchpath_t *)Mem_Alloc(fs_mempool, sizeof(searchpath_t));
-       strlcpy (search->filename, dir, sizeof (search->filename));
+       dp_strlcpy (search->filename, dir, sizeof (search->filename));
        search->next = fs_searchpaths;
        fs_searchpaths = search;
 }
@@ -1493,6 +1493,9 @@ void FS_UnloadPacks_dlcache(void)
 {
        searchpath_t *search = fs_searchpaths, *searchprev = fs_searchpaths, *searchnext;
 
+       if (!fs_unload_dlcache.integer)
+               return;
+
        while (search)
        {
                searchnext = search->next;
@@ -1559,9 +1562,9 @@ void FS_Rescan (void)
        FS_AddGameHierarchy (gamedirname1);
        // update the com_modname (used for server info)
        if (gamedirname2 && gamedirname2[0])
-               strlcpy(com_modname, gamedirname2, sizeof(com_modname));
+               dp_strlcpy(com_modname, gamedirname2, sizeof(com_modname));
        else
-               strlcpy(com_modname, gamedirname1, sizeof(com_modname));
+               dp_strlcpy(com_modname, gamedirname1, sizeof(com_modname));
 
        // add the game-specific path, if any
        // (only used for mission packs and the like, which should set fs_modified)
@@ -1581,11 +1584,11 @@ void FS_Rescan (void)
                fs_modified = true;
                FS_AddGameHierarchy (fs_gamedirs[i]);
                // update the com_modname (used server info)
-               strlcpy (com_modname, fs_gamedirs[i], sizeof (com_modname));
+               dp_strlcpy (com_modname, fs_gamedirs[i], sizeof (com_modname));
                if(i)
-                       strlcat(gamedirbuf, va(vabuf, sizeof(vabuf), " %s", fs_gamedirs[i]), sizeof(gamedirbuf));
+                       dp_strlcat(gamedirbuf, va(vabuf, sizeof(vabuf), " %s", fs_gamedirs[i]), sizeof(gamedirbuf));
                else
-                       strlcpy(gamedirbuf, fs_gamedirs[i], sizeof(gamedirbuf));
+                       dp_strlcpy(gamedirbuf, fs_gamedirs[i], sizeof(gamedirbuf));
        }
        Cvar_SetQuick(&cvar_fs_gamedir, gamedirbuf); // so QC or console code can query it
 
@@ -1603,7 +1606,7 @@ void FS_Rescan (void)
        }
 
        if((i = Sys_CheckParm("-modname")) && i < sys.argc - 1)
-               strlcpy(com_modname, sys.argv[i+1], sizeof(com_modname));
+               dp_strlcpy(com_modname, sys.argv[i+1], sizeof(com_modname));
 
        // If "-condebug" is in the command line, remove the previous log file
        if (Sys_CheckParm ("-condebug") != 0)
@@ -1695,7 +1698,7 @@ qbool FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qbool compl
 
        fs_numgamedirs = numgamedirs;
        for (i = 0;i < fs_numgamedirs;i++)
-               strlcpy(fs_gamedirs[i], gamedirs[i], sizeof(fs_gamedirs[i]));
+               dp_strlcpy(fs_gamedirs[i], gamedirs[i], sizeof(fs_gamedirs[i]));
 
        // reinitialize filesystem to detect the new paks
        FS_Rescan();
@@ -1709,8 +1712,8 @@ qbool FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qbool compl
        // unload all sounds so they will be reloaded from the new files as needed
        S_UnloadAllSounds_f(cmd_local);
 
-       // restart the video subsystem after the config is executed
-       Cbuf_InsertText(cmd_local, "\nloadconfig\nvid_restart\n\n");
+       // reset everything that can be and reload configs
+       Cbuf_InsertText(cmd_local, "\nloadconfig\n");
 
        return true;
 }
@@ -1743,7 +1746,7 @@ static void FS_GameDir_f(cmd_state_t *cmd)
        }
 
        for (i = 0;i < numgamedirs;i++)
-               strlcpy(gamedirs[i], Cmd_Argv(cmd, i+1), sizeof(gamedirs[i]));
+               dp_strlcpy(gamedirs[i], Cmd_Argv(cmd, i+1), sizeof(gamedirs[i]));
 
        if ((cls.state == ca_connected && !cls.demoplayback) || sv.active)
        {
@@ -1870,8 +1873,8 @@ static void FS_ListGameDirs(void)
                        continue;
                if(!*info)
                        continue;
-               strlcpy(fs_all_gamedirs[fs_all_gamedirs_count].name, list2.strings[i], sizeof(fs_all_gamedirs[fs_all_gamedirs_count].name));
-               strlcpy(fs_all_gamedirs[fs_all_gamedirs_count].description, info, sizeof(fs_all_gamedirs[fs_all_gamedirs_count].description));
+               dp_strlcpy(fs_all_gamedirs[fs_all_gamedirs_count].name, list2.strings[i], sizeof(fs_all_gamedirs[fs_all_gamedirs_count].name));
+               dp_strlcpy(fs_all_gamedirs[fs_all_gamedirs_count].description, info, sizeof(fs_all_gamedirs[fs_all_gamedirs_count].description));
                ++fs_all_gamedirs_count;
        }
 }
@@ -1902,7 +1905,7 @@ static void COM_InsertFlags(const char *buf) {
                if(i > args_left)
                        break;
                q = (char *)Mem_Alloc(fs_mempool, sz);
-               strlcpy(q, com_token, sz);
+               dp_strlcpy(q, com_token, sz);
                new_argv[i] = q;
                ++i;
        }
@@ -1925,7 +1928,7 @@ static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t use
        {
                // 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);
+               dp_strlcpy(userdir, "../Documents/", MAX_OSPATH);
                return 1;
        }
        return -1;
@@ -1949,7 +1952,7 @@ static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t use
        default:
                return -1;
        case USERDIRMODE_NOHOME:
-               strlcpy(userdir, fs_basedir, userdirsize);
+               dp_strlcpy(userdir, fs_basedir, userdirsize);
                break;
        case USERDIRMODE_MYGAMES:
                if (!shfolder_dll)
@@ -2020,7 +2023,7 @@ static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t use
        default:
                return -1;
        case USERDIRMODE_NOHOME:
-               strlcpy(userdir, fs_basedir, userdirsize);
+               dp_strlcpy(userdir, fs_basedir, userdirsize);
                break;
        case USERDIRMODE_HOME:
                homedir = getenv("HOME");
@@ -2093,9 +2096,10 @@ void FS_Init_Commands(void)
 {
        Cvar_RegisterVariable (&scr_screenshot_name);
        Cvar_RegisterVariable (&fs_empty_files_in_pack_mark_deletions);
+       Cvar_RegisterVariable (&fs_unload_dlcache);
        Cvar_RegisterVariable (&cvar_fs_gamedir);
 
-       Cmd_AddCommand(CF_SHARED, "gamedir", FS_GameDir_f, "changes active gamedir list (can take multiple arguments), not including base directory (example usage: gamedir ctf)");
+       Cmd_AddCommand(CF_SHARED, "gamedir", FS_GameDir_f, "changes active gamedir list, can take multiple arguments which shouldn't include the base directory, the last gamedir is the \"primary\" and files will be saved there (example usage: gamedir ctf id1)");
        Cmd_AddCommand(CF_SHARED, "fs_rescan", FS_Rescan_f, "rescans filesystem for new pack archives and any other changes");
        Cmd_AddCommand(CF_SHARED, "path", FS_Path_f, "print searchpath (game directories and archives)");
        Cmd_AddCommand(CF_SHARED, "dir", FS_Dir_f, "list files in searchpath matching an * filename pattern, one per line");
@@ -2118,7 +2122,7 @@ static void FS_Init_Dir (void)
        i = Sys_CheckParm ("-basedir");
        if (i && i < sys.argc-1)
        {
-               strlcpy (fs_basedir, sys.argv[i+1], sizeof (fs_basedir));
+               dp_strlcpy (fs_basedir, sys.argv[i+1], sizeof (fs_basedir));
                i = (int)strlen (fs_basedir);
                if (i > 0 && (fs_basedir[i-1] == '\\' || fs_basedir[i-1] == '/'))
                        fs_basedir[i-1] = 0;
@@ -2127,7 +2131,7 @@ static void FS_Init_Dir (void)
        {
 // If the base directory is explicitly defined by the compilation process
 #ifdef DP_FS_BASEDIR
-               strlcpy(fs_basedir, DP_FS_BASEDIR, sizeof(fs_basedir));
+               dp_strlcpy(fs_basedir, DP_FS_BASEDIR, sizeof(fs_basedir));
 #elif defined(__ANDROID__)
                dpsnprintf(fs_basedir, sizeof(fs_basedir), "/sdcard/%s/", gameuserdirname);
 #elif defined(MACOSX)
@@ -2135,7 +2139,7 @@ static void FS_Init_Dir (void)
                if (strstr(sys.argv[0], ".app/"))
                {
                        char *split;
-                       strlcpy(fs_basedir, sys.argv[0], sizeof(fs_basedir));
+                       dp_strlcpy(fs_basedir, sys.argv[0], sizeof(fs_basedir));
                        split = strstr(fs_basedir, ".app/");
                        if (split)
                        {
@@ -2147,7 +2151,7 @@ static void FS_Init_Dir (void)
                                if (stat(va(vabuf, sizeof(vabuf), "%s/Contents/Resources/%s", fs_basedir, gamedirname1), &statresult) == 0)
                                {
                                        // found gamedir inside Resources, use it
-                                       strlcat(fs_basedir, "Contents/Resources/", sizeof(fs_basedir));
+                                       dp_strlcat(fs_basedir, "Contents/Resources/", sizeof(fs_basedir));
                                }
                                else
                                {
@@ -2159,6 +2163,9 @@ static void FS_Init_Dir (void)
                                }
                        }
                }
+#else
+               // use the working directory
+               getcwd(fs_basedir, sizeof(fs_basedir));
 #endif
        }
 
@@ -2166,7 +2173,7 @@ static void FS_Init_Dir (void)
        memset(fs_basedir + sizeof(fs_basedir) - 2, 0, 2);
        // add a path separator to the end of the basedir if it lacks one
        if (fs_basedir[0] && fs_basedir[strlen(fs_basedir) - 1] != '/' && fs_basedir[strlen(fs_basedir) - 1] != '\\')
-               strlcat(fs_basedir, "/", sizeof(fs_basedir));
+               dp_strlcat(fs_basedir, "/", sizeof(fs_basedir));
 
        // Add the personal game directory
        if((i = Sys_CheckParm("-userdir")) && i < sys.argc - 1)
@@ -2176,7 +2183,7 @@ static void FS_Init_Dir (void)
        else
        {
 #ifdef DP_FS_USERDIR
-               strlcpy(fs_userdir, DP_FS_USERDIR, sizeof(fs_userdir));
+               dp_strlcpy(fs_userdir, DP_FS_USERDIR, sizeof(fs_userdir));
 #else
                int dirmode;
                int highestuserdirmode = USERDIRMODE_COUNT - 1;
@@ -2254,7 +2261,7 @@ static void FS_Init_Dir (void)
                        if(p == fs_checkgamedir_missing)
                                Con_Printf(CON_WARN "WARNING: -game %s%s/ not found!\n", fs_basedir, sys.argv[i]);
                        // add the gamedir to the list of active gamedirs
-                       strlcpy (fs_gamedirs[fs_numgamedirs], sys.argv[i], sizeof(fs_gamedirs[fs_numgamedirs]));
+                       dp_strlcpy (fs_gamedirs[fs_numgamedirs], sys.argv[i], sizeof(fs_gamedirs[fs_numgamedirs]));
                        fs_numgamedirs++;
                }
        }
@@ -2664,7 +2671,7 @@ Return the searchpath where the file was found (or NULL)
 and the file index in the package if relevant
 ====================
 */
-static searchpath_t *FS_FindFile (const char *name, int* index, qbool quiet)
+static searchpath_t *FS_FindFile (const char *name, int *index, const char **canonicalname, qbool quiet)
 {
        searchpath_t *search;
        pack_t *pak;
@@ -2702,15 +2709,18 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qbool quiet)
 
                                                if (index != NULL)
                                                        *index = -1;
+                                               if (canonicalname)
+                                                       *canonicalname = NULL;
                                                return NULL;
                                        }
 
                                        if (!quiet && developer_extra.integer)
-                                               Con_DPrintf("FS_FindFile: %s in %s\n",
-                                                                       pak->files[middle].name, pak->filename);
+                                               Con_DPrintf("FS_FindFile: %s in %s\n", pak->files[middle].name, pak->filename);
 
                                        if (index != NULL)
                                                *index = middle;
+                                       if (canonicalname)
+                                               *canonicalname = pak->files[middle].name;
                                        return search;
                                }
 
@@ -2732,6 +2742,8 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qbool quiet)
 
                                if (index != NULL)
                                        *index = -1;
+                               if (canonicalname)
+                                       *canonicalname = name;
                                return search;
                        }
                }
@@ -2742,6 +2754,8 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qbool quiet)
 
        if (index != NULL)
                *index = -1;
+       if (canonicalname)
+               *canonicalname = NULL;
        return NULL;
 }
 
@@ -2758,7 +2772,7 @@ static qfile_t *FS_OpenReadFile (const char *filename, qbool quiet, qbool nonblo
        searchpath_t *search;
        int pack_ind;
 
-       search = FS_FindFile (filename, &pack_ind, quiet);
+       search = FS_FindFile (filename, &pack_ind, NULL, quiet);
 
        // Not found?
        if (search == NULL)
@@ -3623,7 +3637,7 @@ void FS_DefaultExtension (char *path, const char *extension, size_t size_path)
                src--;
        }
 
-       strlcat (path, extension, size_path);
+       dp_strlcat (path, extension, size_path);
 }
 
 
@@ -3639,7 +3653,7 @@ int FS_FileType (const char *filename)
        searchpath_t *search;
        char fullpath[MAX_OSPATH];
 
-       search = FS_FindFile (filename, NULL, true);
+       search = FS_FindFile (filename, NULL, NULL, true);
        if(!search)
                return FS_FILETYPE_NONE;
 
@@ -3656,11 +3670,15 @@ int FS_FileType (const char *filename)
 FS_FileExists
 
 Look for a file in the packages and in the filesystem
+Returns its canonical name (VFS path with correct capitalisation) if found, else NULL.
+If the file is found outside a pak, this will be the same pointer as passed in.
 ==================
 */
-qbool FS_FileExists (const char *filename)
+const char *FS_FileExists (const char *filename)
 {
-       return (FS_FindFile (filename, NULL, true) != NULL);
+       const char *canonicalname;
+
+       return FS_FindFile(filename, NULL, &canonicalname, true) ? canonicalname : NULL;
 }
 
 
@@ -3769,7 +3787,7 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet, const
                        for (i = 0;i < pak->numfiles;i++)
                        {
                                char temp[MAX_OSPATH];
-                               strlcpy(temp, pak->files[i].name, sizeof(temp));
+                               dp_strlcpy(temp, pak->files[i].name, sizeof(temp));
                                while (temp[0])
                                {
                                        if (matchpattern(temp, (char *)pattern, true))
@@ -3841,7 +3859,7 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet, const
 
                                // prevseparator points past the '/' right before the wildcard and nextseparator at the one following it (or at the end of the string)
                                // copy everything up except nextseperator
-                               strlcpy(subpattern, pattern, min(sizeof(subpattern), (size_t) (nextseparator - pattern + 1)));
+                               dp_ustr2stp(subpattern, sizeof(subpattern), pattern, nextseparator - pattern);
                                // find the last '/' before the wildcard
                                prevseparator = strrchr( subpattern, '/' );
                                if (!prevseparator)
@@ -3850,13 +3868,13 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet, const
                                        prevseparator++;
                                // copy everything from start to the previous including the '/' (before the wildcard)
                                // everything up to start is already included in the path of matchedSet's entries
-                               strlcpy(subpath, start, min(sizeof(subpath), (size_t) ((prevseparator - subpattern) - (start - pattern) + 1)));
+                               dp_ustr2stp(subpath, sizeof(subpath), start, (prevseparator - subpattern) - (start - pattern));
 
                                // for each entry in matchedSet try to open the subdirectories specified in subpath
                                for( dirlistindex = 0 ; dirlistindex < matchedSet.numstrings ; dirlistindex++ ) {
                                        char temp[MAX_OSPATH];
-                                       strlcpy( temp, matchedSet.strings[ dirlistindex ], sizeof(temp) );
-                                       strlcat( temp, subpath, sizeof(temp) );
+                                       dp_strlcpy( temp, matchedSet.strings[ dirlistindex ], sizeof(temp) );
+                                       dp_strlcat( temp, subpath, sizeof(temp) );
                                        listdirectory( &foundSet, searchpath->filename, temp );
                                }
                                if( dirlistindex == 0 ) {
@@ -4036,7 +4054,7 @@ void FS_Which_f(cmd_state_t *cmd)
                return;
        }
        filename = Cmd_Argv(cmd, 1);
-       sp = FS_FindFile(filename, &index, true);
+       sp = FS_FindFile(filename, &index, NULL, true);
        if (!sp) {
                Con_Printf("%s isn't anywhere\n", filename);
                return;
@@ -4056,7 +4074,7 @@ void FS_Which_f(cmd_state_t *cmd)
 const char *FS_WhichPack(const char *filename)
 {
        int index;
-       searchpath_t *sp = FS_FindFile(filename, &index, true);
+       searchpath_t *sp = FS_FindFile(filename, &index, NULL, true);
        if(sp && sp->pack)
                return sp->pack->shortname;
        else if(sp)