El código más corto para limpiar de forma segura un disco

9

Escribamos el código más corto para realizar una variante simplificada del método de borrado DoD 5220.22-M con solo dos pases de escritura.

Se acepta cualquier lenguaje de programación, pero está prohibido el uso de bibliotecas orientadas a la limpieza de discos.

Así es como debemos implementarlo en pseudocódigo:

Set x to 0

[Start]
'Write Pass
For each sector in disk write the content of x
'Verification Pass
For each sector in disk {
    If sector does not contain the content of x then goto [Start]
}
'Check whether we already did the pass with 1
If x is not 1 then {
    Set x to 1
    GoTo [Start]
}
Else end

En otras palabras, este código se ejecutará dos veces, con un pase de escritura y un pase de verificación para 0, y un pase de escritura y un pase de verificación para 1.

¿Alguien lo suficientemente valiente como para implementarlo al estilo de golf de código? ;)

MathuSum Mut
fuente
66
Dudo que esto obtenga respuestas debido a lo difícil que será probar.
James
12
En serio, ¿qué te hizo tu SSD para merecer este tipo de tratamiento? ¿Mató toda tu colección de ositos de peluche o algo así?
R. Kap
2
Realmente quiero tratar de abordar esto ... tampoco quiero sacrificar mi HDD para probarlo.
Michelfrancis Bustillos
66
Estoy votando para cerrar esta pregunta como fuera de tema porque este desafío requiere código malicioso.
AdmBorkBork
2
Yo diría lo contrario. Este desafío requiere un código que promueva la privacidad y la seguridad de la información.
MathuSum Mut

Respuestas:

1

Código de máquina x86 (Linux), 116 bytes

