char *secrets_file;
char *exclude;
char *exclude_from;
+ char *log_format;
} service;
NULL, /* secrets file */
NULL, /* exclude */
NULL, /* exclude from */
+ "%o %h [%a] %f %l", /* log format */
};
{"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL, 0},
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from,NULL, 0},
{"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging,NULL,0},
+ {"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL, 0},
{NULL, P_BOOL, P_NONE, NULL, NULL, 0}
};
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
FN_LOCAL_STRING(lp_exclude, exclude)
FN_LOCAL_STRING(lp_exclude_from, exclude_from)
+FN_LOCAL_STRING(lp_log_format, log_format)
/* local prototypes */
static int strwicmp( char *psz1, char *psz2 );
}
-/* this is the rsync debugging function. Call it with FINFO or FERROR */
-void rprintf(int fd, const char *format, ...)
+/* this is the rsync debugging function. Call it with FINFO, FERROR or FLOG */
+ void rprintf(int fd, const char *format, ...)
{
va_list ap;
char buf[1024];
return;
}
+ if (fd == FLOG) {
+ return;
+ }
+
if (fd == FERROR) {
f = stderr;
}
}
+
+/* a generic logging routine for send/recv, with parameter
+ substitiution */
+static void log_formatted(char *op, struct file_struct *file)
+{
+ extern int module_id;
+ char buf[1024];
+ char *p, *s, *n;
+ char buf2[100];
+ int l;
+
+ strlcpy(buf, lp_log_format(module_id), sizeof(buf)-1);
+
+ for (s=&buf[0];
+ s && (p=strchr(s,'%')); ) {
+ n = NULL;
+ s = p + 1;
+
+ switch (p[1]) {
+ case 'h': n = client_name(0); break;
+ case 'a': n = client_addr(0); break;
+ case 'l':
+ slprintf(buf2,sizeof(buf2)-1,"%.0f",
+ (double)file->length);
+ n = buf2;
+ break;
+ case 'p':
+ slprintf(buf2,sizeof(buf2)-1,"%d",
+ (int)getpid());
+ n = buf2;
+ break;
+ case 'o': n = op; break;
+ case 'f': n = f_name(file); break;
+ }
+
+ if (!n) continue;
+
+ l = strlen(n);
+
+ if ((l-1) + ((int)(s - &buf[0])) > sizeof(buf)) {
+ rprintf(FERROR,"buffer overflow expanding %%%c - exiting\n",
+ p[0]);
+ exit_cleanup(1);
+ }
+
+ if (l != 2) {
+ memmove(s+(l-1), s+1, strlen(s+1));
+ }
+ memcpy(p, n, l);
+
+ s = p+l;
+ }
+
+ rprintf(FLOG,"%s\n", buf);
+}
+
/* log the outgoing transfer of a file */
void log_send(struct file_struct *file)
{
extern int module_id;
if (lp_transfer_logging(module_id)) {
- rprintf(FLOG,"Sending %s [%s] %.0f %s\n",
- client_name(0), client_addr(0),
- (double)file->length, f_name(file));
+ log_formatted("send", file);
}
}
{
extern int module_id;
if (lp_transfer_logging(module_id)) {
- rprintf(FLOG,"Receiving %s [%s] %.0f %s\n",
- client_name(0), client_addr(0),
- (double)file->length, f_name(file));
+ log_formatted("recv", file);
}
}
#ifndef ACCESSPERMS
#define ACCESSPERMS 0777
#endif
+
+/* handler for null strings in printf format */
+#define NS(s) ((s)?(s):"<NULL>")
+
+/* use magic gcc attributes to catch format errors */
+ void rprintf(int , const char *, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+;
used by ftp daemons. If you want to customise the log formats look at
log_send, log_recv and log_transfer in log.c
+dit(bf(log format)) The "log format" option allows you to specify the
+format used for logging file transfers when transfer logging is
+enabled. The format is a text string containing embedded single
+character escape sequences prefixed with a percent (%) character.
+
+The prefixes that are understood are:
+
+itemize(
+ it() %h for the remote host name
+ it() %a for the remote IP address
+ it() %l for the length of the file in bytes
+ it() %p for the process id of this rsync session
+ it() %o for the operation, which is either "send" or "recv"
+ it() %f for the filename
+)
+
+The default log format is "%o %h [%a] %f %l"
+
dit(bf(socket options)) This option can provide endless fun for people
who like to tune their systems to the utmost degree. You can set all
sorts of socket options which may make transfers faster (or