C # - How to extract a FAT disk image?

I am really trying to extract a Fat Disk image using DiskUtils, but I am not getting the correct file names ...

I get "\ TURNER ~ 3 \ TOPPER ~ 1.P ~ 1" instead of "\ 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 } } 

This is because DiscUtils does not support LFN [Long File Names] ...

So, I'm looking for the perfect library to extract these files before I try to do it myself ...

Is there a way that I can extract it [maybe DiscUtils] without FileName errors ...

+6
source share
5 answers

Here are some changes you can add to DiscUtils to support FAT LFN s:

First make these changes in the Fat\Directory.cs file like this (you need to add the _lfns variable, the GetLfnChunk function and modify the existing LoadEntries function to add the lines marked with //+++ below):

 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; //+++ } } } 

Second, add these two public functions to the Fat\FatFileSystem.cs . These will be the new API requests for LFN requests:

 /// <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; } 

What is it. Now you can replicate the entire FAT disk in this way, for example:

 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)); } } 

Use your own risks! :)

+3
source

7-Zip can extract FAT images. There is a C # wrapper library at http://sevenzipsharp.codeplex.com that can read file names and extract them into streams.

+2
source

It would seem that there is no support for Long Name files for FAT in DiscUtils. Mark this post. I'm sure you know, since it looks like you asked a question.

+1
source

The DOS DIR command with the / X switch displays both long and short names.

Otherwise, there is a utility for saving LFN: DOSLFNBk.exe , which will help to create a mapping table.

I don’t know the answers you were looking for, but do not manually create the table so that you can do the mapping without DiskUtil, I can’t come up with a utility or method to achieve your goal - but, as you already mentioned, here in SO someone can know an alternative.

Kevin from DiskUtils mentioned that he would infringe on a Mirosoft patent if he turned on LFN support, I don’t assume that you are violating (NOT A DEFINITELY NOT a commercial project), but if it's just personal or if you can find a library like 7-Zip has a license ...

Your screenshot shows VNext .. same error with RTM versions?

0
source

The best way with the command line is to use this:

7z "e" + source + "-o" + path + "* -r"

  • "e" = Extract
  • source = path to disk image
  • "-o" = Output / Extract to
  • path = Destination to extract to
  • "*" = All files
  • "-r" = Recursive

In C #, you can use this method, which I did (I copied 7z.exe to the Debug folder of my application)

 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 } } 
0
source

Source: https://habr.com/ru/post/915382/


All Articles