X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/eb86d661d79f25c91788964a768b54223717e8f6..37863201ad549b11ce70ecfb1e348165637f2e44:/util.c diff --git a/util.c b/util.c index 34c8f8b0..70743a66 100644 --- a/util.c +++ b/util.c @@ -98,6 +98,9 @@ int piped_child(char **command,int *f_in,int *f_out) *f_in = from_child_pipe[0]; *f_out = to_child_pipe[1]; + + set_nonblocking(*f_in); + set_nonblocking(*f_out); return pid; } @@ -291,7 +294,7 @@ int copy_file(char *source, char *dest, mode_t mode) } ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode); - if (ofd < 0) { + if (ofd == -1) { rprintf(FERROR,"open %s: %s\n", dest,strerror(errno)); close(ifd); @@ -686,7 +689,7 @@ int u_strcmp(const char *cs1, const char *cs2) return (int)*s1 - (int)*s2; } -static int last_pct = -1; +static OFF_T last_ofs; void end_progress(void) { @@ -695,7 +698,7 @@ void end_progress(void) if (do_progress && !am_server) { rprintf(FINFO,"\n"); } - last_pct = -1; + last_ofs = 0; } void show_progress(OFF_T ofs, OFF_T size) @@ -703,10 +706,57 @@ void show_progress(OFF_T ofs, OFF_T size) extern int do_progress, am_server; if (do_progress && !am_server) { - int pct = (int)((100.0*ofs)/size + 0.5); - if (pct != last_pct) { + if (ofs > last_ofs + 1000) { + int pct = (int)((100.0*ofs)/size); rprintf(FINFO,"%.0f (%d%%)\r", (double)ofs, pct); - last_pct = pct; + last_ofs = ofs; + } + } +} + +/* determine if a symlink points outside the current directory tree */ +int unsafe_symlink(char *dest, char *src) +{ + char *tok; + int depth = 0; + + /* all absolute and null symlinks are unsafe */ + if (!dest || !(*dest) || (*dest == '/')) return 1; + + src = strdup(src); + if (!src) out_of_memory("unsafe_symlink"); + + /* find out what our safety margin is */ + for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) { + if (strcmp(tok,"..") == 0) { + depth=0; + } else if (strcmp(tok,".") == 0) { + /* nothing */ + } else { + depth++; } } + free(src); + + /* drop by one to account for the filename portion */ + depth--; + + dest = strdup(dest); + if (!dest) out_of_memory("unsafe_symlink"); + + for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) { + if (strcmp(tok,"..") == 0) { + depth--; + } else if (strcmp(tok,".") == 0) { + /* nothing */ + } else { + depth++; + } + /* if at any point we go outside the current directory then + stop - it is unsafe */ + if (depth < 0) break; + } + + free(dest); + return (depth < 0); }