133 lines
3.3 KiB
C#
133 lines
3.3 KiB
C#
#nullable disable
|
|
|
|
using System;
|
|
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Threading;
|
|
|
|
namespace BizHawk.Common
|
|
{
|
|
/// <summary>
|
|
/// Starts a thread which cleans any filenames in %temp% beginning with bizhawk.bizdelete.
|
|
/// Files shouldn't be named that unless they're safe to delete, but notably, they may still be in use. That won't hurt this component.
|
|
/// When they're no longer in use, this component will then be able to delete them.
|
|
/// </summary>
|
|
public static class TempFileManager
|
|
{
|
|
// TODO - manage paths other than %temp%, make not static, or allow adding multiple paths to static instance
|
|
|
|
public static string GetTempFilename(string friendlyName, string extension = null, bool delete = true)
|
|
{
|
|
string guidPart = Guid.NewGuid().ToString();
|
|
var fname = $"biz-{System.Diagnostics.Process.GetCurrentProcess().Id}-{friendlyName}-{guidPart}{extension ?? ""}";
|
|
if (delete)
|
|
{
|
|
fname = RenameTempFilenameForDelete(fname);
|
|
}
|
|
|
|
return Path.Combine(Path.GetTempPath(), fname);
|
|
}
|
|
|
|
/// <exception cref="InvalidOperationException">filename in <paramref name="path"/> is not one generated by <see cref="GetTempFilename"/></exception>
|
|
public static string RenameTempFilenameForDelete(string path)
|
|
{
|
|
string filename = Path.GetFileName(path);
|
|
string dir = Path.GetDirectoryName(path);
|
|
if (!filename.StartsWith("biz-"))
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
|
|
filename = $"bizdelete-{filename.Remove(0, 4)}";
|
|
return Path.Combine(dir, filename);
|
|
}
|
|
|
|
public static void Start()
|
|
{
|
|
lock (typeof(TempFileManager))
|
|
{
|
|
if (thread != null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
thread = new Thread(ThreadProc)
|
|
{
|
|
IsBackground = true,
|
|
Priority = ThreadPriority.Lowest
|
|
};
|
|
thread.Start();
|
|
}
|
|
}
|
|
|
|
static void ThreadProc()
|
|
{
|
|
// squirrely logic, trying not to create garbage
|
|
var knownTempDirs = new HashSet<string>();
|
|
var dis = new List<DirectoryInfo>();
|
|
for (;;)
|
|
{
|
|
lock (typeof(TempFileManager))
|
|
{
|
|
knownTempDirs.Add(Path.GetTempPath());
|
|
if (dis.Count != knownTempDirs.Count)
|
|
dis = knownTempDirs.Select(x => new DirectoryInfo(x)).ToList();
|
|
}
|
|
|
|
foreach(var di in dis)
|
|
{
|
|
FileInfo[] fis = null;
|
|
try
|
|
{
|
|
fis = di.GetFiles("bizdelete-*");
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
if (fis != null)
|
|
{
|
|
foreach (var fi in fis)
|
|
{
|
|
try
|
|
{
|
|
if (OSTailoredCode.IsUnixHost)
|
|
{
|
|
fi.Delete(); // naive deletion, Mono doesn't care
|
|
}
|
|
else
|
|
{
|
|
Win32Imports.DeleteFileW(fi.FullName); // SHUT. UP. THE. EXCEPTIONS.
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
// try not to do more than one thing per frame
|
|
Thread.Sleep(100);
|
|
}
|
|
}
|
|
}
|
|
|
|
// try not to slam the filesystem too hard, we don't want this to cause any hiccups
|
|
Thread.Sleep(5000);
|
|
}
|
|
}
|
|
|
|
public static void Stop()
|
|
{
|
|
}
|
|
|
|
static Thread thread;
|
|
|
|
public static void HelperSetTempPath(string path)
|
|
{
|
|
//yes... this is how we're doing it, for now, until it's proven to be troublesome
|
|
Directory.CreateDirectory(path);
|
|
Environment.SetEnvironmentVariable("TMP", path);
|
|
Environment.SetEnvironmentVariable("TEMP", path);
|
|
}
|
|
}
|
|
} |