--- embedaddon/rsync/util.c 2013/10/14 07:51:14 1.1.1.2 +++ embedaddon/rsync/util.c 2016/11/01 09:54:32 1.1.1.3 @@ -4,7 +4,7 @@ * Copyright (C) 1996-2000 Andrew Tridgell * Copyright (C) 1996 Paul Mackerras * Copyright (C) 2001, 2002 Martin Pool - * Copyright (C) 2003-2013 Wayne Davison + * Copyright (C) 2003-2015 Wayne Davison * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,7 @@ #include "itypes.h" #include "inums.h" +extern int dry_run; extern int module_id; extern int protect_args; extern int modify_window; @@ -189,7 +190,7 @@ int make_path(char *fname, int flags) if (flags & MKP_DROP_NAME) { end = strrchr(fname, '/'); - if (!end) + if (!end || end == fname) return 0; *end = '\0'; } else @@ -197,23 +198,35 @@ int make_path(char *fname, int flags) /* Try to find an existing dir, starting from the deepest dir. */ for (p = end; ; ) { - if (do_mkdir(fname, ACCESSPERMS) == 0) { + if (dry_run) { + STRUCT_STAT st; + if (do_stat(fname, &st) == 0) { + if (S_ISDIR(st.st_mode)) + errno = EEXIST; + else + errno = ENOTDIR; + } + } else if (do_mkdir(fname, ACCESSPERMS) == 0) { ret++; break; } + if (errno != ENOENT) { - if (errno != EEXIST) + STRUCT_STAT st; + if (errno != EEXIST || (do_stat(fname, &st) == 0 && !S_ISDIR(st.st_mode))) ret = -ret - 1; break; } while (1) { if (p == fname) { - ret = -ret - 1; + /* We got a relative path that doesn't exist, so assume that '.' + * is there and just break out and create the whole thing. */ + p = NULL; goto double_break; } if (*--p == '/') { if (p == fname) { - ret = -ret - 1; /* impossible... */ + /* We reached the "/" dir, which we assume is there. */ goto double_break; } *p = '\0'; @@ -225,7 +238,10 @@ int make_path(char *fname, int flags) /* Make all the dirs that we didn't find on the way here. */ while (p != end) { - *p = '/'; + if (p) + *p = '/'; + else + p = fname; p += strlen(p); if (ret < 0) /* Skip mkdir on error, but keep restoring the path. */ continue; @@ -858,7 +874,7 @@ int count_dir_elements(const char *p) * CFN_KEEP_TRAILING_SLASH is flagged, and will also collapse ".." elements * (except at the start) if CFN_COLLAPSE_DOT_DOT_DIRS is flagged. If the * resulting name would be empty, returns ".". */ -unsigned int clean_fname(char *name, int flags) +int clean_fname(char *name, int flags) { char *limit = name - 1, *t = name, *f = name; int anchored; @@ -866,6 +882,8 @@ unsigned int clean_fname(char *name, int flags) if (!name) return 0; +#define DOT_IS_DOT_DOT_DIR(bp) (bp[1] == '.' && (bp[2] == '/' || !bp[2])) + if ((anchored = *f == '/') != 0) { *t++ = *f++; #ifdef __CYGWIN__ @@ -878,7 +896,8 @@ unsigned int clean_fname(char *name, int flags) } else if (flags & CFN_KEEP_DOT_DIRS && *f == '.' && f[1] == '/') { *t++ = *f++; *t++ = *f++; - } + } else if (flags & CFN_REFUSE_DOT_DOT_DIRS && *f == '.' && DOT_IS_DOT_DOT_DIR(f)) + return -1; while (*f) { /* discard extra slashes */ if (*f == '/') { @@ -894,9 +913,10 @@ unsigned int clean_fname(char *name, int flags) if (f[1] == '\0' && flags & CFN_DROP_TRAILING_DOT_DIR) break; /* collapse ".." dirs */ - if (flags & CFN_COLLAPSE_DOT_DOT_DIRS - && f[1] == '.' && (f[2] == '/' || !f[2])) { + if (flags & (CFN_COLLAPSE_DOT_DOT_DIRS|CFN_REFUSE_DOT_DOT_DIRS) && DOT_IS_DOT_DOT_DIR(f)) { char *s = t - 1; + if (flags & CFN_REFUSE_DOT_DOT_DIRS) + return -1; if (s == name && anchored) { f += 2; continue; @@ -919,6 +939,8 @@ unsigned int clean_fname(char *name, int flags) *t++ = '.'; *t = '\0'; +#undef DOT_IS_DOT_DOT_DIR + return t - name; } @@ -1305,16 +1327,17 @@ char *timestring(time_t t) int cmp_time(time_t file1, time_t file2) { if (file2 > file1) { - if (file2 - file1 <= modify_window) - return 0; - return -1; + /* The final comparison makes sure that modify_window doesn't overflow a + * time_t, which would mean that file2 must be in the equality window. */ + if (!modify_window || (file2 > file1 + modify_window && file1 + modify_window > file1)) + return -1; + } else if (file1 > file2) { + if (!modify_window || (file1 > file2 + modify_window && file2 + modify_window > file2)) + return 1; } - if (file1 - file2 <= modify_window) - return 0; - return 1; + return 0; } - #ifdef __INSURE__XX #include @@ -1582,6 +1605,14 @@ int flist_ndx_pop(flist_ndx_list *lp) return ndx; } +/* Make sure there is room for one more item in the item list. If there + * is not, expand the list as indicated by the value of "incr": + * - if incr < 0 then increase the malloced size by -1 * incr + * - if incr >= 0 then either make the malloced size equal to "incr" + * or (if that's not large enough) double the malloced size + * After the size check, the list's count is incremented by 1 and a pointer + * to the "new" list item is returned. + */ void *expand_item_list(item_list *lp, size_t item_size, const char *desc, int incr) { @@ -1592,10 +1623,12 @@ void *expand_item_list(item_list *lp, size_t item_size if (incr < 0) new_size += -incr; /* increase slowly */ else if (new_size < (size_t)incr) - new_size += incr; - else + new_size = incr; + else if (new_size) new_size *= 2; - if (new_size < lp->malloced) + else + new_size = 1; + if (new_size <= lp->malloced) overflow_exit("expand_item_list"); /* Using _realloc_array() lets us pass the size, not a type. */ new_ptr = _realloc_array(lp->items, item_size, new_size);