From b695b4bd2408c4ad06a1dcdd95b2a95a3bf63fa5 Mon Sep 17 00:00:00 2001 From: Guillaume Cottenceau Date: Thu, 9 Nov 2000 23:09:17 +0000 Subject: add `mar' archiving program --- mdk-stage1/mar/Makefile | 15 ++ mdk-stage1/mar/mar-extract-only.c | 196 ++++++++++++++++++++++++ mdk-stage1/mar/mar-extract-only.h | 35 +++++ mdk-stage1/mar/mar-frontend.c | 304 ++++++++++++++++++++++++++++++++++++++ mdk-stage1/mar/mar.h | 71 +++++++++ 5 files changed, 621 insertions(+) create mode 100644 mdk-stage1/mar/Makefile create mode 100644 mdk-stage1/mar/mar-extract-only.c create mode 100644 mdk-stage1/mar/mar-extract-only.h create mode 100644 mdk-stage1/mar/mar-frontend.c create mode 100644 mdk-stage1/mar/mar.h (limited to 'mdk-stage1') diff --git a/mdk-stage1/mar/Makefile b/mdk-stage1/mar/Makefile new file mode 100644 index 000000000..91579aac1 --- /dev/null +++ b/mdk-stage1/mar/Makefile @@ -0,0 +1,15 @@ +all: mar + +clean: + rm -f *.o mar + +FLAGS = -Wall -Werror -O1 -fomit-frame-pointer -c + +mar: mar-frontend.o mar-extract-only.o + gcc -o mar mar-frontend.o mar-extract-only.o -lz + +mar-frontend.o: mar-frontend.c mar.h + gcc $(FLAGS) mar-frontend.c + +mar-extract-only.o: mar-extract-only.c mar-extract-only.h mar.h + gcc $(FLAGS) mar-extract-only.c \ No newline at end of file diff --git a/mdk-stage1/mar/mar-extract-only.c b/mdk-stage1/mar/mar-extract-only.c new file mode 100644 index 000000000..013631ce2 --- /dev/null +++ b/mdk-stage1/mar/mar-extract-only.c @@ -0,0 +1,196 @@ +/* + * Guillaume Cottenceau (gc@mandrakesoft.com) + * + * Copyright 2000 MandrakeSoft + * + * This software may be freely redistributed under the terms of the GNU + * public license. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * mar - The Mandrake Archiver + * + * An archiver that supports compression (through zlib). + * + */ + +/* + * This code should suffice for stage1 on-the-fly uncompression of kernel modules. + * (and it DOES perform tests and return values, blaaaah..) + */ + +#include "mar.h" + + +void gzerr(gzFile f) /* decrease code size */ +{ + fprintf(stderr, gzerror(f, &gz_errnum)); +} + +int calc_integrity(mar_stream *s) +{ + char buf[4096]; + int current_crc = 0; + if (gzseek(s->mar_gzfile, sizeof(int), SEEK_SET) != sizeof(int)) + { + gzerr(s->mar_gzfile); + return -1; + } + while (!gzeof(s->mar_gzfile)) + { + int bytes = gzread(s->mar_gzfile, buf, sizeof(buf)); + if (bytes == -1) + { + gzerr(s->mar_gzfile); + return -1; + } + DEBUG_MAR(printf("D: mar::calc_integrity more-bytes-to-handle-for-crc %d\n", bytes);); + while (bytes > 0) + { + bytes--; + current_crc += buf[bytes]; + } + } + DEBUG_MAR(printf("D: mar::calc_integrity computed-crc %d\n", current_crc);); + return current_crc; +} + + +int extract_file(mar_stream *s, char *filename, char *dest_dir) +{ + mar_element * elem = s->first_element; + while (elem != NULL) + { + if (strcmp(elem->filename, filename) == 0) + { + char *buf; + char *dest_file; + int fd; + dest_file = (char *) malloc(strlen(dest_dir) + strlen(filename) + 1); + strcpy(dest_file, dest_dir); + strcat(dest_file, filename); + fd = creat(dest_file, 00660); + if (fd == -1) + { + perror(dest_file); + return -1; + } + buf = (char *) malloc(elem->file_length); + if (buf == NULL) + { + perror(dest_file); + return -1; + } + if (gzseek(s->mar_gzfile, elem->data_offset, SEEK_SET) != elem->data_offset) + { + gzerr(s->mar_gzfile); + return -1; + } + if (gzread(s->mar_gzfile, buf, elem->file_length) != elem->file_length) + { + gzerr(s->mar_gzfile); + return -1; + } + if (write(fd, buf, elem->file_length) != elem->file_length) + { + perror(dest_file); + return -1; + } + close(fd); /* do not check return value for code size */ + return 0; + } + elem = elem->next_element; + } + return 1; /* 1 for file_not_found_in_archive */ +} + + +mar_stream * open_marfile(char *filename) +{ + int end_filetable = 0; + mar_stream * s = (mar_stream *) malloc(sizeof(mar_stream)); + mar_element * previous_element = NULL; + + /* mar_gzfile */ + s->mar_gzfile = gzopen(filename, "rb"); + if (s->mar_gzfile == NULL) + { + perror(filename); + return NULL; + } + + /* crc32 */ + if (gzread(s->mar_gzfile, &(s->crc32), sizeof(int)) != sizeof(int)) + { + gzerr(s->mar_gzfile); + return NULL; + } + + DEBUG_MAR(printf("D: mar::open_marfile crc-in-marfile %d\n", s->crc32);); + /* verify integrity */ + if (s->crc32 != calc_integrity(s)) + { + fprintf(stderr, "E: mar::open_marfile CRC check failed\n"); + return NULL; + } + else + if (gzseek(s->mar_gzfile, sizeof(int), SEEK_SET) != sizeof(int)) + { + gzerr(s->mar_gzfile); + return NULL; + } + + while (end_filetable == 0) + { + char buf[512]; + int ptr = 0; + /* read filename */ + do + { + if (gzread(s->mar_gzfile, &(buf[ptr]), sizeof(char)) != sizeof(char)) + { + gzerr(s->mar_gzfile); + return NULL; + } + ptr++; + } while ((buf[ptr-1] != 0) && (ptr < 512)); + /* ptr == 1 when we arrive on the "char 0" of the end of the filetable */ + if (ptr > 1) + { + mar_element * e = (mar_element *) malloc(sizeof(mar_element)); + e->filename = strdup(buf); + DEBUG_MAR(printf("D: mar::open_marfile processing-file %s\n", e->filename);); + /* read file_length */ + if (gzread(s->mar_gzfile, &(e->file_length), sizeof(int)) != sizeof(int)) + { + gzerr(s->mar_gzfile); + return NULL; + } + /* read data_offset */ + if (gzread(s->mar_gzfile, &(e->data_offset), sizeof(int)) != sizeof(int)) + { + gzerr(s->mar_gzfile); + return NULL; + } + /* write down chaining */ + if (previous_element == NULL) + s->first_element = e; + else + previous_element->next_element = e; + previous_element = e; + } + else + end_filetable = 1; + + } + /* chaining for last element */ + previous_element->next_element = NULL; + + return s; +} + diff --git a/mdk-stage1/mar/mar-extract-only.h b/mdk-stage1/mar/mar-extract-only.h new file mode 100644 index 000000000..5f3280a19 --- /dev/null +++ b/mdk-stage1/mar/mar-extract-only.h @@ -0,0 +1,35 @@ +/* + * Guillaume Cottenceau (gc@mandrakesoft.com) + * + * Copyright 2000 MandrakeSoft + * + * This software may be freely redistributed under the terms of the GNU + * public license. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * mar - The Mandrake Archiver + * + * An archiver that supports compression (through zlib). + * + */ + +/* + * Header for stage1 on-the-fly needs. + */ + +#ifndef MAR_EXTRACT_ONLY_H +#define MAR_EXTRACT_ONLY_H + +#include "mar.h" + +mar_stream * open_marfile(char *filename); +int extract_file(mar_stream *s, char *filename, char *dest_dir); +int calc_integrity(mar_stream *s); + +#endif diff --git a/mdk-stage1/mar/mar-frontend.c b/mdk-stage1/mar/mar-frontend.c new file mode 100644 index 000000000..0b5371d47 --- /dev/null +++ b/mdk-stage1/mar/mar-frontend.c @@ -0,0 +1,304 @@ +/* + * Guillaume Cottenceau (gc@mandrakesoft.com) + * + * Copyright 2000 MandrakeSoft + * + * This software may be freely redistributed under the terms of the GNU + * public license. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * mar - The Mandrake Archiver + * + * An archiver that supports compression (through zlib). + * + */ + +/* + * This code includes the extracting and creating features. + * + */ + +#include "mar.h" +#include "mar-extract-only.h" + +void list_files(mar_stream *s) +{ + mar_element * elem = s->first_element; + printf("%-20s%8s\n", "FILENAME", "LENGTH"); + while (elem != NULL) + { + printf("%-20s%8d\n", elem->filename, elem->file_length); + elem = elem->next_element; + } +} + + +int file_size(char *filename) +{ + FILE * f = fopen(filename, "rb"); + int size; + DEBUG_MAR(printf("D: mar::file_size filename %s\n", filename);); + if (f == NULL) + { + perror(filename); + return -1; + } + if (fseek(f, 0L, SEEK_END) == -1) + { + perror(filename); + return -1; + } + size = ftell(f); + if (size == -1) + { + perror(filename); + return -1; + } + if (fclose(f) != 0) + { + perror(filename); + return -1; + } + return size; +} + + +/* Yes I don't use the datastructure I directly write the final fileformat in memory then write down it. + * Yes it's bad. + */ +/* ``files'' is a NULL-terminated array of char* */ + +int create_marfile(char *dest_file, char **files) +{ + int filenum = 0; + int current_offset_filetable; + int current_offset_rawdata; + char * temp_marfile_buffer; + int total_length; + + /* calculate offset of ``raw_files_data'' */ + current_offset_rawdata = sizeof(int) + sizeof(char); /* crc32, ``char 0'' */ + while (files[filenum] != NULL) + { + current_offset_rawdata += 2*sizeof(int) /* file_length, data_offset */ + strlen(files[filenum]) + 1; + filenum++; + } + DEBUG_MAR(printf("D: mar::create_marfile number-of-files %d offset-data-start %d\n", filenum, current_offset_rawdata);); + + /* calculate length of final uncompressed marfile, for malloc */ + total_length = current_offset_rawdata; /* first part of the marfile: the crc plus filetable */ + filenum = 0; + while (files[filenum] != NULL) + { + int fsiz = file_size(files[filenum]); + if (fsiz == -1) + return -1; + total_length += fsiz; + filenum++; + } + temp_marfile_buffer = (void *) malloc(total_length); /* create the whole file in-memory */ + DEBUG_MAR(printf("D: mar::create_marfile total-length %d\n", total_length);); + + current_offset_filetable = sizeof(int); /* first file is after the crc */ + filenum = 0; + while (files[filenum] != NULL) + { + FILE * f = fopen(files[filenum], "rb"); + int fsize; + if (f == NULL) + { + perror(files[filenum]); + return -1; + } + + /* filename */ + strcpy(&(temp_marfile_buffer[current_offset_filetable]), files[filenum]); + current_offset_filetable += strlen(files[filenum]) + 1; + + /* file_length */ + fsize = file_size(files[filenum]); + if (fsize == -1) return -1; + memcpy(&temp_marfile_buffer[current_offset_filetable], &fsize, sizeof(int)); + current_offset_filetable += sizeof(int); + + /* data_offset */ + memcpy(&temp_marfile_buffer[current_offset_filetable], ¤t_offset_rawdata, sizeof(int)); + current_offset_filetable += sizeof(int); + + /* data_raw_data */ + if (fread(&temp_marfile_buffer[current_offset_rawdata], 1, fsize, f) != fsize) + { + perror(files[filenum]); + return -1; + } + fclose(f); + + current_offset_rawdata += fsize; + + filenum++; + } + + /* calculate crc with all the data we now got */ + { + int current_crc = 0; + int i; + for (i=sizeof(int); i= 3) + { + if (strcmp(argv[1], "-l") == 0) + { + mar_stream *s = open_marfile(argv[2]); + if (s == NULL) + exit(-1); + list_files(s); + if (s->crc32 == calc_integrity(s)) + printf("CRC OK\n"); + else + printf("CRC FAILED!\n"); + exit(0); + } + if ((strcmp(argv[1], "-x") == 0) && argc >= 4) + { + mar_stream *s = open_marfile(argv[2]); + int i = 3; + if (s == NULL) + exit(-1); + while (i < argc) + { + int res = extract_file(s, argv[i], "./"); + if (res == 1) + fprintf(stderr, "W: file-not-found-in-archive %s\n", argv[i]); + if (res == -1) + exit(-1); + i++; + } + exit(0); + } + if ((strcmp(argv[1], "-c") == 0) && argc >= 4) + { + char **files = (char **) malloc(((argc-3)+1) * sizeof(char *)); + int i = 3; + while (i < argc) + { + files[i-3] = strdup(argv[i]); + i++; + } + files[argc-3] = NULL; + exit(create_marfile(argv[2], files)); + } + } + + return 0; +} + /* mar_stream *s; + int res; + char *files[4]; + + char * file1 = "Makefile"; + char * file2 = "mar.c"; + char * file3 = "mar.h"; + + files[0] = file1; + files[1] = file2; + files[2] = file3; + files[3] = NULL; + + create_marfile("test.mar", files); + + + s = open_marfile("test.mar"); + + if (s == NULL) + exit(-1); + + res = extract_file(s, "Makefile", "t/"); + printf("return-code %d\n", res); + + exit(0); +} + char plop[20]; + int i,j; + bzero(plop, 20); + j = 4096; + memcpy(&plop[2], &j, sizeof(j)); + for (i=0; i<20; i++) printf("offset %d, contains char %d\n", i, plop[i]); + exit(-1); + + s.first_element = &e1; +// s.crc32 = calc_integrity(&s); + + e1.filename = "bonjour"; + e1.file_length = 4; + e1.next_element = &e2; + e2.filename = "deuz"; + e2.file_length = 54; + e2.next_element = NULL; + + list_files(&s); +// if (verify_integrity(&s)) { printf("CRC OK\n"); } else { printf("CRC FAILS!\n"); } + return 0; +} + +*/ diff --git a/mdk-stage1/mar/mar.h b/mdk-stage1/mar/mar.h new file mode 100644 index 000000000..5d8d98f61 --- /dev/null +++ b/mdk-stage1/mar/mar.h @@ -0,0 +1,71 @@ +/* + * Guillaume Cottenceau (gc@mandrakesoft.com) + * + * Copyright 2000 MandrakeSoft + * + * This software may be freely redistributed under the terms of the GNU + * public license. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * mar - The Mandrake Archiver + * + * An archiver that supports compression (through zlib). + * + * Designed to be small so these bad designs are inside: + * . archive and compression are mixed together + * . create the mar file in-memory + * . does not free memory + * + */ + +#ifndef MAR_H +#define MAR_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Format of a mar file: + * + * int crc32 \ + * ASCIIZ filename \ | + * int file_length | repeated | gzipped + * int pointer_in_archive / | + * char 0 | + * raw_files_data / + * + */ + +typedef struct mar_element_s +{ + char * filename; /* filename (ASCIIZ) of the element */ + int file_length; /* length (in bytes) of the raw data of the element */ + int data_offset; /* seek start of the raw data in the underlying mar stream */ + struct mar_element_s * next_element; /* pointer to the next element in the mar stream; NULL if last */ +} mar_element; + +typedef struct mar_stream_s +{ + int crc32; /* crc32 of the mar stream; it is the addition of all the 8-bit char's from the stream */ + mar_element * first_element; /* pointer to the first element inside the mar stream */ + gzFile mar_gzfile; /* associated gzFile (opened) */ +} mar_stream; + +int gz_errnum; + +#define DEBUG_MAR(x) + +#endif -- cgit v1.2.1