Saltar al contenido
AZ Tools

Inspector de flujos xz (.xz)

Un archivo .xz está enmarcado, y esa es toda la diferencia con gzip. Cada flujo termina en un pie de 12 bytes cuyo tamaño hacia atrás apunta a un índice, y el índice guarda un registro por bloque con el tamaño sin relleno de ese bloque y su tamaño sin comprimir. Así que el tamaño original real, el número de bloques y todos los puntos de salto se leen en unos pocos cientos de bytes al final del archivo: por eso xz --list responde al instante sobre un archivo de 4 GB, mientras que gzip -l solo puede repetir los últimos cuatro bytes de un .gz y confiar en que describan el conjunto. Esta página lee ese mismo armazón, recorriéndolo hacia atrás desde el final igual que hace xz, y lo muestra entero: los bytes mágicos fd 37 7a 58 5a 00, las banderas del flujo con el tipo de comprobación (None, CRC32, CRC64 —el valor por defecto— o SHA-256) y el CRC32 que protege esos dos bytes; luego, por bloque, el tamaño de la cabecera, si la cabecera declara sus propios tamaños comprimido y sin comprimir, el valor de comprobación guardado y la cadena de filtros interpretada como toca. El tamaño del diccionario de LZMA2 no es un número llano sino un código de seis bits en una escalera que va de 4 KiB a 4 GiB, y delante puede ir un filtro BCJ para x86, ARM, ARM64, PowerPC, IA-64, SPARC, ARM-Thumb o RISC-V con su propio desplazamiento inicial; por eso un archivo hecho con --x86 tiene dos filtros en la cadena, y aquí la cadena se escribe tal como se la volverías a pasar a xz. Tras los bloques vienen los registros del índice, el CRC32 del propio índice y, en el pie, el tamaño hacia atrás, las banderas del flujo repetidas y los bytes mágicos YZ. Nada se descomprime. LZMA2 no está implementado aquí y no hace falta que lo esté, que es justo la idea, pero también significa que el valor de comprobación de cada bloque se copia en vez de verificarse: demostrar que un CRC64 es correcto exigiría decodificar los datos. Los cuatro CRC32 que protegen el armazón sí se recalculan, y una discrepancia se informa en lugar de rechazarse, de modo que un archivo con el índice dañado, o con un pie cuyas banderas no coinciden con la cabecera, sigue enseñándote todo lo que está intacto. El número de bloques merece más atención de la que parece: un solo bloque no se puede descomprimir en más de un núcleo y nadie puede saltar a su interior, que es exactamente lo que cambia xz -T0 al cortar la entrada en bloques de unas tres veces el diccionario, así que una entrada menor que eso sigue siendo un bloque por muchos hilos que pidas. También puede haber varios flujos concatenados en un mismo archivo, separados por un relleno que debe ser múltiplo de cuatro bytes cero; aquí se listan uno a uno, igual que los bytes finales que no pertenecen a ningún flujo.

Cómo usar

  1. Suelta un .xz o un .tar.xz sobre el recuadro. Se lee dentro de la página: no se sube nada y no se descomprime nada.
  2. Empieza por el resumen: flujos, bloques, el tamaño sin comprimir real tomado del índice, la ratio y qué comprobación de integridad usa el archivo.
  3. Abre un flujo para ver su cabecera, su tabla de bloques y su índice. La columna de filtros está escrita como se la pasarías a xz, así que --x86 --lzma2=dict=8MiB es la cadena que construyó ese bloque.
  4. Mira el número de bloques antes de planear una descompresión en paralelo o una lectura parcial: un solo bloque significa un solo núcleo y ninguna búsqueda, por muchos hilos que tenga el lector.
  5. Si la casilla de estructura dice discrepancia, busca la etiqueta roja: la cabecera del flujo, cada cabecera de bloque, el índice y el pie llevan su propio CRC32, y el pie repite las banderas del flujo.

Preguntas frecuentes

