2012-05-10 11 views
6

En realidad estoy tratando de extraer una imagen de disco de grasa con DiskUtils pero no obtengo los nombres de archivo correctos ...C# - ¿Cómo puedo extraer una imagen de disco FAT?

obtengo "\ TURNER ~ 3 \ TOPPER ~ 1.P ~ 1" en lugar de " \ 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 
    } 
} 

Esto se debe a DiscUtils no es compatible con LFN [nombres largos de archivo] ...

Así que estoy buscando para una biblioteca perfecta para extraer estos archivos se acaben intento hacer uno yo mismo ...

¿Hay alguna forma en que puedo Extraerlo [quizás por DiscUtils] sin FileName Errores ...

+0

¿Tiene una ya existente FAT archivo de imagen en alguna parte, podemos jugar? –

+1

Obtenga la [Muestra de Imagen Gorda] (http://www.mediafire.com/?qbnjw7d3c77er15) – Writwick

Respuesta

3

Aquí es algunas modificaciones que se pueden agregar a DiscUtils para apoyar FAT LFN s:

primer lugar, hacer estos cambios en el archivo Fat\Directory.cs, así (es necesario agregar la variable _lfns, la función GetLfnChunk, y modificar la función existente LoadEntries añadir las líneas marcadas con //+++ a continuación):

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

en segundo lugar, añadir estas dos funciones públicas a la Fat\FatFileSystem.cs fi le. Serán las nuevas API para consultar en 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; 
} 

Y eso es todo. Ahora, usted será capaz de volcar un disco FAT toda forma recursiva como este, por ejemplo:

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

uso a su propio riesgo!:)

+0

¿Estabas trabajando en esto? ¡Ya decidí editar los archivos 'DiscUtils' una vez que Bounty Ended! De todos modos, ¡gracias! +60 [Bounty + 10 (+1)] tan pronto como termine Bounty! – Writwick

+0

@ WritwickDas - no, pero el desafío me pareció interesante, y soy un cazarrecompensas :-) –

+0

Bounty va a 'Bounty Hunter' !! – Writwick

2

7-Zip puede extraer imágenes FAT. Hay una biblioteca contenedora de C# en http://sevenzipsharp.codeplex.com que puede leer nombres de archivo y extraer a transmisiones.

+0

¿Está seguro de que puede extraer cualquier tipo de grasa? Diga Fat16 o Fat12 ... Tengo un archivo FAT16 que traté de abrir con el Gui pero informó un Error de archivo inválido ... Pero lo intentaré ... [Sé sobre el SevenZipSharp de antes pero como 7-Zip no pudo abrir el archivo. No lo intenté] – Writwick

+0

Lo he usado con imágenes de disquete y tiene compatibilidad con imágenes de disco duro vhd, por lo que espero que pueda extraer cualquier tipo de FAT. –

+0

El error exacto es ** "No se puede abrir 'Nombre de archivo' como archivo!" ** ¡Comprobado! ¡Winimage puede editar la grasa que tengo, correctamente! – Writwick

1

Parece que no hay soporte de archivos Long Name para FAT en DiscUtils. Check out this post. De lo que estoy seguro es consciente, ya que parece que usted hizo la pregunta.

+0

Tienes razón, hice la pregunta allí ... Así que pedí aquí cualquier alternativa que me falta ... – Writwick

0

El comando DOS DIR con el modificador/X muestra nombres largos y cortos.

De lo contrario, hay una utilidad para guardar LFN: DOSLFNBk.exe que ayudaría a crear una tabla de asignación.

No conozco las respuestas que estaba buscando pero no tengo que crear manualmente una tabla primero para que pueda hacer la asignación sin DiskUtil, no puedo pensar en una utilidad o método para lograr su objetivo, pero como usted menciona , aquí en SO alguien podría saber una alternativa.

Kevin de DiskUtils mencionó que estaría infringiendo una patente de Mirosoft si incluía soporte para LFN, no estoy sugiriendo que infrinja ninguno (DEFINITIVAMENTE NO es un proyecto comercial) pero si esto es solo personal o si puede encuentre una biblioteca como 7-Zip tiene la licencia ...

Su captura de pantalla muestra VNext .. ¿el mismo error con las versiones RTM?

+0

¿Qué quieres decir con _ "Tu captura de pantalla muestra VNext ... el mismo error con las versiones RTM?" _ I no obtuve esta oración ... ¿Y cómo puedo ejecutar el comando DOS DIR con el modificador/X en una imagen de disco gordo? ... Y AFAIK, 'Copia de seguridad de DOS LFN' no es gratis [Encontré esta utilidad antes, pero no tenía idea de [no lo usó ya que no era gratis] y no se puede usar en la imagen del disco. De todos modos, gracias por sus sugerencias. – Writwick

+0

Ahora comprobé que DOSLFNBK tiene una versión de software gratuito 1.6 pero esa versión no es compatible con FAT32 ... Fat32 entró entre la versión 2.0 y 2.3 – Writwick

+0

vNext == VS 2011, lo siento la próxima vez pondré en más investigación –

0

El mejor método con la línea de comandos es utilizar esto:

7z "e" + fuente + "-o" + ruta + "* -r"

  • "e" = Extraer
  • fuente = ruta de la imagen de disco a
  • "-o" = salida/Extraer en
  • path = Destino extraer a
  • "*" = Todos los archivos
  • "r" = recursiva

En C#, puede utilizar este método hice (he copiado 7z.exe a la carpeta de depuración de mi solicitud)

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 
    } 
} 
Cuestiones relacionadas