Imported Upstream version 2.6.0
[debian/amanda] / client-src / sendbackup-gnutar.c
index 666796e2bcc4eff097783acc607fba8579128ffb..c11b55c5a65947ea1984fba7b4ab7274c3f7aa54 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /* 
- * $Id: sendbackup-gnutar.c,v 1.56.2.15.4.4.2.11.2.2 2005/06/23 08:46:07 weichinger 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
 
-#ifdef KRB4_SECURITY
-#include "sendbackup-krb4.h"
-#else                                  /* I'd tell you what this does */
-#define NAUGHTY_BITS                   /* but then I'd have to kill you */
-#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"),
 
@@ -125,21 +118,31 @@ static regex_t re_table[] = {
   AM_STRANGE_RE(NULL)
 };
 
+extern char *efile;
+
 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
-
-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 char *amandates_file;
+/*
+ *  doing similar to $ gtar | compression | encryption 
+ */
+static void
+start_backup(
+    char *     host,
+    char *     disk,
+    char *     amdevice,
+    int                level,
+    char *     dumpdate,
+    int                dataf,
+    int                mesgf,
+    int                indexf)
 {
-    int dumpin, dumpout;
+    char tmppath[PATH_MAX];
+    int dumpin, dumpout, compout;
     char *cmd = NULL;
     char *indexcmd = NULL;
     char *dirname = NULL;
@@ -149,141 +152,180 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
     amandates_t *amdates;
     time_t prev_dumptime;
     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];
 
-    error_pn = stralloc2(get_pname(), "-smbclient");
+    (void)dumpdate;    /* Quiet unused parameter warning */
 
-    fprintf(stderr, "%s: start [%s:%s level %d]\n",
-           get_pname(), host, disk, level);
+    error_pn = stralloc2(get_pname(), "-smbclient");
 
-    NAUGHTY_BITS;
+    qdisk = quote_string(disk);
+    dbprintf(_("start: %s:%s lev %d\n"), host, qdisk, level);
 
-    if(options->compress == COMPR_FAST || options->compress == COMPR_BEST) {
-       char *compopt = skip_argument;
+    g_fprintf(stderr, _("%s: start [%s:%s level %d]\n"),
+           get_pname(), host, qdisk, level);
 
+     /*  apply client-side encryption here */
+     if ( options->encrypt == ENCRYPT_CUST ) {
+         encpid = pipespawn(options->clnt_encrypt, STDIN_PIPE,
+                       &compout, &dataf, &mesgf, 
+                       options->clnt_encrypt, encryptopt, NULL);
+         dbprintf(_("gnutar: pid %ld: %s\n"), (long)encpid, options->clnt_encrypt);
+    } else {
+       compout = dataf;
+       encpid = -1;
+    } 
+     /*  now do the client-side compression */
+    if(options->compress == COMP_FAST || options->compress == COMP_BEST) {
+          compopt = skip_argument;
 #if defined(COMPRESS_BEST_OPT) && defined(COMPRESS_FAST_OPT)
-       if(options->compress == COMPR_BEST) {
+       if(options->compress == COMP_BEST) {
            compopt = COMPRESS_BEST_OPT;
        } else {
            compopt = COMPRESS_FAST_OPT;
        }
 #endif
        comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE,
-                           &dumpout, &dataf, &mesgf,
+                           &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);
+       }
+     } else if (options->compress == COMP_CUST) {
+        compopt = skip_argument;
+       comppid = pipespawn(options->clntcompprog, STDIN_PIPE,
+                           &dumpout, &compout, &mesgf,
+                           options->clntcompprog, compopt, NULL);
+       if(compopt != skip_argument) {
+           dbprintf(_("pid %ld: %s %s\n"),
+                    (long)comppid, options->clntcompprog, compopt);
+       } else {
+           dbprintf(_("pid %ld: %s\n"), (long)comppid, options->clntcompprog);
        }
-       dbprintf(("\n"));
     } else {
-       dumpout = dataf;
+       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]=='/')
        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(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);
 
