Imported Upstream version 3.3.3
[debian/amanda] / server-src / chunker.c
index bbf8676653fe4f2b747b5e93d8d7a93b2196a316..6f81ad2b1cd9ef12cfdcf24ee2d156a3fde131cb 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
  * Copyright (c) 1991-1999 University of Maryland at College Park
+ * Copyright (c) 2007-2012 Zmanda, Inc.  All Rights Reserved.
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -43,6 +44,7 @@
 #include "util.h"
 #include "holding.h"
 #include "timestamp.h"
+#include "sockaddr-util.h"
 
 #ifndef SEEK_SET
 #define SEEK_SET 0
@@ -96,8 +98,8 @@ static ssize_t write_tapeheader(int, dumpfile_t *);
 static void databuf_init(struct databuf *, int, char *, off_t, off_t);
 static int databuf_flush(struct databuf *);
 
-static int startup_chunker(char *, off_t, off_t, struct databuf *, int *);
-static int do_chunk(int, struct databuf *, int);
+static int startup_chunker(char *, off_t, off_t, struct databuf *, int *, int *);
+static int do_chunk(int, struct databuf *, int, int);
 
 /* we use a function pointer for full_write, so that we can "shim" in
  * full_write_with_fake_enospc for testing */
@@ -122,6 +124,7 @@ main(
     config_overrides_t *cfg_ovr = NULL;
     char *cfg_opt = NULL;
     char *m;
+    int header_socket;
     int data_socket;
 
     /*
@@ -307,13 +310,13 @@ main(
            }
 
            if ((header_fd = startup_chunker(filename, use, chunksize, &db,
-                                            &data_socket)) < 0) {
+                                            &header_socket, &data_socket)) < 0) {
                q = quote_string(vstrallocf(_("[chunker startup failed: %s]"), errstr));
                putresult(TRYAGAIN, "%s %s\n", handle, q);
                error("startup_chunker failed: %s", errstr);
            }
            command_in_transit = NULL;
-           if (header_fd >= 0 && do_chunk(header_fd, &db, data_socket)) {
+           if (header_fd >= 0 && do_chunk(header_fd, &db, header_socket, data_socket)) {
                char kb_str[NUM_STR_SIZE];
                char kps_str[NUM_STR_SIZE];
                double rt;
@@ -430,6 +433,7 @@ startup_chunker(
     off_t              use,
     off_t              chunksize,
     struct databuf *   db,
+    int                *headersocket,
     int                *datasocket)
 {
     int header_fd, outfd;
@@ -438,6 +442,9 @@ startup_chunker(
     int header_socket, data_socket;
     int result;
     struct addrinfo *res;
+    struct addrinfo *res_addr;
+    sockaddr_union  *addr = NULL;
+    sockaddr_union   data_addr;
 
     header_port = 0;
     data_port = 0;
@@ -446,10 +453,26 @@ startup_chunker(
                               gai_strerror(result));
        return -1;
     }
-    header_socket = stream_server(res->ai_family, &header_port, 0,
+    for (res_addr = res; res_addr != NULL; res_addr = res_addr->ai_next) {
+       g_debug("ra: %s\n", str_sockaddr((sockaddr_union*)res_addr->ai_addr));
+       if (res_addr->ai_family == AF_INET) {
+           addr = (sockaddr_union *)res_addr->ai_addr;
+           break;
+       }
+    }
+    if (!addr) {
+       addr = (sockaddr_union *)res->ai_addr;
+       g_debug("addr: %s\n", str_sockaddr(addr));
+    }
+
+    header_socket = stream_server(SU_GET_FAMILY(addr), &header_port, 0,
                                STREAM_BUFSIZE, 0);
-    data_socket = stream_server(res->ai_family, &data_port, 0,
+    data_socket = stream_server(SU_GET_FAMILY(addr), &data_port, 0,
                                STREAM_BUFSIZE, 0);
+    copy_sockaddr(&data_addr, addr);
+
+    SU_SET_PORT(&data_addr, data_port);
+
     if (res) freeaddrinfo(res);
 
     if (header_socket < 0) {
@@ -464,7 +487,7 @@ startup_chunker(
        return -1;
     }
 
-    putresult(PORT, "%d 127.0.0.1:%d\n", header_port, data_port);
+    putresult(PORT, "%d %s\n", header_port, str_sockaddr(&data_addr));
 
     header_fd = stream_accept(header_socket, CONNECT_TIMEOUT, 0,
                              STREAM_BUFSIZE);
@@ -475,7 +498,6 @@ startup_chunker(
        aclose(data_socket);
        return -1;
     }
-    aclose(header_socket);
 
     tmp_filename = vstralloc(filename, ".tmp", NULL);
     pc = strrchr(tmp_filename, '/');
@@ -505,6 +527,7 @@ startup_chunker(
     amfree(tmp_filename);
     databuf_init(db, outfd, filename, use, chunksize);
     db->filename_seq++;
+    *headersocket = header_socket;
     *datasocket = data_socket;
     return header_fd;
 }
@@ -513,6 +536,7 @@ static int
 do_chunk(
     int                        header_fd,
     struct databuf *   db,
+    int                 header_socket,
     int                 data_socket)
 {
     size_t nread;
@@ -531,6 +555,8 @@ do_chunk(
      * chunk code will rewrite it.
      */
     nread = full_read(header_fd, header_buf, SIZEOF(header_buf));
+    aclose(header_fd);
+    aclose(header_socket);
     if (nread != sizeof(header_buf)) {
        if(errno != 0) {
            errstr = vstrallocf(_("cannot read header: %s"), strerror(errno));
@@ -568,7 +594,6 @@ do_chunk(
        aclose(data_socket);
        return 0;
     }
-    aclose(data_socket);
 
     /*
      * We've written the file header.  Now, just write data until the
@@ -579,12 +604,16 @@ do_chunk(
        db->datain += nread;
        while(db->dataout < db->datain) {
            if(!databuf_flush(db)) {
+               aclose(data_fd);
+               aclose(data_socket);
                return 0;
            }
        }
     }
     while(db->dataout < db->datain) {
        if(!databuf_flush(db)) {
+           aclose(data_fd);
+           aclose(data_socket);
            return 0;
        }
     }
@@ -592,6 +621,8 @@ do_chunk(
        dumpsize += (off_t)1;                   /* count partial final KByte */
        filesize += (off_t)1;
     }
+    aclose(data_fd);
+    aclose(data_socket);
     return 1;
 }