00000000: 89cb 6a02 5931 d289 4c24 f4b0 05cd 8050  ..j.Y1..L$.....P
00000010: 5b53 6a02 5a31 c9b0 13cd 8089 c65b 5331  [Sj.Z1.......[S1
00000020: d231 c9b0 13cd 8089 f75b 53b2 018d 4c24  .1.......[S...L$
00000030: f8b0 04cd 804e 09f6 75ef 5b53 31d2 31c9  .....N..u.[S1.1.
00000040: b013 cd80 89fe 5b53 8d4c 24f4 b201 b003  ......[S.L$.....
00000050: cd80 4e09 f674 0c8a 4424 f838 4424 f474  ..N..t..D$.8D$.t
00000060: e5eb ad89 fe8a 4424 f8c6 4424 f801 3c01  ......D$..D$..<.
00000070: 759e 58c3                                u.X.

Toma el nombre de archivo como argumento

Asamblea (NASM):

section .text
	global func
func:			;this function uses fastcall conventions
	;seems like no enter instr needed

	;open file
	mov ebx, ecx	;first argument to func (filename)
	push 0x2	;flag O_RDWR
	pop ecx		;pushing a constant is shorter than mov
	xor edx, edx	;mode=0
	mov [esp-12], ecx ;set first byte (msg) to write to 0. msg later in esp-8, buf in esp-12
	mov al, 5	;using 8 bit regs is smaller
	int 0x80	;syscall open
	push eax	;save file descriptor

	write_verify:

	;get file size
	pop ebx		;get fd
	push ebx
	push 0x2	;flag SEEK_END
	pop edx
	xor ecx, ecx 	;offset 0
	mov al, 0x13
	int 0x80	;syscall lseek
	mov esi, eax	;save file byte count in esi
	

	;reset index of file to 0
	pop ebx		;get fd
	push ebx
	xor edx, edx	;flag SEEK_SET=0
	xor ecx, ecx	;ecx=0
	mov al, 0x13
	int 0x80	;syscall lseek

	;***write pass***
	mov edi, esi
	write_loop:	;for each byte in byte count, write [msg]
		;write to file
		pop ebx		;file descriptor
		push ebx
		mov dl, 1	;bytes to write
		lea ecx, [esp-8] ;buffer to write from
		mov al, 4
		int 0x80	;syscall write
		dec esi	;decrement esi (byte count) to 0
		or esi, esi	;cmp esi to 0
		jne write_loop	;while esi!=0, keep looping

	;reset index of file to 0
	pop ebx		;get fd
	push ebx
	xor edx, edx	;flag SEEK_SET=0
	xor ecx, ecx	;ecx=0
	mov al, 0x13
	int 0x80	;syscall lseek

	
	;***verification pass***
	mov esi, edi
	verify_loop:	;for each byte in byte count, verify written byte
		pop ebx		;get fd
		push ebx
		lea ecx, [esp-12] ;buffer to store read byte
		mov dl, 1	;read 1 byte
		mov al, 3
		int 0x80	;syscall read
		dec esi
		or esi, esi	;cmp esi to 0 
		je end_verify	;at final byte, end verification
		mov al, [esp-8]
		cmp byte [esp-12],al
		je verify_loop	 ;keep looping if expected value found
		jmp write_verify ;if byte!=expected value, restart

	end_verify:
	mov esi, edi
	mov al, [esp-8]
	mov byte [esp-8],0x1	;set new byte to write to 1
	cmp al, 0x1
	jne write_verify	;if old byte to write!=1, goto start
	
	pop eax			;reset stack
	ret

Pruébalo en línea! (Utiliza un archivo temporal)

-11 bytes optimizando registros móviles y usando la pila como un búfer en lugar de una ubicación constante en la memoria.

Logern
fuente
3

En un sistema Linux no hay necesidad de manejo especial de dispositivos. Simplemente use la interfaz de archivo del dispositivo.

Python 3 (cadenas de bytes) - 141 bytes

d=input()
f=open(d,'r+b')
z=f.seek
z(0,2)
s=f.tell()
i=0
while i<2:
 z(0);f.write([b'\0',b'\xff'][i]*s);f.flush();z(0)
 if f.read()==x:i+=1

Es bastante sencillo y no está muy optimizado, pero funciona. Aquí hay un resumen básico.

  • Obtener entrada (ruta del archivo del dispositivo)
  • Abrir archivo de dispositivo
  • Busque hasta el final, obtenga el tamaño del archivo (los dispositivos de bloque siempre tienen su tamaño real)
  • ingrese el ciclo de escritura y verificación
  • construir cadenas de 0 bits y 1 bit (x)
  • escribir cadena de bits
  • salida de descarga (podría haber establecido el almacenamiento en búfer = 0 pero esto es más corto)
  • pruebe el archivo contra x e incremente el paso del bucle si pasa

salir del bucle cuando el incremento es lo suficientemente alto

Como beneficio adicional, puede modificar esto para cualquier conjunto y número de patrones de modificación de bytes, como 0x55 / 0xaa para efectos de sobrescritura más fuertes.

Realmente probé esto en un archivo de dispositivo, usando loopback. Sin embargo, no estoy 100% seguro de que la verificación realmente funcione. Puede ser necesario cerrar y volver a abrir el archivo cada pasada, debido a los comportamientos de almacenamiento en búfer. Espero que flush evite esto.

* editado para incorporar algunas sugerencias en los comentarios

William Shipley
fuente
1
Bienvenido al sitio. Ciertamente no necesita espacios en blanco alrededor de un =python. También puede reducir su recuento de bytes al usar ;para reducir la sangría.
Ad Hoc Garf Hunter
Normalmente, contamos los envíos en bytes, no en caracteres. También puede alias algunas de sus funciones, por ejemplo f.seek(0);f.seek(0)(19 bytes) puede ser s=f.seek;s(0);s(0)(18 bytes). Además, if f.read()==x:i+=1puede ser i+=f.read()==x.
Jonathan Frech
Tampoco debería necesitar la cadena vacía como argumento para ingresar.
Quintec
Creo que en b'\0'lugar de b'\x00'debería funcionar.
Jason
Acabo de darme cuenta de una característica importante. Este programa consumirá RAM igual al tamaño del dispositivo borrado.
William Shipley
2

C (clang) , -DZ=lseek(d,0+ 139 = 152 bytes

g,j,x,d,s,i,c;f(n){x=0;d=open(n,2);s=Z,2);for(j=2;j--;x++){Z,0);for(i=s;i--;write(d,&x,1));Z,0);for(i=s;i--;read(d,&c,1),c!=x&&x--&&j--);}}

Pruébalo en línea!

Toma el nombre del archivo como argumento

Sin golf:

#include <unistd.h>
int g,j,x,d,s,i,c;
void f(char*n){
	x=0; /*Byte to write*/
	d=open(n,O_RDWR);
	s=lseek(d,0,SEEK_END); /*Get size of file*/
	j=0;
	for(j=0;j<2;j++){
		/*Write Pass*/
		lseek(d,0,SEEK_SET); /*Start writing from start of file*/
		for(i=0;i<s;i++){
			write(d,&x,1);
		}
		
		/*Verification Pass*/
		lseek(d,0,SEEK_SET);
		for(i=0;i<s;i++){
			read(d,&c,1);
			if(c!=x)x--,j--; /*If verification fails, repeat loop with the same value*/
		}
		x++;
	}
}
Logern
fuente
Hmm ... ¿el TiO borrará internet? ;-D
Titus
@Titus Crea un archivo temporal y lo borra.
Logern
1

Tcl, 286 bytes

proc f {o i l} {seek $o 0
set s [string repeat $i $l]
puts -nonewline $o $s
flush $o
seek $o 0
return [string equal [read $o $l] $s]}
set n [open $argv r+]
fconfigure $n -translation binary
seek $n 0 end
set m [tell $n]
while {![f $n "\0" $m]} {}
while {![f $n "\xff" $m]} {}

Realmente no optimizado tan bien. Intenté lo que pude, pero no sé mucho sobre Tcl.

Guardar como "f.tcl" y ejecutar en Unix con tclsh f.tcl "your filename". ¡Asegúrate de que haya exactamente un argumento! Probé esto en un archivo simple, pero también debería funcionar en un archivo de dispositivo.

Establecer variables e indexación está más involucrado en Tcl, así que decidí poner el código común entre los pases en una función. Luego lo llamo primero con "\ 0" y repito mientras no se verifica. Hago lo mismo con "\ xff".

Me sonrojé después de escribir; Puede que no sea necesario. fconfigure -translation binary -buffering nonees más largo.

-2 bytes eliminando comillas alrededor r+.

Jason
fuente