-       ap_snprintf(number, sizeof(number), "%d", level);
+       g_snprintf(number, SIZEOF(number), "%d", level);
        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) {
+       infd = -1;
+       while (infd == -1) {
            if (--baselevel >= 0) {
-               ap_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 (fullwrite(outfd, &buf, (size_t)nb) < 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"),
+                    level, fquoted, tquoted);
+           amfree(fquoted);
+       } else {
+           dbprintf(_("doing level %d dump as listed-incremental to '%s'\n"),
+                    level, tquoted);
        }
-       dbprintf((" to %s\n", incrname));
+       amfree(tquoted);
        amfree(inputname);
        amfree(basename);
     }
-#endif                                                                 /* } */
 
     /* find previous dump time */
 
-    if(!start_amandates(0))
-       error("error [opening %s: %s]", AMANDATES_FILE, strerror(errno));
+    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);
 
@@ -297,25 +339,26 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
     free_amandates();
 
     gmtm = gmtime(&prev_dumptime);
-    ap_snprintf(dumptimestr, sizeof(dumptimestr),
+    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 date: %s\n"),
+             level, dumptimestr);
 
     dirname = amname_to_dirname(amdevice);
 
     cur_dumptime = time(0);
     cur_level = level;
     cur_disk = stralloc(disk);
-    indexcmd = vstralloc(
 #ifdef GNUTAR
-                        GNUTAR,
+#  define PROGRAM_GNUTAR GNUTAR
 #else
-                        "tar",
+#  define PROGRAM_GNUTAR "tar"
 #endif
+    indexcmd = vstralloc(
+                        PROGRAM_GNUTAR,
                         " -tf", " -",
                         " 2>/dev/null",
                         " | sed", " -e",
@@ -327,27 +370,29 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
     if (amdevice[0] == '/' && amdevice[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);
        if (!share) {
-            amfree(share);
-            amfree(subdir);
-            set_pname(error_pn);
-            amfree(error_pn);
-            error("cannot parse disk entry '%s' for share/subdir", disk);
+           amfree(share);
+           amfree(subdir);
+           set_pname(error_pn);
+           amfree(error_pn);
+           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);
+           amfree(share);
+           amfree(subdir);
+           set_pname(error_pn);
+           amfree(error_pn);
+           error(_("subdirectory specified for share %s but samba not v2 or better"), qdisk);
+           /*NOTREACHED*/
        }
        if ((user_and_password = findpass(share, &domain)) == NULL) {
            if(domain) {
@@ -356,7 +401,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) {
@@ -368,7 +414,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);
@@ -381,7 +428,8 @@ 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");
@@ -398,15 +446,15 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
            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);
-       write_tapeheader();
+       info_tapeheader();
 
        start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
 
@@ -446,7 +494,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);
@@ -457,8 +506,9 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
        amfree(taropt);
        tarpid = dumppid;
     } else
-#endif                                                                 /* } */
+#endif                 /*end of samba */
     {
+
        int nb_exclude = 0;
        int nb_include = 0;
        char **my_argv;
@@ -474,28 +524,38 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
        if(nb_exclude > 0) file_exclude = build_exclude(disk, amdevice, options, 0);
        if(nb_include > 0) file_include = build_include(disk, amdevice, options, 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);
-       write_tapeheader();
+       cmd = vstralloc(amlibexecdir, "/", "runtar", versionsuffix(), NULL);
+       info_tapeheader();
 
        start_index(options->createindex, 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
@@ -528,11 +588,9 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
        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);
@@ -542,34 +600,34 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
 
     aclose(dumpin);
     aclose(dumpout);
+    aclose(compout);
     aclose(dataf);
     aclose(mesgf);
     if (options->createindex)
        aclose(indexf);
 }
 
-static void end_backup(goterror)
-int goterror;
+static void
+end_backup(
+    int                goterror)
 {
     if(!options->no_record && !goterror) {
-#ifdef GNUTAR_LISTED_INCREMENTAL_DIR
        if (incrname != NULL && strlen(incrname) > 4) {
            char *nodotnew;
        
            nodotnew = stralloc(incrname);
            nodotnew[strlen(nodotnew)-4] = '\0';
-           if (rename(incrname, nodotnew) != 0) {
-               fprintf(stderr, "%s: warning [renaming %s to %s: %s]\n",
+           if (rename(incrname, nodotnew)) {
+               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]\n", get_pname(),
-                   AMANDATES_FILE, strerror(errno));
+        if(!start_amandates(amandates_file, 1)) {
+           g_fprintf(stderr, _("%s: warning [opening %s: %s]"), get_pname(),
+                   amandates_file, strerror(errno));
        }
        else {
            amandates_updateone(cur_disk, cur_level, cur_dumptime);