mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
This is a gigantic kerfuffle because Chromium expects a very specific directory & app bundle layout. Have to change a bunch of resource loading code to account for content development being launched from an app bundle, and also had to make automatic MSBuild tooling & a python script to generate such an app bundle
106 lines
3.9 KiB
C#
106 lines
3.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using Robust.Shared.Utility;
|
|
|
|
namespace Robust.Shared.ContentPack
|
|
{
|
|
/// <summary>
|
|
/// Utility functions
|
|
/// </summary>
|
|
internal static class PathHelpers
|
|
{
|
|
/// <summary>
|
|
/// Get the full directory path that the executable is located in.
|
|
/// </summary>
|
|
internal static string GetExecutableDirectory()
|
|
{
|
|
// TODO: remove this shitty hack, either through making it less hardcoded into shared,
|
|
// or by making our file structure less spaghetti somehow.
|
|
string location;
|
|
if (Process.GetCurrentProcess().MainModule is { } mod)
|
|
{
|
|
location = mod.FileName;
|
|
}
|
|
else
|
|
{
|
|
// Fallback in case the above doesn't work ig?
|
|
var assembly = typeof(PathHelpers).Assembly;
|
|
location = assembly.Location;
|
|
}
|
|
|
|
if (location == string.Empty)
|
|
{
|
|
// See https://docs.microsoft.com/en-us/dotnet/api/system.reflection.assembly.location?view=net-5.0#remarks
|
|
// This doesn't apply to us really because we don't do that kind of publishing, but whatever.
|
|
throw new InvalidOperationException("Cannot find path of executable.");
|
|
}
|
|
return Path.GetDirectoryName(location)!;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Turns a relative path from the executable directory into a full path.
|
|
/// </summary>
|
|
public static string ExecutableRelativeFile(string file)
|
|
{
|
|
return Path.GetFullPath(Path.Combine(GetExecutableDirectory(), file));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recursively gets all files in a directory and all sub directories.
|
|
/// </summary>
|
|
/// <param name="path">Directory to start in.</param>
|
|
/// <returns>Enumerable of all file paths in that directory and sub directories.</returns>
|
|
public static IEnumerable<string> GetFiles(string path)
|
|
{
|
|
return Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories);
|
|
}
|
|
|
|
public static bool IsFileInUse(IOException exception)
|
|
{
|
|
var errorCode = exception.HResult & 0xFFFF;
|
|
return errorCode switch
|
|
{
|
|
// TODO: verify works on non-win systems
|
|
32 => /* sharing not allowed */ true,
|
|
33 => /* file is locked */ true,
|
|
_ => false
|
|
};
|
|
}
|
|
|
|
// TODO: gaf
|
|
public static bool IsFileSystemCaseSensitive() =>
|
|
!OperatingSystem.IsWindows()
|
|
&& !OperatingSystem.IsMacOS();
|
|
|
|
|
|
internal static string SafeGetResourcePath(string baseDir, ResPath path)
|
|
{
|
|
var relSysPath = path.ToRelativeSystemPath();
|
|
|
|
// This also blocks files like "..foo.yml". But whatever, I CBF fixing that.
|
|
if (relSysPath.Contains("\\..")
|
|
|| relSysPath.Contains("/..")
|
|
|| relSysPath.StartsWith(".."))
|
|
{
|
|
// Hard cap on any exploit smuggling a .. in there.
|
|
// Since that could allow leaving sandbox.
|
|
throw new InvalidOperationException($"This branch should never be reached. Path: {path}");
|
|
}
|
|
|
|
var retPath = Path.GetFullPath(Path.Join(baseDir, relSysPath));
|
|
// better safe than sorry check
|
|
if (!retPath.StartsWith(baseDir))
|
|
{
|
|
// Allow path to match if it's just missing the directory separator at the end.
|
|
if (retPath != baseDir.TrimEnd(Path.DirectorySeparatorChar))
|
|
throw new InvalidOperationException($"This branch should never be reached. Path: {path}");
|
|
}
|
|
|
|
return retPath;
|
|
}
|
|
}
|
|
}
|