Reorganise archive extraction code
authorGlenn L McGrath <bug1@ihug.co.nz>
Wed, 13 Jun 2001 07:26:39 +0000 (07:26 -0000)
committerGlenn L McGrath <bug1@ihug.co.nz>
Wed, 13 Jun 2001 07:26:39 +0000 (07:26 -0000)
Makefile
ar.c
archival/ar.c
archival/dpkg.c
archival/dpkg_deb.c
dpkg.c
dpkg_deb.c
include/libbb.h
libbb/deb_extract.c
libbb/get_ar_headers.c
libbb/libbb.h

index 2af152516932ededbf64fb75a81b1057f2ccc7e7..f8e60443e89b9a5a2bba54ee159eb291398127a0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -236,21 +236,21 @@ endif
     
 LIBBB    = libbb
 LIBBB_LIB = libbb.a
-LIBBB_CSRC= ask_confirmation.c chomp.c \
-concat_path_file.c copy_file.c copy_file_chunk.c create_path.c \
+LIBBB_CSRC= append_archive_list.c add_from_archive_list.c ask_confirmation.c \
+chomp.c concat_path_file.c copy_file.c copy_file_chunk.c create_path.c \
 daemon.c deb_extract.c device_open.c error_msg.c error_msg_and_die.c \
-find_mount_point.c find_pid_by_name.c find_root_device.c full_read.c \
-full_write.c get_ar_headers.c get_console.c get_last_path_component.c \
-get_line_from_file.c gz_open.c human_readable.c isdirectory.c \
-kernel_version.c loop.c mode_string.c module_syscalls.c mtab.c mtab_file.c \
-my_getgrnam.c my_getgrgid.c my_getpwnam.c my_getpwnamegid.c my_getpwuid.c \
-parse_mode.c parse_number.c perror_msg.c perror_msg_and_die.c print_file.c \
-process_escape_sequence.c read_package_field.c read_text_file_to_buffer.c \
-recursive_action.c safe_read.c safe_strncpy.c seek_ared_file.c syscalls.c \
-syslog_msg_with_name.c time_string.c trim.c untar.c unzip.c vdprintf.c \
-verror_msg.c vperror_msg.c wfopen.c xfuncs.c xgetcwd.c xreadlink.c \
-xregcomp.c interface.c remove_file.c last_char_is.c copyfd.c \
-vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c
+extract_archive.c fgets_str.c find_mount_point.c find_pid_by_name.c \
+find_root_device.c full_read.c full_write.c get_ar_headers.c get_console.c \
+get_last_path_component.c get_line_from_file.c get_tar_headers.c \
+get_tar_gz_headers.c gz_open.c human_readable.c isdirectory.c kernel_version.c \
+loop.c mode_string.c module_syscalls.c mtab.c mtab_file.c my_getgrnam.c \
+my_getgrgid.c my_getpwnam.c my_getpwnamegid.c my_getpwuid.c parse_mode.c \
+parse_number.c perror_msg.c perror_msg_and_die.c print_file.c \
+process_escape_sequence.c read_package_field.c recursive_action.c safe_read.c \
+safe_strncpy.c syscalls.c syslog_msg_with_name.c time_string.c \
+trim.c unzip.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c xfuncs.c \
+xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \
+copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c
 LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC))
 LIBBB_CFLAGS = -I$(LIBBB)
 ifneq ($(strip $(BB_SRC_DIR)),)
