add a changelog entry
[debian/amanda] / recover-src / extract_list.c
index d254022ed573a72b3efe060ef171ffec3fa746ab..9f7217b58654ba19417951fdf589490420bdb5ce 100644 (file)
@@ -45,6 +45,7 @@
 #include "event.h"
 #include "client_util.h"
 #include "security.h"
+#include "pipespawn.h"
 
 typedef struct EXTRACT_LIST_ITEM {
     char *path;
@@ -72,6 +73,7 @@ typedef struct ctl_data_s {
   data_path_t              data_path;
   char                    *addrs;
   backup_support_option_t *bsu;
+  gint64                   bytes_read;
 } ctl_data_t;
 
 #define SKIP_TAPE 2
@@ -95,6 +97,9 @@ static char *dump_device_name = NULL;
 static char *errstr;
 static char *amidxtaped_line = NULL;
 extern char *localhost;
+static char header_buf[32768];
+static int  header_size = 0;
+
 
 /* global pid storage for interrupt handler */
 pid_t extract_restore_child_pid = -1;
@@ -972,9 +977,10 @@ add_file(
                        continue;
                    }
                     fp = s-1;
-                    skip_non_whitespace(s, ch);
+                    skip_quoted_string(s, ch);
                     s[-1] = '\0';
-                    lditem.tape = newstralloc(lditem.tape, fp);
+                   amfree(lditem.tape);
+                   lditem.tape = unquote_string(fp);
                     s[-1] = (char)ch;
 
                    if(am_has_feature(indexsrv_features, fe_amindexd_fileno_in_ORLD)) {
@@ -1886,6 +1892,8 @@ extract_files_child(
     case IS_TAR:
     case IS_GNUTAR:
        g_ptr_array_add(argv_ptr, stralloc("tar"));
+       /* ignore trailing zero blocks on input (this was the default until tar-1.21) */
+       g_ptr_array_add(argv_ptr, stralloc("--ignore-zeros"));
        g_ptr_array_add(argv_ptr, stralloc("--numeric-owner"));
        g_ptr_array_add(argv_ptr, stralloc("-xpGvf"));
        g_ptr_array_add(argv_ptr, stralloc("-"));       /* data on stdin */
@@ -1949,7 +1957,8 @@ extract_files_child(
            GSList   *scriptlist;
            script_t *script;
 
-           merge_properties(dump_dle->application_property, proplist);
+           merge_properties(dump_dle, NULL, dump_dle->application_property,
+                            proplist, 0);
            application_property_add_to_argv(argv_ptr, dump_dle, NULL,
                                             tapesrv_features);
            for (scriptlist = dump_dle->scriptlist; scriptlist != NULL;
@@ -1961,7 +1970,7 @@ extract_files_child(
            }
 
        } else if (proplist) {
-           g_hash_table_foreach(proplist, &proplist_add_to_argv, argv_ptr);
+           property_add_to_argv(argv_ptr, proplist);
        }
        break;
     }
@@ -2100,7 +2109,9 @@ writer_intermediary(
     ctl_data.data_path     = DATA_PATH_AMANDA;
     ctl_data.addrs         = NULL;
     ctl_data.bsu           = NULL;
+    ctl_data.bytes_read    = 0;
 
+    header_size = 0;
     security_stream_read(amidxtaped_streams[DATAFD].fd,
                         read_amidxtaped_data, &ctl_data);
 
@@ -2169,6 +2180,7 @@ writer_intermediary(
            return -1;
        }
     }
+    g_debug("bytes read: %jd", (intmax_t)ctl_data.bytes_read);
     return(0);
 }
 
@@ -2283,7 +2295,7 @@ extract_files(void)
        all_level = g_slist_append(all_level, level);
     }
     if (dump_dle) {
-       g_slist_free_full(dump_dle->levellist);
+       slist_free_full(dump_dle->levellist, g_free);
        dump_dle->levellist = all_level;
        run_client_scripts(EXECUTE_ON_PRE_RECOVER, &g_options, dump_dle,
                           stderr);
@@ -2331,7 +2343,7 @@ extract_files(void)
            dump_dle->levellist = g_slist_append(dump_dle->levellist, level);
            run_client_scripts(EXECUTE_ON_INTER_LEVEL_RECOVER, &g_options,
                               dump_dle, stderr);
-           g_slist_free_full(dump_dle->levellist);
+           slist_free_full(dump_dle->levellist, g_free);
            dump_dle->levellist = NULL;
        }
 
@@ -2367,7 +2379,7 @@ extract_files(void)
        if (dump_dle) {
            run_client_scripts(EXECUTE_ON_POST_LEVEL_RECOVER, &g_options,
                               dump_dle, stderr);
-           g_slist_free_full(dump_dle->levellist);
+           slist_free_full(dump_dle->levellist, g_free);
            dump_dle->levellist = NULL;
        }
     }
