Get rid of global_opts struct as suggested by Dave -- too many
authorMartin Pool <mbp@samba.org>
Tue, 18 Dec 2001 05:54:57 +0000 (05:54 +0000)
committerMartin Pool <mbp@samba.org>
Tue, 18 Dec 2001 05:54:57 +0000 (05:54 +0000)
problems with initialization.

Change the algorithm from trying to open an inbound socket with
getaddrinfo: keep trying suggested addresses until we find one on
which we can both get a socket and bind.  Not convinced this is the
best, but it's probably better.

clientserver.c
options.c
socket.c

index 1b3801b..7389376 100644 (file)
@@ -45,6 +45,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
        extern char *shell_cmd;
        extern int kludge_around_eof;
        extern char *bind_address;
+       extern int default_af_hint;
        
        if (argc == 0 && !am_sender) {
                extern int list_only;
@@ -79,7 +80,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
        if (!user) user = getenv("LOGNAME");
 
        fd = open_socket_out_wrapped (host, rsync_port, bind_address,
-                                     global_opts.af_hint);
+                                     default_af_hint);
        if (fd == -1) {
                exit_cleanup(RERR_SOCKETIO);
        }
@@ -486,6 +487,7 @@ int daemon_main(void)
        extern char *config_file;
        extern int orig_umask;
        char *pid_file;
+       extern int no_detach;
 
        if (is_a_socket(STDIN_FILENO)) {
                int i;
@@ -501,7 +503,7 @@ int daemon_main(void)
                return start_daemon(STDIN_FILENO);
        }
 
