#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;
data_path_t data_path;
char *addrs;
backup_support_option_t *bsu;
+ gint64 bytes_read;
} ctl_data_t;
#define SKIP_TAPE 2
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;
{
next = this->next;
amfree(this->path);
+ amfree(this->tpath);
amfree(this);
this = next;
}
ofn2 = fn2;
fn2 = fn2->next;
amfree(ofn2->path);
+ amfree(ofn2->tpath);
amfree(ofn2);
pfn2->next = fn2;
} else if (remove_fn1 == 0) {
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;
{
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);
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;
}
}
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;
{
this->next = extract_list;
extract_list = this;
- amfree(ditem_path);
return 0;
}
for (this1 = extract_list; this1->next != NULL; this1 = this1->next)
{
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;
}
/* first on list */
this->files = that->next;
amfree(that->path);
+ amfree(that->tpath);
amfree(that);
/* if list empty delete it */
if (this->files == NULL)
{
prev->next = that->next;
amfree(that->path);
+ amfree(that->tpath);
amfree(that);
amfree(ditem_path);
return 0;
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;
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);
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;
}
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) {
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)) {
err = _("bad reply: missing directory field");
continue;
}
- dir = s - 1;
skip_quoted_string(s, ch);
dir_undo = s - 1;
dir_undo_ch = *dir_undo;
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"),
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);
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);
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;
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;
}
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 . */
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);
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 */
{
if (i == -1) {
amfree(ditem_path);
- amfree(path_on_disk);
+ amfree(tpath_on_disk);
exit(1);
}
if(err) {
err = _("bad reply: cannot parse fileno field");
continue;
}
- fileno = (off_t)fileno_;
skip_integer(s, ch);
}
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:
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
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;
}
}
}
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);
}
}
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) {
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"));
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 */
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)
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;
}
} else if (proplist) {
- g_hash_table_foreach(proplist, &proplist_add_to_argv, argv_ptr);
+ property_add_to_argv(argv_ptr, proplist);
}
break;
}
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);
return -1;
}
}
+ g_debug("bytes read: %jd", (intmax_t)ctl_data.bytes_read);
return(0);
}
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);
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;
}
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;
}
}
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;
}
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();
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.
/*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 */