Add support for optional ":PORT" in rsync URL.
[rsync/rsync.git] / util.c
diff --git a/util.c b/util.c
index 6e0fbab..001694b 100644 (file)
--- a/util.c
+++ b/util.c
@@ -61,14 +61,14 @@ int piped_child(char **command,int *f_in,int *f_out)
   if (pipe(to_child_pipe) < 0 ||
       pipe(from_child_pipe) < 0) {
     rprintf(FERROR,"pipe: %s\n",strerror(errno));
-    exit_cleanup(1);
+    exit_cleanup(RERR_IPC);
   }
 
 
   pid = do_fork();
   if (pid < 0) {
     rprintf(FERROR,"fork: %s\n",strerror(errno));
-    exit_cleanup(1);
+    exit_cleanup(RERR_IPC);
   }
 
   if (pid == 0)
@@ -79,7 +79,7 @@ int piped_child(char **command,int *f_in,int *f_out)
          close(from_child_pipe[0]) < 0 ||
          dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
        rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
-       exit_cleanup(1);
+       exit_cleanup(RERR_IPC);
       }
       if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
       if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
@@ -87,13 +87,13 @@ int piped_child(char **command,int *f_in,int *f_out)
       execvp(command[0], command);
       rprintf(FERROR,"Failed to exec %s : %s\n",
              command[0],strerror(errno));
-      exit_cleanup(1);
+      exit_cleanup(RERR_IPC);
     }
 
   if (close(from_child_pipe[1]) < 0 ||
       close(to_child_pipe[0]) < 0) {
     rprintf(FERROR,"Failed to close : %s\n",strerror(errno));   
-    exit_cleanup(1);
+    exit_cleanup(RERR_IPC);
   }
 
   *f_in = from_child_pipe[0];
@@ -114,14 +114,14 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
        if (pipe(to_child_pipe) < 0 ||
            pipe(from_child_pipe) < 0) {
                rprintf(FERROR,"pipe: %s\n",strerror(errno));
-               exit_cleanup(1);
+               exit_cleanup(RERR_IPC);
        }
 
 
        pid = do_fork();
        if (pid < 0) {
                rprintf(FERROR,"fork: %s\n",strerror(errno));
-               exit_cleanup(1);
+               exit_cleanup(RERR_IPC);
        }
 
        if (pid == 0) {
@@ -136,7 +136,7 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
                    close(from_child_pipe[0]) < 0 ||
                    dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
                        rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
-                       exit_cleanup(1);
+                       exit_cleanup(RERR_IPC);
                }
                if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
                if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
@@ -146,7 +146,7 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
        if (close(from_child_pipe[1]) < 0 ||
            close(to_child_pipe[0]) < 0) {
                rprintf(FERROR,"Failed to close : %s\n",strerror(errno));   
-               exit_cleanup(1);
+               exit_cleanup(RERR_IPC);
        }
 
        *f_in = from_child_pipe[0];
@@ -160,13 +160,13 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
 void out_of_memory(char *str)
 {
   rprintf(FERROR,"ERROR: out of memory in %s\n",str);
-  exit_cleanup(1);
+  exit_cleanup(RERR_MALLOC);
 }
 
 void overflow(char *str)
 {
   rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
-  exit_cleanup(1);
+  exit_cleanup(RERR_MALLOC);
 }
 
 
@@ -507,7 +507,6 @@ void strlower(char *s)
    pass 1023 for n */
 int vslprintf(char *str, int n, const char *format, va_list ap)
 {
-#ifdef HAVE_VSNPRINTF
        int ret = vsnprintf(str, n, format, ap);
        if (ret > n || ret < 0) {
                str[n] = 0;
@@ -515,42 +514,6 @@ int vslprintf(char *str, int n, const char *format, va_list ap)
        }
        str[ret] = 0;
        return ret;
-#else
-       static char *buf;
-       static int len=MAXPATHLEN*8;
-       int ret;
-
-       /* this code is NOT a proper vsnprintf() implementation. It
-          relies on the fact that all calls to slprintf() in rsync
-          pass strings which have already been checked to be less
-          than MAXPATHLEN in length and never more than 2 strings are
-          concatenated. This means the above buffer is absolutely
-          ample and can never be overflowed.
-
-          In the future we would like to replace this with a proper
-          vsnprintf() implementation but right now we need a solution
-          that is secure and portable. This is it.  */
-
-       if (!buf) {
-               buf = malloc(len);
-               if (!buf) {
-                       /* can't call debug or we would recurse */
-                       exit_cleanup(1);
-               }
-       }
-
-       vsprintf(buf, format, ap);
-       ret = strlen(buf);
-       if (ret > n) {
-               /* yikes! */
-               exit_cleanup(1);
-       }
-       buf[ret] = 0;
-       
-       memcpy(str, buf, ret+1);
-
-       return ret;
-#endif
 }
 
 
@@ -752,3 +715,72 @@ int unsafe_symlink(char *dest, char *src)
        free(dest);
        return (depth < 0);
 }
+
+/*
+ * Make path appear as if a chroot had occurred:
+ *    1. remove leading "/" (or replace with "." if at end)
+ *    2. remove leading ".." components
+ *    3. delete any other "<dir>/.." (recursively)
+ * Return a malloc'ed copy.
+ * Contributed by Dave Dykstra <dwd@bell-labs.com>
+ */
+
+char *sanitize_path(char *p)
+{
+       char *copy, *copyp;
+
+       copy = (char *) malloc(strlen(p)+1);
+       copyp = copy;
+       while (*p != '\0') {
+               if ((*p == '/') && (copyp == copy)) {
+                       /* remove leading slash */
+                       p++;
+               }
+               else if ((*p == '.') && (*(p+1) == '.') &&
+                           ((*(p+2) == '/') || (*(p+2) == '\0'))) {
+                       /* remove .. followed by slash or end */
+                       p += 2;
+                       if (copyp != copy) {
+                               /* backup the copy one level */
+                               while ((--copyp != copy) && (*copyp == '/'))
+                                       /* skip trailing slashes */
+                                       ;
+                               while ((copyp != copy) && (*copyp != '/'))
+                                       /* skip back through slash */
+                                       copyp--;
+                       }
+               } else {
+                       /* copy one component */
+                       while (1) {
+                               *copyp++ = *p++;
+                               if ((*p == '\0') || (*(p-1) == '/'))
+                                       break;
+                       }
+               }
+       }
+       *copyp = '\0';
+       return(copy);
+}
+
+
+/****************************************************************************
+  return the date and time as a string
+****************************************************************************/
+char *timestring(time_t t)
+{
+       static char TimeBuf[200];
+       struct tm *tm = localtime(&t);
+
+#ifdef HAVE_STRFTIME
+       strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
+#else
+       strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf)-1);
+#endif
+
+       if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
+               TimeBuf[strlen(TimeBuf)-1] = 0;
+       }
+
+       return(TimeBuf);
+}
+