-       if (!global_opts.no_detach)
+       if (!no_detach)
            become_daemon();
 
        if (!lp_load(config_file, 1)) {
index 9bb22f4..8893195 100644 (file)
--- a/options.c
+++ b/options.c
@@ -74,18 +74,21 @@ int modify_window=0;
 #endif
 int blocking_io=0;
 
-/** Global options set from command line. **/
-struct global_opts global_opts = {
+/** Network address family. **/
 #ifdef INET6
-       0,                      /* af_hint -- allow any protocol */
+int default_af_hint = 0;       /* Any protocol */
 #else
-       AF_INET,                /* af_hint -- prefer IPv4 */
+int default_af_hint = AF_INET; /* Must use IPv4 */
 #endif
-       0,                      /* no_detach */
-};
 
-int read_batch=0;  /* dw */
-int write_batch=0; /* dw */
+/** Do not go into the background when run as --daemon.  Good
+ * for debugging and required for running as a service on W32,
+ * or under Unix process-monitors. **/
+int no_detach = 0;
+
+
+int read_batch=0;
+int write_batch=0;
 
 char *backup_suffix = BACKUP_SUFFIX;
 char *tmpdir = NULL;
@@ -178,8 +181,8 @@ void usage(enum logcode F)
   rprintf(F,"     --backup-dir            make backups into this directory\n");
   rprintf(F,"     --suffix=SUFFIX         override backup suffix\n");  
   rprintf(F," -u, --update                update only (don't overwrite newer files)\n");
-  rprintf(F," -l, --links                 preserve soft links\n");
-  rprintf(F," -L, --copy-links            treat soft links like regular files\n");
+  rprintf(F," -l, --links                 copy symlinks as symlinks\n");
+  rprintf(F," -L, --copy-links            copy the referent of symlinks\n");
   rprintf(F,"     --copy-unsafe-links     copy links outside the source tree\n");
   rprintf(F,"     --safe-links            ignore links outside the destination tree\n");
   rprintf(F," -H, --hard-links            preserve hard links\n");
@@ -306,7 +309,7 @@ static struct poptOption long_options[] = {
   /* TODO: Should this take an optional int giving the compression level? */
   {"compress",        'z', POPT_ARG_NONE,   &do_compression},
   {"daemon",           0,  POPT_ARG_NONE,   &am_daemon},
-  {"no-detach",        0,  POPT_ARG_NONE,   &global_opts.no_detach},
+  {"no-detach",        0,  POPT_ARG_NONE,   &no_detach},
   {"stats",            0,  POPT_ARG_NONE,   &do_stats},
   {"progress",         0,  POPT_ARG_NONE,   &do_progress},
   {"partial",          0,  POPT_ARG_NONE,   &keep_partial},
@@ -323,8 +326,8 @@ static struct poptOption long_options[] = {
   {"read-batch",      'f', POPT_ARG_STRING, &batch_ext, 'f'},
   {"write-batch",     'F', POPT_ARG_NONE,   &write_batch, 0},
 #ifdef INET6
-  {0,                '4', POPT_ARG_VAL,    &global_opts.af_hint,   AF_INET },
-  {0,                '6', POPT_ARG_VAL,    &global_opts.af_hint,   AF_INET6 },
+  {0,                '4', POPT_ARG_VAL,    &default_af_hint,   AF_INET },
+  {0,                '6', POPT_ARG_VAL,    &default_af_hint,   AF_INET6 },
 #endif
   {0,0,0,0}
 };
index 0ad8a16..850cb14 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -267,7 +267,7 @@ static int open_socket_in(int type, int port, const char *bind_address,
 {
        int one=1;
        int s;
-       struct addrinfo hints, *res, *resp;
+       struct addrinfo hints, *all_ai, *resp;
        char portbuf[10];
        int error;
 
@@ -276,54 +276,43 @@ static int open_socket_in(int type, int port, const char *bind_address,
        hints.ai_socktype = type;
        hints.ai_flags = AI_PASSIVE;
        snprintf(portbuf, sizeof(portbuf), "%d", port);
-       error = getaddrinfo(bind_address, portbuf, &hints, &res);
+       error = getaddrinfo(bind_address, portbuf, &hints, &all_ai);
        if (error) {
                rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
                        bind_address, gai_strerror(error));
                return -1;
        }
-       /* XXX: Do we need to care about getting multiple results
-        * back?  I think probably not; if the user passed
-        * bind_address == NULL and we set AI_PASSIVE then we ought to
-        * get a wildcard result. */
 
-       resp = res;
-       while (1) {
-               s = socket(resp->ai_family, resp->ai_socktype, resp->ai_protocol);
-
-               if (s >= 0) {
-                       break;  /* got a socket */
-               } else if ((resp = resp->ai_next)) {
-                       switch (errno) {
-                       case EPROTONOSUPPORT:
-                       case EAFNOSUPPORT:
-                       case EPFNOSUPPORT:
-                       case EINVAL:
-                               /* See if there's another address that will work... */
-                               continue;
-                       }
+       /* We may not be able to create the socket, if for example the
+        * machine knows about IPv6 in the C library, but not in the
+        * kernel. */
+       for (resp = all_ai; resp; resp = resp->ai_next) {
+               s = socket(resp->ai_family, resp->ai_socktype,
+                          resp->ai_protocol);
+
+               if (s == -1) 
+                       /* See if there's another address that will work... */
+                       continue;
+               
+               setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+                          (char *)&one, sizeof one);
+               
+               /* now we've got a socket - we need to bind it */
+               if (bind(s, all_ai->ai_addr, all_ai->ai_addrlen) < 0) {
+                       /* Nope, try another */
+                       close(s);
+                       continue;
                }
                
-               rprintf(FERROR, RSYNC_NAME ": open inbound socket"
-                       "(dom=%d, type=%d, proto=%d) failed: %s\n",
-                       resp->ai_family, resp->ai_socktype, resp->ai_protocol,
-                       strerror(errno));
-                       goto fail;
+               return s;
        }
 
-       setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
-
-       /* now we've got a socket - we need to bind it */
-       if (bind(s, res->ai_addr, res->ai_addrlen) < 0) { 
-               rprintf(FERROR, RSYNC_NAME ": bind failed on port %d\n", port);
-               close(s);
-               goto fail;
-       }
-
-       return s;
+       rprintf(FERROR, RSYNC_NAME ": open inbound socket on port %d failed: "
+               "%s\n",
+               port, 
+               strerror(errno));
 
-fail:
-       freeaddrinfo(res);
+       freeaddrinfo(all_ai);
        return -1; 
 }
 
@@ -358,10 +347,10 @@ void start_accept_loop(int port, int (*fn)(int ))
 {
        int s;
        extern char *bind_address;
+       extern int default_af_hint;
 
        /* open an incoming socket */
-       s = open_socket_in(SOCK_STREAM, port, bind_address,
-                          global_opts.af_hint);
+       s = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
        if (s == -1)
                exit_cleanup(RERR_SOCKETIO);