diff --git a/ar.c b/ar.c
index 08cd5c50125cdd6649c8f338f61e48a0a6c812c8..7359f49105f35ddeee2056bde4e8f3269f81f2a2 100644 (file)
--- a/ar.c
+++ b/ar.c
 
 extern int ar_main(int argc, char **argv)
 {
-       const int preserve_date = 1;    /* preserve original dates */
-       const int verbose = 2;          /* be verbose */
-       const int display = 4;          /* display contents */
-       const int extract_to_file = 8;  /* extract contents of archive */
-       const int extract_to_stdout = 16;       /* extract to stdout */
-
-       FILE *src_file = NULL, *dst_file = NULL;
-       int funct = 0, opt=0;
-
-       ar_headers_t *head, *ar_extract_list=NULL;
-
-       ar_extract_list = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t));
-       head = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t));
+       FILE *src_stream = NULL;
+       int extract_function = 0, opt = 0;
+       file_headers_t *head;
+       file_headers_t *ar_extract_list = NULL;
 
        while ((opt = getopt(argc, argv, "ovtpx")) != -1) {
                switch (opt) {
                case 'o':
-                       funct |= preserve_date;
+                       extract_function |= extract_preserve_date;
                        break;
                case 'v':
-                       funct |= verbose;
+                       extract_function |= extract_verbose_list;
                        break;
                case 't':
-                       funct |= display;
+                       extract_function |= extract_list;
                        break;
                case 'p':
-                       funct |= extract_to_stdout;
+                       extract_function |= extract_to_stdout;
                        break;
                case 'x':
-                       funct |= extract_to_file;
+                       extract_function |= extract_all_to_fs;
                        break;
                default:
                        show_usage();
@@ -71,57 +62,28 @@ extern int ar_main(int argc, char **argv)
                show_usage();
        }
 
-       if ( (src_file = wfopen(argv[optind], "r")) < 0) {
-               error_msg_and_die("Cannot read %s", argv[optind]);
-       }
+       src_stream = xfopen(argv[optind++], "r");
+       head = get_ar_headers(src_stream);
 
-       optind++;       
-       head = get_ar_headers(src_file);
        /* find files to extract or display */
        /* search through argv and build extract list */
-       for (;optind < argc; optind++) {
-               ar_headers_t *ar_entry;
-               ar_entry = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t));
-               ar_entry = head;
-               while (ar_entry->next != NULL) {
-                       if (strcmp(argv[optind], ar_entry->name) == 0) {
-                               ar_headers_t *tmp;
-                               tmp = (ar_headers_t *) xmalloc(sizeof(ar_headers_t));
-                               *tmp = *ar_extract_list;
-                               *ar_extract_list = *ar_entry;
-                               ar_extract_list->next = tmp;
-                               break;                                  
-                       }
-                       ar_entry=ar_entry->next;
+       ar_extract_list = (file_headers_t *) xcalloc(1, sizeof(file_headers_t));
+       if (optind < argc) {
+               while (optind < argc) {
+                       ar_extract_list = add_from_archive_list(head, ar_extract_list, argv[optind]);
+                       optind++;
                }
-       }
-
-       /* if individual files not found extract all files */   
-       if (ar_extract_list->next==NULL) {
+       } else {
                ar_extract_list = head;
        }
 
-       /* find files to extract or display */  
-       while (ar_extract_list->next != NULL) {
-               if (funct & extract_to_file) {
-                       dst_file = wfopen(ar_extract_list->name, "w");                          
-               }
-               else if (funct & extract_to_stdout) {
-                       dst_file = stdout;
-               }
-               if ((funct & extract_to_file) || (funct & extract_to_stdout)) {
-                       fseek(src_file, ar_extract_list->offset, SEEK_SET);
-                       copy_file_chunk(src_file, dst_file, ar_extract_list->size);                     
-               }
-               if (funct & verbose) {
-                       printf("%s %d/%d %8d %s ", mode_string(ar_extract_list->mode), 
-                               ar_extract_list->uid, ar_extract_list->gid,
-                               (int) ar_extract_list->size, time_string(ar_extract_list->mtime));
-               }
-               if ((funct & display) || (funct & verbose)){
-                       puts(ar_extract_list->name);
-               }
-               ar_extract_list = ar_extract_list->next;
-       }
+       /* If there isnt even one possible entry then abort */
+       if (ar_extract_list->name == NULL) {
+               error_msg_and_die("No files to extract");
+       }       
+
+       fseek(src_stream, 0, SEEK_SET);
+       extract_archive(src_stream, stdout, ar_extract_list, extract_function, "./");
+
        return EXIT_SUCCESS;
 }
index 08cd5c50125cdd6649c8f338f61e48a0a6c812c8..7359f49105f35ddeee2056bde4e8f3269f81f2a2 100644 (file)
 
 extern int ar_main(int argc, char **argv)
 {
-       const int preserve_date = 1;    /* preserve original dates */
-       const int verbose = 2;          /* be verbose */
-       const int display = 4;          /* display contents */
-       const int extract_to_file = 8;  /* extract contents of archive */
-       const int extract_to_stdout = 16;       /* extract to stdout */
-
-       FILE *src_file = NULL, *dst_file = NULL;
-       int funct = 0, opt=0;
-
-       ar_headers_t *head, *ar_extract_list=NULL;
-
-       ar_extract_list = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t));
-       head = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t));
+       FILE *src_stream = NULL;
+       int extract_function = 0, opt = 0;
+       file_headers_t *head;
+       file_headers_t *ar_extract_list = NULL;
 
        while ((opt = getopt(argc, argv, "ovtpx")) != -1) {
                switch (opt) {
                case 'o':
-                       funct |= preserve_date;
+                       extract_function |= extract_preserve_date;
                        break;
                case 'v':
-                       funct |= verbose;
+                       extract_function |= extract_verbose_list;
                        break;
                case 't':
-                       funct |= display;
+                       extract_function |= extract_list;
                        break;
                case 'p':
-                       funct |= extract_to_stdout;
+                       extract_function |= extract_to_stdout;
                        break;
                case 'x':
-                       funct |= extract_to_file;
+                       extract_function |= extract_all_to_fs;
                        break;
                default:
                        show_usage();
@@ -71,57 +62,28 @@ extern int ar_main(int argc, char **argv)
                show_usage();
        }
 
-       if ( (src_file = wfopen(argv[optind], "r")) < 0) {
-               error_msg_and_die("Cannot read %s", argv[optind]);
-       }
+       src_stream = xfopen(argv[optind++], "r");
+       head = get_ar_headers(src_stream);
 
-       optind++;       
-       head = get_ar_headers(src_file);
        /* find files to extract or display */
        /* search through argv and build extract list */
-       for (;optind < argc; optind++) {
-               ar_headers_t *ar_entry;
-               ar_entry = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t));
-               ar_entry = head;
-               while (ar_entry->next != NULL) {
-                       if (strcmp(argv[optind], ar_entry->name) == 0) {
-                               ar_headers_t *tmp;
-                               tmp = (ar_headers_t *) xmalloc(sizeof(ar_headers_t));
-                               *tmp = *ar_extract_list;
-                               *ar_extract_list = *ar_entry;
-                               ar_extract_list->next = tmp;
-                               break;                                  
-                       }
-                       ar_entry=ar_entry->next;
+       ar_extract_list = (file_headers_t *) xcalloc(1, sizeof(file_headers_t));
+       if (optind < argc) {
+               while (optind < argc) {
+                       ar_extract_list = add_from_archive_list(head, ar_extract_list, argv[optind]);
+                       optind++;
                }
-       }
-
-       /* if individual files not found extract all files */   
-       if (ar_extract_list->next==NULL) {
+       } else {
                ar_extract_list = head;
        }
 
-       /* find files to extract or display */  
-       while (ar_extract_list->next != NULL) {
-               if (funct & extract_to_file) {
-                       dst_file = wfopen(ar_extract_list->name, "w");                          
-               }
-               else if (funct & extract_to_stdout) {
-                       dst_file = stdout;
-               }
-               if ((funct & extract_to_file) || (funct & extract_to_stdout)) {
-                       fseek(src_file, ar_extract_list->offset, SEEK_SET);
-                       copy_file_chunk(src_file, dst_file, ar_extract_list->size);                     
-               }
-               if (funct & verbose) {
-                       printf("%s %d/%d %8d %s ", mode_string(ar_extract_list->mode), 
-                               ar_extract_list->uid, ar_extract_list->gid,
-                               (int) ar_extract_list->size, time_string(ar_extract_list->mtime));
-               }
-               if ((funct & display) || (funct & verbose)){
-                       puts(ar_extract_list->name);
-               }
-               ar_extract_list = ar_extract_list->next;
-       }
+       /* If there isnt even one possible entry then abort */
+       if (ar_extract_list->name == NULL) {
+               error_msg_and_die("No files to extract");
+       }       
+
+       fseek(src_stream, 0, SEEK_SET);
+       extract_archive(src_stream, stdout, ar_extract_list, extract_function, "./");
+
        return EXIT_SUCCESS;
 }
