summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuillaume Cottenceau <gc@mandriva.com>2000-11-09 23:09:17 +0000
committerGuillaume Cottenceau <gc@mandriva.com>2000-11-09 23:09:17 +0000
commitb695b4bd2408c4ad06a1dcdd95b2a95a3bf63fa5 (patch)
tree7f890201f7b16e38103141b0f47a47a30fe8d403
parent9166c569774a7580df1b39ccebc8cc5abd46b1d9 (diff)
downloaddrakx-b695b4bd2408c4ad06a1dcdd95b2a95a3bf63fa5.tar
drakx-b695b4bd2408c4ad06a1dcdd95b2a95a3bf63fa5.tar.gz
drakx-b695b4bd2408c4ad06a1dcdd95b2a95a3bf63fa5.tar.bz2
drakx-b695b4bd2408c4ad06a1dcdd95b2a95a3bf63fa5.tar.xz
drakx-b695b4bd2408c4ad06a1dcdd95b2a95a3bf63fa5.zip
add `mar' archiving program
-rw-r--r--mdk-stage1/mar/Makefile15
-rw-r--r--mdk-stage1/mar/mar-extract-only.c196
-rw-r--r--mdk-stage1/mar/mar-extract-only.h35
-rw-r--r--mdk-stage1/mar/mar-frontend.c304
-rw-r--r--mdk-stage1/mar/mar.h71
5 files changed, 621 insertions, 0 deletions
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], &current_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<total_length ; i++)
+ current_crc += temp_marfile_buffer[i];
+ memcpy(&temp_marfile_buffer[0], &current_crc, sizeof(int));
+ DEBUG_MAR(printf("D: mar::create_marfile computed-crc %d\n", current_crc););
+ }
+
+ /* ok, buffer is ready, let's write it on-disk */
+ {
+ gzFile f = gzopen(dest_file, "wb");
+ if (f == NULL)
+ {
+ perror(dest_file);
+ return -1;
+ }
+ if (gzwrite(f, temp_marfile_buffer, total_length) != total_length)
+ {
+ fprintf(stderr, gzerror(f, &gz_errnum));
+ return -1;
+ }
+ gz_errnum = gzclose(f);
+ }
+
+// /* uncompressed write
+//
+// int fd = creat(dest_file, 00660);
+// if (fd == -1)
+// {
+// perror("E: mar::create_marfile::creat");
+// return -1;
+// }
+// if (write(fd, temp_marfile_buffer, total_length) != total_length)
+// {
+// perror("E: mar::create_marfile::write");
+// return -1;
+// }
+// if (close(fd) != 0)
+// {
+// perror("E: mar::create_marfile::close");
+// return -1;
+// }
+// */
+
+ return 0;
+}
+
+
+void print_usage(char *progname)
+{
+ printf("Usage: %s [-lxc] [files..]\n", progname);
+ exit(0);
+}
+
+int main(int argc, char **argv)
+{
+ if (argc <= 2)
+ print_usage(argv[0]);
+
+ if (argc >= 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <zlib.h>
+
+/*
+ * 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