domingo, 14 de junio de 2009

Usar hexdump para leer ficheros binarios...

Hoy he hecho una de las cosas más frikis en mucho tiempo... Crear un script de bash que lee un fichero binario con campos de longitud variable (la longitud se almacena en un campo binario).

Mi objetivo era leer un par de datos de los ficheros crid producidos por mi grabador personal de video (PVR), que ejecuta un pequeño linux. Normalmente haría esto con C, porque en cualquier ordenador con linux suele haber un compiladorcillo de C. Pero el grabador personal lleva una versión reducida de linux (busybox) que no incluye compilador, ni cabeceras del kernel, ni una idea sobre qué versión de las bibliotecas de C utiliza. Así que prefiero no experimentar con compiladores.

El reto era usar hexdump para leer no el fichero entero sino sólo un par de bytes del archivo, convirtiéndolos después en una cifra que indicaba la longitud del primer campo de texto. A continuación, a partir de ese dato obtenía la ubicación del segundo campo de texto, cuya longitud debía volver a leer. Finalmente, leía los dos campos de texto y los mostraba en pantalla.



#!/bin/bash
# This file uses expr instead of $[ ] to be compatible with busybox
if [ -z "$1" ]; then
#
# No se nos ha proporcionado ningún argumento.
#
echo "Crid file identifier"
echo "Usage: $0 cridfile.crid"
exit 1
else
#
# Asigna el primer argumento a input.
#
input=$1
fi

#Obtener la longitud del primer campo de texto:
# Lee 2 bytes desde el byte 48,
# y usa 1 iteración de 2 bytes para mostrar
# un valor decimal de 2 bytes.
# Asigna el resultado a ltitle
#
ltitle=$(hexdump -s 48 -n 2 -e '1/2 "%2d\n"' $input)
#
#obtener la longitud del segundo campo de texto:
# Lee 2 bytes desde el byte 48 +ltitle + 8,
# y usa 1 iteración de 2 bytes para mostrar
# un valor decimal de 2 bytes.
# Asigna el resultado a ltitle
#
lfmpg=$(hexdump -s $(expr \( 48 \+ 8 \+ $ltitle \) ) -n 2 -e '1/2 "%2d\n"' $input)
#
#Obtener el primer campo de texto:
# Lee ltitle bytes desde el byte 48+2,
# durante $ltitle iteraciones de 1 carácter,
# almacena el resultado en $ltitle.
#
title=$(hexdump -s $(expr \( 48 + 2 \) ) -n $ltitle -e "$ltitle/1 \"%c\"" $input)
#
#Obtener el primer campo de texto:
# Lee ltitle bytes desde el byte 48+10 + ltitle,
# durante $lfmpg iteraciones de 1 carácter,
# almacena el resultado en $ltitle.
#
fmpgfile=$(hexdump -s $(expr \( 48 \+ $ltitle \+ 10 \) ) -n $lfmpg -e "$lfmpg/1 \"%c\"" $input)
#
echo \[ $title \] is \[ $fmpgfile \]





Por su interés para la gente que tenga un PVR, he subido el script a www.todopvr.com

4 comentarios:

cristal00k dijo...

¿Mande?
A ver... un poco frikie si eres... jajaja pero cada uno tiene sus aficiones y ya sabes lo que dicen: "cauno, es cauno, y sus cadaunadas"
Un abrazo.

cristal00k dijo...

Y por cierto, ya me gustaría a mí tener un 1% de tu sapiencia informática. ¡Vaya!

cristal00k dijo...

Este... hoy es miércoles...

Davo Valdés dijo...

o_O

Yo no tengo idea de lo que hablas, pero creo que es bastante friki :)

¡Saludos!