#ifdef WIN32
# include <direct.h>
# include <io.h>
+# include <shlobj.h>
#else
# include <pwd.h>
# include <sys/stat.h>
return true;
// Load the DLL
- if (! Sys_LoadLibrary (dllnames, &zlib_dll, zlibfuncs))
- {
- Con_Printf ("Compressed files support disabled\n");
- return false;
- }
-
- Con_Printf ("Compressed files support enabled\n");
- return true;
+ return Sys_LoadLibrary (dllnames, &zlib_dll, zlibfuncs);
}
int i;
stringlist_t list;
searchpath_t *search;
- char pakfile[MAX_OSPATH];
strlcpy (fs_gamedir, dir, sizeof (fs_gamedir));
stringlistinit(&list);
- listdirectory(&list, dir);
+ listdirectory(&list, "", dir);
stringlistsort(&list);
// add any PAK package in the directory
{
if (!strcasecmp(FS_FileExtension(list.strings[i]), "pak"))
{
- dpsnprintf (pakfile, sizeof (pakfile), "%s%s", dir, list.strings[i]);
- FS_AddPack_Fullpath(pakfile, NULL, false);
+ FS_AddPack_Fullpath(list.strings[i], NULL, false);
}
}
{
if (!strcasecmp(FS_FileExtension(list.strings[i]), "pk3"))
{
- dpsnprintf (pakfile, sizeof (pakfile), "%s%s", dir, list.strings[i]);
- FS_AddPack_Fullpath(pakfile, NULL, false);
+ FS_AddPack_Fullpath(list.strings[i], NULL, false);
}
}
void FS_AddGameHierarchy (const char *dir)
{
int i;
- const char *homedir;
char userdir[MAX_QPATH];
+#ifdef WIN32
+ TCHAR mydocsdir[MAX_PATH + 1];
+#else
+ const char *homedir;
+#endif
// Add the common game directory
FS_AddGameDirectory (va("%s%s/", fs_basedir, dir));
// Add the personal game directory
#ifdef WIN32
- homedir = getenv ("APPDATA");
- dpsnprintf(userdir, sizeof(userdir), "%s/%s/", homedir, gameuserdirname);
+ if(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, mydocsdir) == S_OK)
+ dpsnprintf(userdir, sizeof(userdir), "%s/My Games/%s/", mydocsdir, gameuserdirname);
+ fprintf(stderr, "userdir = %s\n", userdir);
#else
homedir = getenv ("HOME");
- dpsnprintf(userdir, sizeof(userdir), "%s/.%s/", homedir, gameuserdirname);
+ if(homedir)
+ dpsnprintf(userdir, sizeof(userdir), "%s/.%s/", homedir, gameuserdirname);
#endif
#ifdef WIN32
- if(!COM_CheckParm("-appdata")) // TODO make this the default when fs_basedir isn't writable
-#else
- if(COM_CheckParm("-nohome"))
+ if(!COM_CheckParm("-mygames"))
+ {
+ int fd = open (va("%s%s/config.cfg", fs_basedir, dir), O_WRONLY | O_CREAT, 0666); // note: no O_TRUNC here!
+ if(fd >= 0)
+ {
+ close(fd);
+ *userdir = 0; // we have write access to the game dir, so let's use it
+ }
+ }
#endif
+
+ if(COM_CheckParm("-nohome"))
*userdir = 0;
if((i = COM_CheckParm("-userdir")) && i < com_argc - 1)
qboolean success;
stringlist_t list;
stringlistinit(&list);
- listdirectory(&list, va("%s%s/", fs_basedir, gamedir));
+ listdirectory(&list, va("%s%s/", fs_basedir, gamedir), "");
success = list.numstrings > 0;
stringlistfreecontents(&list);
return success;
*/
qfile_t* FS_Open (const char* filepath, const char* mode, qboolean quiet, qboolean nonblocking)
{
+#ifdef FS_FIX_PATHS
+ char fixedFileName[MAX_QPATH];
+ char *d;
+ strlcpy( fixedFileName, filepath, MAX_QPATH );
+ // try to fix common mistakes (\ instead of /)
+ for( d = fixedFileName ; *d ; d++ )
+ if( *d == '\\' )
+ *d = '/';
+ filepath = fixedFileName;
+#endif
+
if (FS_CheckNastyPath(filepath, false))
{
Con_Printf("FS_Open(\"%s\", \"%s\", %s): nasty filename rejected\n", filepath, mode, quiet ? "true" : "false");
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)
return false;
}
- Con_DPrintf("FS_WriteFile: %s\n", filename);
+ Con_DPrintf("FS_WriteFile: %s (%u bytes)\n", filename, (unsigned int)len);
FS_Write (file, data, len);
FS_Close (file);
return true;
}
+/*
+==================
+FS_FileType
+
+Look for a file in the packages and in the filesystem
+==================
+*/
+int FS_FileType (const char *filename)
+{
+ searchpath_t *search;
+ char fullpath[MAX_QPATH];
+
+ search = FS_FindFile (filename, NULL, true);
+ if(!search)
+ return FS_FILETYPE_NONE;
+
+ if(search->pack)
+ return FS_FILETYPE_FILE; // TODO can't check directories in paks yet, maybe later
+
+ dpsnprintf(fullpath, sizeof(fullpath), "%s%s", search->filename, filename);
+ return FS_SysFileType(fullpath);
+}
+
+
/*
==================
FS_FileExists
Look for a file in the filesystem only
==================
*/
-qboolean FS_SysFileExists (const char *path)
+int FS_SysFileType (const char *path)
{
#if WIN32
- int desc;
+ DWORD result = GetFileAttributes(path);
- // TODO: use another function instead, to avoid opening the file
- desc = open (path, O_RDONLY | O_BINARY);
- if (desc < 0)
- return false;
+ if(result == INVALID_FILE_ATTRIBUTES)
+ return FS_FILETYPE_NONE;
- close (desc);
- return true;
+ if(result & FILE_ATTRIBUTE_DIRECTORY)
+ return FS_FILETYPE_DIRECTORY;
+
+ return FS_FILETYPE_FILE;
#else
struct stat buf;
if (stat (path,&buf) == -1)
- return false;
+ return FS_FILETYPE_NONE;
- return true;
+ if(S_ISDIR(buf.st_mode))
+ return FS_FILETYPE_DIRECTORY;
+
+ return FS_FILETYPE_FILE;
#endif
}
+qboolean FS_SysFileExists (const char *path)
+{
+ return FS_SysFileType (path) != FS_FILETYPE_NONE;
+}
+
void FS_mkdir (const char *path)
{
#if WIN32
stringlist_t dirlist;
const char *slash, *backslash, *colon, *separator;
char *basepath;
- char netpath[MAX_OSPATH];
char temp[MAX_OSPATH];
for (i = 0;pattern[i] == '.' || pattern[i] == ':' || pattern[i] == '/' || pattern[i] == '\\';i++)
if (resultlistindex == resultlist.numstrings)
{
stringlistappend(&resultlist, temp);
- if (!quiet)
- Con_DPrintf("SearchPackFile: %s : %s\n", pak->filename, temp);
+ if (!quiet && developer_loading.integer)
+ Con_Printf("SearchPackFile: %s : %s\n", pak->filename, temp);
}
}
// strip off one path element at a time until empty
}
else
{
- // get a directory listing and look at each name
- dpsnprintf(netpath, sizeof (netpath), "%s%s", searchpath->filename, basepath);
- stringlistinit(&dirlist);
- listdirectory(&dirlist, netpath);
- for (dirlistindex = 0;dirlistindex < dirlist.numstrings;dirlistindex++)
+ stringlist_t matchedSet, foundSet;
+ int resultindex = 0;
+ const char *start = pattern;
+
+ stringlistinit(&matchedSet);
+ stringlistinit(&foundSet);
+ // add a first entry to the set
+ stringlistappend(&matchedSet, "");
+ // iterate through pattern's path
+ while (*start)
+ {
+ const char *asterisk, *wildcard, *nextseparator, *prevseparator;
+ char subpath[MAX_OSPATH];
+ char subpattern[MAX_OSPATH];
+
+ // find the next wildcard
+ wildcard = strchr(start, '?');
+ asterisk = strchr(start, '*');
+ if (asterisk && (!wildcard || asterisk < wildcard))
+ {
+ wildcard = asterisk;
+ }
+
+ if (wildcard)
+ {
+ nextseparator = strchr( wildcard, '/' );
+ }
+ else
+ {
+ nextseparator = NULL;
+ }
+
+ if( !nextseparator ) {
+ nextseparator = start + strlen( start );
+ }
+
+ // copy everything up except nextseperator
+ strlcpy(subpattern, pattern, min(sizeof(subpattern), nextseparator - pattern + 1));
+ // find the last /
+ prevseparator = strrchr( subpattern, '/' ) + 1;
+ if (!prevseparator)
+ {
+ prevseparator = subpattern;
+ }
+ // copy everything including the last '/'
+ strlcpy(subpath, start, min(sizeof(subpath), (prevseparator - subpattern) - (start - pattern) + 1));
+
+ // prevseparator points to the one right before the wildcard and nextseparator to the one following it (or past the end of the string (at \0))
+ // start to prevseparator can be opened now and added to the other resultset
+ for( dirlistindex = 0 ; dirlistindex < matchedSet.numstrings ; dirlistindex++ ) {
+ strlcpy( temp, matchedSet.strings[ dirlistindex ], sizeof(temp) );
+ strlcat( temp, subpath, sizeof(temp) );
+ listdirectory( &foundSet, searchpath->filename, temp );
+ }
+ if( dirlistindex == 0 ) {
+ break;
+ }
+ // reset the current result set
+ stringlistfreecontents( &matchedSet );
+ // match against the pattern
+ for( dirlistindex = 0 ; dirlistindex < foundSet.numstrings ; dirlistindex++ ) {
+ const char *direntry = foundSet.strings[ dirlistindex ];
+ if (matchpattern(direntry, subpattern, true)) {
+ stringlistappend( &matchedSet, direntry );
+ }
+ }
+ stringlistfreecontents( &foundSet );
+
+ start = nextseparator;
+ }
+
+ for (dirlistindex = 0;dirlistindex < matchedSet.numstrings;dirlistindex++)
{
- dpsnprintf(temp, sizeof(temp), "%s%s", basepath, dirlist.strings[dirlistindex]);
+ const char *temp = matchedSet.strings[dirlistindex];
if (matchpattern(temp, (char *)pattern, true))
{
for (resultlistindex = 0;resultlistindex < resultlist.numstrings;resultlistindex++)
if (resultlistindex == resultlist.numstrings)
{
stringlistappend(&resultlist, temp);
- if (!quiet)
- Con_DPrintf("SearchDirFile: %s\n", temp);
+ if (!quiet && developer_loading.integer)
+ Con_Printf("SearchDirFile: %s\n", temp);
}
}
}
- stringlistfreecontents(&dirlist);
+ stringlistfreecontents( &matchedSet );
}
}