++
++void db_log_delete(char *fname, int mode)
++{
++ char strSqlStatement[2048];
++ SQLHDBC db_handle = (am_generator) ? db_handle_g : db_handle_r;
++ SQLHSTMT sql_statement_handle = (am_generator) ? sql_statement_handle_g : sql_statement_handle_r;
++
++ if (!am_daemon || dry_run || !lp_database_logging(module_id))
++ return;
++
++ if (db_handle != NULL) {
++ snprintf(strSqlStatement, sizeof strSqlStatement,
++ "INSERT INTO %s (session_id, date, path, mode) VALUES ('%ld','%s','%s','%d');",
++ lp_delete_table_name(module_id), session_id, timestring(time(NULL)), sanitizeSql(fname), mode);
++
++ result = SQLExecDirect(sql_statement_handle,strSqlStatement,SQL_NTS);
++
++ if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO) {
++ SQLGetDiagRec(SQL_HANDLE_DBC, db_handle,1, sql_status,&V_OD_err,V_OD_msg,100,&V_OD_mlen);
++ rprintf(FERROR,"Error at db_log_delete: Error in Insert %s %s\n",strSqlStatement,V_OD_msg);
++ }
++ } else {
++ rprintf(FERROR,"Error at db_log_delete: Not connected to database!\n");
++ }
++}
++
++void db_log_error(enum logcode code, int errcode, const char *format,...)
++{
++ char strSqlStatement[MAXPATHLEN+1024];
++ va_list ap;
++ char buf[MAXPATHLEN+512];
++ size_t len;
++ SQLHDBC db_handle = (am_generator) ? db_handle_g : db_handle_r;
++ SQLHSTMT sql_statement_handle = (am_generator) ? sql_statement_handle_g : sql_statement_handle_r;
++
++ if (!lp_database_logging(module_id))
++ return;
++
++ 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';
++ }
++ }
++
++ if (db_handle != NULL) {
++ snprintf(strSqlStatement, sizeof strSqlStatement,
++ "INSERT INTO %s (session_id, date, logcode, error_number, error_text) VALUES ('%ld','%s','%d','%d','%s');",
++ lp_error_table_name(module_id), session_id, timestring(time(NULL)), code, errcode, sanitizeSql(buf));
++
++ result = SQLExecDirect(sql_statement_handle,strSqlStatement,SQL_NTS);
++
++ if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO) {
++ SQLGetDiagRec(SQL_HANDLE_DBC, db_handle,1, sql_status,&V_OD_err,V_OD_msg,100,&V_OD_mlen);
++ rprintf(FERROR,"Error at db_log_error: Error in Insert %s %s\n",strSqlStatement,V_OD_msg);
++ }
++ } else {
++ rprintf(FERROR,"Error at db_log_error: Not connected to database!\n");
++ }
++}
+--- old/instructions
++++ new/instructions
+@@ -0,0 +1,84 @@
++This patch adds the following options:
++
++"database logging"
++ If set to True, rsync will attempt to connect to
++ the specified datasource and write to the named tables.
++ Defaults to False.
++
++"database datasource"
++ Specifies the name of the ODBC data source to use.
++
++"database username"
++ The username to use when connecting to the database.
++
++"database password"
++ The password to use when connecting to the database.
++
++"transfer table name"
++ The name of the transfer table to log to. This table contains individual
++ filenames, file sizes, bytes transferred, checksum bytes transferred,
++ operation (send or receive), and a timestamp.
++
++"session table name"
++ The name of the session table to log to. This table contains the username,
++ module name, module path, ip address, process ID, and a timestamp.
++
++"exit table name"
++
++ The name of the exit table to log to. This table contains the total bytes
++ read, total bytes written, total size of all files, error code, line the
++ error occured at, file the error occured at and the text of the error.
++ (most of which will be blank if the program exited normally).
++
++"delete table name"
++
++ The name of the table to log deleted files/directories to.
++
++"error table name"
++
++ The name of the table errors will be logged to.
++
++"unique id method"
++ Different databases use different methods to get a unique identifier.
++ Some databases support sequence objects, and use various forms of the
++ nextval command to retrieve a unique identifier from it. Other databases
++ support an autonumber field, and support different methds of retrieving
++ the ID used in the last insert. Valid values for this option are:
++
++ nextval-postgres
++ uses the syntax of nextval for PostgreSQL databases
++
++ nextval-oracle
++ uses the syntax of nextval for Oracle databases
++
++ nextval-db2
++ uses the syntax of nextval for DB2 databases
++
++ last_insert_id
++ uses the last_insert_id() command for the MySQL databases
++
++ @@IDENTITY
++ uses the @@IDENTITY command for Sybase databases
++
++ custom
++ Define your own method to get a unique identifier. See the
++ "custom unique id select", and the "get custom id before select"
++ parameters.
++
++"sequence name"
++ If your database supports sequences, list the name of the sequence to use
++ for the session unique identifier.
++
++"custom unique id select"
++ Only used if you specify the custom method in "unique id method". This is
++ a SQL statement to be executed to get a unique ID. This SQL statement must
++ return one column with the unique ID to use for the session ID. Should be
++ used in concert with the "get custom id before select" parameter.
++
++"get custom id before insert"
++ This parameter is ignored unless the "unique id method" is set to custom.
++ If set to true, the "custom unique id select" statement will be executed
++ BEFORE the session row is inserted into the database. (as is done when a
++ sequence is used for unique IDs). If False the statement will be executed
++ after the session row is inserted (as is done when the session ID is
++ automatically generates unique IDs). Defaults to True.
+--- old/loadparm.c
++++ new/loadparm.c
+@@ -121,9 +121,16 @@ typedef struct