Пример #1
0
  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;
  }
Пример #2
0
  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;
    }
  }
Пример #3
0
  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;
  }
Пример #4
0
/**
 * 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;
}
Пример #5
0
  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);
  }
Пример #6
0
FileIter 
File::getFiles(void)
{
  return FileIter(*this);
}