X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=recover-src%2Fextract_list.c;h=9a453cb0fd8de01d3399efe9b7cd872d91c7659f;hb=d28952249e392eb31bc8eecc53f6c477f30c617b;hp=d254022ed573a72b3efe060ef171ffec3fa746ab;hpb=fd48f3e498442f0cbff5f3606c7c403d0566150e;p=debian%2Famanda diff --git a/recover-src/extract_list.c b/recover-src/extract_list.c index d254022..9a453cb 100644 --- a/recover-src/extract_list.c +++ b/recover-src/extract_list.c @@ -1,6 +1,7 @@ /* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1998, 2000 University of Maryland at College Park + * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved. * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -45,9 +46,11 @@ #include "event.h" #include "client_util.h" #include "security.h" +#include "pipespawn.h" typedef struct EXTRACT_LIST_ITEM { char *path; + char *tpath; struct EXTRACT_LIST_ITEM *next; } EXTRACT_LIST_ITEM; @@ -72,6 +75,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 +99,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; @@ -267,6 +274,7 @@ clear_tape_list( { next = this->next; amfree(this->path); + amfree(this->tpath); amfree(this); this = next; } @@ -380,6 +388,7 @@ clean_tape_list( ofn2 = fn2; fn2 = fn2->next; amfree(ofn2->path); + amfree(ofn2->tpath); amfree(ofn2); pfn2->next = fn2; } else if (remove_fn1 == 0) { @@ -391,10 +400,11 @@ clean_tape_list( if(remove_fn1 != 0) { /* fn2->path is always valid */ /*@i@*/ dbprintf(_("removing path %s, it is included in %s\n"), - /*@i@*/ fn1->path, fn2->path); + /*@i@*/ fn1->tpath, fn2->tpath); ofn1 = fn1; fn1 = fn1->next; amfree(ofn1->path); + amfree(ofn1->tpath); if(pfn1 == NULL) { amfree(tape_list->files); tape_list->files = fn1; @@ -578,7 +588,7 @@ add_extract_item( { EXTRACT_LIST *this, *this1; EXTRACT_LIST_ITEM *that, *curr; - char *ditem_path = NULL; + char *ditem_path; ditem_path = stralloc(ditem->path); clean_pathname(ditem_path); @@ -593,16 +603,16 @@ add_extract_item( while(curr!=NULL) { if (strcmp(curr->path,ditem_path) == 0) { - amfree(ditem_path); + g_free(ditem_path); return 1; } curr=curr->next; } that = (EXTRACT_LIST_ITEM *)alloc(sizeof(EXTRACT_LIST_ITEM)); - that->path = stralloc(ditem_path); + that->path = ditem_path; + that->tpath = clean_pathname(g_strdup(ditem->tpath)); that->next = this->files; this->files = that; /* add at front since easiest */ - amfree(ditem_path); return 0; } } @@ -614,7 +624,8 @@ add_extract_item( this->fileno = ditem->fileno; this->date = stralloc(ditem->date); that = (EXTRACT_LIST_ITEM *)alloc(sizeof(EXTRACT_LIST_ITEM)); - that->path = stralloc(ditem_path); + that->path = ditem_path; + that->tpath = clean_pathname(g_strdup(ditem->tpath)); that->next = NULL; this->files = that; @@ -625,7 +636,6 @@ add_extract_item( { this->next = extract_list; extract_list = this; - amfree(ditem_path); return 0; } for (this1 = extract_list; this1->next != NULL; this1 = this1->next) @@ -635,14 +645,12 @@ add_extract_item( { this->next = this1->next; this1->next = this; - amfree(ditem_path); return 0; } } /* add at end */ this->next = NULL; this1->next = this; - amfree(ditem_path); return 0; } @@ -673,6 +681,7 @@ delete_extract_item( /* first on list */ this->files = that->next; amfree(that->path); + amfree(that->tpath); amfree(that); /* if list empty delete it */ if (this->files == NULL) @@ -688,6 +697,7 @@ delete_extract_item( { prev->next = that->next; amfree(that->path); + amfree(that->tpath); amfree(that); amfree(ditem_path); return 0; @@ -821,12 +831,12 @@ add_file( char * regex) { DIR_ITEM *ditem, lditem; - char *path_on_disk = NULL; + char *tpath_on_disk = NULL; char *cmd = NULL; char *err = NULL; int i; ssize_t j; - char *dir, *dir_undo, dir_undo_ch = '\0'; + char *dir_undo, dir_undo_ch = '\0'; char *ditem_path = NULL; char *qditem_path = NULL; char *l = NULL; @@ -860,34 +870,34 @@ add_file( if (strcmp(disk_path, "/") == 0) { if (*regex == '/') { /* No mods needed if already starts with '/' */ - path_on_disk = stralloc(regex); + tpath_on_disk = g_strdup(regex); } else { /* Prepend '/' */ - path_on_disk = stralloc2("/", regex); + tpath_on_disk = g_strconcat("/", regex, NULL); } } else { - char *clean_disk_path = clean_regex(disk_path, 0); - path_on_disk = vstralloc(clean_disk_path, "/", regex, NULL); - amfree(clean_disk_path); + char *clean_disk_tpath = clean_regex(disk_tpath, 0); + tpath_on_disk = g_strjoin(NULL, clean_disk_tpath, "/", regex, NULL); + amfree(clean_disk_tpath); } - dbprintf(_("add_file: Converted path=\"%s\" to path_on_disk=\"%s\"\n"), - regex, path_on_disk); + dbprintf(_("add_file: Converted path=\"%s\" to tpath_on_disk=\"%s\"\n"), + regex, tpath_on_disk); found_one = 0; dir_entries = 0; for (ditem=get_dir_list(); ditem!=NULL; ditem=get_next_dir_item(ditem)) { dir_entries++; - quoted = quote_string(ditem->path); + quoted = quote_string(ditem->tpath); dbprintf(_("add_file: Pondering ditem->path=%s\n"), quoted); amfree(quoted); - if (match(path_on_disk, ditem->path)) + if (match(tpath_on_disk, ditem->tpath)) { found_one = 1; - j = (ssize_t)strlen(ditem->path); - if((j > 0 && ditem->path[j-1] == '/') - || (j > 1 && ditem->path[j-2] == '/' && ditem->path[j-1] == '.')) + j = (ssize_t)strlen(ditem->tpath); + if((j > 0 && ditem->tpath[j-1] == '/') + || (j > 1 && ditem->tpath[j-2] == '/' && ditem->tpath[j-1] == '.')) { /* It is a directory */ ditem_path = newstralloc(ditem_path, ditem->path); clean_pathname(ditem_path); @@ -898,7 +908,7 @@ add_file( if(send_command(cmd) == -1) { amfree(cmd); amfree(ditem_path); - amfree(path_on_disk); + amfree(tpath_on_disk); exit(1); } amfree(cmd); @@ -906,25 +916,28 @@ add_file( /* skip preamble */ if ((i = get_reply_line()) == -1) { amfree(ditem_path); - amfree(path_on_disk); + amfree(tpath_on_disk); exit(1); } if(i==0) { /* assume something wrong */ amfree(ditem_path); - amfree(path_on_disk); + amfree(tpath_on_disk); l = reply_line(); g_printf("%s\n", l); return; } dir_undo = NULL; added=0; - lditem.path = newstralloc(lditem.path, ditem->path); + g_free(lditem.path); + g_free(lditem.tpath); + lditem.path = g_strdup(ditem->path); + lditem.tpath = g_strdup(ditem->tpath); /* skip the last line -- duplicate of the preamble */ while ((i = get_reply_line()) != 0) { if (i == -1) { amfree(ditem_path); - amfree(path_on_disk); + amfree(tpath_on_disk); exit(1); } if(err) { @@ -972,9 +985,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)) { @@ -994,7 +1008,6 @@ add_file( err = _("bad reply: missing directory field"); continue; } - dir = s - 1; skip_quoted_string(s, ch); dir_undo = s - 1; dir_undo_ch = *dir_undo; @@ -1007,7 +1020,7 @@ add_file( break; case 0: - quoted = quote_string(lditem.path); + quoted = quote_string(lditem.tpath); g_printf(_("Added dir %s at date %s\n"), quoted, lditem.date); dbprintf(_("add_file: (Successful) Added dir %s at date %s\n"), @@ -1043,14 +1056,14 @@ add_file( break; case 0: - quoted = quote_string(ditem->path); + quoted = quote_string(ditem->tpath); g_printf(_("Added file %s\n"), quoted); dbprintf(_("add_file: (Successful) Added %s\n"), quoted); amfree(quoted); break; case 1: - quoted = quote_string(ditem->path); + quoted = quote_string(ditem->tpath); g_printf(_("File %s already added\n"), quoted); dbprintf(_("add_file: file %s already added\n"), quoted); amfree(quoted); @@ -1061,9 +1074,10 @@ add_file( amfree(cmd); amfree(ditem_path); - amfree(path_on_disk); + amfree(tpath_on_disk); amfree(lditem.path); + amfree(lditem.tpath); amfree(lditem.date); amfree(lditem.tape); @@ -1175,11 +1189,11 @@ delete_regex( void delete_file( - char * path, + char * tpath, char * regex) { DIR_ITEM *ditem, lditem; - char *path_on_disk = NULL; + char *tpath_on_disk = NULL; char *cmd = NULL; char *err = NULL; int i; @@ -1188,8 +1202,8 @@ delete_file( char *tape, *tape_undo, tape_undo_ch = '\0'; char *dir_undo, dir_undo_ch = '\0'; int level = 0; - off_t fileno; char *ditem_path = NULL; + char *ditem_tpath = NULL; char *qditem_path; char *l = NULL; int deleted; @@ -1204,7 +1218,7 @@ delete_file( } memset(&lditem, 0, sizeof(lditem)); /* Prevent use of bogus data... */ - dbprintf(_("delete_file: Looking for \"%s\"\n"), path); + dbprintf(_("delete_file: Looking for \"%s\"\n"), tpath); if (strcmp(regex, "[^/]*[/]*$") == 0) { /* Looking for * find everything but single . */ @@ -1220,38 +1234,40 @@ delete_file( if (*regex == '/') { if (strcmp(regex, "/[/]*$") == 0) { /* We want "/" to match the directory itself: "/." */ - path_on_disk = stralloc("/\\.[/]*$"); + tpath_on_disk = stralloc("/\\.[/]*$"); } else { /* No mods needed if already starts with '/' */ - path_on_disk = stralloc(regex); + tpath_on_disk = stralloc(regex); } } else { /* Prepend '/' */ - path_on_disk = stralloc2("/", regex); + tpath_on_disk = g_strconcat("/", regex, NULL); } } else { - char *clean_disk_path = clean_regex(disk_path, 0); - path_on_disk = vstralloc(clean_disk_path, "/", regex, NULL); - amfree(clean_disk_path); + char *clean_disk_tpath = clean_regex(disk_tpath, 0); + tpath_on_disk = g_strjoin(NULL, clean_disk_tpath, "/", regex, NULL); + amfree(clean_disk_tpath); } - dbprintf(_("delete_file: Converted path=\"%s\" to path_on_disk=\"%s\"\n"), - regex, path_on_disk); + dbprintf(_("delete_file: Converted path=\"%s\" to tpath_on_disk=\"%s\"\n"), + regex, tpath_on_disk); found_one = 0; for (ditem=get_dir_list(); ditem!=NULL; ditem=get_next_dir_item(ditem)) { - quoted = quote_string(ditem->path); + quoted = quote_string(ditem->tpath); dbprintf(_("delete_file: Pondering ditem->path=%s\n"), quoted); amfree(quoted); - if (match(path_on_disk, ditem->path)) + if (match(tpath_on_disk, ditem->tpath)) { found_one = 1; - j = (ssize_t)strlen(ditem->path); - if((j > 0 && ditem->path[j-1] == '/') - || (j > 1 && ditem->path[j-2] == '/' && ditem->path[j-1] == '.')) + j = (ssize_t)strlen(ditem->tpath); + if((j > 0 && ditem->tpath[j-1] == '/') + || (j > 1 && ditem->tpath[j-2] == '/' && ditem->tpath[j-1] == '.')) { /* It is a directory */ ditem_path = newstralloc(ditem_path, ditem->path); + ditem_tpath = newstralloc(ditem_tpath, ditem->tpath); clean_pathname(ditem_path); + clean_pathname(ditem_tpath); qditem_path = quote_string(ditem_path); cmd = newstralloc2(cmd, "ORLD ", qditem_path); @@ -1259,26 +1275,27 @@ delete_file( if(send_command(cmd) == -1) { amfree(cmd); amfree(ditem_path); - amfree(path_on_disk); + amfree(tpath_on_disk); exit(1); } amfree(cmd); /* skip preamble */ if ((i = get_reply_line()) == -1) { amfree(ditem_path); - amfree(path_on_disk); + amfree(tpath_on_disk); exit(1); } if(i==0) /* assume something wrong */ { amfree(ditem_path); - amfree(path_on_disk); + amfree(tpath_on_disk); l = reply_line(); g_printf("%s\n", l); return; } deleted=0; lditem.path = newstralloc(lditem.path, ditem->path); + lditem.tpath = newstralloc(lditem.tpath, ditem->tpath); amfree(cmd); tape_undo = dir_undo = NULL; /* skip the last line -- duplicate of the preamble */ @@ -1286,7 +1303,7 @@ delete_file( { if (i == -1) { amfree(ditem_path); - amfree(path_on_disk); + amfree(tpath_on_disk); exit(1); } if(err) { @@ -1346,7 +1363,6 @@ delete_file( err = _("bad reply: cannot parse fileno field"); continue; } - fileno = (off_t)fileno_; skip_integer(s, ch); } @@ -1362,16 +1378,17 @@ delete_file( lditem.date = newstralloc(lditem.date, date); lditem.level=level; - lditem.tape = newstralloc(lditem.tape, tape); + g_free(lditem.tape); + lditem.tape = unquote_string(tape); switch(delete_extract_item(&lditem)) { case -1: g_printf(_("System error\n")); dbprintf(_("delete_file: (Failed) System error\n")); break; case 0: - g_printf(_("Deleted dir %s at date %s\n"), ditem_path, date); + g_printf(_("Deleted dir %s at date %s\n"), ditem_tpath, date); dbprintf(_("delete_file: (Successful) Deleted dir %s at date %s\n"), - ditem_path, date); + ditem_tpath, date); deleted=1; break; case 1: @@ -1387,9 +1404,9 @@ delete_file( puts(cmd); } else if(deleted == 0) { g_printf(_("Warning - dir '%s' not on tape list\n"), - ditem_path); + ditem_tpath); dbprintf(_("delete_file: dir '%s' not on tape list\n"), - ditem_path); + ditem_tpath); } } else @@ -1400,15 +1417,15 @@ delete_file( dbprintf(_("delete_file: (Failed) System error\n")); break; case 0: - g_printf(_("Deleted %s\n"), ditem->path); + g_printf(_("Deleted %s\n"), ditem->tpath); dbprintf(_("delete_file: (Successful) Deleted %s\n"), - ditem->path); + ditem->tpath); break; case 1: g_printf(_("Warning - file '%s' not on tape list\n"), - ditem->path); + ditem->tpath); dbprintf(_("delete_file: file '%s' not on tape list\n"), - ditem->path); + ditem->tpath); break; } } @@ -1416,12 +1433,13 @@ delete_file( } amfree(cmd); amfree(ditem_path); - amfree(path_on_disk); + amfree(ditem_tpath); + amfree(tpath_on_disk); if(! found_one) { - g_printf(_("File %s doesn't exist in directory\n"), path); + g_printf(_("File %s doesn't exist in directory\n"), tpath); dbprintf(_("delete_file: (Failed) File %s doesn't exist in directory\n"), - path); + tpath); } } @@ -1473,7 +1491,7 @@ display_extract_list( g_fprintf(fp, _("TAPE %s LEVEL %d DATE %s\n"), this->tape, this->level, this->date); for (that = this->files; that != NULL; that = that->next) - g_fprintf(fp, "\t%s\n", that->path); + g_fprintf(fp, "\t%s\n", that->tpath); } if (file == NULL) { @@ -1682,7 +1700,14 @@ extract_files_setup( tt = newstralloc2(tt, "FEATURES=", our_features_string); send_to_tape_server(amidxtaped_streams[CTLFD].fd, tt); get_amidxtaped_line(); - if(strncmp_const(amidxtaped_line,"FEATURES=") == 0) { + if (!amidxtaped_line) { + g_fprintf(stderr, _("amrecover - amidxtaped closed the connection\n")); + stop_amidxtaped(); + amfree(disk_regex); + amfree(host_regex); + amfree(clean_datestamp); + return -1; + } else if(strncmp_const(amidxtaped_line,"FEATURES=") == 0) { tapesrv_features = am_string_to_feature(amidxtaped_line+9); } else { g_fprintf(stderr, _("amrecover - expecting FEATURES line from amidxtaped\n")); @@ -1836,7 +1861,7 @@ extract_files_child( /*NOTREACHED*/ } - if (ctl_data->file.program != NULL) { + if (ctl_data->file.program[0] != '\0') { if (strcmp(ctl_data->file.program, "APPLICATION") == 0) dumptype = IS_APPLICATION_API; #ifdef GNUTAR @@ -1886,6 +1911,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 */ @@ -1899,7 +1926,6 @@ extract_files_child( case IS_DUMP: g_ptr_array_add(argv_ptr, stralloc("restore")); #ifdef AIX_BACKUP - restore_args[j++] = stralloc("-xB"); g_ptr_array_add(argv_ptr, stralloc("-xB")); #else #if defined(XFSDUMP) @@ -1949,7 +1975,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 +1988,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 +2127,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 +2198,7 @@ writer_intermediary( return -1; } } + g_debug("bytes read: %jd", (intmax_t)ctl_data.bytes_read); return(0); } @@ -2278,12 +2308,12 @@ extract_files(void) g_options.hostname = dump_hostname; for (elist = first_tape_list(); elist != NULL; elist = next_tape_list(elist)) { - level_t *level = g_new0(level_t, 1); + am_level_t *level = g_new0(am_level_t, 1); level->level = elist->level; 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); @@ -2320,18 +2350,18 @@ extract_files(void) dump_datestamp = newstralloc(dump_datestamp, elist->date); if (last_level != -1 && dump_dle) { - level_t *level; + am_level_t *level; - level = g_new0(level_t, 1); + level = g_new0(am_level_t, 1); level->level = last_level; dump_dle->levellist = g_slist_append(dump_dle->levellist, level); - level = g_new0(level_t, 1); + level = g_new0(am_level_t, 1); level->level = elist->level; 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; } @@ -2343,9 +2373,9 @@ extract_files(void) return; } if (dump_dle) { - level_t *level; + am_level_t *level; - level = g_new0(level_t, 1); + level = g_new0(am_level_t, 1); level->level = elist->level; dump_dle->levellist = g_slist_append(dump_dle->levellist, level); run_client_scripts(EXECUTE_ON_PRE_LEVEL_RECOVER, &g_options, @@ -2367,7 +2397,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 +2405,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 +2711,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) { + /* wait to read more data */ + return; + } else if (header_size > 32768) { + error("header_size is %d\n", header_size); + } + assert (to_move == size); + security_stream_read_cancel(amidxtaped_streams[DATAFD].fd); /* 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,13 +2783,12 @@ 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. */ (void)full_write(ctl_data->child_pipe[1], buf, (size_t)size); - security_stream_read(amidxtaped_streams[DATAFD].fd, - read_amidxtaped_data, cookie); } } @@ -2818,6 +2861,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 */