X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=fs.c;h=093d0ac9ad3a7cec37d5bd7d803d6d9efaf3e164;hp=6ad2201d83b5a61e91418f8e57924509f170dd08;hb=1e1dbc1c5b89ae4ab8cdd9b32dc6413c67f5dd84;hpb=f272bd1d9660f9bbd3242f46b254221f9f50c841 diff --git a/fs.c b/fs.c index 6ad2201d..093d0ac9 100644 --- a/fs.c +++ b/fs.c @@ -231,6 +231,22 @@ typedef struct searchpath_s } searchpath_t; +/* +============================================================================= + +FUNCTION PROTOTYPES + +============================================================================= +*/ + +void FS_Dir_f(void); +void FS_Ls_f(void); + +static packfile_t* FS_AddFileToPack (const char* name, pack_t* pack, + size_t offset, size_t packsize, + size_t realsize, file_flags_t flags); + + /* ============================================================================= @@ -328,7 +344,7 @@ qboolean PK3_OpenLibrary (void) #ifdef WIN32 dllname = "zlib.dll"; #else - dllname = "libz.so.1"; + dllname = "libz.so"; #endif // Initializations @@ -447,7 +463,6 @@ int PK3_BuildFileList (pack_t *pack, const pk3_endOfCentralDir_t *eocd) for (ind = 0; ind < eocd->nbentries; ind++) { size_t namesize, count; - packfile_t *file; // Checking the remaining size if (remaining < ZIP_CDIR_CHUNK_BASE_SIZE) @@ -483,19 +498,24 @@ int PK3_BuildFileList (pack_t *pack, const pk3_endOfCentralDir_t *eocd) // WinZip doesn't use the "directory" attribute, so we need to check the name directly if (ptr[ZIP_CDIR_CHUNK_BASE_SIZE + namesize - 1] != '/') { - // Extract the name - file = &pack->files[pack->numfiles]; - memcpy (file->name, &ptr[ZIP_CDIR_CHUNK_BASE_SIZE], namesize); - file->name[namesize] = '\0'; + char filename [sizeof (pack->files[0].name)]; + size_t offset, packsize, realsize; + file_flags_t flags; - // Compression, sizes and offset - if (BuffLittleShort (&ptr[10])) - file->flags = FILE_FLAG_DEFLATED; - file->packsize = BuffLittleLong (&ptr[20]); - file->realsize = BuffLittleLong (&ptr[24]); - file->offset = BuffLittleLong (&ptr[42]); + // Extract the name (strip it if necessary) + if (namesize >= sizeof (filename)) + namesize = sizeof (filename) - 1; + memcpy (filename, &ptr[ZIP_CDIR_CHUNK_BASE_SIZE], namesize); + filename[namesize] = '\0'; - pack->numfiles++; + if (BuffLittleShort (&ptr[10])) + flags = FILE_FLAG_DEFLATED; + else + flags = 0; + offset = BuffLittleLong (&ptr[42]); + packsize = BuffLittleLong (&ptr[20]); + realsize = BuffLittleLong (&ptr[24]); + FS_AddFileToPack (filename, pack, offset, packsize, realsize, flags); } } @@ -559,7 +579,7 @@ pack_t *FS_LoadPackPK3 (const char *packfile) if (real_nb_files <= 0) Sys_Error ("%s is not a valid PK3 file", packfile); - Con_Printf ("Added packfile %s (%i files)\n", packfile, real_nb_files); + Con_Printf("Added packfile %s (%i files)\n", packfile, real_nb_files); return pack; } @@ -602,11 +622,64 @@ OTHER PRIVATE FUNCTIONS */ +/* +==================== +FS_AddFileToPack + +Add a file to the list of files contained into a package +==================== +*/ +static packfile_t* FS_AddFileToPack (const char* name, pack_t* pack, + size_t offset, size_t packsize, + size_t realsize, file_flags_t flags) +{ + int (*strcmp_funct) (const char* str1, const char* str2); + size_t left, right, middle; + int diff; + packfile_t *file; + + strcmp_funct = pack->ignorecase ? strcasecmp : strcmp; + + // Look for the slot we should put that file into (binary search) + left = 0; + right = pack->numfiles; + while (left != right) + { + middle = (left + right - 1) / 2; + diff = strcmp_funct (pack->files[middle].name, name); + + // If we found the file, there's a problem + if (!diff) + Sys_Error ("Package %s contains several time the file %s\n", + pack->filename, name); + + // If we're too far in the list + if (diff > 0) + right = middle; + else + left = middle + 1; + } + + // We have to move the right of the list by one slot to free the one we need + file = &pack->files[left]; + memmove (file + 1, file, (pack->numfiles - left) * sizeof (*file)); + pack->numfiles++; + + strlcpy (file->name, name, sizeof (file->name)); + file->offset = offset; + file->packsize = packsize; + file->realsize = realsize; + file->flags = flags; + + return file; +} + + /* ============ FS_CreatePath -Only used for FS_WriteFile. +Only used for FS_Open. ============ */ void FS_CreatePath (char *path) @@ -637,15 +710,15 @@ void FS_Path_f (void) { searchpath_t *s; - Con_Printf ("Current search path:\n"); + Con_Print("Current search path:\n"); for (s=fs_searchpaths ; s ; s=s->next) { if (s->pack) { - Con_Printf ("%s (%i files)\n", s->pack->filename, s->pack->numfiles); + Con_Printf("%s (%i files)\n", s->pack->filename, s->pack->numfiles); } else - Con_Printf ("%s\n", s->filename); + Con_Printf("%s\n", s->filename); } } @@ -690,7 +763,7 @@ pack_t *FS_LoadPackPAK (const char *packfile) pack->ignorecase = false; // PAK is case sensitive strlcpy (pack->filename, packfile, sizeof (pack->filename)); pack->handle = packhandle; - pack->numfiles = numpackfiles; + pack->numfiles = 0; pack->mempool = Mem_AllocPool(packfile); pack->files = Mem_Alloc(pack->mempool, numpackfiles * sizeof(packfile_t)); pack->next = packlist; @@ -703,20 +776,15 @@ pack_t *FS_LoadPackPAK (const char *packfile) // parse the directory for (i = 0;i < numpackfiles;i++) { - size_t size; - packfile_t *file = &pack->files[i]; - - strlcpy (file->name, info[i].name, sizeof (file->name)); - file->offset = LittleLong(info[i].filepos); - size = LittleLong (info[i].filelen); - file->packsize = size; - file->realsize = size; - file->flags = FILE_FLAG_TRUEOFFS; + size_t offset = LittleLong (info[i].filepos); + size_t size = LittleLong (info[i].filelen); + + FS_AddFileToPack (info[i].name, pack, offset, size, size, FILE_FLAG_TRUEOFFS); } Mem_Free(info); - Con_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles); + Con_Printf("Added packfile %s (%i files)\n", packfile, numpackfiles); return pack; } @@ -738,11 +806,13 @@ void FS_AddGameDirectory (char *dir) strlcpy (fs_gamedir, dir, sizeof (fs_gamedir)); +#ifndef AKVERSION // add the directory to the search path search = Mem_Alloc(pak_mempool, sizeof(searchpath_t)); strlcpy (search->filename, dir, sizeof (search->filename)); search->next = fs_searchpaths; fs_searchpaths = search; +#endif list = listdirectory(dir); @@ -784,6 +854,15 @@ void FS_AddGameDirectory (char *dir) } } freedirectory(list); + +// Unpacked files have the priority over packed files if AKVERSION is defined +#ifdef AKVERSION + // add the directory to the search path + search = Mem_Alloc(pak_mempool, sizeof(searchpath_t)); + strlcpy (search->filename, dir, sizeof (search->filename)); + search->next = fs_searchpaths; + fs_searchpaths = search; +#endif } @@ -816,8 +895,6 @@ char *FS_FileExtension (const char *in) return exten; } -void FS_Dir_f(void); -void FS_Ls_f(void); /* ================ @@ -967,218 +1044,177 @@ qfile_t *FS_OpenRead (const char *path, int offs, int len) return file; } + /* -=========== -FS_FOpenFile +==================== +FS_FindFile -If the requested file is inside a packfile, a new qfile_t* will be opened -into the file. +Look for a file in the packages and in the filesystem -Sets fs_filesize -=========== +Return the searchpath where the file was found (or NULL) +and the file index in the package if relevant +==================== */ -qfile_t *FS_FOpenFile (const char *filename, qboolean quiet) +static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet) { searchpath_t *search; - char netpath[MAX_OSPATH]; pack_t *pak; - int i, filenamelen, matched; + int (*strcmp_funct) (const char* str1, const char* str2); - filenamelen = strlen (filename); - - // LordHavoc: this is not written right! - // (should search have higher priority for files in each gamedir, while - // preserving the gamedir priorities, not searching for all paks in all - // gamedirs and then all files in all gamedirs) -#ifdef AKVERSION - // first we search for a real file, after that we start to search through the paks // search through the path, one element at a time - search = fs_searchpaths; - - for( ; search ; search = search->next) - if(!search->pack) - { - snprintf (netpath, sizeof (netpath), "%s/%s",search->filename, filename); - - if (!FS_SysFileExists (netpath)) - continue; - - if (!quiet) - Sys_Printf ("FindFile: %s\n",netpath); - return FS_OpenRead (netpath, -1, -1); - } - - search = fs_searchpaths; - for ( ; search ; search = search->next) + for (search = fs_searchpaths;search;search = search->next) + { // is the element a pak file? if (search->pack) { - // look through all the pak file elements + size_t left, right, middle; + pak = search->pack; - for (i=0 ; inumfiles ; i++) - { - if (pak->ignorecase) - matched = !strcasecmp (pak->files[i].name, filename); - else - matched = !strcmp (pak->files[i].name, filename); - if (matched) // found it? - { - qfile_t *file; + strcmp_funct = pak->ignorecase ? strcasecmp : strcmp; - if (!quiet) - Sys_Printf ("PackFile: %s : %s\n",pak->filename, pak->files[i].name); + // Look for the file (binary search) + left = 0; + right = pak->numfiles; + while (left != right) + { + int diff; - // If we don't have the true offset, get it now - if (! (pak->files[i].flags & FILE_FLAG_TRUEOFFS)) - PK3_GetTrueFileOffset (&pak->files[i], pak); + middle = (left + right - 1) / 2; + diff = strcmp_funct (pak->files[middle].name, name); - // No Zlib DLL = no compressed files - if (!zlib_dll && (pak->files[i].flags & FILE_FLAG_DEFLATED)) - { - Con_Printf ("WARNING: can't open the compressed file %s\n" - "You need the Zlib DLL to use compressed files\n", filename); - fs_filesize = -1; - return NULL; - } + // Found it + if (!diff) + { + if (!quiet) + Sys_Printf("FS_FindFile: %s in %s\n", + pak->files[middle].name, pak->filename); - // open a new file in the pakfile - file = FS_OpenRead (pak->filename, pak->files[i].offset, pak->files[i].packsize); - fs_filesize = pak->files[i].realsize; + if (index != NULL) + *index = middle; + return search; + } - if (pak->files[i].flags & FILE_FLAG_DEFLATED) - { - ztoolkit_t *ztk; + // If we're too far in the list + if (diff > 0) + right = middle; + else + left = middle + 1; + } + } + else + { + char netpath[MAX_OSPATH]; + snprintf(netpath, sizeof(netpath), "%s/%s", search->filename, name); + if (FS_SysFileExists (netpath)) + { + if (!quiet) + Sys_Printf("FS_FindFile: %s\n", netpath); - file->flags |= FS_FLAG_DEFLATED; + if (index != NULL) + *index = -1; + return search; + } + } + } - // We need some more variables - ztk = Mem_Alloc (fs_mempool, sizeof (*file->z)); + if (!quiet) + Sys_Printf("FS_FindFile: can't find %s\n", name); - ztk->real_length = pak->files[i].realsize; + if (index != NULL) + *index = -1; + return NULL; +} - // Initialize zlib stream - ztk->zstream.next_in = ztk->input; - ztk->zstream.avail_in = 0; - /* From Zlib's "unzip.c": - * - * windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. - * In unzip, i don't wait absolutely Z_STREAM_END because I known the - * size of both compressed and uncompressed data - */ - if (qz_inflateInit2 (&ztk->zstream, -MAX_WBITS) != Z_OK) - Sys_Error ("inflate init error (file: %s)", filename); +/* +=========== +FS_FOpenFile - ztk->zstream.next_out = ztk->output; - ztk->zstream.avail_out = sizeof (ztk->output); +If the requested file is inside a packfile, a new qfile_t* will be opened +into the file. - file->z = ztk; - } +Sets fs_filesize +=========== +*/ +qfile_t *FS_FOpenFile (const char *filename, qboolean quiet) +{ + searchpath_t *search; + packfile_t *packfile; + int i; + qfile_t *file; - return file; - } - } - } -#else - // search through the path, one element at a time - search = fs_searchpaths; + search = FS_FindFile (filename, &i, quiet); - for ( ; search ; search = search->next) + // Not found? + if (search == NULL) { - // is the element a pak file? - if (search->pack) - { - // look through all the pak file elements - pak = search->pack; - for (i=0 ; inumfiles ; i++) - { - if (pak->ignorecase) - matched = !strcasecmp (pak->files[i].name, filename); - else - matched = !strcmp (pak->files[i].name, filename); - if (matched) // found it? - { - qfile_t *file; - - if (!quiet) - Sys_Printf ("PackFile: %s : %s\n",pak->filename, pak->files[i].name); - - // If we don't have the true offset, get it now - if (! (pak->files[i].flags & FILE_FLAG_TRUEOFFS)) - PK3_GetTrueFileOffset (&pak->files[i], pak); + fs_filesize = -1; + return NULL; + } - // No Zlib DLL = no compressed files - if (!zlib_dll && (pak->files[i].flags & FILE_FLAG_DEFLATED)) - { - Con_Printf ("WARNING: can't open the compressed file %s\n" - "You need the Zlib DLL to use compressed files\n", filename); - fs_filesize = -1; - return NULL; - } + // Found in the filesystem? + if (i < 0) + { + char netpath[MAX_OSPATH]; + snprintf(netpath, sizeof(netpath), "%s/%s", search->filename, filename); + return FS_OpenRead(netpath, -1, -1); + } - // open a new file in the pakfile - file = FS_OpenRead (pak->filename, pak->files[i].offset, pak->files[i].packsize); - fs_filesize = pak->files[i].realsize; + // So, we found it in a package... + packfile = &search->pack->files[i]; - if (pak->files[i].flags & FILE_FLAG_DEFLATED) - { - ztoolkit_t *ztk; + // If we don't have the true offset, get it now + if (! (packfile->flags & FILE_FLAG_TRUEOFFS)) + PK3_GetTrueFileOffset (packfile, search->pack); - file->flags |= FS_FLAG_DEFLATED; + // No Zlib DLL = no compressed files + if (!zlib_dll && (packfile->flags & FILE_FLAG_DEFLATED)) + { + Con_Printf("WARNING: can't open the compressed file %s\n" + "You need the Zlib DLL to use compressed files\n", + filename); + fs_filesize = -1; + return NULL; + } - // We need some more variables - ztk = Mem_Alloc (fs_mempool, sizeof (*file->z)); + // open a new file in the pakfile + file = FS_OpenRead (search->pack->filename, packfile->offset, packfile->packsize); + fs_filesize = packfile->realsize; - ztk->real_length = pak->files[i].realsize; + if (packfile->flags & FILE_FLAG_DEFLATED) + { + ztoolkit_t *ztk; - // Initialize zlib stream - ztk->zstream.next_in = ztk->input; - ztk->zstream.avail_in = 0; + file->flags |= FS_FLAG_DEFLATED; - /* From Zlib's "unzip.c": - * - * windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. - * In unzip, i don't wait absolutely Z_STREAM_END because I known the - * size of both compressed and uncompressed data - */ - if (qz_inflateInit2 (&ztk->zstream, -MAX_WBITS) != Z_OK) - Sys_Error ("inflate init error (file: %s)", filename); + // We need some more variables + ztk = Mem_Alloc (fs_mempool, sizeof (*file->z)); - ztk->zstream.next_out = ztk->output; - ztk->zstream.avail_out = sizeof (ztk->output); + ztk->real_length = packfile->realsize; - file->z = ztk; - } + // Initialize zlib stream + ztk->zstream.next_in = ztk->input; + ztk->zstream.avail_in = 0; - return file; - } - } - } - else - { - snprintf (netpath, sizeof (netpath), "%s/%s",search->filename, filename); + /* From Zlib's "unzip.c": + * + * windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + if (qz_inflateInit2 (&ztk->zstream, -MAX_WBITS) != Z_OK) + Sys_Error ("inflate init error (file: %s)", filename); - if (!FS_SysFileExists (netpath)) - continue; + ztk->zstream.next_out = ztk->output; + ztk->zstream.avail_out = sizeof (ztk->output); - if (!quiet) - Sys_Printf ("FindFile: %s\n",netpath); - return FS_OpenRead (netpath, -1, -1); - } + file->z = ztk; } -#endif - - if (!quiet) - Sys_Printf ("FindFile: can't find %s\n", filename); - fs_filesize = -1; - return NULL; + return file; } @@ -1308,12 +1344,13 @@ size_t FS_Read (qfile_t* file, void* buffer, size_t buffersize) // If "input" is also empty, we need to fill it if (ztk->in_ind == ztk->in_max) { - size_t remain = file->length - ztk->in_position; + size_t remain; // If we are at the end of the file - if (!remain) + if (ztk->out_position == ztk->real_length) return nb; + remain = file->length - ztk->in_position; count = (remain > sizeof (ztk->input)) ? sizeof (ztk->input) : remain; fread (ztk->input, 1, count, file->stream); @@ -1394,6 +1431,18 @@ int FS_Flush (qfile_t* file) } +/* +==================== +FS_Print + +Print a string into a file +==================== +*/ +int FS_Print(qfile_t* file, const char *msg) +{ + return FS_Write(file, msg, strlen(msg)); +} + /* ==================== FS_Printf @@ -1401,7 +1450,7 @@ FS_Printf Print a string into a file ==================== */ -int FS_Printf (qfile_t* file, const char* format, ...) +int FS_Printf(qfile_t* file, const char* format, ...) { int result; va_list args; @@ -1670,7 +1719,7 @@ Filename are relative to the quake directory. Always appends a 0 byte. ============ */ -qbyte *FS_LoadFile (const char *path, qboolean quiet) +qbyte *FS_LoadFile (const char *path, mempool_t *pool, qboolean quiet) { qfile_t *h; qbyte *buf; @@ -1680,7 +1729,7 @@ qbyte *FS_LoadFile (const char *path, qboolean quiet) if (!h) return NULL; - buf = Mem_Alloc(tempmempool, fs_filesize+1); + buf = Mem_Alloc(pool, fs_filesize+1); if (!buf) Sys_Error ("FS_LoadFile: not enough available memory for %s (size %i)", path, fs_filesize); @@ -1702,24 +1751,18 @@ The filename will be prefixed by the current game directory */ qboolean FS_WriteFile (const char *filename, void *data, int len) { - FILE *handle; - char name[MAX_OSPATH]; - - snprintf (name, sizeof (name), "%s/%s", fs_gamedir, filename); + qfile_t *handle; - // Create directories up to the file - FS_CreatePath (name); - - handle = fopen (name, "wb"); + handle = FS_Open (filename, "wb", false); if (!handle) { - Con_Printf ("FS_WriteFile: failed on %s\n", name); + Con_Printf("FS_WriteFile: failed on %s\n", filename); return false; } - Con_DPrintf ("FS_WriteFile: %s\n", name); - fwrite (data, 1, len, handle); - fclose (handle); + Con_DPrintf("FS_WriteFile: %s\n", filename); + FS_Write (handle, data, len); + FS_Close (handle); return true; } @@ -1784,34 +1827,26 @@ void FS_DefaultExtension (char *path, const char *extension, size_t size_path) } +/* +================== +FS_FileExists + +Look for a file in the packages and in the filesystem +================== +*/ qboolean FS_FileExists (const char *filename) { - searchpath_t *search; - char netpath[MAX_OSPATH]; - pack_t *pak; - int i; - - for (search = fs_searchpaths;search;search = search->next) - { - if (search->pack) - { - pak = search->pack; - for (i = 0;i < pak->numfiles;i++) - if (!strcmp (pak->files[i].name, filename)) - return true; - } - else - { - snprintf (netpath, sizeof (netpath), "%s/%s",search->filename, filename); - if (FS_SysFileExists (netpath)) - return true; - } - } - - return false; + return (FS_FindFile (filename, NULL, true) != NULL); } +/* +================== +FS_SysFileExists + +Look for a file in the filesystem only +================== +*/ qboolean FS_SysFileExists (const char *path) { #if WIN32 @@ -1856,11 +1891,12 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) fssearch_t *search; searchpath_t *searchpath; pack_t *pak; - int i, basepathlength, numfiles, numchars, step; - stringlist_t *dir, *dirfile; + int i, basepathlength, numfiles, numchars; + stringlist_t *dir, *dirfile, *liststart, *listcurrent, *listtemp; const char *slash, *backslash, *colon, *separator; char *basepath; char netpath[MAX_OSPATH]; + char temp[MAX_OSPATH]; while(!strncmp(pattern, "./", 2)) pattern += 2; @@ -1868,94 +1904,122 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) pattern += 2; search = NULL; - numfiles = 0; - numchars = 0; + liststart = NULL; + listcurrent = NULL; + listtemp = NULL; slash = strrchr(pattern, '/'); backslash = strrchr(pattern, '\\'); colon = strrchr(pattern, ':'); - separator = slash; + separator = pattern; + if (separator < slash) + separator = slash; if (separator < backslash) separator = backslash; if (separator < colon) separator = colon; - if (separator) - basepathlength = separator + 1 - pattern; - else - basepathlength = 0; + basepathlength = separator - pattern; basepath = Z_Malloc(basepathlength + 1); if (basepathlength) memcpy(basepath, pattern, basepathlength); basepath[basepathlength] = 0; - for (step = 0;step < 2;step++) + // search through the path, one element at a time + for (searchpath = fs_searchpaths;searchpath;searchpath = searchpath->next) { - // search through the path, one element at a time - for (searchpath = fs_searchpaths;searchpath;searchpath = searchpath->next) + // is the element a pak file? + if (searchpath->pack) { - // is the element a pak file? - if (searchpath->pack) + // look through all the pak file elements + pak = searchpath->pack; + for (i = 0;i < pak->numfiles;i++) { - // look through all the pak file elements - pak = searchpath->pack; - for (i = 0;i < pak->numfiles;i++) + strcpy(temp, pak->files[i].name); + while (temp[0]) { - if (matchpattern(pak->files[i].name, (char *)pattern, caseinsensitive || pak->ignorecase)) + if (matchpattern(temp, (char *)pattern, true)) { - if (search) + for (listtemp = liststart;listtemp;listtemp = listtemp->next) + if (!strcmp(listtemp->text, temp)) + break; + if (listtemp == NULL) { - search->filenames[numfiles] = search->filenamesbuffer + numchars; - strcpy(search->filenames[numfiles], pak->files[i].name); + listcurrent = stringlistappend(listcurrent, temp); + if (liststart == NULL) + liststart = listcurrent; + if (!quiet) + Sys_Printf("SearchPackFile: %s : %s\n", pak->filename, temp); } - numfiles++; - numchars += strlen(pak->files[i].name) + 1; - if (!quiet) - Sys_Printf("SearchPackFile: %s : %s\n", pak->filename, pak->files[i].name); } + // strip off one path element at a time until empty + // this way directories are added to the listing if they match the pattern + slash = strrchr(temp, '/'); + backslash = strrchr(temp, '\\'); + colon = strrchr(temp, ':'); + separator = temp; + if (separator < slash) + separator = slash; + if (separator < backslash) + separator = backslash; + if (separator < colon) + separator = colon; + *((char *)separator) = 0; } } - else + } + else + { + // get a directory listing and look at each name + snprintf(netpath, sizeof (netpath), "%s/%s", searchpath->filename, basepath); + if ((dir = listdirectory(netpath))) { - // get a directory listing and look at each name - snprintf(netpath, sizeof (netpath), "%s/%s", searchpath->filename, pattern); - if ((dir = listdirectory(netpath))) + for (dirfile = dir;dirfile;dirfile = dirfile->next) { - for (dirfile = dir;dirfile;dirfile = dirfile->next) + snprintf(temp, sizeof(temp), "%s/%s", basepath, dirfile->text); + if (matchpattern(temp, (char *)pattern, true)) { - if (matchpattern(dirfile->text, (char *)pattern + basepathlength, caseinsensitive)) + for (listtemp = liststart;listtemp;listtemp = listtemp->next) + if (!strcmp(listtemp->text, temp)) + break; + if (listtemp == NULL) { - if (search) - { - search->filenames[numfiles] = search->filenamesbuffer + numchars; - memcpy(search->filenames[numfiles], basepath, basepathlength); - strcpy(search->filenames[numfiles] + basepathlength, dirfile->text); - } - numfiles++; - numchars += basepathlength + strlen(dirfile->text) + 1; + listcurrent = stringlistappend(listcurrent, temp); + if (liststart == NULL) + liststart = listcurrent; if (!quiet) - Sys_Printf("SearchDirFile: %s\n", dirfile->text); + Sys_Printf("SearchDirFile: %s\n", temp); } } - freedirectory(dir); } + freedirectory(dir); } } + } - if (step == 0) + if (liststart) + { + liststart = stringlistsort(liststart); + numfiles = 0; + numchars = 0; + for (listtemp = liststart;listtemp;listtemp = listtemp->next) { - if (!numfiles || !numchars) - { - Z_Free(basepath); - return NULL; - } - // prepare for second pass (allocate the memory to fill in) - search = Z_Malloc(sizeof(fssearch_t) + numchars + numfiles * sizeof(char *)); - search->filenames = (char **)((char *)search + sizeof(fssearch_t)); - search->filenamesbuffer = (char *)((char *)search + sizeof(fssearch_t) + numfiles * sizeof(char *)); - search->numfilenames = numfiles; - // these are used for tracking as the buffers are written on the second pass - numfiles = 0; - numchars = 0; + numfiles++; + numchars += strlen(listtemp->text) + 1; + } + search = Z_Malloc(sizeof(fssearch_t) + numchars + numfiles * sizeof(char *)); + search->filenames = (char **)((char *)search + sizeof(fssearch_t)); + search->filenamesbuffer = (char *)((char *)search + sizeof(fssearch_t) + numfiles * sizeof(char *)); + search->numfilenames = numfiles; + numfiles = 0; + numchars = 0; + for (listtemp = liststart;listtemp;listtemp = listtemp->next) + { + search->filenames[numfiles] = search->filenamesbuffer + numchars; + strcpy(search->filenames[numfiles], listtemp->text); + numfiles++; + numchars += strlen(listtemp->text) + 1; } + if (liststart) + stringlistfree(liststart); } Z_Free(basepath); @@ -2036,49 +2100,29 @@ int FS_ListDirectory(const char *pattern, int oneperline) return numfiles; } -void FS_Dir_f(void) +static void FS_ListDirectoryCmd (const char* cmdname, int oneperline) { - char pattern[MAX_OSPATH]; + const char *pattern; if (Cmd_Argc() > 3) { - Con_Printf("usage:\ndir [path/pattern]\n"); + Con_Printf("usage:\n%s [path/pattern]\n", cmdname); return; } if (Cmd_Argc() == 2) - { - snprintf(pattern, sizeof(pattern), "%s", Cmd_Argv(1)); - if (!FS_ListDirectory(pattern, true)) - { - snprintf(pattern, sizeof(pattern), "%s/*", Cmd_Argv(1)); - if (!FS_ListDirectory(pattern, true)) - Con_Printf("No files found.\n"); - } - } + pattern = Cmd_Argv(1); else - { - if (!FS_ListDirectory("*", true)) - Con_Printf("No files found.\n"); - } + pattern = "*"; + if (!FS_ListDirectory(pattern, oneperline)) + Con_Print("No files found.\n"); +} + +void FS_Dir_f(void) +{ + FS_ListDirectoryCmd("dir", true); } void FS_Ls_f(void) { - char pattern[MAX_OSPATH]; - if (Cmd_Argc() > 3) - { - Con_Printf("usage:\ndir [path/pattern]\n"); - return; - } - if (Cmd_Argc() == 2) - { - snprintf(pattern, sizeof(pattern), "%s", Cmd_Argv(1)); - if (!FS_ListDirectory(pattern, false)) - { - snprintf(pattern, sizeof(pattern), "%s/*", Cmd_Argv(1)); - FS_ListDirectory(pattern, false); - } - } - else - FS_ListDirectory("*", false); + FS_ListDirectoryCmd("ls", false); }