Me di cuenta de esto a mí mismo después de un poco de trabajo. El tar file spec realmente le dice todo lo que necesita saber.
En primer lugar, cada archivo comienza con una cabecera de 512 bytes, por lo que puede representar con un char [512] o un char * que apunta a algún lugar de su matriz de caracteres de mayor tamaño (si tiene el archivo completo cargado en una matriz por ejemplo).
La cabecera tiene el siguiente aspecto:
location size field
0 100 File name
100 8 File mode
108 8 Owner's numeric user ID
116 8 Group's numeric user ID
124 12 File size in bytes
136 12 Last modification time in numeric Unix time format
148 8 Checksum for header block
156 1 Link indicator (file type)
157 100 Name of linked file
lo tanto, si desea que el nombre del archivo, lo agarras aquí con string filename(buffer[0], 100);
. El nombre del archivo es nulo, por lo que puede hacer una comprobación para asegurarse de que haya al menos un nulo y luego dejar el tamaño si desea ahorrar espacio.
Ahora queremos saber si es un archivo o una carpeta. El campo "indicador de enlace" tiene esta información, por lo que:
// Note that we're comparing to ascii numbers, not ints
switch(buffer[156]){
case '0': // intentionally dropping through
case '\0':
// normal file
break;
case '1':
// hard link
break;
case '2':
// symbolic link
break;
case '3':
// device file/special file
break;
case '4':
// block device
break;
case '5':
// directory
break;
case '6':
// named pipe
break;
}
En este punto, ya tenemos toda la información que necesitamos sobre directorios, pero necesitamos una cosa más de los archivos normales: el contenido real de los archivos.
La longitud del archivo se puede almacenar de dos maneras diferentes, ya sea como una cadena octal terminada en cero 0 o espacio-acolchada, o "una codificación base-256 que se indica configurando el bit de orden superior del byte más a la izquierda de un campo numérico ".
Los valores numéricos están codificados en números octales utilizando dígitos ASCII, con ceros a la izquierda. Por razones históricas, se debe usar un carácter NUL o espacio final. Por lo tanto, aunque hay 12 bytes reservados para almacenar el tamaño del archivo, solo se pueden almacenar 11 dígitos octales.Esto proporciona un tamaño de archivo máximo de 8 gigabytes en archivos archivados. Para superar esta limitación, star en 2001 introdujo una codificación de base-256 que se indica configurando el bit de orden superior del byte más a la izquierda de un campo numérico. GNU-tar y BSD-tar siguieron esta idea. Además, las versiones de tar antes del primer estándar POSIX de 1988 rellenan los valores con espacios en lugar de ceros.
Aquí es cómo se lee el formato octal, pero no han de código escrito para la versión base-256:
// in one function
int size_of_file = octal_string_to_int(&buffer[124], 11);
// elsewhere
int octal_string_to_int(char *current_char, unsigned int size){
unsigned int output = 0;
while(size > 0){
output = output * 8 + *current_char - '0';
current_char++;
size--;
}
return output;
}
Ok, así que ahora tenemos todo excepto el contenido real de los archivos. Todo lo que tenemos que hacer es agarrar los próximos size
bytes de datos del archivo de alquitrán y tendremos nuestros contenidos de archivo:
// Get to the next block after the header ends
location += 512;
file_contents = new char[size];
memcpy(file_contents, &buffer[location], size);
// Go to the next block by rounding up to 512
// This isn't necessarily the most efficient way to do this,
// but it's the most obvious.
location += (int)ceil(size/512.0)
'man tar' me dice' -t Listar los contenidos del archivo a stdout. ¿Eso es lo que quieres? – Potatoswatter
Lo que realmente quiero es lo opuesto: leer un archivo tar desde stdin. –