No error checking and other features, but a very basic .tar extracting snippet:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
struct tarheader { // for parsing the tar headers
char name[100];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char typeflag;
char linkname[100];
char magic[8];
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char prefix[155];
char padding[12];
};
static void _mkdir(const char *dir, __mode_t mode) { // mkdir with parent tree
char tmp[256];
char *p = NULL;
size_t len;
snprintf(tmp, sizeof(tmp), "%s", dir);
len = strlen(tmp);
if (tmp[len - 1] == '/') tmp[len - 1] = 0;
for (p = tmp + 1; *p; p++)
if(*p == '/') {
*p = 0;
mkdir(tmp, mode);
*p = '/';
}
mkdir(tmp, mode);
}
int unpack_tar(const char* tarname, const char* prefix) {
struct tarheader header;
char buf[512];
long size;
FILE* tar = fopen(tarname, "rb");
FILE* output; // reuse same pointer for every file
while (fread(&header, 1, 512, tar)!=0) {
size = strtol(header.size, NULL, 8); // octal numbers, who doesn't love them?
if (header.typeflag == '0') {
char filename[FILENAME_MAX];
strcpy(filename, prefix);
strcat(filename, "/");
strcat(filename, header.name);
output = fopen(filename, "wb");
printf("%s\n", filename);
while (size > 512) {
fread(&buf, 1, 512, tar);
fwrite(&buf, 1, 512, output);
size -= 512;
}
fread(&buf, 1, 512, tar);
fwrite(&buf, 1, size, output); // don't write those pesky zeroes out
fclose(output);
} else if (header.typeflag == '5') {
char foldername[FILENAME_MAX];
strcpy(foldername, prefix);
strcat(foldername, "/");
strcat(foldername, header.name);
_mkdir(foldername, (__mode_t) strtol(header.mode, NULL, 8));
fseek(tar, size + (512 - size & 0x1ff), SEEK_CUR);
} else {
fseek(tar, size + (512 - size & 0x1ff), SEEK_CUR);
}
}
}
int main(int argc, char* argv[]) {
unpack_tar("test.tar", ".");
return 0;
}