Esta es una pequeña herramienta que permite copiar un archivo en otro. Ya se que, a simple vista, no parece tener mucha utilidad, pero la verdad es que sabiéndola usar nos permitirá hacer algunas cosas muy interesantes.
El codigo (es una aplicion de consola):
program dump; {$APPTYPE CONSOLE} uses SysUtils, Classes; type EGetOptError = class(Exception); var Options: record BlockSize: Integer; Count: Integer; InputFile: String; InputMode: Integer; Mult: Integer; OutputFile: String; OutputMode: Integer; end; procedure WriteHelp; begin Writeln; Writeln('Uso: dump [opciones]'); Writeln(' --bs'); Writeln(' Numero de bytes que componen un bloque'); Writeln(' --count'); Writeln(' Numero de bloques a copiar'); Writeln(' --if'); Writeln(' Ruta del archivo de entrada'); Writeln(' --of'); Writeln(' Ruta del archivo de salida'); Writeln(' --im'); Writeln(' Modo de apertura del archivo de entrada'); Writeln(' --om'); Writeln(' Modo de apertura del archivo de salida'); Writeln(' --x'); Writeln(' Factor por el que multiplicar --bs (1=Kb, 2=Mb, 3=Gb)'); Writeln; Writeln('Posibles valores para "--im" y "--om":'); Writeln(' 01 Crea un archivo nuevo (Create)'); Writeln(' 02 Abre el archivo solo para lectura (OpenRead)'); Writeln(' 04 Abre el archivo solo para escritura (OpenWrite)'); Writeln(' 08 Abre el archivo para su modificacion (OpenReadWrite)'); Writeln('Se pueden combinar con los siguientes valores:'); Writeln(' 16 Otras aplicaciones pueden leer y escribir el archivo (ShareDenyNone)'); Writeln(' 32 Otras apliaciones pueden leer el archivo (ShareDenyWrite)'); Writeln(' 64 No permite que otras aplicaciones abran el archivo (ShareExclusive)'); Writeln('El valor por defecto para "--im" es 18, y para "--om" es 1'); Writeln; Writeln('Ejemplo:'); Writeln(' dump --if=\\.\F: --of=imagen.bin --bs=4096'); Writeln(' Guarda una imagen del disco F en el archivo "imagen.bin"'); Writeln; end; function Starts(Sub, Str: String): Boolean; begin Result:= SameText(Sub,Copy(Str,1,Length(sub))); end; procedure Getopt; var i: Integer; Str: String; begin FillChar(Options,Sizeof(Options),#0); Options.Count:= -1; if ParamCount > 0 then for i:= 1 to ParamCount do begin Str:= ParamStr(i); if (Copy(Str,1,2) = '--') and (Length(Str) > 2) then begin if Starts('--if=',Str) then begin if Options.InputFile = EmptyStr then Options.InputFile:= Copy(Str,Length('--if=') + 1,MAXINT) else raise EGetOptError.Create(Str); end else if Starts('--of=',Str) then begin if Options.OutputFile = EmptyStr then Options.OutputFile:= Copy(Str,Length('--of=') + 1,MAXINT) else raise EGetOptError.Create(Str); end else if Starts('--bs=',Str) then begin if Options.BlockSize = 0 then Options.BlockSize:= StrToInt(Copy(Str,Length('--bs=') + 1,MAXINT)) else raise EGetOptError.Create(Str); end else if Starts('--count=',Str) then begin if Options.Count = -1 then Options.Count:= StrToInt(Copy(Str,Length('--count=') + 1,MAXINT)) else raise EGetOptError.Create(Str); end else if Starts('--im=',Str) then begin if Options.InputMode = 0 then begin case StrToInt(Copy(Str,Length('--im=') + 1,MAXINT)) and $0F of 1: Options.InputMode:= fmCreate; 2: Options.InputMode:= fmOpenRead; 4: Options.InputMode:= fmOpenWrite; 8: Options.InputMode:= fmOpenReadWrite; else raise EGetOptError.Create(Str); end; case StrToInt(Copy(Str,Length('--im=') + 1,MAXINT)) and $F0 of 0: ; 16: Options.InputMode:= Options.InputMode + fmShareDenyNone; 32: Options.InputMode:= Options.InputMode + fmShareDenyWrite; 64: Options.InputMode:= Options.InputMode + fmShareExclusive; else raise EGetOptError.Create(Str); end; end else raise EGetOptError.Create(Str); end else if Starts('--om=',Str) then begin if Options.OutputMode = 0 then begin case StrToInt(Copy(Str,Length('--om=') + 1,MAXINT)) and $0F of 1: Options.OutputMode:= fmCreate; 2: Options.OutputMode:= fmOpenRead; 4: Options.OutputMode:= fmOpenWrite; 8: Options.OutputMode:= fmOpenReadWrite; else raise EGetOptError.Create(Str); end; case StrToInt(Copy(Str,Length('--om=') + 1,MAXINT)) and $F0 of 0: ; 16: Options.OutputMode:= Options.OutputMode + fmShareDenyNone; 32: Options.OutputMode:= Options.OutputMode + fmShareDenyWrite; 64: Options.OutputMode:= Options.OutputMode + fmShareExclusive; else raise EGetOptError.Create(Str); end; end else raise EGetOptError.Create(Str); end else if Starts('--x=',Str) then begin if Options.Mult = 0 then case StrToInt(Copy(Str,Length('--x=') + 1,MAXINT)) of 1: Options.Mult:= 1024; 2: Options.Mult:= 1024*1024; 3: Options.Mult:= 1024*1024*1024; else raise EGetOptError.Create(Str); end else raise EGetOptError.Create(Str); end else if SameText('--help',Str) then begin WriteHelp; Halt; end else raise EGetOptError.Create(Str); end else if (Copy(Str,1,1) = '-') and (Length(Str) > 1) then begin if SameText('-h',Str) then begin WriteHelp; Halt; end else raise EGetOptError.Create(Str); end else begin raise EGetOptError.Create(Str); end; end else begin WriteHelp; Halt; end; end; procedure WriteHeader; begin Writeln; Writeln('Dump 0.2 - Copyright (c) 2007 Domingo Seoane'); Writeln('<a href="http://delphi.jmrds.com'">http://delphi.jmrds.com'</a>); Writeln; end; var i: Integer; Buffer: PChar; Src, Dst: TFileStream; begin WriteHeader; try GetOpt; if Options.Mult > 0 then Options.BlockSize:= Options.BlockSize * Options.Mult; if Options.BlockSize < 1 then Options.BlockSize:= 8 * 1024 * 1024; if Options.InputMode = 0 then Options.InputMode:= fmOpenRead or fmShareDenyNone; if Options.OutputMode = 0 then Options.OutputMode:= fmCreate; GetMem(Buffer,Options.BlockSize); try Src:= TFileStream.Create(Options.InputFile,Options.InputMode); try Dst:= TFileStream.Create(Options.OutputFile,Options.OutputMode); try i:= Src.Read(Buffer^,Options.BlockSize); while i > 0 do begin Dst.WriteBuffer(Buffer^,i); if Options.Count > 0 then begin dec(Options.Count); if Options.Count = 0 then break; end; i:= Src.Read(Buffer^,Options.BlockSize); end; finally Dst.Free; end; finally Src.Free; end; finally FreeMem(Buffer); end; except On E: Exception do Writeln('Error: ' + E.Message); end; end.
El código y el programa ya compilado puedes bajarlo de aquí
La primera utilidad que se me ocurre es crear una imagen de un disco duro, disquete, memoria usb o incluso un Cdrom. Solo hay que recordar que para leer este tipo de dispositivos hay que hacerlo en bloques de un tamaño determinado, normalmente ese tamaño tiene que cumplir la condición de ser múltiplo de 512 (el tamaño de un sector). Esto se explica mejor con un ejemplo:
dump --if=\\.\F: --of=imagen.bin --bs=4096
Guarda una imagen del disco F en el archivo "imagen.bin"
dump --of=\\.\a: --if=imagen.bin --bs=1 --x=2 --om=24
Graba una imagen en un disquete, solo hay que tener en cuenta que para escribir en un disco el parámetro "--om" debe ser 24.
ACTUALIZACIÓN: En Windows Vista y Windows 7 para poder escribir en un disco de debe ejecutar la aplicación como administrador, y tener acceso exclusivo. Por eso hay que utilizar el parámetro "--om=72", asegurándose primero de que ninguna otra aplicación esta utilizando el disco.
Comentarios
Hola Domingo, Como siempre,
Hola Domingo,
Como siempre, muy interesante tu entrada. Te felicito por ello. Saludos.
PD. Hay una errata que impide bajar el programa siguiendo el enlace: en lugar de "href" verás que pone "hre".
Me he llevado una sorpresa.
Me he llevado una sorpresa. Había visto que un dd para Windows que anda por ahí usaba esa notación para las unidades de disco. Pero pensaba que era algo que hace el programa, no sabía que lo permite el sistema operativo.
Por cierto que está chulo el programita :-)
Si, mucha gente no lo sabe
Si, mucha gente no lo sabe pero windows permite leer varios dispositivos como si de archivos se trataran (discos, puerto serie, ...). Y aunque no llega al nivel de linux, en que "casi todo" se puede tratar como un archivo (solo hay que ver la carpeta "/dev"), si tiene posibilidades interesantes, como borrar ... perdón, copiar el MBR, jejeje. Solo hay que tener cuidado con las características propias de cada dispositivo, por ejemplo, los discos solo se pueden leer en bloques múltiplos de 512 y se deben de abrir con los permisos que menciono arriba, el puerto serie no soporta la función seek, etc ...
Si te interesa el tema, en este otro articulo sobre como recuperar fotos jpg borradas de un disco, puedes ver un código que se puede compilar tanto en windows como en linux (freepascal) y la única diferencia entre usarlo en windows o en linux es que mientras en windows el parámetro "--if" seria algo así "\\.\C:" en linux seria así "/dev/hda1".
Fabuloso :)
Fabuloso :)
Sí, fabuloso, aunque
Sí, fabuloso, aunque ¡¡¡no se puede descargar el archivo!!! :D:D:D
Vaya, no perdonáis una,
Vaya, no perdonáis una, jejeje. Era domingo por la tarde y una "f" se le olvida a cualquiera. El enlace ya funciona.
El comando dd tambien está
El comando dd tambien está para Windows, y usa una sintaxis de unidades como la que expones:
http://www.chrysocome.net/dd
Por otra parte: joder, qué bueno eres.