* file named AUTHORS, in the root directory of this distribution.
*/
/*
- * $Id: extract_list.c,v 1.117 2006/08/24 01:57:15 paddy_s Exp $
+ * $Id$
*
* implements the "extract" command in amrecover
*/
#include "amanda.h"
-#include "version.h"
+#include "match.h"
#include "amrecover.h"
#include "fileheader.h"
#include "dgram.h"
#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;
}
EXTRACT_LIST;
+typedef struct ctl_data_s {
+ int header_done;
+ int child_pipe[2];
+ int pid;
+ EXTRACT_LIST *elist;
+ dumpfile_t file;
+ data_path_t data_path;
+ char *addrs;
+ backup_support_option_t *bsu;
+ gint64 bytes_read;
+} ctl_data_t;
+
#define SKIP_TAPE 2
#define RETRY_TAPE 3
static void amidxtaped_response(void *, pkt_t *, security_handle_t *);
static void stop_amidxtaped(void);
-char *amidxtaped_client_get_security_conf(char *, void *);
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;
size_t buflen,
long timeout_s);
static void clear_tape_list(EXTRACT_LIST *tape_list);
-static void extract_files_child(int in_fd, EXTRACT_LIST *elist);
+static void extract_files_child(ctl_data_t *ctl_data);
static void send_to_tape_server(security_stream_t *stream, char *cmd);
int writer_intermediary(EXTRACT_LIST *elist);
int get_amidxtaped_line(void);
static void read_amidxtaped_data(void *, void *, ssize_t);
+static char *merge_path(char *path1, char *path2);
+static gboolean ask_file_overwrite(ctl_data_t *ctl_data);
+static void start_processing_data(ctl_data_t *ctl_data);
/*
* Function: ssize_t read_buffer(datafd, buffer, buflen, timeout_s)
EXTRACT_LIST * tape_list)
{
EXTRACT_LIST_ITEM *this, *next;
-
+
this = tape_list->files;
while (this != NULL)
{
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;
}
+static char *
+file_of_path(
+ char *path,
+ char **dir)
+{
+ char *npath = g_path_get_basename(path);
+ *dir = g_path_get_dirname(path);
+ if (strcmp(*dir, ".") == 0) {
+ amfree(*dir);
+ }
+ return npath;
+}
+
void
clean_extract_list(void)
{
{
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;
/* add this in date increasing order */
/* because restore must be done in this order */
/* add at begining */
- if(extract_list==NULL || strcmp(this->date,extract_list->date) < 0)
+ if(extract_list==NULL || strcmp(this->date,extract_list->date) < 0)
{
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;
return 1;
}
+static char *
+merge_path(
+ char *path1,
+ char *path2)
+{
+ char *result;
+ int len = strlen(path1);
+ if (path1[len-1] == '/' && path2[0] == '/') {
+ result = stralloc2(path1, path2+1);
+ } else if (path1[len-1] != '/' && path2[0] != '/') {
+ result = vstralloc(path1, "/", path2, NULL);
+ } else {
+ result = stralloc2(path1, path2);
+ }
+ return result;
+}
void
add_glob(
char *regex;
char *regex_path;
char *s;
- char *uqglob = unquote_string(glob);
-
- regex = glob_to_regex(uqglob);
- dbprintf(_("add_glob (%s) -> %s\n"), uqglob, regex);
- if ((s = validate_regexp(regex)) != NULL) {
- g_printf(_("%s is not a valid shell wildcard pattern: "), glob);
- puts(s);
- } else {
- /*
- * glob_to_regex() anchors the beginning of the pattern with ^,
- * but we will be tacking it onto the end of the current directory
- * in add_file, so strip that off. Also, it anchors the end with
- * $, but we need to match an optional trailing /, so tack that on
- * the end.
- */
- regex_path = stralloc(regex + 1);
- regex_path[strlen(regex_path) - 1] = '\0';
- strappend(regex_path, "[/]*$");
- add_file(uqglob, regex_path);
- amfree(regex_path);
+ char *uqglob;
+ char *dir;
+ char *sdir = NULL;
+ int result = 1;
+
+ if (disk_path == NULL) {
+ g_printf(_("Must select directory before adding files\n"));
+ return;
}
- amfree(regex);
+
+ uqglob = unquote_string(glob);
+ glob = file_of_path(uqglob, &dir);
+ if (dir) {
+ sdir = merge_path(mount_point, disk_path);
+ result = cd_glob(dir, 0);
+ amfree(dir);
+ }
+ if (result) {
+ regex = glob_to_regex(glob);
+ dbprintf(_("add_glob (%s) -> %s\n"), uqglob, regex);
+ if ((s = validate_regexp(regex)) != NULL) {
+ g_printf(_("%s is not a valid shell wildcard pattern: "), glob);
+ puts(s);
+ } else {
+ /*
+ * glob_to_regex() anchors the beginning of the pattern with ^,
+ * but we will be tacking it onto the end of the current directory
+ * in add_file, so strip that off. Also, it anchors the end with
+ * $, but we need to match an optional trailing /, so tack that on
+ * the end.
+ */
+ regex_path = stralloc(regex + 1);
+ regex_path[strlen(regex_path) - 1] = '\0';
+ strappend(regex_path, "[/]*$");
+ add_file(uqglob, regex_path);
+ amfree(regex_path);
+ }
+ if (sdir) {
+ set_directory(sdir, 0);
+ }
+ amfree(regex);
+ }
+ amfree(sdir);
amfree(uqglob);
+ amfree(glob);
}
void
char * regex)
{
char *s;
- char *uqregex = unquote_string(regex);
-
- if ((s = validate_regexp(uqregex)) != NULL) {
- g_printf(_("\"%s\" is not a valid regular expression: "), regex);
- puts(s);
- } else {
- add_file(uqregex, regex);
+ char *dir;
+ char *sdir = NULL;
+ char *uqregex;
+ char *newregex;
+ int result = 1;
+
+ if (disk_path == NULL) {
+ g_printf(_("Must select directory before adding files\n"));
+ return;
}
+
+ uqregex = unquote_string(regex);
+ newregex = file_of_path(uqregex, &dir);
+ if (dir) {
+ sdir = merge_path(mount_point, disk_path);
+ result = cd_regex(dir, 0);
+ amfree(dir);
+ }
+
+ if (result) {
+ if ((s = validate_regexp(newregex)) != NULL) {
+ g_printf(_("\"%s\" is not a valid regular expression: "), newregex);
+ puts(s);
+ } else {
+ add_file(uqregex, newregex);
+ }
+ if (sdir) {
+ set_directory(sdir, 0);
+ }
+ }
+ amfree(sdir);
amfree(uqregex);
+ amfree(newregex);
}
void
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);
- 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);
char *regex;
char *regex_path;
char *s;
- char *uqglob = unquote_string(glob);
-
- regex = glob_to_regex(uqglob);
- dbprintf(_("delete_glob (%s) -> %s\n"), uqglob, regex);
- if ((s = validate_regexp(regex)) != NULL) {
- g_printf(_("\"%s\" is not a valid shell wildcard pattern: "), glob);
- puts(s);
- } else {
- /*
- * glob_to_regex() anchors the beginning of the pattern with ^,
- * but we will be tacking it onto the end of the current directory
- * in add_file, so strip that off. Also, it anchors the end with
- * $, but we need to match an optional trailing /, so tack that on
- * the end.
- */
- regex_path = stralloc(regex + 1);
- regex_path[strlen(regex_path) - 1] = '\0';
- strappend(regex_path, "[/]*$");
- delete_file(uqglob, regex_path);
- amfree(regex_path);
+ char *uqglob;
+ char *newglob;
+ char *dir;
+ char *sdir = NULL;
+ int result = 1;
+
+ if (disk_path == NULL) {
+ g_printf(_("Must select directory before adding files\n"));
+ return;
}
- amfree(regex);
+
+ uqglob = unquote_string(glob);
+ newglob = file_of_path(uqglob, &dir);
+ if (dir) {
+ sdir = merge_path(mount_point, disk_path);
+ result = cd_glob(dir, 0);
+ amfree(dir);
+ }
+ if (result) {
+ regex = glob_to_regex(newglob);
+ dbprintf(_("delete_glob (%s) -> %s\n"), newglob, regex);
+ if ((s = validate_regexp(regex)) != NULL) {
+ g_printf(_("\"%s\" is not a valid shell wildcard pattern: "),
+ newglob);
+ puts(s);
+} else {
+ /*
+ * glob_to_regex() anchors the beginning of the pattern with ^,
+ * but we will be tacking it onto the end of the current directory
+ * in add_file, so strip that off. Also, it anchors the end with
+ * $, but we need to match an optional trailing /, so tack that on
+ * the end.
+ */
+ regex_path = stralloc(regex + 1);
+ regex_path[strlen(regex_path) - 1] = '\0';
+ strappend(regex_path, "[/]*$");
+ delete_file(uqglob, regex_path);
+ amfree(regex_path);
+ }
+ if (sdir) {
+ set_directory(sdir, 0);
+ }
+ amfree(regex);
+ }
+ amfree(sdir);
amfree(uqglob);
+ amfree(newglob);
}
void
char * regex)
{
char *s;
- char *uqregex = unquote_string(regex);
+ char *dir;
+ char *sdir = NULL;
+ char *uqregex;
+ char *newregex;
+ int result = 1;
- if ((s = validate_regexp(regex)) != NULL) {
- g_printf(_("\"%s\" is not a valid regular expression: "), regex);
- puts(s);
- } else {
- delete_file(uqregex, uqregex);
+ if (disk_path == NULL) {
+ g_printf(_("Must select directory before adding files\n"));
+ return;
}
+
+ uqregex = unquote_string(regex);
+ newregex = file_of_path(uqregex, &dir);
+ if (dir) {
+ sdir = merge_path(mount_point, disk_path);
+ result = cd_regex(dir, 0);
+ amfree(dir);
+ }
+
+ if (result == 1) {
+ if ((s = validate_regexp(newregex)) != NULL) {
+ g_printf(_("\"%s\" is not a valid regular expression: "), newregex);
+ puts(s);
+ } else {
+ delete_file(newregex, regex);
+ }
+ if (sdir) {
+ set_directory(sdir, 0);
+ }
+ }
+ amfree(sdir);
amfree(uqregex);
+ amfree(newregex);
}
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);
- 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) {
{
char *msg = stralloc2(cmd, "\r\n");
+ g_debug("send_to_tape_server: %s\n", cmd);
if (security_stream_write(stream, msg, strlen(msg)) < 0)
{
error(_("Error writing to tape server"));
return -1;
}
- disk_regex = alloc(strlen(disk_name) * 2 + 3);
-
- ch = disk_name;
- ch1 = disk_regex;
-
- /* we want to force amrestore to only match disk_name exactly */
- *(ch1++) = '^';
-
- /* We need to escape some characters first... NT compatibilty crap */
- for (; *ch != 0; ch++, ch1++) {
- switch (*ch) { /* done this way in case there are more */
- case '$':
- *(ch1++) = '\\';
- /* no break; we do want to fall through... */
- default:
- *ch1 = *ch;
- }
- }
-
- /* we want to force amrestore to only match disk_name exactly */
- *(ch1++) = '$';
-
- *ch1 = '\0';
-
- host_regex = alloc(strlen(dump_hostname) * 2 + 3);
-
- ch = dump_hostname;
- ch1 = host_regex;
-
- /* we want to force amrestore to only match dump_hostname exactly */
- *(ch1++) = '^';
-
- /* We need to escape some characters first... NT compatibilty crap */
- for (; *ch != 0; ch++, ch1++) {
- switch (*ch) { /* done this way in case there are more */
- case '$':
- *(ch1++) = '\\';
- /* no break; we do want to fall through... */
- default:
- *ch1 = *ch;
- }
- }
-
- /* we want to force amrestore to only match dump_hostname exactly */
- *(ch1++) = '$';
-
- *ch1 = '\0';
+ disk_regex = make_exact_disk_expression(disk_name);
+ host_regex = make_exact_host_expression(dump_hostname);
clean_datestamp = stralloc(dump_datestamp);
for(ch=ch1=clean_datestamp;*ch1 != '\0';ch1++) {
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"));
amfree(clean_datestamp);
return -1;
}
- am_release_feature_set(tapesrv_features);
+ } else {
+ *tapesrv_features = *indexsrv_features;
}
static void
extract_files_child(
- int in_fd,
- EXTRACT_LIST * elist)
+ ctl_data_t *ctl_data)
{
int save_errno;
- int extra_params = 0;
- int i,j=0;
- char **restore_args = NULL;
+ int i;
+ guint j;
+ GPtrArray *argv_ptr = g_ptr_array_new();
int files_off_tape;
EXTRACT_LIST_ITEM *fn;
enum dumptypes dumptype = IS_UNKNOWN;
- char buffer[DISK_BLOCK_BYTES];
- dumpfile_t file;
size_t len_program;
char *cmd = NULL;
- int passwd_field = -1;
+ guint passwd_field = 999999999;
#ifdef SAMBA_CLIENT
char *domain = NULL, *smbpass = NULL;
#endif
- backup_support_option_t *bsu;
- GPtrArray *errarray;
/* code executed by child to do extraction */
/* never returns */
/* make in_fd be our stdin */
- if (dup2(in_fd, STDIN_FILENO) == -1)
+ if (dup2(ctl_data->child_pipe[0], STDIN_FILENO) == -1)
{
error(_("dup2 failed in extract_files_child: %s"), strerror(errno));
/*NOTREACHED*/
}
- /* read the file header */
- fh_init(&file);
- read_file_header(buffer, &file, sizeof(buffer), STDIN_FILENO);
-
- if(file.type != F_DUMPFILE) {
- print_header(stdout, &file);
+ if(ctl_data->file.type != F_DUMPFILE) {
+ dump_dumpfile_t(&ctl_data->file);
error(_("bad header"));
/*NOTREACHED*/
}
- if (file.program != NULL) {
- if (strcmp(file.program, "BACKUP") == 0)
+ if (ctl_data->file.program != NULL) {
+ if (strcmp(ctl_data->file.program, "APPLICATION") == 0)
dumptype = IS_APPLICATION_API;
#ifdef GNUTAR
- if (strcmp(file.program, GNUTAR) == 0)
+ if (strcmp(ctl_data->file.program, GNUTAR) == 0)
dumptype = IS_GNUTAR;
#endif
if (dumptype == IS_UNKNOWN) {
- len_program = strlen(file.program);
+ len_program = strlen(ctl_data->file.program);
if(len_program >= 3 &&
- strcmp(&file.program[len_program-3],"tar") == 0)
+ strcmp(&ctl_data->file.program[len_program-3],"tar") == 0)
dumptype = IS_TAR;
}
#ifdef SAMBA_CLIENT
- if (dumptype == IS_UNKNOWN && strcmp(file.program, SAMBA_CLIENT) ==0) {
+ if (dumptype == IS_UNKNOWN && strcmp(ctl_data->file.program, SAMBA_CLIENT) ==0) {
if (samba_extract_method == SAMBA_TAR)
dumptype = IS_SAMBA_TAR;
else
}
/* form the arguments to restore */
- files_off_tape = length_of_tape_list(elist);
- switch (dumptype) {
+ files_off_tape = length_of_tape_list(ctl_data->elist);
+ switch(dumptype) {
case IS_SAMBA:
#ifdef SAMBA_CLIENT
- extra_params = 10;
- break;
-#endif
- case IS_TAR:
- case IS_GNUTAR:
- extra_params = 4;
- break;
- case IS_SAMBA_TAR:
- extra_params = 3;
- break;
- case IS_UNKNOWN:
- case IS_DUMP:
-#ifdef AIX_BACKUP
- extra_params = 2;
-#else
-#if defined(XFSDUMP)
- if (strcmp(file.program, XFSDUMP) == 0) {
- extra_params = 4 + files_off_tape;
- } else
-#endif
- {
- extra_params = 4;
- }
-#endif
- break;
- case IS_APPLICATION_API:
- extra_params = 12;
- if (dump_dle) {
- GSList *scriptlist;
- script_t *script;
- extra_params += application_property_argv_size(dump_dle);
- for (scriptlist = dump_dle->scriptlist; scriptlist != NULL;
- scriptlist = scriptlist->next) {
- script = (script_t *)scriptlist->data;
- if (script->result && script->result->proplist) {
- extra_params += property_argv_size(script->result->proplist);
- }
+ g_ptr_array_add(argv_ptr, stralloc("smbclient"));
+ smbpass = findpass(ctl_data->file.disk, &domain);
+ if (smbpass) {
+ g_ptr_array_add(argv_ptr, stralloc(ctl_data->file.disk));
+ g_ptr_array_add(argv_ptr, stralloc("-U"));
+ passwd_field = argv_ptr->len;
+ g_ptr_array_add(argv_ptr, stralloc(smbpass));
+ if (domain) {
+ g_ptr_array_add(argv_ptr, stralloc("-W"));
+ g_ptr_array_add(argv_ptr, stralloc(domain));
}
}
+ g_ptr_array_add(argv_ptr, stralloc("-d0"));
+ g_ptr_array_add(argv_ptr, stralloc("-Tx"));
+ g_ptr_array_add(argv_ptr, stralloc("-")); /* data on stdin */
break;
- }
- restore_args = (char **)alloc((size_t)((extra_params + files_off_tape + 1)
- * sizeof(char *)));
- switch(dumptype) {
- case IS_SAMBA:
-#ifdef SAMBA_CLIENT
- restore_args[j++] = stralloc("smbclient");
- smbpass = findpass(file.disk, &domain);
- if (smbpass) {
- restore_args[j++] = stralloc(file.disk);
- passwd_field=j;
- restore_args[j++] = stralloc("-U");
- restore_args[j++] = smbpass;
- if (domain) {
- restore_args[j++] = stralloc("-W");
- restore_args[j++] = stralloc(domain);
- } else
- extra_params -= 2;
- } else
- extra_params -= 6;
- restore_args[j++] = stralloc("-d0");
- restore_args[j++] = stralloc("-Tx");
- restore_args[j++] = stralloc("-"); /* data on stdin */
- break;
#endif
case IS_TAR:
case IS_GNUTAR:
- restore_args[j++] = stralloc("tar");
- restore_args[j++] = stralloc("--numeric-owner");
- restore_args[j++] = stralloc("-xpGvf");
- restore_args[j++] = stralloc("-"); /* data on stdin */
+ 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 */
break;
case IS_SAMBA_TAR:
- restore_args[j++] = stralloc("tar");
- restore_args[j++] = stralloc("-xpvf");
- restore_args[j++] = stralloc("-"); /* data on stdin */
+ g_ptr_array_add(argv_ptr, stralloc("tar"));
+ g_ptr_array_add(argv_ptr, stralloc("-xpvf"));
+ g_ptr_array_add(argv_ptr, stralloc("-")); /* data on stdin */
break;
case IS_UNKNOWN:
case IS_DUMP:
- restore_args[j++] = stralloc("restore");
+ 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)
- if (strcmp(file.program, XFSDUMP) == 0) {
- restore_args[j++] = stralloc("-v");
- restore_args[j++] = stralloc("silent");
+ if (strcmp(ctl_data->file.program, XFSDUMP) == 0) {
+ g_ptr_array_add(argv_ptr, stralloc("-v"));
+ g_ptr_array_add(argv_ptr, stralloc("silent"));
} else
#endif
#if defined(VDUMP)
- if (strcmp(file.program, VDUMP) == 0) {
- restore_args[j++] = stralloc("xf");
- restore_args[j++] = stralloc("-"); /* data on stdin */
+ if (strcmp(ctl_data->file.program, VDUMP) == 0) {
+ g_ptr_array_add(argv_ptr, stralloc("xf"));
+ g_ptr_array_add(argv_ptr, stralloc("-")); /* data on stdin */
} else
#endif
{
- restore_args[j++] = stralloc("xbf");
- restore_args[j++] = stralloc("2"); /* read in units of 1K */
- restore_args[j++] = stralloc("-"); /* data on stdin */
+ g_ptr_array_add(argv_ptr, stralloc("xbf"));
+ g_ptr_array_add(argv_ptr, stralloc("2")); /* read in units of 1K */
+ g_ptr_array_add(argv_ptr, stralloc("-")); /* data on stdin */
}
#endif
break;
case IS_APPLICATION_API:
- {
- g_option_t g_options;
- g_options.config = get_config_name();
- g_options.hostname = dump_hostname;
- if (dump_dle) {
- bsu = backup_support_option(file.application, &g_options,
- file.disk, dump_dle->device,
- &errarray);
- } else {
- bsu = backup_support_option(file.application, &g_options,
- file.disk, NULL,
- &errarray);
- }
- }
- restore_args[j++] = stralloc(file.application);
- restore_args[j++] = stralloc("restore");
- restore_args[j++] = stralloc("--config");
- restore_args[j++] = stralloc(get_config_name());
- restore_args[j++] = stralloc("--disk");
- restore_args[j++] = stralloc(file.disk);
+ g_ptr_array_add(argv_ptr, stralloc(ctl_data->file.application));
+ g_ptr_array_add(argv_ptr, stralloc("restore"));
+ g_ptr_array_add(argv_ptr, stralloc("--config"));
+ g_ptr_array_add(argv_ptr, stralloc(get_config_name()));
+ g_ptr_array_add(argv_ptr, stralloc("--disk"));
+ g_ptr_array_add(argv_ptr, stralloc(ctl_data->file.disk));
if (dump_dle && dump_dle->device) {
- restore_args[j++] = stralloc("--device");
- restore_args[j++] = stralloc(dump_dle->device);
+ g_ptr_array_add(argv_ptr, stralloc("--device"));
+ g_ptr_array_add(argv_ptr, stralloc(dump_dle->device));
}
- if (bsu->smb_recover_mode && samba_extract_method == SAMBA_SMBCLIENT){
- restore_args[j++] = "--recover-mode";
- restore_args[j++] = "smb";
+ if (ctl_data->data_path == DATA_PATH_DIRECTTCP) {
+ g_ptr_array_add(argv_ptr, stralloc("--data-path"));
+ g_ptr_array_add(argv_ptr, stralloc("DIRECTTCP"));
+ g_ptr_array_add(argv_ptr, stralloc("--direct-tcp"));
+ g_ptr_array_add(argv_ptr, stralloc(ctl_data->addrs));
}
+ if (ctl_data->bsu && ctl_data->bsu->smb_recover_mode &&
+ samba_extract_method == SAMBA_SMBCLIENT){
+ g_ptr_array_add(argv_ptr, stralloc("--recover-mode"));
+ g_ptr_array_add(argv_ptr, stralloc("smb"));
+ }
+ g_ptr_array_add(argv_ptr, stralloc("--level"));
+ g_ptr_array_add(argv_ptr, g_strdup_printf("%d", ctl_data->elist->level));
if (dump_dle) {
GSList *scriptlist;
script_t *script;
- j += application_property_add_to_argv(&restore_args[j], dump_dle, NULL);
+ 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;
scriptlist = scriptlist->next) {
script = (script_t *)scriptlist->data;
if (script->result && script->result->proplist) {
- j += property_add_to_argv(&restore_args[j],
- script->result->proplist);
+ property_add_to_argv(argv_ptr, script->result->proplist);
}
}
+ } else if (proplist) {
+ property_add_to_argv(argv_ptr, proplist);
}
break;
}
-
- for (i = 0, fn = elist->files; i < files_off_tape; i++, fn = fn->next)
+
+ for (i = 0, fn = ctl_data->elist->files; i < files_off_tape;
+ i++, fn = fn->next)
{
switch (dumptype) {
- case IS_APPLICATION_API:
+ case IS_APPLICATION_API:
case IS_TAR:
case IS_GNUTAR:
case IS_SAMBA_TAR:
case IS_SAMBA:
if (strcmp(fn->path, "/") == 0)
- restore_args[j++] = stralloc(".");
+ g_ptr_array_add(argv_ptr, stralloc("."));
else
- restore_args[j++] = stralloc2(".", fn->path);
+ g_ptr_array_add(argv_ptr, stralloc2(".", fn->path));
break;
case IS_UNKNOWN:
case IS_DUMP:
#if defined(XFSDUMP)
- if (strcmp(file.program, XFSDUMP) == 0) {
+ if (strcmp(ctl_data->file.program, XFSDUMP) == 0) {
/*
* xfsrestore needs a -s option before each file to be
* restored, and also wants them to be relative paths.
*/
- restore_args[j++] = stralloc("-s");
- restore_args[j++] = stralloc(fn->path + 1);
+ g_ptr_array_add(argv_ptr, stralloc("-s"));
+ g_ptr_array_add(argv_ptr, stralloc(fn->path + 1));
} else
#endif
{
- restore_args[j++] = stralloc(fn->path);
+ g_ptr_array_add(argv_ptr, stralloc(fn->path));
}
break;
}
}
#if defined(XFSDUMP)
- if (strcmp(file.program, XFSDUMP) == 0) {
- restore_args[j++] = stralloc("-");
- restore_args[j++] = stralloc(".");
+ if (strcmp(ctl_data->file.program, XFSDUMP) == 0) {
+ g_ptr_array_add(argv_ptr, stralloc("-"));
+ g_ptr_array_add(argv_ptr, stralloc("."));
}
#endif
- restore_args[j] = NULL;
+ g_ptr_array_add(argv_ptr, NULL);
switch (dumptype) {
case IS_SAMBA:
case IS_DUMP:
cmd = NULL;
#if defined(DUMP)
- if (strcmp(file.program, DUMP) == 0) {
+ if (strcmp(ctl_data->file.program, DUMP) == 0) {
cmd = stralloc(RESTORE);
}
#endif
#if defined(VDUMP)
- if (strcmp(file.program, VDUMP) == 0) {
+ if (strcmp(ctl_data->file.program, VDUMP) == 0) {
cmd = stralloc(VRESTORE);
}
#endif
#if defined(VXDUMP)
- if (strcmp(file.program, VXDUMP) == 0) {
+ if (strcmp(ctl_data->file.program, VXDUMP) == 0) {
cmd = stralloc(VXRESTORE);
}
#endif
#if defined(XFSDUMP)
- if (strcmp(file.program, XFSDUMP) == 0) {
+ if (strcmp(ctl_data->file.program, XFSDUMP) == 0) {
cmd = stralloc(XFSRESTORE);
}
#endif
if (cmd == NULL) {
g_fprintf(stderr, _("warning: restore program for %s not available.\n"),
- file.program);
+ ctl_data->file.program);
cmd = stralloc("restore");
}
break;
case IS_APPLICATION_API:
- cmd = vstralloc(APPLICATION_DIR, "/", file.application, NULL);
+ cmd = vstralloc(APPLICATION_DIR, "/", ctl_data->file.application, NULL);
break;
}
if (cmd) {
dbprintf(_("Exec'ing %s with arguments:\n"), cmd);
- for (i = 0; i < j; i++) {
- if( i == passwd_field)
+ for (j = 0; j < argv_ptr->len - 1; j++) {
+ if (j == passwd_field)
dbprintf("\tXXXXX\n");
else
- dbprintf(_("\t%s\n"), restore_args[i]);
+ dbprintf(_("\t%s\n"), (char *)g_ptr_array_index(argv_ptr, j));
}
safe_fd(-1, 0);
- (void)execv(cmd, restore_args);
+ (void)execv(cmd, (char **)argv_ptr->pdata);
/* only get here if exec failed */
save_errno = errno;
- for (i = 0; i < j; i++) {
- amfree(restore_args[i]);
- }
- amfree(restore_args);
+ g_ptr_array_free_full(argv_ptr);
errno = save_errno;
perror(_("amrecover couldn't exec"));
g_fprintf(stderr, _(" problem executing %s\n"), cmd);
/*NOT REACHED */
}
-typedef struct ctl_data_s {
- int header_done;
- int child_pipe[2];
- int pid;
- EXTRACT_LIST *elist;
-} ctl_data_t;
-
/*
* Interpose something between the process writing out the dump (writing it to
* some extraction program, really) and the socket from which we're reading, so
ctl_data.child_pipe[1] = -1;
ctl_data.pid = -1;
ctl_data.elist = elist;
+ fh_init(&ctl_data.file);
+ 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);
while(get_amidxtaped_line() >= 0) {
char desired_tape[MAX_TAPE_LABEL_BUF];
-
+ g_debug("get amidxtaped line: %s", amidxtaped_line);
+
/* if prompted for a tape, relay said prompt to the user */
if(sscanf(amidxtaped_line, "FEEDME %132s\n", desired_tape) == 1) {
int done;
send_to_tape_server(amidxtaped_streams[CTLFD].fd, "ERROR");
break;
}
+ } else if (strncmp_const(amidxtaped_line, "USE-DATAPATH ") == 0) {
+ if (strncmp_const(amidxtaped_line+13, "AMANDA") == 0) {
+ ctl_data.data_path = DATA_PATH_AMANDA;
+ g_debug("Using AMANDA data-path");
+ } else if (strncmp_const(amidxtaped_line+13, "DIRECT-TCP") == 0) {
+ ctl_data.data_path = DATA_PATH_DIRECTTCP;
+ ctl_data.addrs = stralloc(amidxtaped_line+24);
+ g_debug("Using DIRECT-TCP data-path with %s", ctl_data.addrs);
+ }
+ start_processing_data(&ctl_data);
} else if(strncmp_const(amidxtaped_line, "MESSAGE ") == 0) {
g_printf("%s\n",&amidxtaped_line[8]);
} else {
/* CTL might be close before DATA */
event_loop(0);
+ dumpfile_free_data(&ctl_data.file);
+ amfree(ctl_data.addrs);
+ amfree(ctl_data.bsu);
if (ctl_data.child_pipe[1] != -1)
aclose(ctl_data.child_pipe[1]);
return -1;
}
}
+ g_debug("bytes read: %jd", (intmax_t)ctl_data.bytes_read);
return(0);
}
extract_files(void)
{
EXTRACT_LIST *elist;
- char * cwd;
char *l;
int first;
int otc;
tapelist_t *tlist = NULL, *a_tlist;
g_option_t g_options;
- GSList *all_level = NULL;
+ levellist_t all_level = NULL;
int last_level;
if (!is_extract_list_nonempty())
}
else
g_printf(" ");
- tlist = unmarshal_tapelist_str(elist->tape);
+ tlist = unmarshal_tapelist_str(elist->tape);
for(a_tlist = tlist ; a_tlist != NULL; a_tlist = a_tlist->next)
g_printf(" %s", a_tlist->label);
g_printf("\n");
}
else
g_printf(" ");
- tlist = unmarshal_tapelist_str(elist->tape);
+ tlist = unmarshal_tapelist_str(elist->tape);
for(a_tlist = tlist; a_tlist != NULL; a_tlist = a_tlist->next)
g_printf(" %s", a_tlist->label);
g_printf("\n");
}
g_printf("\n");
- cwd = g_get_current_dir();
- if (cwd == NULL) {
- perror(_("extract_list: Current working directory unavailable"));
- exit(1);
- }
-
- g_printf(_("Restoring files into directory %s\n"), cwd);
- check_file_overwrite(cwd);
-
- if (samba_extract_method == SAMBA_SMBCLIENT)
- g_printf(_("(unless it is a Samba backup, that will go through to the SMB server)\n"));
- dbprintf(_("Checking with user before restoring into directory %s\n"), cwd);
- if (!okay_to_continue(0,0,0)) {
- amfree(cwd);
- return;
- }
- g_printf("\n");
-
- if (!do_unlink_list()) {
- g_fprintf(stderr, _("Can't recover because I can't cleanup the cwd (%s)\n"),
- cwd);
- amfree(cwd);
- return;
- }
- free_unlink_list();
-
g_options.config = get_config_name();
g_options.hostname = dump_hostname;
for (elist = first_tape_list(); elist != NULL;
elist = next_tape_list(elist)) {
- all_level = g_slist_append(all_level, GINT_TO_POINTER(elist->level));
+ level_t *level = g_new0(level_t, 1);
+ level->level = elist->level;
+ all_level = g_slist_append(all_level, level);
}
if (dump_dle) {
- g_slist_free(dump_dle->level);
- dump_dle->level = all_level;
+ 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->level = NULL;
+ dump_dle->levellist = NULL;
}
last_level = -1;
while ((elist = first_tape_list()) != NULL)
if(elist->tape[0]=='/') {
dump_device_name = newstralloc(dump_device_name, elist->tape);
g_printf(_("Extracting from file "));
- tlist = unmarshal_tapelist_str(dump_device_name);
+ tlist = unmarshal_tapelist_str(dump_device_name);
for(a_tlist = tlist; a_tlist != NULL; a_tlist = a_tlist->next)
g_printf(" %s", a_tlist->label);
g_printf("\n");
else {
g_printf(_("Extracting files using tape drive %s on host %s.\n"),
tape_device_name, tape_server_name);
- tlist = unmarshal_tapelist_str(elist->tape);
+ tlist = unmarshal_tapelist_str(elist->tape);
g_printf(_("Load tape %s now\n"), tlist->label);
dbprintf(_("Requesting tape %s from user\n"), tlist->label);
free_tapelist(tlist);
dump_datestamp = newstralloc(dump_datestamp, elist->date);
if (last_level != -1 && dump_dle) {
- dump_dle->level = g_slist_append(dump_dle->level,
- GINT_TO_POINTER(last_level));
- dump_dle->level = g_slist_append(dump_dle->level,
- GINT_TO_POINTER(elist->level));
+ level_t *level;
+
+ level = g_new0(level_t, 1);
+ level->level = last_level;
+ dump_dle->levellist = g_slist_append(dump_dle->levellist, level);
+
+ level = g_new0(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(dump_dle->level);
- dump_dle->level = NULL;
+ slist_free_full(dump_dle->levellist, g_free);
+ dump_dle->levellist = NULL;
}
/* connect to the tape handler daemon on the tape drive server */
return;
}
if (dump_dle) {
- dump_dle->level = g_slist_append(dump_dle->level,
- GINT_TO_POINTER(elist->level));
+ level_t *level;
+
+ level = g_new0(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,
dump_dle, stderr);
}
am_has_feature(indexsrv_features, fe_amrecover_feedme_tape))
delete_tape_list(elist); /* tape done so delete from list */
+ am_release_feature_set(tapesrv_features);
stop_amidxtaped();
if (dump_dle) {
run_client_scripts(EXECUTE_ON_POST_LEVEL_RECOVER, &g_options,
dump_dle, stderr);
- g_slist_free(dump_dle->level);
- dump_dle->level = NULL;
+ slist_free_full(dump_dle->levellist, g_free);
+ dump_dle->levellist = NULL;
}
}
if (dump_dle) {
- dump_dle->level = all_level;
+ dump_dle->levellist = all_level;
run_client_scripts(EXECUTE_ON_POST_RECOVER, &g_options, dump_dle,
stderr);
- g_slist_free(dump_dle->level);
+ slist_free_full(dump_dle->levellist, g_free);
all_level = NULL;
- dump_dle->level = NULL;
+ dump_dle->levellist = NULL;
}
}
ctl_buffer = stralloc("");
while (!strstr(ctl_buffer,"\r\n")) {
+ if (amidxtaped_streams[CTLFD].fd == NULL)
+ return -1;
+
size = security_stream_read_sync(amidxtaped_streams[CTLFD].fd, &buf);
if(size < 0) {
return -1;
newbuf[strlen(ctl_buffer)+size] = '\0';
amfree(ctl_buffer);
ctl_buffer = newbuf;
+ amfree(buf);
}
s = strstr(ctl_buffer,"\r\n");
assert(buf != NULL);
if (ctl_data->header_done == 0) {
- ctl_data->header_done = 1;
- if(pipe(ctl_data->child_pipe) == -1) {
- error(_("extract_list - error setting up pipe to extractor: %s\n"),
- strerror(errno));
- /*NOTREACHED*/
+ 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);
}
-
- /* okay, ready to extract. fork a child to do the actual work */
- if ((ctl_data->pid = fork()) == 0) {
- /* this is the child process */
- /* never gets out of this clause */
- aclose(ctl_data->child_pipe[1]);
- extract_files_child(ctl_data->child_pipe[0], ctl_data->elist);
- /*NOTREACHED*/
+ assert (to_move == size);
+ /* parse the file header */
+ fh_init(&ctl_data->file);
+ parse_file_header(header_buf, &ctl_data->file, (size_t)header_size);
+
+ /* call backup_support_option */
+ g_options.config = get_config_name();
+ g_options.hostname = dump_hostname;
+ if (strcmp(ctl_data->file.program, "APPLICATION") == 0) {
+ if (dump_dle) {
+ ctl_data->bsu = backup_support_option(ctl_data->file.application,
+ &g_options,
+ ctl_data->file.disk,
+ dump_dle->device,
+ &errarray);
+ } else {
+ ctl_data->bsu = backup_support_option(ctl_data->file.application,
+ &g_options,
+ ctl_data->file.disk, NULL,
+ &errarray);
+ }
+ if (!ctl_data->bsu) {
+ guint i;
+ for (i=0; i < errarray->len; i++) {
+ char *line;
+ line = g_ptr_array_index(errarray, i);
+ g_fprintf(stderr, "%s\n", line);
+ }
+ g_ptr_array_free_full(errarray);
+ exit(1);
+ }
+ data_path_set = ctl_data->bsu->data_path_set;
}
-
- if (ctl_data->pid == -1) {
- errstr = newstralloc(errstr, _("writer_intermediary - error forking child"));
- g_printf(_("writer_intermediary - error forking child"));
+ /* handle backup_support_option failure */
+
+ ctl_data->header_done = 1;
+ if (!ask_file_overwrite(ctl_data)) {
+ if (am_has_feature(tapesrv_features, fe_amidxtaped_abort)) {
+ send_to_tape_server(amidxtaped_streams[CTLFD].fd, "ABORT");
+ }
+ stop_amidxtaped();
return;
}
- aclose(ctl_data->child_pipe[0]);
+
+ if (am_has_feature(tapesrv_features, fe_amidxtaped_datapath)) {
+ char *msg;
+ /* send DATA-PATH request */
+ msg = stralloc("AVAIL-DATAPATH");
+ if (data_path_set & DATA_PATH_AMANDA)
+ vstrextend(&msg, " AMANDA", NULL);
+ if (data_path_set & DATA_PATH_DIRECTTCP)
+ vstrextend(&msg, " DIRECT-TCP", NULL);
+ send_to_tape_server(amidxtaped_streams[CTLFD].fd, msg);
+ amfree(msg);
+ } else {
+ 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);
}
- /*
- * 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);
}
-char *
-amidxtaped_client_get_security_conf(
- char * string,
- void * arg)
+static gboolean
+ask_file_overwrite(
+ ctl_data_t *ctl_data)
{
- (void)arg; /* Quiet unused parameter warning */
+ char *restore_dir = NULL;
+
+ if (ctl_data->file.dumplevel == 0) {
+ property_t *property = g_hash_table_lookup(proplist, "directory");
+ if (property && property->values && property->values->data) {
+ /* take first property value */
+ restore_dir = strdup(property->values->data);
+ }
+ if (samba_extract_method == SAMBA_SMBCLIENT ||
+ (ctl_data->bsu &&
+ ctl_data->bsu->recover_path == RECOVER_PATH_REMOTE)) {
+ if (!restore_dir) {
+ restore_dir = g_strdup(ctl_data->file.disk);
+ }
+ g_printf(_("Restoring files into target host %s\n"), restore_dir);
+ } else {
+ if (!restore_dir) {
+ restore_dir = g_get_current_dir();
+ }
+ g_printf(_("Restoring files into directory %s\n"), restore_dir);
+ }
- if(!string || !*string)
- return(NULL);
+ /* Collect files to delete befause of a bug in gnutar */
+ if (strcmp(ctl_data->file.program, "GNUTAR") == 0 ||
+ (strcmp(ctl_data->file.program, "APPLICATION") == 0 &&
+ strcmp(ctl_data->file.application, "amgtar") == 0)) {
+ check_file_overwrite(restore_dir);
+ } else {
+ g_printf(_("All existing files in %s can be deleted\n"),
+ restore_dir);
+ }
+
+ if (!okay_to_continue(0,0,0)) {
+ free_unlink_list();
+ amfree(restore_dir);
+ return FALSE;
+ }
+ g_printf("\n");
+
+ /* delete the files for gnutar */
+ if (unlink_list) {
+ if (!do_unlink_list()) {
+ g_fprintf(stderr, _("Can't recover because I can't cleanup the restore directory (%s)\n"),
+ restore_dir);
+ free_unlink_list();
+ amfree(restore_dir);
+ return FALSE;
+ }
+ free_unlink_list();
+ }
+ amfree(restore_dir);
+ }
+ return TRUE;
+}
- if(strcmp(string, "auth")==0) {
- return(getconf_str(CNF_AUTH));
+static void
+start_processing_data(
+ ctl_data_t *ctl_data)
+{
+ if (pipe(ctl_data->child_pipe) == -1) {
+ error(_("extract_list - error setting up pipe to extractor: %s\n"),
+ strerror(errno));
+ /*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 */
+ /* never gets out of this clause */
+ aclose(ctl_data->child_pipe[1]);
+ extract_files_child(ctl_data);
+ /*NOTREACHED*/
+ }
+
+ if (ctl_data->pid == -1) {
+ errstr = newstralloc(errstr, _("writer_intermediary - error forking child"));
+ g_printf(_("writer_intermediary - error forking child"));
+ return;
}
- if(strcmp(string, "ssh_keys")==0) {
- return(getconf_str(CNF_SSH_KEYS));
+ aclose(ctl_data->child_pipe[0]);
+ security_stream_read(amidxtaped_streams[DATAFD].fd, read_amidxtaped_data,
+ ctl_data);
+ if (am_has_feature(tapesrv_features, fe_amidxtaped_datapath)) {
+ send_to_tape_server(amidxtaped_streams[CTLFD].fd, "DATAPATH-OK");
}
- return(NULL);
}