@@ -2375,7 +2387,7 @@ extract_files(void)
        dump_dle->levellist = all_level;
        run_client_scripts(EXECUTE_ON_POST_RECOVER, &g_options, dump_dle,
                           stderr);
-       g_slist_free_full(dump_dle->levellist);
+       slist_free_full(dump_dle->levellist, g_free);
        all_level = NULL;
        dump_dle->levellist = NULL;
     }
@@ -2681,10 +2693,24 @@ read_amidxtaped_data(
        GPtrArray  *errarray;
        g_option_t  g_options;
        data_path_t data_path_set = DATA_PATH_AMANDA;
+       int to_move;
 
+       to_move = MIN(32768-header_size, size);
+       memcpy(header_buf+header_size, buf, to_move);
+       header_size += to_move;
+
+       g_debug("read header %zd => %d", size, header_size);
+       if (header_size < 32768) {
+            security_stream_read(amidxtaped_streams[DATAFD].fd,
+                                read_amidxtaped_data, cookie);
+           return;
+       } else if (header_size > 32768) {
+           error("header_size is %d\n", header_size);
+       }
+       assert (to_move == size);
        /* parse the file header */
        fh_init(&ctl_data->file);
-       parse_file_header(buf, &ctl_data->file, (size_t)size);
+       parse_file_header(header_buf, &ctl_data->file, (size_t)header_size);
 
        /* call backup_support_option */
        g_options.config = get_config_name();
@@ -2739,6 +2765,7 @@ read_amidxtaped_data(
            start_processing_data(ctl_data);
        }
     } else {
+       ctl_data->bytes_read += size;
        /* Only the data is sent to the child */
        /*
         * We ignore errors while writing to the index file.
@@ -2818,6 +2845,43 @@ start_processing_data(
        /*NOTREACHED*/
     }
 
+    /* decrypt */
+    if (ctl_data->file.encrypted) {
+       char *argv[3];
+       int  crypt_out;
+       int  errfd = fileno(stderr);
+
+       g_debug("image is encrypted %s %s", ctl_data->file.clnt_encrypt, ctl_data->file.clnt_decrypt_opt);
+       argv[0] = ctl_data->file.clnt_encrypt;
+       argv[1] = ctl_data->file.clnt_decrypt_opt;
+       argv[2] = NULL;
+       pipespawnv(ctl_data->file.clnt_encrypt, STDOUT_PIPE, 0, &ctl_data->child_pipe[0], &crypt_out, &errfd, argv);
+       ctl_data->child_pipe[0] = crypt_out;
+    }
+
+    /* decompress */
+    if (ctl_data->file.compressed) {
+       char *argv[3];
+       int  comp_out;
+       int  errfd = fileno(stderr);
+       char *comp_prog;
+       char *comp_arg;
+
+       g_debug("image is compressed %s", ctl_data->file.clntcompprog);
+       if (strlen(ctl_data->file.clntcompprog) > 0) {
+           comp_prog = ctl_data->file.clntcompprog;
+           comp_arg = "-d";
+       } else {
+           comp_prog = UNCOMPRESS_PATH;
+           comp_arg = UNCOMPRESS_OPT;
+       }
+       argv[0] = comp_prog;
+       argv[1] = comp_arg;
+       argv[2] = NULL;
+       pipespawnv(comp_prog, STDOUT_PIPE, 0, &ctl_data->child_pipe[0], &comp_out, &errfd, argv);
+       ctl_data->child_pipe[0] = comp_out;
+    }
+
     /* okay, ready to extract. fork a child to do the actual work */
     if ((ctl_data->pid = fork()) == 0) {
        /* this is the child process */