mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-25 13:51:43 +00:00
Merge branch 'folder-fixes' into 'next'
Fix minor issues with folder addons See merge request STJr/SRB2!1617
This commit is contained in:
commit
df249a4a4d
8 changed files with 405 additions and 188 deletions
|
@ -944,13 +944,13 @@ static void D_AddFile(char **list, const char *file)
|
|||
|
||||
static void D_AddFolder(char **list, const char *file)
|
||||
{
|
||||
size_t pnumwadfiles, len = strlen(file);
|
||||
size_t pnumwadfiles;
|
||||
char *newfile;
|
||||
|
||||
for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++)
|
||||
;
|
||||
|
||||
newfile = malloc(len + 2); // NULL terminator + path separator
|
||||
newfile = malloc(strlen(file) + 2); // Path delimiter + NULL terminator
|
||||
if (!newfile)
|
||||
I_Error("No more free memory to AddFolder %s",file);
|
||||
|
||||
|
|
|
@ -3416,9 +3416,10 @@ static void Command_Addfolder(void)
|
|||
for (curarg = 1; curarg < argc; curarg++)
|
||||
{
|
||||
const char *fn, *p;
|
||||
char *fullpath;
|
||||
char buf[256];
|
||||
char *buf_p = buf;
|
||||
INT32 i;
|
||||
INT32 i, stat;
|
||||
size_t ii;
|
||||
boolean folderadded = false;
|
||||
|
||||
|
@ -3461,6 +3462,13 @@ static void Command_Addfolder(void)
|
|||
break;
|
||||
++p;
|
||||
|
||||
// Don't add an empty path.
|
||||
if (M_IsStringEmpty(fn))
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Folder name is empty, skipping\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
// check total packet size and no of files currently loaded
|
||||
// See W_InitFile in w_wad.c
|
||||
if ((numwadfiles >= MAX_WADFILES)
|
||||
|
@ -3470,10 +3478,52 @@ static void Command_Addfolder(void)
|
|||
return;
|
||||
}
|
||||
|
||||
WRITESTRINGN(buf_p,p,240);
|
||||
// Check if the path is valid.
|
||||
stat = W_IsPathToFolderValid(fn);
|
||||
|
||||
if (stat == 0)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Path %s is invalid, skipping\n"), fn);
|
||||
continue;
|
||||
}
|
||||
else if (stat < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Error accessing %s (%s), skipping\n"), fn, strerror(direrror));
|
||||
#else
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Error accessing %s, skipping\n"), fn);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the full path for this folder.
|
||||
fullpath = W_GetFullFolderPath(fn);
|
||||
|
||||
if (fullpath == NULL)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Path %s is invalid, skipping\n"), fn);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the folder is already added.
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (wadfiles[i]->type != RET_FOLDER)
|
||||
continue;
|
||||
|
||||
if (samepaths(wadfiles[i]->path, fullpath) > 0)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Z_Free(fullpath);
|
||||
|
||||
addedfolders[numfoldersadded++] = fn;
|
||||
|
||||
WRITESTRINGN(buf_p,p,240);
|
||||
|
||||
if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file
|
||||
SendNetXCmd(XD_REQADDFOLDER, buf, buf_p - buf);
|
||||
else
|
||||
|
|
|
@ -1584,20 +1584,23 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
|
|||
return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found
|
||||
}
|
||||
|
||||
// Searches for a folder.
|
||||
// This can be used with a full path, or an incomplete path.
|
||||
// In the latter case, the function will try to find folders in
|
||||
// srb2home, srb2path, and the current directory.
|
||||
filestatus_t findfolder(const char *path)
|
||||
{
|
||||
// Check the path by itself first.
|
||||
if (checkfolderpath(path, NULL, true))
|
||||
if (concatpaths(path, NULL) == 1)
|
||||
return FS_FOUND;
|
||||
|
||||
#define checkpath(startpath) { \
|
||||
if (checkfolderpath(path, startpath, true)) \
|
||||
return FS_FOUND; \
|
||||
}
|
||||
#define checkpath(startpath) \
|
||||
if (concatpaths(path, startpath) == 1) \
|
||||
return FS_FOUND
|
||||
|
||||
checkpath(srb2home) // Then, look in srb2home.
|
||||
checkpath(srb2path) // Now, look in srb2path.
|
||||
checkpath(".") // Finally, look in ".".
|
||||
checkpath(srb2home); // Then, look in srb2home.
|
||||
checkpath(srb2path); // Now, look in srb2path.
|
||||
checkpath("."); // Finally, look in the current directory.
|
||||
|
||||
#undef checkpath
|
||||
|
||||
|
|
329
src/filesrch.c
329
src/filesrch.c
|
@ -341,8 +341,8 @@ char *refreshdirname = NULL;
|
|||
size_t packetsizetally = 0;
|
||||
size_t mainwadstally = 0;
|
||||
|
||||
#define folderpathlen 1024
|
||||
#define maxfolderdepth 48
|
||||
#define dirpathlen 1024
|
||||
#define maxdirdepth 48
|
||||
|
||||
#define isuptree(dirent) ((dirent)[0]=='.' && ((dirent)[1]=='\0' || ((dirent)[1]=='.' && (dirent)[2]=='\0')))
|
||||
|
||||
|
@ -448,182 +448,227 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
|||
return retval;
|
||||
}
|
||||
|
||||
// Called from findfolder and ResGetLumpsFolder in w_wad.c.
|
||||
// Call with cleanup true if the path has to be verified.
|
||||
boolean checkfolderpath(const char *path, const char *startpath, boolean cleanup)
|
||||
{
|
||||
char folderpath[folderpathlen], basepath[folderpathlen], *fn = NULL;
|
||||
DIR *dirhandle;
|
||||
#ifndef AVOID_ERRNO
|
||||
int direrror = 0;
|
||||
#endif
|
||||
|
||||
// Remove path separators from the filename, and don't try adding "/".
|
||||
// See also the same code in W_InitFolder.
|
||||
if (cleanup)
|
||||
{
|
||||
const char *p = path + strlen(path);
|
||||
size_t len;
|
||||
|
||||
--p;
|
||||
while (*p == '\\' || *p == '/' || *p == ':')
|
||||
{
|
||||
p--;
|
||||
if (p < path)
|
||||
return false;
|
||||
}
|
||||
++p;
|
||||
|
||||
// Allocate the new path name.
|
||||
len = (p - path) + 1;
|
||||
fn = ZZ_Alloc(len);
|
||||
strlcpy(fn, path, len);
|
||||
}
|
||||
|
||||
if (startpath)
|
||||
{
|
||||
snprintf(basepath, sizeof basepath, "%s" PATHSEP, startpath);
|
||||
|
||||
if (cleanup)
|
||||
{
|
||||
snprintf(folderpath, sizeof folderpath, "%s%s", basepath, fn);
|
||||
Z_Free(fn); // Don't need this anymore.
|
||||
}
|
||||
else
|
||||
snprintf(folderpath, sizeof folderpath, "%s%s", basepath, path);
|
||||
|
||||
// Home path and folder path are the same? Not valid.
|
||||
if (!strcmp(basepath, folderpath))
|
||||
return false;
|
||||
}
|
||||
else if (cleanup)
|
||||
{
|
||||
snprintf(folderpath, sizeof folderpath, "%s", fn);
|
||||
Z_Free(fn); // Don't need this anymore.
|
||||
}
|
||||
else
|
||||
snprintf(folderpath, sizeof folderpath, "%s", path);
|
||||
|
||||
dirhandle = opendir(folderpath);
|
||||
if (dirhandle == NULL)
|
||||
return false;
|
||||
else
|
||||
closedir(dirhandle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
INT32 pathisfolder(const char *path)
|
||||
// Checks if the specified path is a directory.
|
||||
// Returns 1 if so, 0 if not, and -1 if an error occurred.
|
||||
// direrror is set if there was an error.
|
||||
INT32 pathisdirectory(const char *path)
|
||||
{
|
||||
struct stat fsstat;
|
||||
|
||||
if (stat(path, &fsstat) < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = errno;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else if (S_ISDIR(fsstat.st_mode))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Concatenates two paths, and checks if it is a directory that can be opened.
|
||||
// Returns 1 if so, 0 if not, and -1 if an error occurred.
|
||||
INT32 concatpaths(const char *path, const char *startpath)
|
||||
{
|
||||
char dirpath[dirpathlen];
|
||||
DIR *dirhandle;
|
||||
INT32 stat;
|
||||
|
||||
if (startpath)
|
||||
{
|
||||
char basepath[dirpathlen];
|
||||
|
||||
snprintf(basepath, sizeof basepath, "%s" PATHSEP, startpath);
|
||||
snprintf(dirpath, sizeof dirpath, "%s%s", basepath, path);
|
||||
|
||||
// Base path and directory path are the same? Not valid.
|
||||
stat = samepaths(basepath, dirpath);
|
||||
|
||||
if (stat == 1)
|
||||
return 0;
|
||||
else if (stat < 0)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
snprintf(dirpath, sizeof dirpath, "%s", path);
|
||||
|
||||
// Check if the path is a directory.
|
||||
// Will return -1 if there was an error.
|
||||
stat = pathisdirectory(dirpath);
|
||||
if (stat == 0)
|
||||
return 0;
|
||||
else if (stat < 0)
|
||||
{
|
||||
// The path doesn't exist, so it can't be a directory.
|
||||
if (direrror == ENOENT)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Open the directory.
|
||||
// Will return 0 if it couldn't be opened.
|
||||
dirhandle = opendir(dirpath);
|
||||
if (dirhandle == NULL)
|
||||
return 0;
|
||||
else
|
||||
closedir(dirhandle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Checks if two paths are the same. Returns 1 if so, and 0 if not.
|
||||
// Returns -1 if an error occurred with the first path,
|
||||
// and returns -2 if an error occurred with the second path.
|
||||
// direrror is set if there was an error.
|
||||
INT32 samepaths(const char *path1, const char *path2)
|
||||
{
|
||||
struct stat stat1;
|
||||
struct stat stat2;
|
||||
|
||||
if (stat(path1, &stat1) < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = errno;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
if (stat(path2, &stat2) < 0)
|
||||
return -1;
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = errno;
|
||||
#endif
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (stat1.st_dev == stat2.st_dev)
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
return (stat1.st_ino == stat2.st_ino);
|
||||
#else
|
||||
// The above doesn't work on NTFS or FAT.
|
||||
HANDLE file1 = CreateFileA(path1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
HANDLE file2 = CreateFileA(path2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
BY_HANDLE_FILE_INFORMATION file1info, file2info;
|
||||
boolean ok = false;
|
||||
|
||||
if (file1 != INVALID_HANDLE_VALUE && file2 != INVALID_HANDLE_VALUE)
|
||||
if (file1 == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetFileInformationByHandle(file1, &file1info) && GetFileInformationByHandle(file2, &file2info))
|
||||
{
|
||||
if (file1info.dwVolumeSerialNumber == file2info.dwVolumeSerialNumber
|
||||
&& file1info.nFileIndexLow == file2info.nFileIndexLow
|
||||
&& file1info.nFileIndexHigh == file2info.nFileIndexHigh)
|
||||
ok = true;
|
||||
}
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = ENOENT;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else if (file2 == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(file1);
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = ENOENT;
|
||||
#endif
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (file1 != INVALID_HANDLE_VALUE)
|
||||
// I have no idea why GetFileInformationByHandle would fail.
|
||||
// Microsoft's documentation doesn't tell me.
|
||||
// I'll just use EIO...
|
||||
if (!GetFileInformationByHandle(file1, &file1info))
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = EIO;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else if (!GetFileInformationByHandle(file2, &file2info))
|
||||
{
|
||||
CloseHandle(file1);
|
||||
if (file2 != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(file2);
|
||||
#ifndef AVOID_ERRNO
|
||||
direrror = EIO;
|
||||
#endif
|
||||
return -2;
|
||||
}
|
||||
|
||||
return ok;
|
||||
if (file1info.dwVolumeSerialNumber == file2info.dwVolumeSerialNumber
|
||||
&& file1info.nFileIndexLow == file2info.nFileIndexLow
|
||||
&& file1info.nFileIndexHigh == file2info.nFileIndexHigh)
|
||||
{
|
||||
CloseHandle(file1);
|
||||
CloseHandle(file2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Folder loading
|
||||
// Directory loading
|
||||
//
|
||||
|
||||
static void initfolderpath(char *folderpath, size_t *folderpathindex, int depthleft)
|
||||
static void initdirpath(char *dirpath, size_t *dirpathindex, int depthleft)
|
||||
{
|
||||
folderpathindex[depthleft] = strlen(folderpath) + 1;
|
||||
dirpathindex[depthleft] = strlen(dirpath) + 1;
|
||||
|
||||
if (folderpath[folderpathindex[depthleft]-2] != PATHSEP[0])
|
||||
if (dirpath[dirpathindex[depthleft]-2] != PATHSEP[0])
|
||||
{
|
||||
folderpath[folderpathindex[depthleft]-1] = PATHSEP[0];
|
||||
folderpath[folderpathindex[depthleft]] = 0;
|
||||
dirpath[dirpathindex[depthleft]-1] = PATHSEP[0];
|
||||
dirpath[dirpathindex[depthleft]] = 0;
|
||||
}
|
||||
else
|
||||
folderpathindex[depthleft]--;
|
||||
dirpathindex[depthleft]--;
|
||||
}
|
||||
|
||||
lumpinfo_t *getfolderfiles(const char *path, UINT16 *nlmp, UINT16 *nfiles, UINT16 *nfolders)
|
||||
lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders)
|
||||
{
|
||||
DIR **dirhandle;
|
||||
struct dirent *dent;
|
||||
struct stat fsstat;
|
||||
|
||||
int rootfolder = (maxfolderdepth - 1);
|
||||
int depthleft = rootfolder;
|
||||
int rootdir = (maxdirdepth - 1);
|
||||
int depthleft = rootdir;
|
||||
|
||||
char folderpath[folderpathlen];
|
||||
size_t *folderpathindex;
|
||||
char dirpath[dirpathlen];
|
||||
size_t *dirpathindex;
|
||||
|
||||
lumpinfo_t *lumpinfo, *lump_p;
|
||||
UINT16 i = 0, numlumps = (*nlmp);
|
||||
UINT16 i = 0, numlumps = 0;
|
||||
|
||||
dirhandle = (DIR **)malloc(maxfolderdepth * sizeof (DIR*));
|
||||
folderpathindex = (size_t *)malloc(maxfolderdepth * sizeof(size_t));
|
||||
boolean failure = false;
|
||||
|
||||
dirhandle = (DIR **)malloc(maxdirdepth * sizeof (DIR*));
|
||||
dirpathindex = (size_t *)malloc(maxdirdepth * sizeof(size_t));
|
||||
|
||||
// Open the root directory
|
||||
strlcpy(folderpath, path, folderpathlen);
|
||||
dirhandle[depthleft] = opendir(folderpath);
|
||||
strlcpy(dirpath, path, dirpathlen);
|
||||
dirhandle[depthleft] = opendir(dirpath);
|
||||
|
||||
if (dirhandle[depthleft] == NULL)
|
||||
{
|
||||
free(dirhandle);
|
||||
free(folderpathindex);
|
||||
free(dirpathindex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
initfolderpath(folderpath, folderpathindex, depthleft);
|
||||
(*nfiles) = 0;
|
||||
initdirpath(dirpath, dirpathindex, depthleft);
|
||||
(*nfolders) = 0;
|
||||
|
||||
// Count files and directories
|
||||
while (depthleft < maxfolderdepth)
|
||||
while (depthleft < maxdirdepth)
|
||||
{
|
||||
folderpath[folderpathindex[depthleft]] = 0;
|
||||
dirpath[dirpathindex[depthleft]] = 0;
|
||||
dent = readdir(dirhandle[depthleft]);
|
||||
|
||||
if (!dent)
|
||||
{
|
||||
if (depthleft != rootfolder) // Don't close the root directory
|
||||
if (depthleft != rootdir) // Don't close the root directory
|
||||
closedir(dirhandle[depthleft]);
|
||||
depthleft++;
|
||||
continue;
|
||||
|
@ -631,62 +676,67 @@ lumpinfo_t *getfolderfiles(const char *path, UINT16 *nlmp, UINT16 *nfiles, UINT1
|
|||
else if (isuptree(dent->d_name))
|
||||
continue;
|
||||
|
||||
strcpy(&folderpath[folderpathindex[depthleft]], dent->d_name);
|
||||
strcpy(&dirpath[dirpathindex[depthleft]], dent->d_name);
|
||||
|
||||
if (stat(folderpath, &fsstat) < 0)
|
||||
if (stat(dirpath, &fsstat) < 0)
|
||||
;
|
||||
else if (S_ISDIR(fsstat.st_mode) && depthleft)
|
||||
{
|
||||
folderpathindex[--depthleft] = strlen(folderpath) + 1;
|
||||
dirhandle[depthleft] = opendir(folderpath);
|
||||
dirpathindex[--depthleft] = strlen(dirpath) + 1;
|
||||
dirhandle[depthleft] = opendir(dirpath);
|
||||
|
||||
if (dirhandle[depthleft])
|
||||
{
|
||||
numlumps++;
|
||||
(*nfolders)++;
|
||||
}
|
||||
else
|
||||
depthleft++;
|
||||
|
||||
folderpath[folderpathindex[depthleft]-1] = '/';
|
||||
folderpath[folderpathindex[depthleft]] = 0;
|
||||
dirpath[dirpathindex[depthleft]-1] = '/';
|
||||
dirpath[dirpathindex[depthleft]] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
numlumps++;
|
||||
(*nfiles)++;
|
||||
}
|
||||
|
||||
if (numlumps == (UINT16_MAX-1))
|
||||
// Failure: Too many files.
|
||||
if (numlumps == UINT16_MAX)
|
||||
{
|
||||
(*nlmp) = UINT16_MAX;
|
||||
failure = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Failure: No files have been found.
|
||||
if (!(*nfiles))
|
||||
if (!numlumps)
|
||||
{
|
||||
(*nfiles) = UINT16_MAX;
|
||||
free(folderpathindex);
|
||||
(*nlmp) = 0;
|
||||
failure = true;
|
||||
}
|
||||
|
||||
// Close any open directories and return if something went wrong.
|
||||
if (failure)
|
||||
{
|
||||
free(dirpathindex);
|
||||
free(dirhandle);
|
||||
for (; depthleft < maxfolderdepth; closedir(dirhandle[depthleft++])); // Close any open directories.
|
||||
for (; depthleft < maxdirdepth; closedir(dirhandle[depthleft++]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create the files and directories as lump entries
|
||||
// It's possible to create lumps and count files at the same time,
|
||||
// but I didn't to constantly have to reallocate memory for every lump.
|
||||
rewinddir(dirhandle[rootfolder]);
|
||||
depthleft = rootfolder;
|
||||
// but I didn't want to have to reallocate memory for every lump.
|
||||
rewinddir(dirhandle[rootdir]);
|
||||
depthleft = rootdir;
|
||||
|
||||
strlcpy(folderpath, path, folderpathlen);
|
||||
initfolderpath(folderpath, folderpathindex, depthleft);
|
||||
strlcpy(dirpath, path, dirpathlen);
|
||||
initdirpath(dirpath, dirpathindex, depthleft);
|
||||
|
||||
lump_p = lumpinfo = Z_Calloc(numlumps * sizeof(lumpinfo_t), PU_STATIC, NULL);
|
||||
|
||||
while (depthleft < maxfolderdepth)
|
||||
while (depthleft < maxdirdepth)
|
||||
{
|
||||
char *fullname, *trimname;
|
||||
|
||||
folderpath[folderpathindex[depthleft]] = 0;
|
||||
dirpath[dirpathindex[depthleft]] = 0;
|
||||
dent = readdir(dirhandle[depthleft]);
|
||||
|
||||
if (!dent)
|
||||
|
@ -697,29 +747,30 @@ lumpinfo_t *getfolderfiles(const char *path, UINT16 *nlmp, UINT16 *nfiles, UINT1
|
|||
else if (isuptree(dent->d_name))
|
||||
continue;
|
||||
|
||||
strcpy(&folderpath[folderpathindex[depthleft]], dent->d_name);
|
||||
strcpy(&dirpath[dirpathindex[depthleft]], dent->d_name);
|
||||
|
||||
if (stat(folderpath, &fsstat) < 0)
|
||||
if (stat(dirpath, &fsstat) < 0)
|
||||
continue;
|
||||
else if (S_ISDIR(fsstat.st_mode) && depthleft)
|
||||
{
|
||||
folderpathindex[--depthleft] = strlen(folderpath) + 1;
|
||||
dirhandle[depthleft] = opendir(folderpath);
|
||||
dirpathindex[--depthleft] = strlen(dirpath) + 1;
|
||||
dirhandle[depthleft] = opendir(dirpath);
|
||||
|
||||
if (!dirhandle[depthleft])
|
||||
if (dirhandle[depthleft])
|
||||
{
|
||||
depthleft++;
|
||||
continue;
|
||||
dirpath[dirpathindex[depthleft]-1] = '/';
|
||||
dirpath[dirpathindex[depthleft]] = 0;
|
||||
}
|
||||
else
|
||||
depthleft++;
|
||||
|
||||
folderpath[folderpathindex[depthleft]-1] = '/';
|
||||
folderpath[folderpathindex[depthleft]] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
lump_p->diskpath = Z_StrDup(folderpath); // Path in the filesystem to the file
|
||||
lump_p->diskpath = Z_StrDup(dirpath); // Path in the filesystem to the file
|
||||
lump_p->compression = CM_NOCOMPRESSION; // Lump is uncompressed
|
||||
|
||||
// Remove the folder path.
|
||||
// Remove the directory's path.
|
||||
fullname = lump_p->diskpath;
|
||||
if (strstr(fullname, path))
|
||||
fullname += strlen(path) + 1;
|
||||
|
@ -747,7 +798,7 @@ lumpinfo_t *getfolderfiles(const char *path, UINT16 *nlmp, UINT16 *nfiles, UINT1
|
|||
lump_p->longname = Z_Calloc(1, PU_STATIC, NULL);
|
||||
|
||||
// The complete name of the file, with its extension,
|
||||
// excluding the path of the folder where it resides.
|
||||
// excluding the path of the directory where it resides.
|
||||
lump_p->fullname = Z_StrDup(fullname);
|
||||
|
||||
lump_p++;
|
||||
|
@ -755,12 +806,12 @@ lumpinfo_t *getfolderfiles(const char *path, UINT16 *nlmp, UINT16 *nfiles, UINT1
|
|||
|
||||
if (i > numlumps || i == (UINT16_MAX-1))
|
||||
{
|
||||
for (; depthleft < maxfolderdepth; closedir(dirhandle[depthleft++])); // Close any open directories.
|
||||
for (; depthleft < maxdirdepth; closedir(dirhandle[depthleft++])); // Close any open directories.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(folderpathindex);
|
||||
free(dirpathindex);
|
||||
free(dirhandle);
|
||||
|
||||
(*nlmp) = numlumps;
|
||||
|
|
|
@ -29,11 +29,15 @@ extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_sh
|
|||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
|
||||
boolean completepath, int maxsearchdepth);
|
||||
|
||||
INT32 pathisfolder(const char *path);
|
||||
boolean checkfolderpath(const char *path, const char *startpath, boolean cleanup);
|
||||
INT32 pathisdirectory(const char *path);
|
||||
INT32 samepaths(const char *path1, const char *path2);
|
||||
boolean concatpaths(const char *path, const char *startpath);
|
||||
|
||||
lumpinfo_t *getfolderfiles(const char *path, UINT16 *nlmp, UINT16 *nfiles, UINT16 *nfolders);
|
||||
#ifndef AVOID_ERRNO
|
||||
extern int direrror;
|
||||
#endif
|
||||
|
||||
lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders);
|
||||
|
||||
#define menudepth 20
|
||||
|
||||
|
|
|
@ -2694,7 +2694,7 @@ boolean M_IsStringEmpty(const char *s)
|
|||
{
|
||||
const char *ch = s;
|
||||
|
||||
if (ch == NULL || (ch && strlen(ch) < 1))
|
||||
if (s == NULL || s[0] == '\0')
|
||||
return true;
|
||||
|
||||
for (;;ch++)
|
||||
|
|
168
src/w_wad.c
168
src/w_wad.c
|
@ -687,11 +687,67 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
|
|||
return lumpinfo;
|
||||
}
|
||||
|
||||
static INT32 CheckPathsNotEqual(const char *path1, const char *path2)
|
||||
{
|
||||
INT32 stat = samepaths(path1, path2);
|
||||
|
||||
if (stat == 1)
|
||||
return 0;
|
||||
else if (stat < 0)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Returns 1 if the path is valid, 0 if not, and -1 if there was an error.
|
||||
INT32 W_IsPathToFolderValid(const char *path)
|
||||
{
|
||||
INT32 stat;
|
||||
|
||||
// Remove path delimiters.
|
||||
const char *p = path + (strlen(path) - 1);
|
||||
while (*p == '\\' || *p == '/' || *p == ':')
|
||||
{
|
||||
p--;
|
||||
if (p < path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if the path is a directory.
|
||||
stat = pathisdirectory(path);
|
||||
if (stat == 0)
|
||||
return 0;
|
||||
else if (stat < 0)
|
||||
{
|
||||
// The path doesn't exist, so it can't be a directory.
|
||||
if (direrror == ENOENT)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Don't add your home, you sodding tic tac.
|
||||
stat = CheckPathsNotEqual(path, srb2home);
|
||||
if (stat != 1)
|
||||
return stat;
|
||||
|
||||
// Do the same checks for SRB2's path, and the current directory.
|
||||
stat = CheckPathsNotEqual(path, srb2path);
|
||||
if (stat != 1)
|
||||
return stat;
|
||||
|
||||
stat = CheckPathsNotEqual(path, ".");
|
||||
if (stat != 1)
|
||||
return stat;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Checks if the combination of the first path and the second path are valid.
|
||||
// If they are, the concatenated path is returned.
|
||||
static char *W_CheckFolderPath(const char *startpath, const char *path)
|
||||
static char *CheckConcatFolderPath(const char *startpath, const char *path)
|
||||
{
|
||||
if (checkfolderpath(path, startpath, false))
|
||||
if (concatpaths(path, startpath) == 1)
|
||||
{
|
||||
char *fn;
|
||||
|
||||
|
@ -710,23 +766,23 @@ static char *W_CheckFolderPath(const char *startpath, const char *path)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Returns the first valid path for a folder.
|
||||
static char *W_GetFullFolderPath(const char *path)
|
||||
// Looks for the first valid full path for a folder.
|
||||
// Returns NULL if the folder doesn't exist, or it isn't valid.
|
||||
char *W_GetFullFolderPath(const char *path)
|
||||
{
|
||||
// Check the path by itself first.
|
||||
char *fn = W_CheckFolderPath(NULL, path);
|
||||
char *fn = CheckConcatFolderPath(NULL, path);
|
||||
if (fn)
|
||||
return fn;
|
||||
|
||||
#define checkpath(startpath) { \
|
||||
fn = W_CheckFolderPath(startpath, path); \
|
||||
#define checkpath(startpath) \
|
||||
fn = CheckConcatFolderPath(startpath, path); \
|
||||
if (fn) \
|
||||
return fn; \
|
||||
} \
|
||||
return fn
|
||||
|
||||
checkpath(srb2home) // Then, look in srb2home.
|
||||
checkpath(srb2path) // Now, look in srb2path.
|
||||
checkpath(".") // Finally, look in ".".
|
||||
checkpath(srb2home); // Then, look in srb2home.
|
||||
checkpath(srb2path); // Now, look in srb2path.
|
||||
checkpath("."); // Finally, look in the current directory.
|
||||
|
||||
#undef checkpath
|
||||
|
||||
|
@ -734,9 +790,9 @@ static char *W_GetFullFolderPath(const char *path)
|
|||
}
|
||||
|
||||
// Loads files from a folder into a lumpinfo structure.
|
||||
static lumpinfo_t *ResGetLumpsFolder(const char *path, UINT16 *nlmp, UINT16 *nfiles, UINT16 *nfolders)
|
||||
static lumpinfo_t *ResGetLumpsFolder(const char *path, UINT16 *nlmp, UINT16 *nfolders)
|
||||
{
|
||||
return getfolderfiles(path, nlmp, nfiles, nfolders);
|
||||
return getdirectoryfiles(path, nlmp, nfolders);
|
||||
}
|
||||
|
||||
static UINT16 W_InitFileError (const char *filename, boolean exitworthy)
|
||||
|
@ -908,7 +964,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
wadfile->type = type;
|
||||
wadfile->handle = handle;
|
||||
wadfile->numlumps = numlumps;
|
||||
wadfile->filecount = wadfile->foldercount = 0;
|
||||
wadfile->foldercount = 0;
|
||||
wadfile->lumpinfo = lumpinfo;
|
||||
wadfile->important = important;
|
||||
fseek(handle, 0, SEEK_END);
|
||||
|
@ -966,11 +1022,12 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
|
|||
lumpinfo_t *lumpinfo = NULL;
|
||||
wadfile_t *wadfile;
|
||||
UINT16 numlumps = 0;
|
||||
UINT16 filecount, foldercount;
|
||||
UINT16 foldercount;
|
||||
size_t i;
|
||||
char *fn, *fullpath;
|
||||
const char *p;
|
||||
int important;
|
||||
INT32 stat;
|
||||
|
||||
if (!(refreshdirmenu & REFRESHDIR_ADDFILE))
|
||||
refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier
|
||||
|
@ -1006,16 +1063,15 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
|
|||
packetsizetally = packetsize;
|
||||
}
|
||||
|
||||
// Remove path separators from the filename, and don't try adding "/".
|
||||
p = path+strlen(path);
|
||||
--p;
|
||||
// Remove path delimiters.
|
||||
p = path + (strlen(path) - 1);
|
||||
|
||||
while (*p == '\\' || *p == '/' || *p == ':')
|
||||
{
|
||||
p--;
|
||||
if (p < path)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Path %s is prohibited\n"), path);
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Path %s is invalid\n"), path);
|
||||
return W_InitFileError(path, startup);
|
||||
}
|
||||
}
|
||||
|
@ -1026,6 +1082,7 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
|
|||
fn = ZZ_Alloc(i);
|
||||
strlcpy(fn, path, i);
|
||||
|
||||
// Don't add an empty path.
|
||||
if (M_IsStringEmpty(fn))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Folder name is empty\n"));
|
||||
|
@ -1037,14 +1094,36 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
|
|||
return W_InitFileError("a folder", false);
|
||||
}
|
||||
|
||||
// Get the full path for this filename.
|
||||
// Check if the path is valid.
|
||||
stat = W_IsPathToFolderValid(fn);
|
||||
|
||||
if (stat != 1)
|
||||
{
|
||||
if (stat == 0)
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Path %s is invalid\n"), fn);
|
||||
else if (stat < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Could not stat %s: %s\n"), fn, strerror(direrror));
|
||||
#else
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Could not stat %s\n"), fn);
|
||||
#endif
|
||||
}
|
||||
|
||||
Z_Free(fn);
|
||||
return W_InitFileError(path, startup);
|
||||
}
|
||||
|
||||
// Get the full path for this folder.
|
||||
fullpath = W_GetFullFolderPath(fn);
|
||||
if (fullpath == NULL)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Path %s is invalid\n"), fn);
|
||||
Z_Free(fn);
|
||||
return W_InitFileError(path, false);
|
||||
return W_InitFileError(path, startup);
|
||||
}
|
||||
|
||||
// Check if the folder is already added.
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (wadfiles[i]->type != RET_FOLDER)
|
||||
|
@ -1061,11 +1140,16 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
|
|||
}
|
||||
}
|
||||
|
||||
lumpinfo = ResGetLumpsFolder(fullpath, &numlumps, &filecount, &foldercount);
|
||||
lumpinfo = ResGetLumpsFolder(fullpath, &numlumps, &foldercount);
|
||||
|
||||
if (lumpinfo == NULL)
|
||||
{
|
||||
if (filecount == UINT16_MAX)
|
||||
if (!numlumps)
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Folder %s is empty\n"), path);
|
||||
else if (numlumps == UINT16_MAX)
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Folder %s contains too many files\n"), path);
|
||||
else
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Unknown error enumerating files from folder %s\n"), path);
|
||||
|
||||
Z_Free(fn);
|
||||
Z_Free(fullpath);
|
||||
|
@ -1082,7 +1166,6 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
|
|||
wadfile->type = RET_FOLDER;
|
||||
wadfile->handle = NULL;
|
||||
wadfile->numlumps = numlumps;
|
||||
wadfile->filecount = filecount;
|
||||
wadfile->foldercount = foldercount;
|
||||
wadfile->lumpinfo = lumpinfo;
|
||||
wadfile->important = important;
|
||||
|
@ -1094,7 +1177,7 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
|
|||
Z_Calloc(numlumps * sizeof (*wadfile->lumpcache), PU_STATIC, &wadfile->lumpcache);
|
||||
Z_Calloc(numlumps * sizeof (*wadfile->patchcache), PU_STATIC, &wadfile->patchcache);
|
||||
|
||||
CONS_Printf(M_GetText("Added folder %s (%u files, %u folders)\n"), fn, filecount, foldercount);
|
||||
CONS_Printf(M_GetText("Added folder %s (%u files, %u folders)\n"), fn, numlumps, foldercount);
|
||||
wadfiles[numwadfiles] = wadfile;
|
||||
numwadfiles++;
|
||||
|
||||
|
@ -1506,12 +1589,24 @@ size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump)
|
|||
|
||||
l = wadfiles[wad]->lumpinfo + lump;
|
||||
|
||||
// Open the external file for this lump, if the WAD is a folder.
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
{
|
||||
INT32 stat = pathisfolder(l->diskpath);
|
||||
// pathisdirectory calls stat, so if anything wrong has happened,
|
||||
// this is the time to be aware of it.
|
||||
INT32 stat = pathisdirectory(l->diskpath);
|
||||
|
||||
if (stat < 0)
|
||||
I_Error("W_LumpLengthPwad: could not stat %s", l->diskpath);
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
if (direrror == ENOENT)
|
||||
I_Error("W_LumpLengthPwad: file %s doesn't exist", l->diskpath);
|
||||
else
|
||||
I_Error("W_LumpLengthPwad: could not stat %s: %s", l->diskpath, strerror(direrror));
|
||||
#else
|
||||
I_Error("W_LumpLengthPwad: could not access %s", l->diskpath);
|
||||
#endif
|
||||
}
|
||||
else if (stat == 1) // Path is a folder.
|
||||
return 0;
|
||||
else
|
||||
|
@ -1617,7 +1712,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
|
|||
lumpinfo_t *l;
|
||||
FILE *handle = NULL;
|
||||
|
||||
if (!TestValidLump(wad,lump))
|
||||
if (!TestValidLump(wad, lump))
|
||||
return 0;
|
||||
|
||||
l = wadfiles[wad]->lumpinfo + lump;
|
||||
|
@ -1625,10 +1720,21 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
|
|||
// Open the external file for this lump, if the WAD is a folder.
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
{
|
||||
INT32 stat = pathisfolder(l->diskpath);
|
||||
// pathisdirectory calls stat, so if anything wrong has happened,
|
||||
// this is the time to be aware of it.
|
||||
INT32 stat = pathisdirectory(l->diskpath);
|
||||
|
||||
if (stat < 0)
|
||||
I_Error("W_ReadLumpHeaderPwad: could not stat %s", l->diskpath);
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
if (direrror == ENOENT)
|
||||
I_Error("W_ReadLumpHeaderPwad: file %s doesn't exist", l->diskpath);
|
||||
else
|
||||
I_Error("W_ReadLumpHeaderPwad: could not stat %s: %s", l->diskpath, strerror(direrror));
|
||||
#else
|
||||
I_Error("W_ReadLumpHeaderPwad: could not access %s", l->diskpath);
|
||||
#endif
|
||||
}
|
||||
else if (stat == 1) // Path is a folder.
|
||||
return 0;
|
||||
else
|
||||
|
|
|
@ -122,7 +122,7 @@ typedef struct wadfile_s
|
|||
lumpcache_t *lumpcache;
|
||||
lumpcache_t *patchcache;
|
||||
UINT16 numlumps; // this wad's number of resources
|
||||
UINT16 filecount, foldercount; // file and folder count
|
||||
UINT16 foldercount; // folder count
|
||||
FILE *handle;
|
||||
UINT32 filesize; // for network
|
||||
UINT8 md5sum[16];
|
||||
|
@ -152,6 +152,9 @@ void W_InitMultipleFiles(char **filenames);
|
|||
|
||||
#define W_FileHasFolders(wadfile) ((wadfile)->type == RET_PK3 || (wadfile)->type == RET_FOLDER)
|
||||
|
||||
boolean W_IsPathToFolderValid(const char *path);
|
||||
char *W_GetFullFolderPath(const char *path);
|
||||
|
||||
const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump);
|
||||
const char *W_CheckNameForNum(lumpnum_t lumpnum);
|
||||
|
||||
|
|
Loading…
Reference in a new issue