+ Changed two buffers to use BIGPATHBUFLEN instead of MAXPATHLEN+512.
[rsync/rsync.git] / util.c
diff --git a/util.c b/util.c
index e99ede8..876b926 100644 (file)
--- a/util.c
+++ b/util.c
@@ -31,6 +31,8 @@ extern int verbose;
 extern int dry_run;
 extern int module_id;
 extern int modify_window;
+extern int relative_paths;
+extern int human_readable;
 extern char *partial_dir;
 extern struct filter_list_struct server_filter_list;
 
@@ -528,7 +530,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;
@@ -553,9 +554,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");
                }
@@ -756,7 +757,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);
@@ -791,9 +792,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 */
@@ -1114,6 +1119,63 @@ int unsafe_symlink(const char *dest, const char *src)
        return (depth < 0);
 }
 
+/* Return the int64 number as a string.  If the --human-readable option was
+ * specified, we may output the number in K, M, or G units.  We can return
+ * up to 4 buffers at a time. */
+char *human_num(int64 num)
+{
+       static char bufs[4][128]; /* more than enough room */
+       static unsigned int n;
+       char *s;
+
+       n = (n + 1) % (sizeof bufs / sizeof bufs[0]);
+
+       if (human_readable) {
+               char units = '\0';
+               int mult = human_readable == 1 ? 1024 : 1000;
+               double dnum = 0;
+               if (num > mult*mult*mult) {
+                       dnum = (double)num / (mult*mult*mult);
+                       units = 'G';
+               } else if (num > mult*mult) {
+                       dnum = (double)num / (mult*mult);
+                       units = 'M';
+               } else if (num > mult) {
+                       dnum = (double)num / mult;
+                       units = 'K';
+               }
+               if (units) {
+                       sprintf(bufs[n], "%.2f%c", dnum, units);
+                       return bufs[n];
+               }
+       }
+
+       s = bufs[n] + sizeof bufs[0] - 1;
+       *s = '\0';
+
+       if (!num)
+               *--s = '0';
+       while (num) {
+               *--s = (num % 10) + '0';
+               num /= 10;
+       }
+       return s;
+}
+
+/* Return the double number as a string.  If the --human-readable option was
+ * specified, we may output the number in K, M, or G units.  We use a buffer
+ * from human_num() to return our result. */
+char *human_dnum(double dnum, int decimal_digits)
+{
+       char *buf = human_num(dnum);
+       int len = strlen(buf);
+       if (isdigit(*(uchar*)(buf+len-1))) {
+               /* There's extra room in buf prior to the start of the num. */
+               buf -= decimal_digits + 1;
+               snprintf(buf, len + decimal_digits + 2, "%.*f", decimal_digits, dnum);
+       }
+       return buf;
+}
 
 /**
  * Return the date and time as a string