¿Cómo puede dar el tamaño sin comprimir sin descomprimir nada?
Porque el formato .xz deja ese número escrito. Cada flujo termina con un índice que enumera, para cada bloque, su tamaño sin relleno y su tamaño sin comprimir, y el tamaño hacia atrás del pie dice cuánto antes empieza ese índice. El lector salta a los últimos 12 bytes, va al índice, suma los registros y ya está: eso hace xz --list y eso hace esta página. Es también la razón de que se pueda saltar dentro de un .xz, porque el índice dice qué bloque contiene un desplazamiento dado. gzip no tiene nada equivalente: su ISIZE vive en los últimos cuatro bytes, describe solo al último miembro y está tomado módulo 2^32, así que un .gz de varios miembros o de más de 4 GB sencillamente no puede declarar su tamaño desde el armazón.
¿Por qué mi archivo tiene un único bloque si lo comprimí con -T0?
Porque la compresión con hilos parte la entrada en bloques de aproximadamente tres veces el tamaño del diccionario, y con el preajuste 6 por defecto el diccionario es de 8 MiB, así que nada por debajo de unos 24 MiB llega a cortarse en dos. -T0 solo pide tantos hilos como núcleos haya; no puede fabricar un segundo bloque a partir de una entrada que cabe en uno. Si quieres los bloques por sí mismos —descompresión en paralelo, o un lector que salte— pídelos explícitamente con --block-size o --block-list. El precio es la ratio: cada bloque arranca con el diccionario vacío, así que ninguna coincidencia cruza una frontera de bloque.
¿Qué tipo de comprobación conviene usar y cuánto cuesta?
Las banderas del flujo nombran uno de cuatro: None, CRC32, CRC64 o SHA-256, que guardan 0, 4, 8 o 32 bytes después de cada bloque. CRC64 es el valor por defecto y casi siempre la respuesta correcta: cuesta unos pocos bytes por bloque y detecta el daño accidental que de verdad producen el almacenamiento y las transferencias. SHA-256 cuesta 32 bytes por bloque y bastante más CPU, y conviene ser claro sobre lo que no compra: el resumen vive dentro del archivo, así que quien pueda alterar los datos puede alterarlo también. Es detección de accidentes, no defensa frente a un atacante; para eso hace falta una firma sobre el archivo entero. Y --check=none ahorra entre cuatro y ocho bytes a cambio de eliminar lo único que te habría avisado de que los datos estaban dañados, algo defendible cuando el contenido ya lleva su propia suma de verificación y rara vez en otro caso.
¿En qué se diferencian el tamaño sin relleno, el tamaño total y el tamaño comprimido?
Son tres vistas del mismo bloque. El tamaño comprimido cuenta solo lo que sacó LZMA2. El tamaño sin relleno —el número que de verdad se guarda en el índice— es la cabecera del bloque más esos datos comprimidos más el valor de comprobación, sin contar el relleno. El tamaño total es el anterior redondeado hacia arriba a un múltiplo de cuatro, porque cada bloque se rellena con bytes cero para que el siguiente empiece alineado. Restando obtienes el relleno, de cero a tres bytes. Esta página muestra por separado el tamaño de los datos comprimidos y el relleno, y contrasta ambos con la cabecera del bloque siempre que la cabecera declara sus propios tamaños, que es lo que significan la c y la u de la columna de tamaños.
La página dice que hay una discrepancia y xz -t solo dice que los datos están corruptos. ¿Cuál tiene razón?
Las dos, a distinta profundidad. xz -t decodifica todo el contenido y verifica el valor de comprobación de cada bloque, así que detecta daños en cualquier sitio, pero se detiene en el primer error y lo informa con la misma frase sea cual sea el fallo. Esta página nunca decodifica el contenido, de modo que no ve en absoluto la corrupción dentro de los datos comprimidos; a cambio recalcula por separado cada uno de los CRC32 del armazón, así que puede decir qué estructura está dañada: la cabecera del flujo, la cabecera de un bloque concreto, el índice o el pie. También compara las banderas del flujo de la cabecera con la copia del pie, una discrepancia invisible para cualquier comprobación basada en tamaños y una señal genuina de corrupción. Usa esta página para localizar el daño y xz -t para decidir si los datos siguen sirviendo.
¿Puede listar los archivos que hay dentro de un .tar.xz?
No, y ningún lector puede sin descomprimir. El archivo tar —con sus nombres, tamaños y permisos— es el contenido, y ese contenido está comprimido con LZMA2 como una tirada opaca de bytes. Lo que sí aprendes del armazón es cuánto ocupará ese tar al salir, lo que te dice si cabrá antes de empezar; cuántos bloques tiene, lo que te dice si la extracción puede usar más de un núcleo; y si el contenedor está intacto. Si el tamaño sin comprimir es un múltiplo exacto de 512, es buena señal de que efectivamente se trata de un tar, porque tar rellena cada miembro y el archivo entero hasta ese tamaño de bloque.
¿Qué me dice en realidad el tamaño del diccionario de la cadena de filtros?
Hasta dónde pudo mirar atrás el compresor buscando una repetición y, por tanto, cuánta memoria necesitará aproximadamente el descompresor: un decodificador reserva un búfer del tamaño del diccionario, así que un .xz escrito con -9 (64 MiB) pide unos 65 MB para abrirse en una máquina que quizá no los tenga, y esa es la razón habitual de que una descompresión falle en un sistema empotrado o en integración continua mientras el mismo archivo se abre sin problema en un portátil. LZMA2 lo guarda como un código de seis bits: el bit 0 elige una mantisa de 2 o 3 y el resto es un exponente, de modo que la escalera va 4 KiB, 6 KiB, 8 KiB, 12 KiB y así hasta 3 GiB, con el único valor 40 reservado para 4 GiB menos uno. Leído como entero llano, el diccionario de 8 MiB por defecto aparecería como 22.

Herramientas relacionadas