/* ================ Sys_ListFiles ================ */ int Sys_ListFiles( const char *directory, const char *extension, idStrList &list ) { struct dirent *d; DIR *fdir; bool dironly = false; char search[MAX_OSPATH]; struct stat st; bool debug; list.Clear(); debug = cvarSystem->GetCVarBool( "fs_debug" ); if (!extension) extension = ""; // passing a slash as extension will find directories if (extension[0] == '/' && extension[1] == 0) { extension = ""; dironly = true; } // search // NOTE: case sensitivity of directory path can screw us up here if ((fdir = opendir(directory)) == NULL) { if (debug) { common->Printf("Sys_ListFiles: opendir %s failed\n", directory); } return -1; } while ((d = readdir(fdir)) != NULL) { idStr::snPrintf(search, sizeof(search), "%s/%s", directory, d->d_name); if (stat(search, &st) == -1) continue; if (!dironly) { idStr look(search); idStr ext; look.ExtractFileExtension(ext); if (extension[0] != '\0' && ext.Icmp(&extension[1]) != 0) { continue; } } if ((dironly && !(st.st_mode & S_IFDIR)) || (!dironly && (st.st_mode & S_IFDIR))) continue; list.Append(d->d_name); } closedir(fdir); if ( debug ) { common->Printf( "Sys_ListFiles: %d entries in %s\n", list.Num(), directory ); } return list.Num(); }
/* =============== idSessionLocal::GetSaveGameList =============== */ void idSessionLocal::GetSaveGameList( idStrList &fileList, idList<fileTIME_T> &fileTimes ) { int i; idFileList *files; // NOTE: no fs_game_base for savegames idStr game = cvarSystem->GetCVarString( "fs_game" ); if( game.Length() ) { files = fileSystem->ListFiles( "savegames", ".save", false, false, game ); } else { files = fileSystem->ListFiles( "savegames", ".save" ); } fileList = files->GetList(); fileSystem->FreeFileList( files ); for ( i = 0; i < fileList.Num(); i++ ) { ID_TIME_T timeStamp; fileSystem->ReadFile( "savegames/" + fileList[i], NULL, &timeStamp ); fileList[i].StripLeading( '/' ); fileList[i].StripFileExtension(); fileTIME_T ft; ft.index = i; ft.timeStamp = timeStamp; fileTimes.Append( ft ); } fileTimes.Sort( idListSaveGameCompare ); }
/* ============ idAASBuild::CheckForEntities ============ */ bool idAASBuild::CheckForEntities( const idMapFile *mapFile, idStrList &entityClassNames ) const { int i; idStr classname; com_editors |= EDITOR_AAS; for( i = 0; i < mapFile->GetNumEntities(); i++ ) { if( !mapFile->GetEntity( i )->epairs.GetString( "classname", "", classname ) ) { continue; } if( aasSettings->ValidEntity( classname ) ) { entityClassNames.AddUnique( classname ); } } com_editors &= ~EDITOR_AAS; return ( entityClassNames.Num() != 0 ); }
/* ======================== idResourceContainer::WriteManifestFile ======================== */ void idResourceContainer::WriteManifestFile( const char* name, const idStrList& list ) { idStr filename( name ); filename.SetFileExtension( "manifest" ); filename.Insert( "maps/", 0 ); idFile* outFile = fileSystem->OpenFileWrite( filename ); if( outFile != NULL ) { int num = list.Num(); outFile->WriteBig( num ); for( int i = 0; i < num; i++ ) { outFile->WriteString( list[ i ] ); } delete outFile; } }
/* ======================== idResourceContainer::ReadManifestFile ======================== */ int idResourceContainer::ReadManifestFile( const char* name, idStrList& list ) { idFile* inFile = fileSystem->OpenFileRead( name ); if( inFile != NULL ) { list.SetGranularity( 16384 ); idStr str; int num; list.Clear(); inFile->ReadBig( num ); for( int i = 0; i < num; i++ ) { inFile->ReadString( str ); list.Append( str ); } delete inFile; } return list.Num(); }
/* ============== Sys_ListFiles ============== */ int Sys_ListFiles(const char *directory, const char *extension, idStrList &list) { idStr search; struct _finddata_t findinfo; int findhandle; int flag; if (!extension) { extension = ""; } // passing a slash as extension will find directories if (extension[0] == '/' && extension[1] == 0) { extension = ""; flag = 0; } else { flag = _A_SUBDIR; } sprintf(search, "%s\\*%s", directory, extension); // search list.Clear(); findhandle = _findfirst(search, &findinfo); if (findhandle == -1) { return -1; } do { if (flag ^(findinfo.attrib & _A_SUBDIR)) { list.Append(findinfo.name); } } while (_findnext(findhandle, &findinfo) != -1); _findclose(findhandle); return list.Num(); }
void CDialogTextures::addStrList( const char *root, const idStrList &list, int id ) { idStr out, path; HTREEITEM base = m_treeTextures.GetRootItem(); while (base) { out = m_treeTextures.GetItemText(base); if (stricmp(root, out) == 0) { break; } base = m_treeTextures.GetNextSiblingItem(base); } if (base == NULL) { base = m_treeTextures.InsertItem(root); } HTREEITEM item = base; HTREEITEM add; int count = list.Num(); idStr last, qt; for (int i = 0; i < count; i++) { idStr name = list[i]; // now break the name down convert to slashes name.BackSlashesToSlashes(); name.Strip(' '); int index; int len = last.Length(); if (len == 0) { index = name.Last('/'); if (index >= 0) { name.Left(index, last); } } else if (idStr::Icmpn(last, name, len) == 0 && name.Last('/') <= len) { name.Right(name.Length() - len - 1, out); add = m_treeTextures.InsertItem(out, item); qt = root; qt += "/"; qt += name; quickTree.Set(qt, add); m_treeTextures.SetItemData(add, id); m_treeTextures.SetItemImage(add, 2, 2); continue; } else { last.Empty(); } index = 0; item = base; path = ""; while (index >= 0) { index = name.Find('/'); if (index >= 0) { HTREEITEM newItem = NULL; HTREEITEM *check = NULL; name.Left( index, out ); path += out; qt = root; qt += "/"; qt += path; if (quickTree.Get(qt, &check)) { newItem = *check; } //HTREEITEM newItem = FindTreeItem(&m_treeTextures, item, name.Left(index, out), item); if (newItem == NULL) { newItem = m_treeTextures.InsertItem(out, item); qt = root; qt += "/"; qt += path; quickTree.Set(qt, newItem); m_treeTextures.SetItemImage(newItem, 0, 1); } assert(newItem); item = newItem; name.Right( name.Length() - index - 1, out ); name = out; path += "/"; } else { add = m_treeTextures.InsertItem(name, item); qt = root; qt += "/"; qt += path; qt += name; quickTree.Set(qt, add); m_treeTextures.SetItemData(add, id); m_treeTextures.SetItemImage(add, 2, 2); path = ""; } } } }
/* ================ Sys_ListFiles ================ */ int Sys_ListFiles( const char* directory, const char* extension, idStrList& list ) { struct dirent* d; DIR* fdir; bool dironly = false; char search[MAX_OSPATH]; struct stat st; bool debug; list.Clear(); debug = cvarSystem->GetCVarBool( "fs_debug" ); // DG: we use fnmatch for shell-style pattern matching // so the pattern should at least contain "*" to match everything, // the extension will be added behind that (if !dironly) idStr pattern( "*" ); // passing a slash as extension will find directories if( extension[0] == '/' && extension[1] == 0 ) { dironly = true; } else { // so we have *<extension>, the same as in the windows code basically pattern += extension; } // DG end // NOTE: case sensitivity of directory path can screw us up here if( ( fdir = opendir( directory ) ) == NULL ) { if( debug ) { common->Printf( "Sys_ListFiles: opendir %s failed\n", directory ); } return -1; } // DG: use readdir_r instead of readdir for thread safety // the following lines are from the readdir_r manpage.. fscking ugly. int nameMax = pathconf( directory, _PC_NAME_MAX ); if( nameMax == -1 ) nameMax = 255; int direntLen = offsetof( struct dirent, d_name ) + nameMax + 1; struct dirent* entry = ( struct dirent* )Mem_Alloc( direntLen, TAG_CRAP ); if( entry == NULL ) { common->Warning( "Sys_ListFiles: Mem_Alloc for entry failed!" ); closedir( fdir ); return 0; } while( readdir_r( fdir, entry, &d ) == 0 && d != NULL ) { // DG end idStr::snPrintf( search, sizeof( search ), "%s/%s", directory, d->d_name ); if( stat( search, &st ) == -1 ) continue; if( !dironly ) { // DG: the original code didn't work because d3 bfg abuses the extension // to match whole filenames and patterns in the savegame-code, not just file extensions... // so just use fnmatch() which supports matching shell wildcard patterns ("*.foo" etc) // if we should ever need case insensitivity, use FNM_CASEFOLD as third flag if( fnmatch( pattern.c_str(), d->d_name, 0 ) != 0 ) continue; // DG end } if( ( dironly && !( st.st_mode & S_IFDIR ) ) || ( !dironly && ( st.st_mode & S_IFDIR ) ) ) continue; list.Append( d->d_name ); } closedir( fdir ); Mem_Free( entry ); if( debug ) { common->Printf( "Sys_ListFiles: %d entries in %s\n", list.Num(), directory ); } return list.Num(); }
HTREEITEM CDialogSound::AddStrList(const char *root, const idStrList &list, int id) { idStr out; HTREEITEM base = treeSounds.InsertItem(root); HTREEITEM item = base; HTREEITEM add; int count = list.Num(); idStr last, path, path2; for (int i = 0; i < count; i++) { idStr name = list[i]; // now break the name down convert to slashes name.BackSlashesToSlashes(); name.Strip(' '); int index; int len = last.Length(); if (len == 0) { index = name.Last('/'); if (index >= 0) { name.Left(index, last); } } else if (idStr::Icmpn(last, name, len) == 0 && name.Last('/') <= len) { name.Right(name.Length() - len - 1, out); add = treeSounds.InsertItem(out, item); quickTree.Set(name, add); treeSounds.SetItemData(add, id); treeSounds.SetItemImage(add, 2, 2); continue; } else { last.Empty(); } index = 0; item = base; path = ""; path2 = ""; while (index >= 0) { index = name.Find('/'); if (index >= 0) { HTREEITEM newItem = NULL; HTREEITEM *check = NULL; name.Left( index, out ); path += out; if (quickTree.Get(path, &check)) { newItem = *check; } //HTREEITEM newItem = FindTreeItem(&treeSounds, item, name.Left(index, out), item); if (newItem == NULL) { newItem = treeSounds.InsertItem(out, item); quickTree.Set(path, newItem); treeSounds.SetItemData(newItem, WAVEDIR); treeSounds.SetItemImage(newItem, 0, 1); } assert(newItem); item = newItem; name.Right( name.Length() - index - 1, out ); name = out; path += "/"; } else { add = treeSounds.InsertItem(name, item); treeSounds.SetItemData(add, id); treeSounds.SetItemImage(add, 2, 2); path = ""; } } } return base; }
/* ======================== idResourceContainer::Open ======================== */ void idResourceContainer::WriteResourceFile( const char* manifestName, const idStrList& manifest, const bool& _writeManifest ) { if( manifest.Num() == 0 ) { return; } idLib::Printf( "Writing resource file %s\n", manifestName ); // build multiple output files at 1GB each idList < idStrList > outPutFiles; idFileManifest outManifest; int64 size = 0; idStrList flist; flist.SetGranularity( 16384 ); for( int i = 0; i < manifest.Num(); i++ ) { flist.Append( manifest[ i ] ); size += fileSystem->GetFileLength( manifest[ i ] ); if( size > 1024 * 1024 * 1024 ) { outPutFiles.Append( flist ); size = 0; flist.Clear(); } outManifest.AddFile( manifest[ i ] ); } outPutFiles.Append( flist ); if( _writeManifest ) { idStr temp = manifestName; temp.Replace( "maps/", "manifests/" ); temp.StripFileExtension(); temp.SetFileExtension( "manifest" ); outManifest.WriteManifestFile( temp ); } for( int idx = 0; idx < outPutFiles.Num(); idx++ ) { idStrList& fileList = outPutFiles[ idx ]; if( fileList.Num() == 0 ) { continue; } idStr fileName = manifestName; if( idx > 0 ) { fileName = va( "%s_%02d", manifestName, idx ); } fileName.SetFileExtension( "resources" ); idFile* resFile = fileSystem->OpenFileWrite( fileName ); if( resFile == NULL ) { idLib::Warning( "Cannot open %s for writing.\n", fileName.c_str() ); return; } idLib::Printf( "Writing resource file %s\n", fileName.c_str() ); int tableOffset = 0; int tableLength = 0; int tableNewLength = 0; uint32 resourceFileMagic = RESOURCE_FILE_MAGIC; resFile->WriteBig( resourceFileMagic ); resFile->WriteBig( tableOffset ); resFile->WriteBig( tableLength ); idList< idResourceCacheEntry > entries; entries.Resize( fileList.Num() ); for( int i = 0; i < fileList.Num(); i++ ) { idResourceCacheEntry ent; ent.filename = fileList[ i ]; ent.length = 0; ent.offset = 0; idFile* file = fileSystem->OpenFileReadMemory( ent.filename, false ); idFile_Memory* fm = dynamic_cast< idFile_Memory* >( file ); if( fm == NULL ) { continue; } // if the entry is uncompressed, align the file pointer to a 16 byte boundary // so it will be usable if memory mapped ent.length = fm->Length(); // always get the offset, even if the file will have zero length ent.offset = resFile->Tell(); entries.Append( ent ); if( ent.length == 0 ) { ent.filename = ""; delete fm; continue; } resFile->Write( fm->GetDataPtr(), ent.length ); delete fm; // pacifier every ten megs if( ( ent.offset + ent.length ) / 10000000 != ent.offset / 10000000 ) { idLib::Printf( "." ); } } idLib::Printf( "\n" ); // write the table out now that we have all the files tableOffset = resFile->Tell(); // count how many we are going to write for this platform int numFileResources = entries.Num(); resFile->WriteBig( numFileResources ); // write the individual resource entries for( int i = 0; i < entries.Num(); i++ ) { entries[ i ].Write( resFile ); if( i + 1 == numFileResources ) { // we just wrote out the last new entry tableNewLength = resFile->Tell() - tableOffset; } } // go back and write the header offsets again, now that we have file offsets and lengths tableLength = resFile->Tell() - tableOffset; resFile->Seek( 0, FS_SEEK_SET ); resFile->WriteBig( resourceFileMagic ); resFile->WriteBig( tableOffset ); resFile->WriteBig( tableLength ); delete resFile; } }