preparing for release of 2.1.1
[rsync/rsync.git] / util.c
diff --git a/util.c b/util.c
index 639a4a4..6e0fbab 100644 (file)
--- a/util.c
+++ b/util.c
@@ -98,6 +98,9 @@ int piped_child(char **command,int *f_in,int *f_out)
 
   *f_in = from_child_pipe[0];
   *f_out = to_child_pipe[1];
+
+  set_nonblocking(*f_in);
+  set_nonblocking(*f_out);
   
   return pid;
 }
@@ -250,7 +253,7 @@ static int full_write(int desc, char *ptr, int len)
    for an error.  
 
    derived from GNU C's cccp.c. */
-int safe_read(int desc, char *ptr, int len)
+static int safe_read(int desc, char *ptr, int len)
 {
        int n_chars;
  
@@ -291,7 +294,7 @@ int copy_file(char *source, char *dest, mode_t mode)
        }
 
        ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
-       if (ofd < 0) {
+       if (ofd == -1) {
                rprintf(FERROR,"open %s: %s\n",
                        dest,strerror(errno));
                close(ifd);
@@ -407,14 +410,6 @@ int name_to_gid(char *name, gid_t *gid)
 }
 
 
-/****************************************************************************
-check if a process exists. 
-****************************************************************************/
-int process_exists(int pid)
-{
-       return(kill(pid,0) == 0 || errno != ESRCH);
-}
-
 /* lock a byte range in a open file */
 int lock_range(int fd, int offset, int len)
 {
@@ -432,7 +427,7 @@ int lock_range(int fd, int offset, int len)
 
 static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
 {
-#ifndef HAVE_GLOB
+#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
        if (!*s) s = ".";
        argv[*argc] = strdup(s);
        (*argc)++;
@@ -685,3 +680,75 @@ int u_strcmp(const char *cs1, const char *cs2)
        
        return (int)*s1 - (int)*s2;
 }
+
+static OFF_T last_ofs;
+
+void end_progress(void)
+{
+       extern int do_progress, am_server;
+
+       if (do_progress && !am_server) {
+               rprintf(FINFO,"\n");
+       }
+       last_ofs = 0;
+}
+
+void show_progress(OFF_T ofs, OFF_T size)
+{
+       extern int do_progress, am_server;
+
+       if (do_progress && !am_server) {
+               if (ofs > last_ofs + 1000) {
+                       int pct = (int)((100.0*ofs)/size);
+                       rprintf(FINFO,"%.0f (%d%%)\r", (double)ofs, pct);
+                       last_ofs = ofs;
+               }
+       }
+}
+
+/* determine if a symlink points outside the current directory tree */
+int unsafe_symlink(char *dest, char *src)
+{
+       char *tok;
+       int depth = 0;
+
+       /* all absolute and null symlinks are unsafe */
+       if (!dest || !(*dest) || (*dest == '/')) return 1;
+
+       src = strdup(src);
+       if (!src) out_of_memory("unsafe_symlink");
+
+       /* find out what our safety margin is */
+       for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) {
+               if (strcmp(tok,"..") == 0) {
+                       depth=0;
+               } else if (strcmp(tok,".") == 0) {
+                       /* nothing */
+               } else {
+                       depth++;
+               }
+       }
+       free(src);
+
+       /* drop by one to account for the filename portion */
+       depth--;
+
+       dest = strdup(dest);
+       if (!dest) out_of_memory("unsafe_symlink");
+
+       for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) {
+               if (strcmp(tok,"..") == 0) {
+                       depth--;
+               } else if (strcmp(tok,".") == 0) {
+                       /* nothing */
+               } else {
+                       depth++;
+               }
+               /* if at any point we go outside the current directory then
+                  stop - it is unsafe */
+               if (depth < 0) break;
+       }
+
+       free(dest);
+       return (depth < 0);
+}