X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/f8be5ef4cb86bee9227b14b41238ac867c820759..37f9805dabba76b7a00bd2a0227762f6f239b598:/util.c diff --git a/util.c b/util.c index 7be0be30..c5bb4a70 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); } @@ -359,28 +359,34 @@ 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) + terminates. bufsize is the size of the destination buffer */ +size_t strlcpy(char *d, const char *s, size_t bufsize) { - int len = strlen(s); - if (len > maxlen) len = maxlen; + size_t len = strlen(s); + size_t ret = len; + if (len >= bufsize) len = bufsize-1; memcpy(d, s, len); d[len] = 0; + return ret; } /* 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) + terminates. bufsize is the length of the buffer, which should + be one more than the maximum resulting string length */ +size_t strlcat(char *d, const char *s, size_t bufsize) { - int len1 = strlen(d); - int len2 = strlen(s); - if (len1+len2 > maxlen) { - len2 = maxlen-len1; + size_t len1 = strlen(d); + size_t len2 = strlen(s); + size_t ret = len1 + len2; + + if (len1+len2 >= bufsize) { + len2 = bufsize - (len1+1); } if (len2 > 0) { memcpy(d+len1, s, len2); d[len1+len2] = 0; } + return ret; } /* turn a user name into a uid */ @@ -502,14 +508,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 +584,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 "