+/* This is the rsync debugging function. Call it with FINFO, FERROR or
+ * FLOG. */
+void rprintf(enum logcode code, const char *format, ...)
+{
+ va_list ap;
+ char buf[MAXPATHLEN+512];
+ size_t len;
+
+ va_start(ap, format);
+ len = vsnprintf(buf, sizeof buf, format, ap);
+ va_end(ap);
+
+ /* Deal with buffer overruns. Instead of panicking, just
+ * truncate the resulting string. (Note that configure ensures
+ * that we have a vsnprintf() that doesn't ever return -1.) */
+ if (len > sizeof buf - 1) {
+ const char ellipsis[] = "[...]";
+
+ /* Reset length, and zero-terminate the end of our buffer */
+ len = sizeof buf - 1;
+ buf[len] = '\0';
+
+ /* Copy the ellipsis to the end of the string, but give
+ * us one extra character:
+ *
+ * v--- null byte at buf[sizeof buf - 1]
+ * abcdefghij0
+ * -> abcd[...]00 <-- now two null bytes at end
+ *
+ * If the input format string has a trailing newline,
+ * we copy it into that extra null; if it doesn't, well,
+ * all we lose is one byte. */
+ strncpy(buf+len-sizeof ellipsis, ellipsis, sizeof ellipsis);
+ if (format[strlen(format)-1] == '\n') {
+ buf[len-1] = '\n';
+ }
+ }
+
+ rwrite(code, buf, len);
+}
+
+
+/* This is like rprintf, but it also tries to print some
+ * representation of the error code. Normally errcode = errno.
+ *
+ * Unlike rprintf, this always adds a newline and there should not be
+ * one in the format string.
+ *
+ * Note that since strerror might involve dynamically loading a
+ * message catalog we need to call it once before chroot-ing. */
+void rsyserr(enum logcode code, int errcode, const char *format, ...)
+{
+ va_list ap;
+ char buf[MAXPATHLEN+512];
+ size_t len;
+
+ strcpy(buf, RSYNC_NAME ": ");
+ len = (sizeof RSYNC_NAME ": ") - 1;
+
+ va_start(ap, format);
+ len += vsnprintf(buf + len, sizeof buf - len, format, ap);
+ va_end(ap);