Imported Upstream version 2.6.1
[debian/amanda] / client-src / sendbackup-gnutar.c
index f3c74fc6cb07d2b33b66c5777beb21115fa38836..4439f308b12079c1fb4a0ae5441a55cdcc5b12be 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /* 
- * $Id: sendbackup-gnutar.c,v 1.92 2005/12/09 03:22:52 paddy_s Exp $
+ * $Id: sendbackup-gnutar.c,v 1.98 2006/07/25 18:35:21 martinea Exp $
  *
  * send backup data using GNU tar
  */
 #include "util.h"
 #include "getfsent.h"                  /* for amname_to_dirname lookup */
 #include "version.h"
+#include "conffile.h"
 
 #ifdef SAMBA_CLIENT
 #include "findpass.h"
 #endif
 
-static regex_t re_table[] = {
+static amregex_t re_table[] = {
   /* tar prints the size in bytes */
-  AM_SIZE_RE("^ *Total bytes written: [0-9][0-9]*", 1),
+  AM_SIZE_RE("^ *Total bytes written: [0-9][0-9]*", 1, 1),
   AM_NORMAL_RE("^Elapsed time:"),
   AM_NORMAL_RE("^Throughput"),
 
@@ -123,217 +124,237 @@ int cur_level;
 char *cur_disk;
 time_t cur_dumptime;
 
-#ifdef GNUTAR_LISTED_INCREMENTAL_DIR
+static char *gnutar_list_dir = NULL;
 static char *incrname = NULL;
-#endif
 /*
  *  doing similar to $ gtar | compression | encryption 
  */
-static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, indexf)
-    char *host;
-    char *disk, *amdevice;
-    int level, dataf, mesgf, indexf;
-    char *dumpdate;
+static void
+start_backup(
+    dle_t      *dle,
+    char       *host,
+    int                dataf,
+    int                mesgf,
+    int                indexf)
 {
+    char tmppath[PATH_MAX];
     int dumpin, dumpout, compout;
     char *cmd = NULL;
     char *indexcmd = NULL;
     char *dirname = NULL;
     int l;
-    char dumptimestr[80];
+    char dumptimestr[80] = "UNUSED";
     struct tm *gmtm;
-    amandates_t *amdates;
-    time_t prev_dumptime;
+    amandates_t *amdates = NULL;
+    time_t prev_dumptime = 0;
     char *error_pn = NULL;
     char *compopt  = NULL;
     char *encryptopt = skip_argument;
+    char *tquoted;
+    char *fquoted;
+    char *qdisk;
+    int infd, outfd;
+    ssize_t nb;
+    char buf[32768];
+    char *amandates_file = NULL;
 
     error_pn = stralloc2(get_pname(), "-smbclient");
 
+    qdisk = quote_string(dle->disk);
+    dbprintf(_("start: %s:%s lev %d\n"), host, qdisk, GPOINTER_TO_INT(dle->level->data));
+
+    g_fprintf(stderr, _("%s: start [%s:%s level %d]\n"),
+           get_pname(), host, qdisk, GPOINTER_TO_INT(dle->level->data));
 
-    fprintf(stderr, "%s: start [%s:%s level %d]\n",
-           get_pname(), host, disk, level);
      /*  apply client-side encryption here */
-     if ( options->encrypt == ENCRYPT_CUST ) {
-      encpid = pipespawn(options->clnt_encrypt, STDIN_PIPE,
+     if ( dle->encrypt == ENCRYPT_CUST ) {
+         encpid = pipespawn(dle->clnt_encrypt, STDIN_PIPE, 0, 
                        &compout, &dataf, &mesgf, 
-                       options->clnt_encrypt, encryptopt, NULL);
-      dbprintf(("%s: pid %ld: %s\n",
-                 debug_prefix_time("-gnutar"), (long)encpid, options->clnt_encrypt));
+                       dle->clnt_encrypt, encryptopt, NULL);
+         dbprintf(_("gnutar: pid %ld: %s\n"), (long)encpid, dle->clnt_encrypt);
     } else {
        compout = dataf;
        encpid = -1;
     } 
      /*  now do the client-side compression */
-    if(options->compress == COMPR_FAST || options->compress == COMPR_BEST) {
+    if(dle->compress == COMP_FAST || dle->compress == COMP_BEST) {
           compopt = skip_argument;
 #if defined(COMPRESS_BEST_OPT) && defined(COMPRESS_FAST_OPT)
-       if(options->compress == COMPR_BEST) {
+       if(dle->compress == COMP_BEST) {
            compopt = COMPRESS_BEST_OPT;
        } else {
            compopt = COMPRESS_FAST_OPT;
        }
 #endif
-       comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE,
+       comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE, 0,
                            &dumpout, &compout, &mesgf,
                            COMPRESS_PATH, compopt, NULL);
-       dbprintf(("%s: pid %ld: %s",
-                 debug_prefix_time("-gnutar"), (long)comppid, COMPRESS_PATH));
+       dbprintf(_("gnutar: pid %ld: %s"), (long)comppid, COMPRESS_PATH);
        if(compopt != skip_argument) {
-           dbprintf((" %s", compopt));
+           dbprintf(_("pid %ld: %s %s\n"),
+                       (long)comppid, COMPRESS_PATH, compopt);
+       } else {
+           dbprintf(_("pid %ld: %s\n"), (long)comppid, COMPRESS_PATH);
        }
-       dbprintf(("\n"));
-     } else if (options->compress == COMPR_CUST) {
+     } else if (dle->compress == COMP_CUST) {
         compopt = skip_argument;
-       comppid = pipespawn(options->clntcompprog, STDIN_PIPE,
+       comppid = pipespawn(dle->compprog, STDIN_PIPE, 0,
                            &dumpout, &compout, &mesgf,
-                           options->clntcompprog, compopt, NULL);
-       dbprintf(("%s: pid %ld: %s",
-                 debug_prefix_time("-gnutar-cust"), (long)comppid, options->clntcompprog));
+                           dle->compprog, compopt, NULL);
        if(compopt != skip_argument) {
-           dbprintf((" %s", compopt));
+           dbprintf(_("pid %ld: %s %s\n"),
+                    (long)comppid, dle->compprog, compopt);
+       } else {
+           dbprintf(_("pid %ld: %s\n"), (long)comppid, dle->compprog);
        }
-       dbprintf(("\n"));
     } else {
        dumpout = compout;
        comppid = -1;
     }
 
-#ifdef GNUTAR_LISTED_INCREMENTAL_DIR                                   /* { */
+    gnutar_list_dir = getconf_str(CNF_GNUTAR_LIST_DIR);
+    if (strlen(gnutar_list_dir) == 0)
+       gnutar_list_dir = NULL;
+
 #ifdef SAMBA_CLIENT                                                    /* { */
-    if (amdevice[0] == '/' && amdevice[1]=='/')
+    if (dle->device[0] == '/' && dle->device[1]=='/')
        amfree(incrname);
     else
 #endif                                                                 /* } */
-    {
+    if (gnutar_list_dir) {
        char *basename = NULL;
        char number[NUM_STR_SIZE];
-       char *s;
-       int ch;
        char *inputname = NULL;
-       FILE *in = NULL;
-       FILE *out;
        int baselevel;
-       char *line = NULL;
+       char *sdisk = sanitise_filename(dle->disk);
 
-       basename = vstralloc(GNUTAR_LISTED_INCREMENTAL_DIR,
+       basename = vstralloc(gnutar_list_dir,
                             "/",
                             host,
-                            disk,
+                            sdisk,
                             NULL);
-       /*
-        * The loop starts at the first character of the host name,
-        * not the '/'.
-        */
-       s = basename + sizeof(GNUTAR_LISTED_INCREMENTAL_DIR);
-       while((ch = *s++) != '\0') {
-           if(ch == '/' || isspace(ch)) s[-1] = '_';
-       }
+       amfree(sdisk);
 
-       snprintf(number, sizeof(number), "%d", level);
+       g_snprintf(number, SIZEOF(number), "%d", GPOINTER_TO_INT(dle->level->data));
        incrname = vstralloc(basename, "_", number, ".new", NULL);
        unlink(incrname);
 
        /*
-        * Open the listed incremental file for the previous level.  Search
+        * Open the listed incremental file from the previous level.  Search
         * backward until one is found.  If none are found (which will also
         * be true for a level 0), arrange to read from /dev/null.
         */
-       baselevel = level;
-       while (in == NULL) {
+       baselevel = GPOINTER_TO_INT(dle->level->data);
+       infd = -1;
+       while (infd == -1) {
            if (--baselevel >= 0) {
-               snprintf(number, sizeof(number), "%d", baselevel);
+               g_snprintf(number, SIZEOF(number), "%d", baselevel);
                inputname = newvstralloc(inputname,
                                         basename, "_", number, NULL);
            } else {
                inputname = newstralloc(inputname, "/dev/null");
            }
-           if ((in = fopen(inputname, "r")) == NULL) {
+           if ((infd = open(inputname, O_RDONLY)) == -1) {
                int save_errno = errno;
+               char *qname = quote_string(inputname);
 
-               dbprintf(("%s: error opening %s: %s\n",
-                         debug_prefix_time("-gnutar"),
-                         inputname,
-                         strerror(save_errno)));
+               dbprintf(_("gnutar: error opening '%s': %s\n"),
+                         qname,
+                         strerror(save_errno));
                if (baselevel < 0) {
-                   error("error [opening %s: %s]", inputname, strerror(save_errno));
+                   error(_("error [opening '%s': %s]"), qname, strerror(save_errno));
+                   /*NOTREACHED*/
                }
+               amfree(qname);
            }
        }
 
        /*
         * Copy the previous listed incremental file to the new one.
         */
-       if ((out = fopen(incrname, "w")) == NULL) {
-           error("error [opening %s: %s]", incrname, strerror(errno));
+       if ((outfd = open(incrname, O_WRONLY|O_CREAT, 0600)) == -1) {
+           error(_("error [opening '%s': %s]"), incrname, strerror(errno));
+           /*NOTREACHED*/
        }
 
-       for (; (line = agets(in)) != NULL; free(line)) {
-           if(fputs(line, out) == EOF || putc('\n', out) == EOF) {
-               error("error [writing to %s: %s]", incrname, strerror(errno));
+       while ((nb = read(infd, &buf, SIZEOF(buf))) > 0) {
+           if (full_write(outfd, &buf, (size_t)nb) < (size_t)nb) {
+               error(_("error [writing to '%s': %s]"), incrname,
+                      strerror(errno));
+               /*NOTREACHED*/
            }
        }
-       amfree(line);
 
-       if (ferror(in)) {
-           error("error [reading from %s: %s]", inputname, strerror(errno));
+       if (nb < 0) {
+           error(_("error [reading from '%s': %s]"), inputname, strerror(errno));
+           /*NOTREACHED*/
        }
-       if (fclose(in) == EOF) {
-           error("error [closing %s: %s]", inputname, strerror(errno));
+
+       if (close(infd) != 0) {
+           error(_("error [closing '%s': %s]"), inputname, strerror(errno));
+           /*NOTREACHED*/
        }
-       in = NULL;
-       if (fclose(out) == EOF) {
-           error("error [closing %s: %s]", incrname, strerror(errno));
+       if (close(outfd) != 0) {
+           error(_("error [closing '%s': %s]"), incrname, strerror(errno));
+           /*NOTREACHED*/
        }
-       out = NULL;
 
-       dbprintf(("%s: doing level %d dump as listed-incremental",
-                 debug_prefix_time("-gnutar"), level));
+       tquoted = quote_string(incrname);
        if(baselevel >= 0) {
-           dbprintf((" from %s", inputname));
+           fquoted = quote_string(inputname);
+           dbprintf(_("doing level %d dump as listed-incremental from '%s' to '%s'\n"),
+                    GPOINTER_TO_INT(dle->level->data), fquoted, tquoted);
+           amfree(fquoted);
+       } else {
+           dbprintf(_("doing level %d dump as listed-incremental to '%s'\n"),
+                    GPOINTER_TO_INT(dle->level->data), tquoted);
        }
-       dbprintf((" to %s\n", incrname));
+       amfree(tquoted);
        amfree(inputname);
        amfree(basename);
-    }
-#endif                                                                 /* } */
-
-    /* find previous dump time */
+    } else {
+       /* no gnutar-listdir, so we're using amandates */
 
-    if(!start_amandates(0))
-       error("error [opening %s: %s]", AMANDATES_FILE, strerror(errno));
+       /* find previous dump time, failing completely if there's a problem */
+       amandates_file = getconf_str(CNF_AMANDATES);
+       if(!start_amandates(amandates_file, 0)) {
+           error(_("error [opening %s: %s]"), amandates_file, strerror(errno));
+           /*NOTREACHED*/
+       }
 
-    amdates = amandates_lookup(disk);
+       amdates = amandates_lookup(dle->disk);
 
-    prev_dumptime = EPOCH;
-    for(l = 0; l < level; l++) {
-       if(amdates->dates[l] > prev_dumptime)
-           prev_dumptime = amdates->dates[l];
-    }
+       prev_dumptime = EPOCH;
+       for(l = 0; l < GPOINTER_TO_INT(dle->level->data); l++) {
+           if(amdates->dates[l] > prev_dumptime)
+               prev_dumptime = amdates->dates[l];
+       }
 
-    finish_amandates();
-    free_amandates();
+       finish_amandates();
+       free_amandates();
 
-    gmtm = gmtime(&prev_dumptime);
-    snprintf(dumptimestr, sizeof(dumptimestr),
-               "%04d-%02d-%02d %2d:%02d:%02d GMT",
-               gmtm->tm_year + 1900, gmtm->tm_mon+1, gmtm->tm_mday,
-               gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec);
+       gmtm = gmtime(&prev_dumptime);
+       g_snprintf(dumptimestr, SIZEOF(dumptimestr),
+                   "%04d-%02d-%02d %2d:%02d:%02d GMT",
+                   gmtm->tm_year + 1900, gmtm->tm_mon+1, gmtm->tm_mday,
+                   gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec);
 
-    dbprintf(("%s: doing level %d dump from date: %s\n",
-             debug_prefix_time("-gnutar"), level, dumptimestr));
+       dbprintf(_("gnutar: doing level %d dump from amandates-derived date: %s\n"),
+                 GPOINTER_TO_INT(dle->level->data), dumptimestr);
+    }
 
-    dirname = amname_to_dirname(amdevice);
+    dirname = amname_to_dirname(dle->device);
 
     cur_dumptime = time(0);
-    cur_level = level;
-    cur_disk = stralloc(disk);
-    indexcmd = vstralloc(
+    cur_level = GPOINTER_TO_INT(dle->level->data);
+    cur_disk = stralloc(dle->disk);
 #ifdef GNUTAR
-                        GNUTAR,
+#  define PROGRAM_GNUTAR GNUTAR
 #else
-                        "tar",
+#  define PROGRAM_GNUTAR "tar"
 #endif
+    indexcmd = vstralloc(
+                        PROGRAM_GNUTAR,
                         " -tf", " -",
                         " 2>/dev/null",
                         " | sed", " -e",
@@ -342,30 +363,32 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
 
 #ifdef SAMBA_CLIENT                                                    /* { */
     /* Use sambatar if the disk to back up is a PC disk */
-    if (amdevice[0] == '/' && amdevice[1]=='/') {
+    if (dle->device[0] == '/' && dle->device[1]=='/') {
        char *sharename = NULL, *user_and_password = NULL, *domain = NULL;
        char *share = NULL, *subdir = NULL;
-       char *pwtext;
+       char *pwtext = NULL;
        char *taropt;
-       int passwdf;
-       int lpass;
-       int pwtext_len;
+       int passwdf = -1;
+       size_t lpass;
+       size_t pwtext_len;
        char *pw_fd_env;
 
-       parsesharename(amdevice, &share, &subdir);
+       parsesharename(dle->device, &share, &subdir);
        if (!share) {
            amfree(share);
            amfree(subdir);
            set_pname(error_pn);
            amfree(error_pn);
-           error("cannot parse disk entry '%s' for share/subdir", disk);
+           error(_("cannot parse disk entry %s for share/subdir"), qdisk);
+           /*NOTREACHED*/
        }
        if ((subdir) && (SAMBA_VERSION < 2)) {
            amfree(share);
            amfree(subdir);
            set_pname(error_pn);
            amfree(error_pn);
-           error("subdirectory specified for share '%s' but samba not v2 or better", disk);
+           error(_("subdirectory specified for share %s but samba not v2 or better"), qdisk);
+           /*NOTREACHED*/
        }
        if ((user_and_password = findpass(share, &domain)) == NULL) {
            if(domain) {
@@ -374,7 +397,8 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
            }
            set_pname(error_pn);
            amfree(error_pn);
-           error("error [invalid samba host or password not found?]");
+           error(_("error [invalid samba host or password not found?]"));
+           /*NOTREACHED*/
        }
        lpass = strlen(user_and_password);
        if ((pwtext = strchr(user_and_password, '%')) == NULL) {
@@ -386,7 +410,8 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
            }
            set_pname(error_pn);
            amfree(error_pn);
-           error("password field not \'user%%pass\' for %s", disk);
+           error(_("password field not \'user%%pass\' for %s"), qdisk);
+           /*NOTREACHED*/
        }
        *pwtext++ = '\0';
        pwtext_len = strlen(pwtext);
@@ -399,41 +424,42 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
            }
            set_pname(error_pn);
            amfree(error_pn);
-           error("error [can't make share name of %s]", share);
+           error(_("error [can't make share name of %s]"), share);
+           /*NOTREACHED*/
        }
 
        taropt = stralloc("-T");
-       if(options->exclude_file && options->exclude_file->nb_element == 1) {
+       if(dle->exclude_file && dle->exclude_file->nb_element == 1) {
            strappend(taropt, "X");
        }
 #if SAMBA_VERSION >= 2
        strappend(taropt, "q");
 #endif
        strappend(taropt, "c");
-       if (level != 0) {
+       if (GPOINTER_TO_INT(dle->level->data) != 0) {
            strappend(taropt, "g");
-       } else if (!options->no_record) {
+       } else if (dle->record) {
            strappend(taropt, "a");
        }
 
-       dbprintf(("%s: backup of %s", debug_prefix_time("-gnutar"), sharename));
        if (subdir) {
-           dbprintf(("/%s",subdir));
+           dbprintf(_("gnutar: backup of %s/%s\n"), sharename, subdir);
+       } else {
+           dbprintf(_("gnutar: backup of %s\n"), sharename);
        }
-       dbprintf(("\n"));
 
        program->backup_name = program->restore_name = SAMBA_CLIENT;
        cmd = stralloc(program->backup_name);
-       info_tapeheader();
+       info_tapeheader(dle);
 
-       start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
+       start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);
 
        if (pwtext_len > 0) {
            pw_fd_env = "PASSWD_FD";
        } else {
            pw_fd_env = "dummy_PASSWD_FD";
        }
-       dumppid = pipespawn(cmd, STDIN_PIPE|PASSWD_PIPE,
+       dumppid = pipespawn(cmd, STDIN_PIPE|PASSWD_PIPE, 0,
                            &dumpin, &dumpout, &mesgf,
                            pw_fd_env, &passwdf,
                            "smbclient",
@@ -450,13 +476,13 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
                            "-d0",
                            taropt,
                            "-",
-                           options->exclude_file && options->exclude_file->nb_element == 1 ? options->exclude_file->first->name : skip_argument,
+                           dle->exclude_file && dle->exclude_file->nb_element == 1 ? dle->exclude_file->first->name : skip_argument,
                            NULL);
        if(domain) {
            memset(domain, '\0', strlen(domain));
            amfree(domain);
        }
-       if(pwtext_len > 0 && fullwrite(passwdf, pwtext, pwtext_len) < 0) {
+       if(pwtext_len > 0 && full_write(passwdf, pwtext, pwtext_len) < pwtext_len) {
            int save_errno = errno;
 
            aclose(passwdf);
@@ -464,7 +490,8 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
            amfree(user_and_password);
            set_pname(error_pn);
            amfree(error_pn);
-           error("error [password write failed: %s]", strerror(save_errno));
+           error(_("error [password write failed: %s]"), strerror(save_errno));
+           /*NOTREACHED*/
        }
        memset(user_and_password, '\0', lpass);
        amfree(user_and_password);
@@ -485,36 +512,46 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
        char *file_exclude = NULL;
        char *file_include = NULL;
 
-       if(options->exclude_file) nb_exclude+=options->exclude_file->nb_element;
-       if(options->exclude_list) nb_exclude+=options->exclude_list->nb_element;
-       if(options->include_file) nb_include+=options->include_file->nb_element;
-       if(options->include_list) nb_include+=options->include_list->nb_element;
+       if (dle->exclude_file) nb_exclude+=dle->exclude_file->nb_element;
+       if (dle->exclude_list) nb_exclude+=dle->exclude_list->nb_element;
+       if (dle->include_file) nb_include+=dle->include_file->nb_element;
+       if (dle->include_list) nb_include+=dle->include_list->nb_element;
 
-       if(nb_exclude > 0) file_exclude = build_exclude(disk, amdevice, options, 0);
-       if(nb_include > 0) file_include = build_include(disk, amdevice, options, 0);
+       if (nb_exclude > 0) file_exclude = build_exclude(dle, 0);
+       if (nb_include > 0) file_include = build_include(dle, 0);
 
-       my_argv = alloc(sizeof(char *) * (17 + (nb_exclude*2)+(nb_include*2)));
+       my_argv = alloc(SIZEOF(char *) * (22 + (nb_exclude*2)+(nb_include*2)));
 
-       cmd = vstralloc(libexecdir, "/", "runtar", versionsuffix(), NULL);
-       info_tapeheader();
+       cmd = vstralloc(amlibexecdir, "/", "runtar", versionsuffix(), NULL);
+       info_tapeheader(dle);
 
-       start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
+       start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);
 
-       my_argv[i++] = "gtar";
+        my_argv[i++] = "runtar";
+       if (g_options->config)
+           my_argv[i++] = g_options->config;
+       else
+           my_argv[i++] = "NOCONFIG";
+#ifdef GNUTAR
+       my_argv[i++] = GNUTAR;
+#else
+       my_argv[i++] = "tar";
+#endif
        my_argv[i++] = "--create";
        my_argv[i++] = "--file";
        my_argv[i++] = "-";
        my_argv[i++] = "--directory";
-       my_argv[i++] = dirname;
+       canonicalize_pathname(dirname, tmppath);
+       my_argv[i++] = tmppath;
        my_argv[i++] = "--one-file-system";
-#ifdef GNUTAR_LISTED_INCREMENTAL_DIR
-       my_argv[i++] = "--listed-incremental";
-       my_argv[i++] = incrname;
-#else
-       my_argv[i++] = "--incremental";
-       my_argv[i++] = "--newer";
-       my_argv[i++] = dumptimestr;
-#endif
+       if (gnutar_list_dir && incrname) {
+           my_argv[i++] = "--listed-incremental";
+           my_argv[i++] = incrname;
+       } else {
+           my_argv[i++] = "--incremental";
+           my_argv[i++] = "--newer";
+           my_argv[i++] = dumptimestr;
+       }
 #ifdef ENABLE_GNUTAR_ATIME_PRESERVE
        /* --atime-preserve causes gnutar to call
         * utime() after reading files in order to
@@ -540,18 +577,16 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
            my_argv[i++] = ".";
        }
        my_argv[i++] = NULL;
-       dumppid = pipespawnv(cmd, STDIN_PIPE,
+       dumppid = pipespawnv(cmd, STDIN_PIPE, 0,
                             &dumpin, &dumpout, &mesgf, my_argv);
        tarpid = dumppid;
        amfree(file_exclude);
        amfree(file_include);
        amfree(my_argv);
     }
-    dbprintf(("%s: %s: pid %ld\n",
-             debug_prefix_time("-gnutar"),
-             cmd,
-             (long)dumppid));
+    dbprintf(_("gnutar: %s: pid %ld\n"), cmd, (long)dumppid);
 
+    amfree(qdisk);
     amfree(dirname);
     amfree(cmd);
     amfree(indexcmd);
@@ -564,37 +599,47 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
     aclose(compout);
     aclose(dataf);
     aclose(mesgf);
-    if (options->createindex)
+    if (dle->create_index)
        aclose(indexf);
 }
 
-static void end_backup(goterror)
-int goterror;
+static void
+end_backup(
+    dle_t      *dle,
+    int                goterror)
 {
-    if(!options->no_record && !goterror) {
-#ifdef GNUTAR_LISTED_INCREMENTAL_DIR
+    char *amandates_file = NULL;
+
+    if(dle->record && !goterror) {
        if (incrname != NULL && strlen(incrname) > 4) {
            char *nodotnew;
        
            nodotnew = stralloc(incrname);
            nodotnew[strlen(nodotnew)-4] = '\0';
            if (rename(incrname, nodotnew)) {
-               fprintf(stderr, "%s: warning [renaming %s to %s: %s]\n"
+               g_fprintf(stderr, _("%s: warning [renaming %s to %s: %s]\n")
                        get_pname(), incrname, nodotnew, strerror(errno));
            }
            amfree(nodotnew);
            amfree(incrname);
        }
-#endif
 
-        if(!start_amandates(1)) {
-           fprintf(stderr, "%s: warning [opening %s: %s]", get_pname(),
-                   AMANDATES_FILE, strerror(errno));
-       }
-       else {
+       /* update the amandates file */
+       amandates_file = getconf_str(CNF_AMANDATES);
+       if(start_amandates(amandates_file, 1)) {
            amandates_updateone(cur_disk, cur_level, cur_dumptime);
            finish_amandates();
            free_amandates();
+       } else {
+           /* failure is only fatal if we didn't get a gnutar-listdir */
+           char *gnutar_list_dir = getconf_str(CNF_GNUTAR_LIST_DIR);
+           if (!gnutar_list_dir || !*gnutar_list_dir) {
+               error(_("error [opening %s for writing: %s]"), amandates_file, strerror(errno));
+               /* NOTREACHED */
+           } else {
+               g_debug(_("non-fatal error opening '%s' for writing: %s]"),
+                       amandates_file, strerror(errno));
+           }
        }
     }
 }