index 0010df537f098dd75ce0a0ebb584daa5663b7ba4..4224672ec2a18051b6ccb2c118c5264779b894db 100644 (file)
@@ -13,7 +13,6 @@
 
 #include "busybox.h"
 
-
 #define DEPENDSMAX     64      /* maximum number of depends we can handle */
 
 /* Should we do full dependency checking? */
@@ -487,7 +486,7 @@ static void *status_read(void)
                return(NULL);
        }
 
-       while ( (package_control_buffer = read_text_file_to_buffer(f)) != NULL) {
+       while ( (package_control_buffer = fgets_str(f, "\n\n")) != NULL) {
                m = (package_t *)xcalloc(1, sizeof(package_t));
                fill_package_struct(m, package_control_buffer);
                if (m->package) {
@@ -650,24 +649,26 @@ static int dpkg_doconfigure(package_t *pkg)
 
 static int dpkg_dounpack(package_t *pkg)
 {
-       int r = 0;
+       FILE *out_stream;
+       char *info_prefix;
        int status = TRUE;
-       char *lst_path;
+       int r = 0;
 
        DPRINTF("Unpacking %s\n", pkg->package);
 
        /* extract the data file */
-       deb_extract(pkg->filename, extract_extract, "/", NULL);
+       deb_extract(pkg->filename, stdout, (extract_data_tar_gz | extract_all_to_fs), "/", NULL);
 
        /* extract the control files */
-       deb_extract(pkg->filename, extract_control, infodir, pkg->package);
+       info_prefix = (char *) malloc(strlen(pkg->package) + strlen(infodir) + 2 + 5 + 1);
+       sprintf(info_prefix, "%s/%s.", infodir, pkg->package);
+       deb_extract(pkg->package, stdout, (extract_control_tar_gz | extract_all_to_fs), info_prefix, NULL);
 
        /* Create the list file */
-       lst_path = xmalloc(strlen(infodir) + strlen(pkg->package) + 6);
-       strcpy(lst_path, infodir);
-       strcat(lst_path, pkg->package);
-       strcat(lst_path, ".list");
-       deb_extract(pkg->filename, extract_contents_to_file, lst_path, NULL);
+       strcat(info_prefix, "list");
+       out_stream = wfopen(info_prefix, "w");                  
+       deb_extract(pkg->package, out_stream, (extract_data_tar_gz | extract_list), NULL, NULL);
+       fclose(out_stream);
 
        pkg->state_want = state_want_install;
        pkg->state_flag = state_flag_ok;
@@ -692,7 +693,7 @@ static int dpkg_read_control(package_t *pkg)
        if ((pkg_file = wfopen(pkg->filename, "r")) == NULL) {
                return EXIT_FAILURE;
        }
-       control_buffer = deb_extract(pkg->filename, extract_field, NULL, NULL);
+       control_buffer = deb_extract(pkg->filename, stdout, (extract_control_tar_gz | extract_one_to_buffer), NULL, "./control");
        fill_package_struct(pkg, control_buffer);
        return EXIT_SUCCESS;
 }
index 17b5476d0ddefc1f4ab7d1114a788b1af1cc1887..400f2385a11d9ffc9ae5d9b95ffa969f70b06d5e 100644 (file)
 
 extern int dpkg_deb_main(int argc, char **argv)
 {
-       char *argument = NULL;
+       char *prefix = NULL;
+       char *filename = NULL;
        char *output_buffer = NULL;
        int opt = 0;
-       int optflag = 0;        
+       int arg_type = 0;
+       int deb_extract_funct = 0;      
        
+       const int arg_type_prefix = 1;
+       const int arg_type_field = 2;
+       const int arg_type_filename = 4;
+//     const int arg_type_un_ar_gz = 8;
+
        while ((opt = getopt(argc, argv, "ceftXxI")) != -1) {
                switch (opt) {
                        case 'c':
-                               optflag |= extract_contents;
+                               deb_extract_funct |= extract_data_tar_gz;
+                               deb_extract_funct |= extract_verbose_list;
                                break;
                        case 'e':
-                               optflag |= extract_control;
+                               arg_type = arg_type_prefix;
+                               deb_extract_funct |= extract_control_tar_gz;
+                               deb_extract_funct |= extract_all_to_fs;
                                break;
                        case 'f':
-                               optflag |= extract_field;
+                               arg_type = arg_type_field;
+                               deb_extract_funct |= extract_control_tar_gz;
+                               deb_extract_funct |= extract_one_to_buffer;
+                               filename = xstrdup("./control");
                                break;
-                       case 't':
-                               optflag |= extract_fsys_tarfile;
+                       case 't': /* --fsys-tarfile, i just made up this short name */
+                               /* Integrate the functionality needed with some code from ar.c */
+                               error_msg_and_die("Option disabled");
+//                             arg_type = arg_type_un_ar_gz;
                                break;
                        case 'X':
-                               optflag |= extract_verbose_extract;
-                               break;
+                               arg_type = arg_type_prefix;
+                               deb_extract_funct |= extract_data_tar_gz;
+                               deb_extract_funct |= extract_all_to_fs;
+                               deb_extract_funct |= extract_list;
                        case 'x':
-                               optflag |= extract_extract;
+                               arg_type = arg_type_prefix;
+                               deb_extract_funct |= extract_data_tar_gz;
+                               deb_extract_funct |= extract_all_to_fs;
                                break;
                        case 'I':
-                               optflag |= extract_info;
+                               arg_type = arg_type_filename;
+                               deb_extract_funct |= extract_control_tar_gz;
+                               deb_extract_funct |= extract_one_to_buffer;
                                break;
                        default:
                                show_usage();
@@ -58,48 +79,42 @@ extern int dpkg_deb_main(int argc, char **argv)
                show_usage();
        }
 
-       switch (optflag) {
-               case (extract_control):
-               case (extract_extract):
-               case (extract_verbose_extract):
-                       /* argument is a dir name */
-                       if ( (optind + 1) == argc ) {
-                               argument = xstrdup("DEBIAN");
-                       } else {
-                               argument = xstrdup(argv[optind + 1]);
-                       }
-                       break;
-               case (extract_field):
-                       /* argument is a control field name */
-                       if ((optind + 1) != argc) {
-                               argument = xstrdup(argv[optind + 1]);                           
-                       }
-                       break;
-               case (extract_info):
-                       /* argument is a control field name */
-                       if ((optind + 1) != argc) {
-                               argument = xstrdup(argv[optind + 1]);
-                               break;
-                       } else {
-                               error_msg("-I currently requires a filename to be specifies");
-                               return(EXIT_FAILURE);
+       /* Workout where to extract the files */
+       if (arg_type == arg_type_prefix) {
+               /* argument is a dir name */
+               if ((optind + 1) == argc ) {
+                       prefix = xstrdup("./DEBIAN/");
+               } else {
+                       prefix = (char *) xmalloc(strlen(argv[optind + 1]) + 2);
+                       strcpy(prefix, argv[optind + 1]);
+                       /* Make sure the directory has a trailing '/' */
+                       if (last_char_is(prefix, '/') == NULL) {
+                               strcat(prefix, "/");
                        }
-                       /* argument is a filename */
-               default:
+               }
        }
 
-       output_buffer = deb_extract(argv[optind], optflag, argument, NULL);
+       if (arg_type == arg_type_filename) {
+               if ((optind + 1) != argc) {
+                       filename = xstrdup(argv[optind + 1]);
+               } else {
+                       error_msg_and_die("-I currently requires a filename to be specified");
+               }
+       }
 
-       if (optflag & extract_field) {
+       output_buffer = deb_extract(argv[optind], stdout, deb_extract_funct, prefix, filename);
+
+       if ((arg_type == arg_type_filename) && (output_buffer != NULL)) {
+               puts(output_buffer);
+       }
+       else if (arg_type == arg_type_field) {
                char *field = NULL;
-               int field_length = 0;
                int field_start = 0;
 
                while ((field = read_package_field(&output_buffer[field_start])) != NULL) {
-                       field_length = strlen(field);
-                       field_start += (field_length + 1);
-                       if (strstr(field, argument) == field) {
-                               puts(field + strlen(argument) + 2);
+                       field_start += (strlen(field) + 1);
+                       if (strstr(field, argv[optind + 1]) == field) {
+                               puts(field + strlen(argv[optind + 1]) + 2);
                        }
                        free(field);
                }
diff --git a/dpkg.c b/dpkg.c
index 0010df537f098dd75ce0a0ebb584daa5663b7ba4..4224672ec2a18051b6ccb2c118c5264779b894db 100644 (file)
--- a/dpkg.c
+++ b/dpkg.c
@@ -13,7 +13,6 @@
 
 #include "busybox.h"
 
-
 #define DEPENDSMAX     64      /* maximum number of depends we can handle */
 
 /* Should we do full dependency checking? */
@@ -487,7 +486,7 @@ static void *status_read(void)
                return(NULL);
        }
 
-       while ( (package_control_buffer = read_text_file_to_buffer(f)) != NULL) {
+       while ( (package_control_buffer = fgets_str(f, "\n\n")) != NULL) {
                m = (package_t *)xcalloc(1, sizeof(package_t));
                fill_package_struct(m, package_control_buffer);
                if (m->package) {
@@ -650,24 +649,26 @@ static int dpkg_doconfigure(package_t *pkg)
 
 static int dpkg_dounpack(package_t *pkg)
 {
-       int r = 0;
+       FILE *out_stream;
+       char *info_prefix;
        int status = TRUE;
-       char *lst_path;
+       int r = 0;
 
        DPRINTF("Unpacking %s\n", pkg->package);
 
        /* extract the data file */
-       deb_extract(pkg->filename, extract_extract, "/", NULL);
+       deb_extract(pkg->filename, stdout, (extract_data_tar_gz | extract_all_to_fs), "/", NULL);
 
        /* extract the control files */
-       deb_extract(pkg->filename, extract_control, infodir, pkg->package);
+       info_prefix = (char *) malloc(strlen(pkg->package) + strlen(infodir) + 2 + 5 + 1);
+       sprintf(info_prefix, "%s/%s.", infodir, pkg->package);
+       deb_extract(pkg->package, stdout, (extract_control_tar_gz | extract_all_to_fs), info_prefix, NULL);
 
        /* Create the list file */
-       lst_path = xmalloc(strlen(infodir) + strlen(pkg->package) + 6);
-       strcpy(lst_path, infodir);
-       strcat(lst_path, pkg->package);
-       strcat(lst_path, ".list");
-       deb_extract(pkg->filename, extract_contents_to_file, lst_path, NULL);
+       strcat(info_prefix, "list");
+       out_stream = wfopen(info_prefix, "w");                  
+       deb_extract(pkg->package, out_stream, (extract_data_tar_gz | extract_list), NULL, NULL);
+       fclose(out_stream);
 
        pkg->state_want = state_want_install;
        pkg->state_flag = state_flag_ok;
@@ -692,7 +693,7 @@ static int dpkg_read_control(package_t *pkg)
        if ((pkg_file = wfopen(pkg->filename, "r")) == NULL) {
                return EXIT_FAILURE;
        }
-       control_buffer = deb_extract(pkg->filename, extract_field, NULL, NULL);
+       control_buffer = deb_extract(pkg->filename, stdout, (extract_control_tar_gz | extract_one_to_buffer), NULL, "./control");
        fill_package_struct(pkg, control_buffer);
        return EXIT_SUCCESS;
 }
index 17b5476d0ddefc1f4ab7d1114a788b1af1cc1887..400f2385a11d9ffc9ae5d9b95ffa969f70b06d5e 100644 (file)
 
 extern int dpkg_deb_main(int argc, char **argv)
 {
-       char *argument = NULL;
+       char *prefix = NULL;
+       char *filename = NULL;
        char *output_buffer = NULL;
        int opt = 0;
-       int optflag = 0;        
+       int arg_type = 0;
+       int deb_extract_funct = 0;      
        
+       const int arg_type_prefix = 1;
+       const int arg_type_field = 2;
+       const int arg_type_filename = 4;
+//     const int arg_type_un_ar_gz = 8;
+
        while ((opt = getopt(argc, argv, "ceftXxI")) != -1) {
                switch (opt) {
                        case 'c':
-                               optflag |= extract_contents;
+                               deb_extract_funct |= extract_data_tar_gz;
+                               deb_extract_funct |= extract_verbose_list;
                                break;
                        case 'e':
-                               optflag |= extract_control;
+                               arg_type = arg_type_prefix;
+                               deb_extract_funct |= extract_control_tar_gz;
+                               deb_extract_funct |= extract_all_to_fs;
                                break;
                        case 'f':
-                               optflag |= extract_field;
+                               arg_type = arg_type_field;
+                               deb_extract_funct |= extract_control_tar_gz;
+                               deb_extract_funct |= extract_one_to_buffer;
+                               filename = xstrdup("./control");
                                break;
-                       case 't':
-                               optflag |= extract_fsys_tarfile;
+                       case 't': /* --fsys-tarfile, i just made up this short name */
+                               /* Integrate the functionality needed with some code from ar.c */
+                               error_msg_and_die("Option disabled");
+//                             arg_type = arg_type_un_ar_gz;
                                break;
                        case 'X':
-                               optflag |= extract_verbose_extract;
-                               break;
+                               arg_type = arg_type_prefix;
+                               deb_extract_funct |= extract_data_tar_gz;
+                               deb_extract_funct |= extract_all_to_fs;
+                               deb_extract_funct |= extract_list;
                        case 'x':
-                               optflag |= extract_extract;
+                               arg_type = arg_type_prefix;
+                               deb_extract_funct |= extract_data_tar_gz;
+                               deb_extract_funct |= extract_all_to_fs;
                                break;
                        case 'I':
-                               optflag |= extract_info;
+                               arg_type = arg_type_filename;
+                               deb_extract_funct |= extract_control_tar_gz;
+                               deb_extract_funct |= extract_one_to_buffer;
                                break;
                        default:
                                show_usage();
@@ -58,48 +79,42 @@ extern int dpkg_deb_main(int argc, char **argv)
                show_usage();
        }
 
-       switch (optflag) {
-               case (extract_control):
-               case (extract_extract):
-               case (extract_verbose_extract):
-                       /* argument is a dir name */
-                       if ( (optind + 1) == argc ) {
-                               argument = xstrdup("DEBIAN");
-                       } else {
-                               argument = xstrdup(argv[optind + 1]);
-                       }
-                       break;
-               case (extract_field):
-                       /* argument is a control field name */
-                       if ((optind + 1) != argc) {
-                               argument = xstrdup(argv[optind + 1]);                           
-                       }
-                       break;
-               case (extract_info):
-                       /* argument is a control field name */
-                       if ((optind + 1) != argc) {
-                               argument = xstrdup(argv[optind + 1]);
-                               break;
-                       } else {
-                               error_msg("-I currently requires a filename to be specifies");
-                               return(EXIT_FAILURE);
+       /* Workout where to extract the files */
+       if (arg_type == arg_type_prefix) {
+               /* argument is a dir name */
+               if ((optind + 1) == argc ) {
+                       prefix = xstrdup("./DEBIAN/");
+               } else {
+                       prefix = (char *) xmalloc(strlen(argv[optind + 1]) + 2);
+                       strcpy(prefix, argv[optind + 1]);
+                       /* Make sure the directory has a trailing '/' */
+                       if (last_char_is(prefix, '/') == NULL) {
+                               strcat(prefix, "/");
                        }
-                       /* argument is a filename */
-               default:
+               }
        }
 
-       output_buffer = deb_extract(argv[optind], optflag, argument, NULL);
+       if (arg_type == arg_type_filename) {
+               if ((optind + 1) != argc) {
+                       filename = xstrdup(argv[optind + 1]);
+               } else {
+                       error_msg_and_die("-I currently requires a filename to be specified");
+               }
+       }
 
-       if (optflag & extract_field) {
+       output_buffer = deb_extract(argv[optind], stdout, deb_extract_funct, prefix, filename);
+
+       if ((arg_type == arg_type_filename) && (output_buffer != NULL)) {
+               puts(output_buffer);
+       }
+       else if (arg_type == arg_type_field) {
                char *field = NULL;
-               int field_length = 0;
                int field_start = 0;
 
                while ((field = read_package_field(&output_buffer[field_start])) != NULL) {
-                       field_length = strlen(field);
-                       field_start += (field_length + 1);
-                       if (strstr(field, argument) == field) {
-                               puts(field + strlen(argument) + 2);
+                       field_start += (strlen(field) + 1);
+                       if (strstr(field, argv[optind + 1]) == field) {
+                               puts(field + strlen(argv[optind + 1]) + 2);
                        }
                        free(field);
                }
index f99d2578028e7c30d341b9de0251895554820937..f24a38109ccb9feb08551d0e628c3e24a2be67b1 100644 (file)
@@ -213,36 +213,41 @@ char *xreadlink(const char *path);
 char *concat_path_file(const char *path, const char *filename);
 char *last_char_is(const char *s, int c);
 
-typedef struct ar_headers_s {
+typedef struct file_headers_s {
        char *name;
+       char *link_name;
        off_t size;
        uid_t uid;
        gid_t gid;
        mode_t mode;
        time_t mtime;
        off_t offset;
-       struct ar_headers_s *next;
-} ar_headers_t;
-extern ar_headers_t *get_ar_headers(FILE *in_file);
-extern int seek_ared_file(FILE *in_file, ar_headers_t *headers, const char *tar_gz_file);
-
-typedef enum extract_function_e {
-       extract_contents = 1,
-       extract_control = 2,
-       extract_info = 4,
-       extract_extract = 8,
-       extract_verbose_extract = 16,
-       extract_list = 32,
-       extract_fsys_tarfile = 64,
-       extract_field = 128,
-       extract_contents_to_file = 256
-} extract_function_t;
-extern char *deb_extract(const char *package_filename, int function,
-       const char *argument, const char *argument2);
-extern char *untar(FILE *src_tar_file, FILE *output, int untar_function,
-       const char *argument, const char *file_prefix);
-extern char *read_text_file_to_buffer(FILE *src_file);
-extern char *read_package_field(const char *package_buffer);
+       dev_t device;
+       struct file_headers_s *next;
+} file_headers_t;
+file_headers_t *get_ar_headers(FILE *in_file);
+file_headers_t *get_tar_headers(FILE *tar_stream);
+file_headers_t *get_tar_gz_headers(FILE *compressed_stream);
+file_headers_t *append_archive_list(file_headers_t *head, file_headers_t *tail_entry);
+file_headers_t *add_from_archive_list(file_headers_t *master_list, file_headers_t *new_list, const char *name);
+
+enum extract_functions_e {
+       extract_verbose_list = 1,
+       extract_list = 2,
+       extract_one_to_buffer = 4,
+       extract_to_stdout = 8,
+       extract_all_to_fs = 16,
+       extract_preserve_date = 32,
+       extract_data_tar_gz = 64,
+       extract_control_tar_gz = 128,
+       extract_unzip_only = 256
+};
+char *extract_archive(FILE *src_stream, FILE *out_stream, file_headers_t *extract_headers, int function, const char *prefix);
+char *deb_extract(const char *package_filename, FILE *out_stream, const int function,
+       const char *prefix, const char *filename);
+char *read_package_field(const char *package_buffer);
+int seek_sub_file(FILE *in_file, file_headers_t *headers, const char *tar_gz_file);
+char *fgets_str(FILE *file, const char *terminating_string);
 
 extern int unzip(FILE *l_in_file, FILE *l_out_file);
 extern void gz_close(int gunzip_pid);
index 36cebfa51e1ea6a6d6d22b8c04857c54cf7bae96..f64193970322351da73dc4b84e620bdbb1a92666 100644 (file)
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
-#include <signal.h>
 #include "libbb.h"
 
+int seek_sub_file(FILE *in_file, file_headers_t *headers, const char *tar_gz_file)
+{
+       /* find the headers for the specified .tar.gz file */
+       while (headers != NULL) {
+               if (strcmp(headers->name, tar_gz_file) == 0) {
+                       fseek(in_file, headers->offset, SEEK_SET);
+                       return(EXIT_SUCCESS);
+               }
+               headers = headers->next;
+       }
+
+       return(EXIT_FAILURE);
+}
+
 /*
  * The contents of argument depend on the value of function.
  * It is either a dir name or a control file or field name(see dpkg_deb.c)
  */
-extern char *deb_extract(const char *package_filename, const int function, const char *argument, const char *argument2)
+char *deb_extract(const char *package_filename, FILE *out_stream, const int extract_function,
+       const char *prefix, const char *filename)
 {
+       FILE *deb_stream, *uncompressed_stream;
+       file_headers_t *ar_headers = NULL;
+       file_headers_t *tar_headers = NULL;
+       file_headers_t *list_ptr;
+       file_headers_t *deb_extract_list = (file_headers_t *) calloc(1, sizeof(file_headers_t));
 
-       FILE *deb_file, *uncompressed_file;
-       ar_headers_t *headers = NULL;
        char *ared_file = NULL;
        char *output_buffer = NULL;
        int gunzip_pid;
 
-       switch (function) {
-               case (extract_info):
-               case (extract_control):
-               case (extract_field):
-                       ared_file = xstrdup("control.tar.gz");
-                       break;
-               default:
-                       ared_file = xstrdup("data.tar.gz");
-                       break;
+       if (extract_function & extract_control_tar_gz) {
+               ared_file = xstrdup("control.tar.gz");
+       }
+       else if (extract_function & extract_data_tar_gz) {              
+               ared_file = xstrdup("data.tar.gz");
        }
 
        /* open the debian package to be worked on */
-       deb_file = wfopen(package_filename, "r");
+       deb_stream = wfopen(package_filename, "r");
 
-       headers = (ar_headers_t *) xmalloc(sizeof(ar_headers_t));       
+       ar_headers = (file_headers_t *) xmalloc(sizeof(file_headers_t));        
        
        /* get a linked list of all ar entries */
-       if ((headers = get_ar_headers(deb_file)) == NULL) {
+       ar_headers = get_ar_headers(deb_stream);
+       if (ar_headers == NULL) {
                error_msg("Couldnt get ar headers\n");
                return(NULL);
        }
 
        /* seek to the start of the .tar.gz file within the ar file*/
-       if (seek_ared_file(deb_file, headers, ared_file) == EXIT_FAILURE) {
-               error_msg("Couldnt seek to ar file");
+       fseek(deb_stream, 0, SEEK_SET);
+       if (seek_sub_file(deb_stream, ar_headers, ared_file) == EXIT_FAILURE) {
+               error_msg("Couldnt seek to file %s", ared_file);
        }
 
-       /* open a stream of decompressed data */
-       uncompressed_file = fdopen(gz_open(deb_file, &gunzip_pid), "r");
-
-       if (function & extract_fsys_tarfile) {
-               copy_file_chunk(uncompressed_file, stdout, -1);
-       } else {
-               FILE *output;
+       /* get a linked list of all tar entries */
+       tar_headers = get_tar_gz_headers(deb_stream);
+       if (tar_headers == NULL) {
+               error_msg("Couldnt get tar headers\n");
+               return(NULL);
+       }
 
-               if (function & extract_contents_to_file) {
-                       output = wfopen(argument, "w");
-               } else {
-                       output = stdout;
+       if (extract_function & extract_one_to_buffer) {
+               list_ptr = tar_headers;
+               while (list_ptr != NULL) {
+                       if (strcmp(filename, list_ptr->name) == 0) {
+                               deb_extract_list = append_archive_list(deb_extract_list, list_ptr);
+                               break;
+                       }
+                       list_ptr = list_ptr->next;
                }
+       } else {
+               deb_extract_list = tar_headers;
+       }
 
-               output_buffer = untar(uncompressed_file, output, function, argument, argument2);
-               if (output != stdout) {
-                       fclose(output);
-               }
+       /* seek to the start of the .tar.gz file within the ar file*/
+       if (seek_sub_file(deb_stream, ar_headers, ared_file) == EXIT_FAILURE) {
+               error_msg("Couldnt seek to ar file");
        }
+
+       /* open a stream of decompressed data */
+       uncompressed_stream = fdopen(gz_open(deb_stream, &gunzip_pid), "r");
+
+       output_buffer = extract_archive(uncompressed_stream, out_stream, deb_extract_list, extract_function, prefix);
+
        gz_close(gunzip_pid);
-       fclose(deb_file);
-       fclose(uncompressed_file);
+       fclose(deb_stream);
+       fclose(uncompressed_stream);
        free(ared_file);
 
        return(output_buffer);
index 151caafe1e88020f6fe4284ecd7f545e030b3021..414498b4f59bc0f5225251e5bdeb7a2d7654f321 100644 (file)
@@ -30,7 +30,7 @@
 #include <unistd.h>
 #include "libbb.h"
 
-extern ar_headers_t *get_ar_headers(FILE *in_file)
+file_headers_t *get_ar_headers(FILE *in_file)
 {
        typedef struct raw_ar_header_s {        /* Byte Offset */
                char name[16];  /*  0-15 */
@@ -44,7 +44,7 @@ extern ar_headers_t *get_ar_headers(FILE *in_file)
 
        raw_ar_header_t raw_ar_header;
 
-       ar_headers_t *ar_list, *ar_tmp, *ar_entry;
+       file_headers_t *ar_list, *ar_entry;
        char ar_magic[8];
        char *long_name=NULL;
        
@@ -59,10 +59,10 @@ extern ar_headers_t *get_ar_headers(FILE *in_file)
                return(NULL);
        }
        
-       ar_list = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t));
+       ar_list = (file_headers_t *) xcalloc(1, sizeof(file_headers_t));
 
        while (fread((char *) &raw_ar_header, 1, 60, in_file) == 60) {
-               ar_entry = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t));
+               ar_entry = (file_headers_t *) xcalloc(1, sizeof(file_headers_t));
                /* check the end of header markers are valid */
                if ((raw_ar_header.fmag[0] != '`') || (raw_ar_header.fmag[1] != '\n')) {
                        char newline;
@@ -113,12 +113,7 @@ extern ar_headers_t *get_ar_headers(FILE *in_file)
 
                fseek(in_file, (off_t) ar_entry->size, SEEK_CUR);
 
-               ar_tmp = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t));
-               *ar_tmp = *ar_list;
-               *ar_list = *ar_entry;
-               free(ar_entry);
-               ar_list->next = ar_tmp;
+               ar_list = append_archive_list(ar_list, ar_entry);
        }
-
        return(ar_list);
 }
index f99d2578028e7c30d341b9de0251895554820937..f24a38109ccb9feb08551d0e628c3e24a2be67b1 100644 (file)
@@ -213,36 +213,41 @@ char *xreadlink(const char *path);
 char *concat_path_file(const char *path, const char *filename);
 char *last_char_is(const char *s, int c);
 
-typedef struct ar_headers_s {
+typedef struct file_headers_s {
        char *name;
+       char *link_name;
        off_t size;
        uid_t uid;
        gid_t gid;
        mode_t mode;
        time_t mtime;
        off_t offset;
-       struct ar_headers_s *next;
-} ar_headers_t;
-extern ar_headers_t *get_ar_headers(FILE *in_file);
-extern int seek_ared_file(FILE *in_file, ar_headers_t *headers, const char *tar_gz_file);
-
-typedef enum extract_function_e {
-       extract_contents = 1,
-       extract_control = 2,
-       extract_info = 4,
-       extract_extract = 8,
-       extract_verbose_extract = 16,
-       extract_list = 32,
-       extract_fsys_tarfile = 64,
-       extract_field = 128,
-       extract_contents_to_file = 256
-} extract_function_t;
-extern char *deb_extract(const char *package_filename, int function,
-       const char *argument, const char *argument2);
-extern char *untar(FILE *src_tar_file, FILE *output, int untar_function,
-       const char *argument, const char *file_prefix);
-extern char *read_text_file_to_buffer(FILE *src_file);
-extern char *read_package_field(const char *package_buffer);
+       dev_t device;
+       struct file_headers_s *next;
+} file_headers_t;
+file_headers_t *get_ar_headers(FILE *in_file);
+file_headers_t *get_tar_headers(FILE *tar_stream);
+file_headers_t *get_tar_gz_headers(FILE *compressed_stream);
+file_headers_t *append_archive_list(file_headers_t *head, file_headers_t *tail_entry);
+file_headers_t *add_from_archive_list(file_headers_t *master_list, file_headers_t *new_list, const char *name);
+
+enum extract_functions_e {
+       extract_verbose_list = 1,
+       extract_list = 2,
+       extract_one_to_buffer = 4,
+       extract_to_stdout = 8,
+       extract_all_to_fs = 16,
+       extract_preserve_date = 32,
+       extract_data_tar_gz = 64,
+       extract_control_tar_gz = 128,
+       extract_unzip_only = 256
+};
+char *extract_archive(FILE *src_stream, FILE *out_stream, file_headers_t *extract_headers, int function, const char *prefix);
+char *deb_extract(const char *package_filename, FILE *out_stream, const int function,
+       const char *prefix, const char *filename);
+char *read_package_field(const char *package_buffer);
+int seek_sub_file(FILE *in_file, file_headers_t *headers, const char *tar_gz_file);
+char *fgets_str(FILE *file, const char *terminating_string);
 
 extern int unzip(FILE *l_in_file, FILE *l_out_file);
 extern void gz_close(int gunzip_pid);