All pastes #999761 Raw Edit

Miscellany

public c v1 · immutable
#999761 ·published 2008-04-27 22:42 UTC
rendered paste body
// pack-u8.c by Superken7 - internal beta version.// BETA VERSION. Does NOT support packing subdirectories// Based on magicus' parse-u8.c // Sorry, i was also too lazy to get all the functions needed// from seghers tools.c , so seghers tools' source code is required.  #define _GNU_SOURCE  #include <sys/stat.h>#include <sys/types.h>#include <dirent.h> #include <string.h>#include <stdlib.h>#include <stdio.h>#include <unistd.h> #include "tools.h" #define round_up(x,n)   (-(-(x) & -(n)))#define round64(x)      round_up(x,0x40)#define round32(x)	round_up(x,0x20)#define round16(x)	round_up(x,0x10)#define ERROR(s) do { fprintf(stderr, s "\n"); exit(1); } while (0) static FILE *fp; static char *outdir; typedef struct {  u16 type;  u16 name_offset;  u32 data_offset; // == absolut offset frn U.8- headerns brjan  u32 size; // last included file num for directories} U8_node; typedef struct{  u32 tag; // 0x55AA382D "U.8-"  u32 rootnode_offset; // offset to root_node, always 0x20.  u32 header_size; // size of header from root_node to end of string table.  u32 data_offset; // offset to data -- this is rootnode_offset + header_size, aligned to 0x40.  u8 zeroes[16];} U8_archive_header;typedef char U8_string[256];int write_file(char *path, FILE *fout){	u8 buffer[4096];	u32 size, tot_size;	FILE *fin;	fin = fopen(path, "rb");	if (fin == NULL)		return 0;	tot_size = 0;	while(!feof(fin)) {		size = fread((u8*)buffer, 1, 4096, fin);		tot_size += size;		fwrite((u8*)buffer, size, 1, fout);	}	while(tot_size - round32(tot_size) != 0) {		fputc(0, fout);		tot_size++;	}		fclose(fin);	return 1;}u32 get_num_entries(DIR *d){	u32 num;	struct dirent *dir;	num = 0;	rewinddir(d);	while((dir=readdir(d)) != NULL) {	//	printf("#%d %s\n",num+1, dir->d_name);		num++;	}		rewinddir(d);	return num;}int build_strings(U8_string *strings, DIR *dir){	int i = 0;	struct stat st;	struct dirent *d;	u16 name_off = 3; // 0x00 + "." + 0x00	u32 size;	rewinddir(dir);	while((d=readdir(dir)) != NULL) {		if (!strcmp(d->d_name, ".") || (!strcmp(d->d_name, "..")))			continue;		strcpy(strings[i], (char*)(d->d_name));		stat(d->d_name, &st);		//printf("#%d %s\n",i+1,d->d_name); fflush(stdout);		name_off += strlen(strings[i]) +1;		i++;	}	return name_off;}int build_nodes(U8_node *nodes, U8_string *strings, DIR *dir, u32 strings_size){	int i = 0;	int j;	struct stat st;	struct dirent *d;	u16 name_off = 3; // 0x00 + "." + 0x00	u32 data_off;	u32 nodes_size;	u32 size;	u32 filedata_off;	rewinddir(dir);	while((d=readdir(dir)) != NULL) {		if (!strcmp(d->d_name, ".") || (!strcmp(d->d_name, "..")))			continue;		stat(d->d_name, &st);		if (S_ISDIR(st.st_mode)) {			nodes[i].type = be16("\x01\x00");//			printf("DIR!\n");		} else {			nodes[i].type = be16("\x00\x00");//			printf("FILE!\n");		}		size = st.st_size;		nodes[i].size = size;		data_off = round32(data_off + size);		nodes[i].name_offset = be16((u8*)&name_off);		name_off += strlen(strings[i]) +1;		i++;	}	filedata_off = 0;	nodes_size = (i+2)*sizeof(U8_node); /* (root node + ./ node + num_files) *size(node) */	for(j=0; j<i; j++) {		/* strtable + nodes_size + header = abs. offset */		nodes[j].data_offset = filedata_off + round32(nodes_size + 0x20 + strings_size); 		nodes[j].data_offset = be32((u8*)&(nodes[j].data_offset));		filedata_off += round32(nodes[j].size);		nodes[j].size = be32((u8*)&(nodes[j].size));	}	return ;} int do_U8_archive(FILE *f, char *path){	U8_archive_header header;	U8_node root_node;	U8_node *nodes;	U8_string *strings;	u32 num_nodes;	u32 root_size;	u32 data_offset;	u16 strtable_size;	u16 i;	DIR *d;	d = opendir(path);	if (d == NULL)		return 0;	chdir(path);	header.tag = 0x55AA382D;	header.tag = be32((u8*)&(header.tag));	header.rootnode_offset = (u32)0x20;//	printf("rootnode offset "); hexdump((u8*)&header.rootnode_offset, 4);	header.rootnode_offset = be32((u8*)&(header.rootnode_offset));	memset(header.zeroes, 0, 0x10);		num_nodes = get_num_entries(d);	//printf("%d entries\n",num_nodes);	root_size = num_nodes +2; // rootnode and ./	root_node.size = be32((u8*)&num_nodes);	root_node.type = 0x0100;	root_node.type = be16((u8*)&(root_node.type));	root_node.name_offset = 0;	root_node.data_offset = 0;		num_nodes -= 2;	printf("%d files found!\n", num_nodes);	strings = (U8_string *)malloc(sizeof(U8_string) * num_nodes);	if (strings == NULL) {		fprintf(stderr,"memory error :/\n");		return 0;	}	nodes = (U8_node *) malloc(sizeof(U8_node) * num_nodes);	if (nodes == NULL) {		fprintf(stderr,"memory error :/\n");		return 0;	}	strtable_size = build_strings(strings, d);//	printf("stringtable %08x\n",strtable_size);	build_nodes(nodes, strings, d, strtable_size);	header.header_size = 2*sizeof(U8_node) + num_nodes*sizeof(U8_node) + strtable_size;//	printf("rootnode offset "); fflush(stdout);hexdump((u8*)&header.rootnode_offset, 4);	header.data_offset = round32(0x20 + header.header_size);	data_offset = header.data_offset; //save in host byte-order for later	header.header_size = be32((u8*)&(header.header_size));//	printf("header size "); fflush(stdout);hexdump((u8*)&header.header_size,4);	header.data_offset = be32((u8*)&(header.data_offset));//	printf("data offset "); fflush(stdout);hexdump((u8*)&header.data_offset,4);	fwrite((u8*)&header, sizeof(U8_archive_header), 1, f);	fwrite((u8*)&root_node, sizeof(U8_node), 1, f);	/* write ./ directory ,	 * just differs from root node in name offset 	 * */	root_node.name_offset = 0x0001;	root_node.name_offset = be16((u8*)&(root_node.name_offset));	fwrite((u8*)&root_node, sizeof(U8_node), 1, f);	/* write nodes */	for(i=0; i<num_nodes; i++) { /* meh, inefficient, but who cares.. */		fwrite((u8*)&(nodes[i]), sizeof(U8_node), 1, f);	}	/* write string table */	fwrite((u8*)"\x00\x2e\x00", 3, 1, f); /* root node + ./ node */	for(i=0; i<num_nodes; i++) {		printf("#%d %s\n",i+1,strings[i]);		fwrite((u8*)strings[i], strlen(strings[i])+1, 1, f);	}	/* align to 0x20 */	for (i=0; i<(data_offset - strtable_size - (num_nodes+2)*sizeof(U8_node) -sizeof(header)); i++)		fputc(0, f);	/* write files */	for (i=0; i<num_nodes; i++) {		write_file(strings[i], f);	}	chdir("..");	free(nodes);	closedir(d);	return 1;} int main(int argc, char **argv){  if (argc != 3)  	return 0;	  printf("U8 packer: \"internal\" beta version by Superken7.\n\n");   fp = fopen(argv[1], "wb");  if (fp == NULL) {  	fprintf(stderr, "Can not open file %s\n",argv[1]);	return 0;  }  do_U8_archive(fp, argv[2]);   fclose(fp);  return 0;}