X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/f8be5ef4cb86bee9227b14b41238ac867c820759..d1be231290b3867648ee417fad341fdf1caaa94b:/util.c diff --git a/util.c b/util.c index 7be0be30..7a4fbb8b 100644 --- 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); } @@ -358,31 +358,6 @@ void kill_all(int sig) } } -/* like strncpy but does not 0 fill the buffer and always null - terminates (thus it can use maxlen+1 space in d) */ -void strlcpy(char *d, char *s, int maxlen) -{ - int len = strlen(s); - if (len > maxlen) len = maxlen; - memcpy(d, s, len); - d[len] = 0; -} - -/* like strncat but does not 0 fill the buffer and always null - terminates (thus it can use maxlen+1 space in d) */ -void strlcat(char *d, char *s, int maxlen) -{ - int len1 = strlen(d); - int len2 = strlen(s); - if (len1+len2 > maxlen) { - len2 = maxlen-len1; - } - if (len2 > 0) { - memcpy(d+len1, s, len2); - d[len1+len2] = 0; - } -} - /* turn a user name into a uid */ int name_to_uid(char *name, uid_t *uid) { @@ -425,7 +400,7 @@ int lock_range(int fd, int offset, int len) } -static void glob_expand_one(char *s, char **argv, int *argc, int maxargs) +static void glob_expand_one(char *s, char **argv, int *argc, int maxargs, int sanitize_paths) { #if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H)) if (!*s) s = "."; @@ -438,7 +413,7 @@ static void glob_expand_one(char *s, char **argv, int *argc, int maxargs) if (!*s) s = "."; - argv[*argc] = strdup(s); + argv[*argc] = sanitize_paths ? sanitize_path(s) : strdup(s); memset(&globbuf, 0, sizeof(globbuf)); glob(argv[*argc], 0, NULL, &globbuf); @@ -457,7 +432,7 @@ static void glob_expand_one(char *s, char **argv, int *argc, int maxargs) #endif } -void glob_expand(char *base1, char **argv, int *argc, int maxargs) +void glob_expand(char *base1, char **argv, int *argc, int maxargs, int sanitize_paths) { char *s = argv[*argc]; char *p, *q; @@ -481,11 +456,11 @@ void glob_expand(char *base1, char **argv, int *argc, int maxargs) while ((p = strstr(q,base)) && ((*argc) < maxargs)) { /* split it at this point */ *p = 0; - glob_expand_one(q, argv, argc, maxargs); + glob_expand_one(q, argv, argc, maxargs, sanitize_paths); q = p+strlen(base); } - if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs); + if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs, sanitize_paths); free(s); free(base); @@ -502,14 +477,13 @@ void strlower(char *s) } } -/* this is like vsnprintf but the 'n' limit does not include - the terminating null. So if you have a 1024 byte buffer then - pass 1023 for n */ +/* this is like vsnprintf but it always null terminates, so you + can fit at most n-1 chars in */ int vslprintf(char *str, int n, const char *format, va_list ap) { int ret = vsnprintf(str, n, format, ap); - if (ret > n || ret < 0) { - str[n] = 0; + if (ret >= n || ret < 0) { + str[n-1] = 0; return -1; } str[ret] = 0; @@ -579,6 +553,75 @@ void clean_fname(char *name) } } +/* + * 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 "/.." (recursively) + * While we're at it, remove double slashes and "." components like + * clean_fname does(), but DON'T remove a trailing slash because that + * is sometimes significant on command line arguments. + * Return a malloc'ed copy. + * Contributed by Dave Dykstra + */ + +char *sanitize_path(char *p) +{ + char *copy, *copyp; + + copy = (char *) malloc(strlen(p)+1); + copyp = copy; + while (*p == '/') { + /* remove leading slashes */ + p++; + } + while (*p != '\0') { + /* this loop iterates once per filename component in p. + * both p (and copyp if the original had a slash) should + * always be left pointing after a slash + */ + if ((*p == '.') && ((*(p+1) == '/') || (*(p+1) == '\0'))) { + /* skip "." component */ + while (*++p == '/') { + /* skip following slashes */ + ; + } + } else if ((*p == '.') && (*(p+1) == '.') && + ((*(p+2) == '/') || (*(p+2) == '\0'))) { + /* skip ".." component followed by slash or end */ + p += 2; + if (*p == '/') + p++; + if (copyp != copy) { + /* back up the copy one level */ + --copyp; /* now pointing at slash */ + while ((copyp > copy) && (*(copyp - 1) != '/')) { + /* skip back up to slash */ + copyp--; + } + } + } else { + while (1) { + /* copy one component through next slash */ + *copyp++ = *p++; + if ((*p == '\0') || (*(p-1) == '/')) { + while (*p == '/') { + /* skip multiple slashes */ + p++; + } + break; + } + } + } + } + if (copyp == copy) { + /* ended up with nothing, so put in "." component */ + *copyp++ = '.'; + } + *copyp = '\0'; + return(copy); +} + static char curr_dir[MAXPATHLEN]; @@ -601,10 +644,10 @@ char *push_dir(char *dir, int save) } if (*dir == '/') { - strlcpy(curr_dir, dir, sizeof(curr_dir)-1); + strlcpy(curr_dir, dir, sizeof(curr_dir)); } else { - strlcat(curr_dir,"/", sizeof(curr_dir)-1); - strlcat(curr_dir,dir, sizeof(curr_dir)-1); + strlcat(curr_dir,"/", sizeof(curr_dir)); + strlcat(curr_dir,dir, sizeof(curr_dir)); } clean_fname(curr_dir); @@ -623,7 +666,7 @@ int pop_dir(char *dir) return ret; } - strlcpy(curr_dir, dir, sizeof(curr_dir)-1); + strlcpy(curr_dir, dir, sizeof(curr_dir)); free(dir); @@ -634,8 +677,8 @@ int pop_dir(char *dir) to ensure that signed/unsigned usage is consistent between machines. */ int u_strcmp(const char *cs1, const char *cs2) { - const uchar *s1 = (uchar *)cs1; - const uchar *s2 = (uchar *)cs2; + const uchar *s1 = (const uchar *)cs1; + const uchar *s2 = (const uchar *)cs2; while (*s1 && *s2 && (*s1 == *s2)) { s1++; s2++; @@ -716,49 +759,25 @@ int unsafe_symlink(char *dest, char *src) 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 "/.." (recursively) - * Return a malloc'ed copy. - * Contributed by Dave Dykstra - */ -char *sanitize_path(char *p) +/**************************************************************************** + return the date and time as a string +****************************************************************************/ +char *timestring(time_t t) { - char *copy, *copyp; + static char TimeBuf[200]; + struct tm *tm = localtime(&t); - 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; - } - } +#ifdef HAVE_STRFTIME + strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm); +#else + strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf)); +#endif + + if (TimeBuf[strlen(TimeBuf)-1] == '\n') { + TimeBuf[strlen(TimeBuf)-1] = 0; } - *copyp = '\0'; - return(copy); + + return(TimeBuf); }