Call delete_in_dir(NULL, NULL, NULL) in do_delete_pass().
[rsync/rsync.git] / util.c
diff --git a/util.c b/util.c
index 735173d..5864b5d 100644 (file)
--- a/util.c
+++ b/util.c
@@ -31,6 +31,7 @@ extern int verbose;
 extern int dry_run;
 extern int module_id;
 extern int modify_window;
+extern int relative_paths;
 extern char *partial_dir;
 extern struct filter_list_struct server_filter_list;
 
@@ -120,7 +121,7 @@ void out_of_memory(char *str)
        exit_cleanup(RERR_MALLOC);
 }
 
-void overflow(char *str)
+void overflow_exit(char *str)
 {
        rprintf(FERROR, "ERROR: buffer overflow in %s\n", str);
        exit_cleanup(RERR_MALLOC);
@@ -128,8 +129,13 @@ void overflow(char *str)
 
 
 
-int set_modtime(char *fname, time_t modtime)
+int set_modtime(char *fname, time_t modtime, mode_t mode)
 {
+#if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
+       if (S_ISLNK(mode))
+               return 1;
+#endif
+
        if (verbose > 2) {
                rprintf(FINFO, "set modtime of %s to (%ld) %s",
                        safe_fname(fname), (long)modtime,
@@ -140,7 +146,18 @@ int set_modtime(char *fname, time_t modtime)
                return 0;
 
        {
-#ifdef HAVE_UTIMBUF
+#ifdef HAVE_UTIMES
+               struct timeval t[2];
+               t[0].tv_sec = time(NULL);
+               t[0].tv_usec = 0;
+               t[1].tv_sec = modtime;
+               t[1].tv_usec = 0;
+# ifdef HAVE_LUTIMES
+               if (S_ISLNK(mode))
+                       return lutimes(fname, t);
+# endif
+               return utimes(fname, t);
+#elif defined HAVE_UTIMBUF
                struct utimbuf tbuf;
                tbuf.actime = time(NULL);
                tbuf.modtime = modtime;
@@ -151,12 +168,7 @@ int set_modtime(char *fname, time_t modtime)
                t[1] = modtime;
                return utime(fname,t);
 #else
-               struct timeval t[2];
-               t[0].tv_sec = time(NULL);
-               t[0].tv_usec = 0;
-               t[1].tv_sec = modtime;
-               t[1].tv_usec = 0;
-               return utimes(fname,t);
+#error No file-time-modification routine found!
 #endif
        }
 }
@@ -517,7 +529,6 @@ static void glob_expand_one(char *s, char ***argv_ptr, int *argc_ptr,
        filter_server_path(s);
 #else
        glob_t globbuf;
-       int i;
 
        if (maxargs <= argc)
                return;
@@ -542,9 +553,9 @@ static void glob_expand_one(char *s, char ***argv_ptr, int *argc_ptr,
        if (globbuf.gl_pathc == 0)
                argv[argc++] = s;
        else {
-               int j = globbuf.gl_pathc;
+               int i;
                free(s);
-               for (i = 0; i < j; i++) {
+               for (i = 0; i < (int)globbuf.gl_pathc; i++) {
                        if (!(argv[argc++] = strdup(globbuf.gl_pathv[i])))
                                out_of_memory("glob_expand_one");
                }
@@ -745,7 +756,7 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
 char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth)
 {
        char *start, *sanp;
-       int rlen = 0;
+       int rlen = 0, leave_one_dotdir = relative_paths;
 
        if (dest != p) {
                int plen = strlen(p);
@@ -780,9 +791,13 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth)
                 * always be left pointing after a slash
                 */
                if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
-                       /* skip "." component */
-                       p++;
-                       continue;
+                       if (leave_one_dotdir && p[1])
+                               leave_one_dotdir = 0;
+                       else {
+                               /* skip "." component */
+                               p++;
+                               continue;
+                       }
                }
                if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
                        /* ".." component followed by slash or end */
@@ -877,12 +892,13 @@ int pop_dir(char *dir)
        return 1;
 }
 
-/* Return the filename, turning any non-printable characters into '?'s.
- * This ensures that outputting it on a line of its own cannot generate an
- * empty line.  This function can return only MAX_SAFE_NAMES values at a
- * time!  The returned value can be longer than MAXPATHLEN (because we
- * may be trying to output an error about a too-long filename)! */
-const char *safe_fname(const char *fname)
+/* Return the filename, turning any non-printable characters into escaped
+ * characters (e.g. \n -> \012, \ -> \\).  This ensures that outputting it
+ * cannot generate an empty line nor corrupt the screen.  This function can
+ * return only MAX_SAFE_NAMES values at a time!  The returned value can be
+ * longer than MAXPATHLEN (because we may be trying to output an error about
+ * a too-long filename)! */
+char *safe_fname(const char *fname)
 {
 #define MAX_SAFE_NAMES 4
        static char fbuf[MAX_SAFE_NAMES][MAXPATHLEN*2];
@@ -892,12 +908,21 @@ const char *safe_fname(const char *fname)
 
        ndx = (ndx + 1) % MAX_SAFE_NAMES;
        for (t = fbuf[ndx]; *fname; fname++) {
-               if (!isprint(*(uchar*)fname))
-                       *t++ = '?';
-               else
+               if (*fname == '\\') {
+                       if ((limit -= 2) < 0)
+                               break;
+                       *t++ = '\\';
+                       *t++ = '\\';
+               } else if (!isprint(*(uchar*)fname)) {
+                       if ((limit -= 4) < 0)
+                               break;
+                       sprintf(t, "\\%03o", *(uchar*)fname);
+                       t += 4;
+               } else {
+                       if (--limit < 0)
+                               break;
                        *t++ = *fname;
-               if (--limit == 0)
-                       break;
+               }
        }
        *t = '\0';
 
@@ -1251,11 +1276,11 @@ const char *find_filename_suffix(const char *fn, int fn_len, int *len_ptr)
                        break;
                s_len = fn_len - (s - fn);
                fn_len = s - fn;
-               if (s_len == 3) {
+               if (s_len == 4) {
                        if (strcmp(s+1, "bak") == 0
                         || strcmp(s+1, "old") == 0)
                                continue;
-               } else if (s_len == 4) {
+               } else if (s_len == 5) {
                        if (strcmp(s+1, "orig") == 0)
                                continue;
                } else if (s_len > 2 && had_tilde