Как извлечь образ диска FAT?
Я на самом деле пытаюсь извлечь образ диска с помощью DiskUtils, но я не получаю правильные имена файлов...
Я получаю "\TURNER~3\TOPPER~1.P~1" вместо "\TURNEROVER\TOPPERSHEATH.PPTX"
FatFileSystem FatImg = new FatFileSystem(MS); //MS = Fat Image MemoryStream
foreach(DiscDirectoryInfo Di in FatImg.Root.GetDirectories())
{
foreach(DiscFileInfo Fi in Di.GetFiles())
{
Stream St = Fi.OpenRead(); // Correct Stream
string FName = Fi.Name; //Wrong Name
}
}
Это связано с тем, что DiscUtils не поддерживает LFN [длинные имена файлов]...
Поэтому я ищу идеальную библиотеку для извлечения этих файлов, прежде чем я попытаюсь создать ее самостоятельно...
Есть ли способ извлечь его [возможно, DiscUtils] без ошибок File Name...
5 ответов
Вот некоторые модификации, которые вы можете добавить к DiscUtils
поддерживать FAT LFN
s:
Сначала внесите эти изменения в Fat\Directory.cs
файл, как это (вам нужно добавить _lfns
переменная, GetLfnChunk
функционировать и изменять существующие LoadEntries
функция для добавления линий, отмеченных //+++
ниже):
internal Dictionary<string, string> _lfns = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
private static string GetLfnChunk(byte[] buffer)
{
// see http://home.teleport.com/~brainy/lfn.htm
// NOTE: we assume ordinals are ok here.
char[] chars = new char[13];
chars[0] = (char)(256 * buffer[2] + buffer[1]);
chars[1] = (char)(256 * buffer[4] + buffer[3]);
chars[2] = (char)(256 * buffer[6] + buffer[5]);
chars[3] = (char)(256 * buffer[8] + buffer[7]);
chars[4] = (char)(256 * buffer[10] + buffer[9]);
chars[5] = (char)(256 * buffer[15] + buffer[14]);
chars[6] = (char)(256 * buffer[17] + buffer[16]);
chars[7] = (char)(256 * buffer[19] + buffer[18]);
chars[8] = (char)(256 * buffer[21] + buffer[20]);
chars[9] = (char)(256 * buffer[23] + buffer[22]);
chars[10] = (char)(256 * buffer[25] + buffer[24]);
chars[11] = (char)(256 * buffer[29] + buffer[28]);
chars[12] = (char)(256 * buffer[31] + buffer[30]);
string chunk = new string(chars);
int zero = chunk.IndexOf('\0');
return zero >= 0 ? chunk.Substring(0, zero) : chunk;
}
private void LoadEntries()
{
_entries = new Dictionary<long, DirectoryEntry>();
_freeEntries = new List<long>();
_selfEntryLocation = -1;
_parentEntryLocation = -1;
string lfn = null; //+++
while (_dirStream.Position < _dirStream.Length)
{
long streamPos = _dirStream.Position;
DirectoryEntry entry = new DirectoryEntry(_fileSystem.FatOptions, _dirStream);
if (entry.Attributes == (FatAttributes.ReadOnly | FatAttributes.Hidden | FatAttributes.System | FatAttributes.VolumeId))
{
// Long File Name entry
_dirStream.Position = streamPos; //+++
lfn = GetLfnChunk(Utilities.ReadFully(_dirStream, 32)) + lfn; //+++
}
else if (entry.Name.IsDeleted())
{
// E5 = Free Entry
_freeEntries.Add(streamPos);
lfn = null; //+++
}
else if (entry.Name == FileName.SelfEntryName)
{
_selfEntry = entry;
_selfEntryLocation = streamPos;
lfn = null; //+++
}
else if (entry.Name == FileName.ParentEntryName)
{
_parentEntry = entry;
_parentEntryLocation = streamPos;
lfn = null; //+++
}
else if (entry.Name == FileName.Null)
{
// Free Entry, no more entries available
_endOfEntries = streamPos;
lfn = null; //+++
break;
}
else
{
if (lfn != null) //+++
{ //+++
_lfns.Add(entry.Name.GetDisplayName(_fileSystem.FatOptions.FileNameEncoding), lfn); //+++
} //+++
_entries.Add(streamPos, entry);
lfn = null; //+++
}
}
}
Во-вторых, добавьте эти две публичные функции в Fat\FatFileSystem.cs
файл. Это будут новые API для запросов к LFN:
/// <summary>
/// Gets the long name of a given file.
/// </summary>
/// <param name="shortFullPath">The short full path to the file. Input path segments must be short names.</param>
/// <returns>The corresponding long file name.</returns>
public string GetLongFileName(string shortFullPath)
{
if (shortFullPath == null)
throw new ArgumentNullException("shortFullPath");
string dirPath = Path.GetDirectoryName(shortFullPath);
string fileName = Path.GetFileName(shortFullPath);
Directory dir = GetDirectory(dirPath);
if (dir == null)
return fileName;
string lfn;
if (dir._lfns.TryGetValue(Path.GetFileName(shortFullPath), out lfn))
return lfn;
return fileName;
}
/// <summary>
/// Gets the long path to a given file.
/// </summary>
/// <param name="shortFullPath">The short full path to the file. Input path segments must be short names.</param>
/// <returns>The corresponding long file path to the file or null if not found.</returns>
public string GetLongFilePath(string shortFullPath)
{
if (shortFullPath == null)
throw new ArgumentNullException("shortFullPath");
string path = null;
string current = null;
foreach (string segment in shortFullPath.Split(Path.DirectorySeparatorChar))
{
if (current == null)
{
current = segment;
path = GetLongFileName(current);
}
else
{
current = Path.Combine(current, segment);
path = Path.Combine(path, GetLongFileName(current));
}
}
return path;
}
И это все. Теперь вы сможете рекурсивно выгружать весь диск FAT, например, так:
static void Main(string[] args)
{
using (FileStream fs = File.Open("fat.ima", FileMode.Open))
{
using (FatFileSystem floppy = new FatFileSystem(fs))
{
Dump(floppy.Root);
}
}
}
static void Dump(DiscDirectoryInfo di)
{
foreach (DiscDirectoryInfo subdi in di.GetDirectories())
{
Dump(subdi);
}
foreach (DiscFileInfo fi in di.GetFiles())
{
Console.WriteLine(fi.FullName);
// get LFN name
Console.WriteLine(" " + ((FatFileSystem)di.FileSystem).GetLongFileName(fi.FullName));
// get LFN-ed full path
Console.WriteLine(" " + ((FatFileSystem)di.FileSystem).GetLongFilePath(fi.FullName));
}
}
Используйте на свой страх и риск!:)
7-Zip может извлекать изображения FAT. На http://sevenzipsharp.codeplex.com/ библиотека-оболочка C#, которая может читать имена файлов и извлекать их в потоки.
Казалось бы, в DiscUtils отсутствует поддержка файлов FAT для длинных имен. Проверьте этот пост. Что, я уверен, вы знаете, так как похоже, что вы задали вопрос.
Лучший метод с командной строкой - использовать это:
7z "e" + source + "-o" + path + "* -r"
- "е" = экстракт
- источник = путь к образу диска
- "-o" = Вывести / Извлечь в
- путь = место назначения для извлечения в
- " *" = Все файлы
- "-r" = рекурсивный
В C# вы можете использовать этот метод, который я сделал (я скопировал 7z.exe в папку Debug моего приложения)
public void ExtractDiskImage(string pathToDiskImage, string extractPath, bool WaitForFinish)
{
ProcessStartInfo UnzipDiskImage = new ProcessStartInfo("7z.exe");
StringBuilder str = new StringBuilder();
str.Append("e ");
str.Append(pathToDiskImage);
str.Append(" -o");
str.Append(extractPath);
str.Append(" * -r");
UnzipDiskImage.Arguments = str.ToString();
UnzipDiskImage.WindowStyle = ProcessWindowStyle.Hidden;
Process process = Process.Start(UnzipDiskImage);
if(WaitForFinish == true)
{
process.WaitForExit(); //My app had to wait for the extract to finish
}
}
Команда DOS DIR с ключом /X отображает как длинные, так и короткие имена.
В противном случае есть утилита для сохранения LFN: DOSLFNBk.exe, которая поможет с созданием таблицы сопоставления.
Я знаю не те ответы, которые вы искали, но если бы не сначала создать таблицу вручную, чтобы вы могли выполнить сопоставление без DiskUtil, я не могу придумать утилиту или метод для достижения вашей цели - но, как вы упомянули, здесь, на SO, кто-то может знать альтернативу.
Кевин из DiskUtils упомянул, что он нарушил бы патент Mirosoft, если бы включил поддержку LFN, я не предлагаю вам также нарушать (ОПРЕДЕЛЕННО НЕ это коммерческий проект), но если это просто личный проект или вы можете найти такую библиотеку, как 7-Zip имеет лицензию...
Ваш скриншот показывает VNext.. та же ошибка с версиями RTM?