PathMan::LookUp PathMan::lookup(const char * path) { LookUp lu = {SUCCESS, State(), 0, 0}; uint32_t len; if (!path) lu.err = NO_PATH; len = strlen(path); if (!len) lu.err = EMPTY_PATH; if (len > 65535) lu.err = PATH_TOO_LONG; if (lu.err == SUCCESS) { PTrie::Tuple tuple = trie._find_i(len, path); if (tuple.index) { Node node = tuple.node->data; if (node.isfile) { FileTuple file = FileIter(files, 0).get_node(node.data); lu.file = file.node; } else if (node.isdir) { DirTuple dir = DirIter(dirs, 0).get_node(node.data); lu.dir = dir.node; } } else { lu.err = NOT_FOUND; } } return lu; }
void PathMan::_rmfile(uint32_t index) { FileIter iter = FileIter(files, 0); FileTuple tuple = iter.get_node(index); if (tuple.index) { tuple.node->next = ffreelist; tuple.node->isused = 0; ffreelist = tuple.index; } }
PathMan::FileTuple PathMan::_mkfile() { FileBank * bank; FileTuple ft = {0,0}; const uint32_t len = sizeof(bank->nodes)/sizeof(bank->nodes[0]); if (ffreelist) { /* reuse nodes from freelist */ FileIter iter = FileIter(files, index2idx(ffreelist)); File * file; if ((bank = iter.get_bank())) { /* get */ file = &bank->nodes[iter.idx - bank->start]; if (!file->isused) { ffreelist = file->next; file->next = 0; ft.node = file; ft.index = idx2index(iter.idx); } } } else { ft = afbank->_mknode(); if (!ft.index && afbank) { uint32_t start = afbank->start + len; bank = new FileBank(start); ft = bank->_mknode(); if (ft.index) { /* link bank in */ files->prev = bank; bank->next = files; files = bank; afbank = bank; } else { delete bank; } } } return ft; }
/** * Helper function designed to determine if the provided package should be backed up or not. * The function checks for many conditions, such as if the package is too large to backup, * if the package has a particular attribute that should prevent it from being backed up (such * as being marked for PIE-use), if cooking is in progress, etc. * * @param InPackage Package which should be checked to see if its valid for backing-up * @param OutFileName File name of the package on disk if the function determines the package * already existed * * @return true if the package is valid for backing-up; false otherwise */ bool FAutoPackageBackup::ShouldBackupPackage( const UPackage& InPackage, FString& OutFilename ) { // Check various conditions to see if the package is a valid candidate for backing up bool bShouldBackup = GIsEditor // Backing up packages only makes sense in the editor && !IsRunningCommandlet() // Don't backup saves resulting from commandlets && IsPackageBackupEnabled() // Ensure that the package backup is enabled in the first place && (InPackage.HasAnyPackageFlags(PKG_PlayInEditor) == false) // Don't back up PIE packages && (InPackage.HasAnyPackageFlags(PKG_ContainsScript) == false); // Don't back up script packages if( bShouldBackup ) { GWarn->StatusUpdate( -1, -1, NSLOCTEXT("UnrealEd", "PackageBackup_ValidityWarning", "Determining asset backup validity...") ); bShouldBackup = FPackageName::DoesPackageExist( InPackage.GetName(), NULL, &OutFilename ); // Make sure the file already exists (no sense in backing up a new package) } // If the package passed the initial backup checks, proceed to check more specific conditions // that might disqualify the package from being backed up const int32 FileSizeOfBackup = IFileManager::Get().FileSize( *OutFilename ); if ( bShouldBackup ) { // Ensure that the size the backup would require is less than that of the maximum allowed // space for backups bShouldBackup = FileSizeOfBackup <= GetMaxAllowedBackupSpace(); } // If all of the prior checks have passed, now see if the package has been backed up // too recently to be considered for an additional backup if ( bShouldBackup ) { // Ensure that the autosave/backup directory exists const FString& BackupSaveDir = GetBackupDirectory(); IFileManager::Get().MakeDirectory( *BackupSaveDir, 1 ); // Find all of the files in the backup directory TArray<FString> FilesInBackupDir; IFileManager::Get().FindFilesRecursive(FilesInBackupDir, *BackupSaveDir, TEXT("*.*"), true, false); // Extract the base file name and extension from the passed-in package file name FString ExistingBaseFileName = FPaths::GetBaseFilename(OutFilename); FString ExistingFileNameExtension = FPaths::GetExtension(OutFilename); bool bFoundExistingBackup = false; int32 DirectorySize = 0; FDateTime LastBackupTimeStamp = FDateTime::MinValue(); TArray<FBackupFileInfo> BackupFileInfoArray; // Check every file in the backup directory for matches against the passed-in package // (Additionally keep statistics on all backup files for potential maintenance) for ( TArray<FString>::TConstIterator FileIter( FilesInBackupDir ); FileIter; ++FileIter ) { const FString CurBackupFileName = FString( *FileIter ); // Create a new backup file info struct for keeping information about each backup file const int32 FileInfoIndex = BackupFileInfoArray.AddZeroed(); FBackupFileInfo& CurBackupFileInfo = BackupFileInfoArray[ FileInfoIndex ]; // Record the backup file's name, size, and timestamp CurBackupFileInfo.FileName = CurBackupFileName; CurBackupFileInfo.FileSize = IFileManager::Get().FileSize( *CurBackupFileName ); // If we failed to get a timestamp or a valid size, something has happened to the file and it shouldn't be considered CurBackupFileInfo.FileTimeStamp = IFileManager::Get().GetTimeStamp(*CurBackupFileName); if (CurBackupFileInfo.FileTimeStamp == FDateTime::MinValue() || CurBackupFileInfo.FileSize == -1) { BackupFileInfoArray.RemoveAt( BackupFileInfoArray.Num() - 1 ); continue; } // Calculate total directory size by adding the size of this backup file DirectorySize += CurBackupFileInfo.FileSize; FString CurBackupBaseFileName = FPaths::GetBaseFilename(CurBackupFileName); FString CurBackupFileNameExtension = FPaths::GetExtension(CurBackupFileName); // The base file name of the backup file is going to include an underscore followed by a timestamp, so they must be removed for comparison's sake CurBackupBaseFileName = CurBackupBaseFileName.Left( CurBackupBaseFileName.Find( TEXT("_"), ESearchCase::CaseSensitive, ESearchDir::FromEnd ) ); // If the base file names and extensions match, we've found a backup if ( CurBackupBaseFileName == ExistingBaseFileName && CurBackupFileNameExtension == ExistingFileNameExtension ) { bFoundExistingBackup = true; // Keep track of the most recent matching time stamp so we can check if the passed-in package // has been backed up too recently if ( CurBackupFileInfo.FileTimeStamp > LastBackupTimeStamp ) { LastBackupTimeStamp = CurBackupFileInfo.FileTimeStamp; } } } // If there was an existing backup, check to see if it was created too recently to allow another backup if ( bFoundExistingBackup ) { // Check the difference in timestamp seconds against the backup interval; if not enough time has elapsed since // the last backup, we don't want to make another one if ((FDateTime::UtcNow() - LastBackupTimeStamp).GetTotalSeconds() < GetBackupInterval()) { bShouldBackup = false; } } // If every other check against the package has succeeded for backup purposes, ensure there is enough directory space // available in the backup directory, as adding the new backup might use more space than the user allowed for backups. // If the backup file size + the current directory size exceeds the max allowed space, deleted old backups until there // is sufficient space. If enough space can't be freed for whatever reason, then no back-up will be created. if ( bShouldBackup && ( FileSizeOfBackup + DirectorySize > GetMaxAllowedBackupSpace() ) ) { bShouldBackup = PerformBackupSpaceMaintenance( BackupFileInfoArray, DirectorySize, FileSizeOfBackup ); } } return bShouldBackup; }
void PathMan::print(int pipe) { FILE * fd = fdopen(pipe, "w"); if (!fd) return; fprintf(fd, "digraph pathman {\n"); fprintf(fd, " graph [rankdir = TD]\n"); fprintf(fd, " node [fontsize = 12, fontname = \"monospace\"]\n"); fprintf(fd, " edge []\n"); fprintf(fd, " \"pathman\" [ shape = plaintext, label = <" "<table cellborder=\"1\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\">" "<tr><td bgcolor=\"red\">pathman</td></tr>" "<tr><td port=\"f0\" bgcolor=\"gray\">%u</td></tr>" "</table>>]\n", trie.root); if (trie.root) { fprintf(fd, " \"pathman\":f0 -> \"dir%u\":f0;\n", trie.root); } DirIter diter = DirIter(dirs, 0); DirTuple dt; FileIter fiter = FileIter(files, 0); FileTuple ft; for (PTrie::Iter iter = PTrie::Iter(trie); iter.go();) { if (iter.tuple.index) { Node node = iter.tuple.node->data; if (node.isdir && iter.word[iter.len-1] == '/') { dt = diter.get_node(node.data); if (dt.index) { fprintf(fd, " \"dir%u\" [ shape = plaintext, label = <", dt.index); fprintf(fd, "<table cellborder=\"1\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\">"); fprintf(fd, "<tr>"); fprintf(fd, "<td port=\"f0\">%d</td>", dt.index); if (dt.node->next) fprintf(fd, "<td port=\"f2\">→%u</td>", dt.node->next); fprintf(fd, "</tr>"); fprintf(fd, "<tr>"); const char * basename = NULL; if (iter.len > 1) { for (uint16_t k = 0; k < iter.len; k++) { if (iter.word[k] == '/') { if (iter.len > 1 && k < iter.len - 1) basename = iter.word + k + 1; } } } else { basename = iter.word; } fprintf(fd, "<td port=\"f1\" bgcolor=\"gray\">%.*s</td>", (int) (iter.len - (basename - iter.word) - (iter.len > 1 ? 1 : 0)), basename); if (dt.node->child) fprintf(fd, "<td port=\"f3\">↓%u</td>", dt.node->child); fprintf(fd, "</tr>"); if (dt.node->file) { fprintf(fd, "<tr>"); fprintf(fd, "<td bgcolor=\"green\" port=\"f4\">%u</td>", dt.node->file); fprintf(fd, "</tr>"); } fprintf(fd, "</table>"); fprintf(fd, ">]\n"); if (dt.node->child) { fprintf(fd, " \"dir%u\":f3 -> \"dir%u\":f0 [color=red];\n", dt.index, dt.node->child); } if (dt.node->next) { fprintf(fd, " \"dir%u\":f2 -> \"dir%u\":f0 [color=blue, minlen=0];\n", dt.index, dt.node->next); } if (dt.node->file) { fprintf(fd, " \"dir%u\":f4 -> \"file%u\":f0 [color=green];\n", dt.index, dt.node->file); } } } else if (node.isfile) { ft = fiter.get_node(node.data); if (ft.index) { fprintf(fd, " \"file%u\" [ shape = plaintext, label = <", ft.index); fprintf(fd, "<table bgcolor=\"green\" cellborder=\"1\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\">"); fprintf(fd, "<tr>"); fprintf(fd, "<td port=\"f0\">%d</td>", ft.index); if (ft.node->next) fprintf(fd, "<td port=\"f2\">→%u</td>", ft.node->next); fprintf(fd, "</tr>"); fprintf(fd, "<tr><td >@%u[%u]</td></tr>", ft.node->offset, ft.node->size); fprintf(fd, "<tr>"); const char * basename = NULL; if (iter.len > 1) { for (uint16_t k = 0; k < iter.len; k++) { if (iter.word[k] == '/') { if (iter.len > 1 && k < iter.len - 1) basename = iter.word + k + 1; } } } else { basename = iter.word; } fprintf(fd, "<td port=\"f1\" bgcolor=\"gray\">%.*s</td>", (int) (iter.len - (basename - iter.word)), basename); fprintf(fd, "</tr>"); fprintf(fd, "</table>"); fprintf(fd, ">]\n"); if (ft.node->next) { fprintf(fd, " \"file%u\":f2 -> \"file%u\":f0 [color=green, minlen=0];\n", ft.index, ft.node->next); } } } } fflush(fd); } fprintf(fd, "}\n"); fclose(fd); }
FileIter File::getFiles(void) { return FileIter(*this); }