- static char *buf=NULL;
- static int bufsize = WRITE_BLOCK_SIZE;
- int total=0;
-
- if (!buf) {
- buf = (char *)malloc(bufsize);
- if (!buf) out_of_memory("read_write");
- }
-
- while (total < size) {
- int n = MIN(size-total,bufsize);
- read_buf(fd_in,buf,n);
- if (write(fd_out,buf,n) != n)
- return total;
- total += n;
- }
- return total;
-}
-
-
-/* this is taken from CVS */
-int piped_child(char **command,int *f_in,int *f_out)
-{
- int pid;
- int to_child_pipe[2];
- int from_child_pipe[2];
-
- if (pipe(to_child_pipe) < 0 ||
- pipe(from_child_pipe) < 0) {
- fprintf(stderr,"pipe: %s\n",strerror(errno));
- exit(1);
- }
-
-
- pid = fork();
- if (pid < 0) {
- fprintf(stderr,"fork: %s\n",strerror(errno));
- exit(1);
- }
-
- if (pid == 0)
- {
- if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
- close(to_child_pipe[1]) < 0 ||
- close(from_child_pipe[0]) < 0 ||
- dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
- fprintf(stderr,"Failed to dup/close : %s\n",strerror(errno));
- exit(1);
- }
- execvp(command[0], command);
- fprintf(stderr,"Failed to exec %s : %s\n",
- command[0],strerror(errno));
- exit(1);
- }
-
- if (close(from_child_pipe[1]) < 0 ||
- close(to_child_pipe[0]) < 0) {
- fprintf(stderr,"Failed to close : %s\n",strerror(errno));
- exit(1);
- }
-
- *f_in = from_child_pipe[0];
- *f_out = to_child_pipe[1];
+ const uchar *s1 = (const uchar *)cs1;
+ const uchar *s2 = (const uchar *)cs2;
+
+ while (*s1 && *s2 && (*s1 == *s2)) {
+ s1++; s2++;
+ }
+
+ return (int)*s1 - (int)*s2;
+}
+
+
+
+/**
+ * Determine if a symlink points outside the current directory tree.
+ * This is considered "unsafe" because e.g. when mirroring somebody
+ * else's machine it might allow them to establish a symlink to
+ * /etc/passwd, and then read it through a web server.
+ *
+ * Null symlinks and absolute symlinks are always unsafe.
+ *
+ * Basically here we are concerned with symlinks whose target contains
+ * "..", because this might cause us to walk back up out of the
+ * transferred directory. We are not allowed to go back up and
+ * reenter.
+ *
+ * @param dest Target of the symlink in question.
+ *
+ * @param src Top source directory currently applicable. Basically this
+ * is the first parameter to rsync in a simple invocation, but it's
+ * modified by flist.c in slightly complex ways.
+ *
+ * @retval True if unsafe
+ * @retval False is unsafe
+ *
+ * @sa t_unsafe.c
+ **/
+int unsafe_symlink(const char *dest, const char *src)
+{
+ const char *name, *slash;
+ int depth = 0;
+
+ /* all absolute and null symlinks are unsafe */
+ if (!dest || !*dest || *dest == '/') return 1;
+
+ /* find out what our safety margin is */
+ for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {
+ if (strncmp(name, "../", 3) == 0) {
+ depth=0;
+ } else if (strncmp(name, "./", 2) == 0) {
+ /* nothing */
+ } else {
+ depth++;
+ }
+ }
+ if (strcmp(name, "..") == 0)
+ depth = 0;
+
+ for (name = dest; (slash = strchr(name, '/')) != 0; name = slash+1) {
+ if (strncmp(name, "../", 3) == 0) {
+ /* if at any point we go outside the current directory
+ then stop - it is unsafe */
+ if (--depth < 0)
+ return 1;
+ } else if (strncmp(name, "./", 2) == 0) {
+ /* nothing */
+ } else {
+ depth++;
+ }
+ }
+ if (strcmp(name, "..") == 0)
+ depth--;
+
+ return (depth < 0);
+}
+
+
+/**
+ * Return the date and time as a string
+ **/
+char *timestring(time_t t)
+{
+ static char TimeBuf[200];
+ struct tm *tm = localtime(&t);
+
+#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;
+ }
+
+ return(TimeBuf);
+}
+
+
+/**
+ * Sleep for a specified number of milliseconds.
+ *
+ * Always returns TRUE. (In the future it might return FALSE if
+ * interrupted.)
+ **/
+int msleep(int t)
+{
+ int tdiff=0;
+ struct timeval tval,t1,t2;
+
+ gettimeofday(&t1, NULL);
+ gettimeofday(&t2, NULL);