The patches for 3.3.0.
[rsync-patches.git] / source-filter_dest-filter.diff
index cd5884c4ce2d31a54eb0ba698664b38d099015e8..3f63d3080ac0fa189c7be215f26e223f6e63f7c3 100644 (file)
@@ -30,11 +30,11 @@ To use this patch, run these commands for a successful build:
     ./configure                                (optional if already run)
     make
 
-based-on: 1c7785ab1ecfe81f7b4f257f8a2bec2f68d43d58
+based-on: 6c8ca91c731b7bf2b081694bda85b7dadc2b7aff
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -64,6 +64,7 @@ extern int append_mode;
+@@ -67,6 +67,7 @@ extern int append_mode;
  extern int make_backups;
  extern int csum_length;
  extern int ignore_times;
@@ -42,19 +42,19 @@ diff --git a/generator.c b/generator.c
  extern int size_only;
  extern OFF_T max_size;
  extern OFF_T min_size;
-@@ -580,7 +581,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
- /* Perform our quick-check heuristic for determining if a file is unchanged. */
- int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
+@@ -618,7 +619,7 @@ int quick_check_ok(enum filetype ftype, const char *fn, struct file_struct *file
  {
--      if (st->st_size != F_LENGTH(file))
-+      if (!times_only && st->st_size != F_LENGTH(file))
-               return 0;
+       switch (ftype) {
+         case FT_REG:
+-              if (st->st_size != F_LENGTH(file))
++              if (!times_only && st->st_size != F_LENGTH(file))
+                       return 0;
  
-       /* if always checksum is set then we use the checksum instead
+               /* If always_checksum is set then we use the checksum instead
 diff --git a/main.c b/main.c
 --- a/main.c
 +++ b/main.c
-@@ -179,7 +179,7 @@ int shell_exec(const char *cmd)
+@@ -191,7 +191,7 @@ int shell_exec(const char *cmd)
  }
  
  /* Wait for a process to exit, calling io_flush while waiting. */
@@ -66,7 +66,7 @@ diff --git a/main.c b/main.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -112,6 +112,7 @@ int safe_symlinks = 0;
+@@ -119,6 +119,7 @@ int safe_symlinks = 0;
  int copy_unsafe_links = 0;
  int munge_symlinks = 0;
  int size_only = 0;
@@ -74,33 +74,16 @@ diff --git a/options.c b/options.c
  int daemon_bwlimit = 0;
  int bwlimit = 0;
  int fuzzy_basis = 0;
-@@ -171,6 +172,8 @@ char *logfile_name = NULL;
+@@ -179,6 +180,8 @@ char *logfile_name = NULL;
  char *logfile_format = NULL;
  char *stdout_format = NULL;
  char *password_file = NULL;
 +char *source_filter = NULL;
 +char *dest_filter = NULL;
+ char *early_input_file = NULL;
  char *rsync_path = RSYNC_PATH;
  char *backup_dir = NULL;
- char backup_dir_buf[MAXPATHLEN];
-@@ -765,6 +768,7 @@ void usage(enum logcode F)
-   rprintf(F," -I, --ignore-times          don't skip files that match in size and mod-time\n");
-   rprintf(F," -M, --remote-option=OPTION  send OPTION to the remote side only\n");
-   rprintf(F,"     --size-only             skip files that match in size\n");
-+  rprintf(F,"     --times-only            skip files that match in mod-time\n");
-   rprintf(F," -@, --modify-window=NUM     set the accuracy for mod-time comparisons\n");
-   rprintf(F," -T, --temp-dir=DIR          create temporary files in directory DIR\n");
-   rprintf(F," -y, --fuzzy                 find similar file for basis if no dest file\n");
-@@ -808,6 +812,8 @@ void usage(enum logcode F)
-   rprintf(F,"     --write-batch=FILE      write a batched update to FILE\n");
-   rprintf(F,"     --only-write-batch=FILE like --write-batch but w/o updating destination\n");
-   rprintf(F,"     --read-batch=FILE       read a batched update from FILE\n");
-+  rprintf(F,"     --source-filter=COMMAND filter file through COMMAND at source\n");
-+  rprintf(F,"     --dest-filter=COMMAND   filter file through COMMAND at destination\n");
-   rprintf(F,"     --protocol=NUM          force an older protocol version to be used\n");
- #ifdef ICONV_OPTION
-   rprintf(F,"     --iconv=CONVERT_SPEC    request charset conversion of filenames\n");
-@@ -928,6 +934,7 @@ static struct poptOption long_options[] = {
+@@ -689,6 +692,7 @@ static struct poptOption long_options[] = {
    {"chmod",            0,  POPT_ARG_STRING, 0, OPT_CHMOD, 0, 0 },
    {"ignore-times",    'I', POPT_ARG_NONE,   &ignore_times, 0, 0, 0 },
    {"size-only",        0,  POPT_ARG_NONE,   &size_only, 0, 0, 0 },
@@ -108,16 +91,16 @@ diff --git a/options.c b/options.c
    {"one-file-system", 'x', POPT_ARG_NONE,   0, 'x', 0, 0 },
    {"no-one-file-system",0, POPT_ARG_VAL,    &one_file_system, 0, 0, 0 },
    {"no-x",             0,  POPT_ARG_VAL,    &one_file_system, 0, 0, 0 },
-@@ -1053,6 +1060,8 @@ static struct poptOption long_options[] = {
-   {"password-file",    0,  POPT_ARG_STRING, &password_file, 0, 0, 0 },
+@@ -829,6 +833,8 @@ static struct poptOption long_options[] = {
+   {"early-input",      0,  POPT_ARG_STRING, &early_input_file, 0, 0, 0 },
    {"blocking-io",      0,  POPT_ARG_VAL,    &blocking_io, 1, 0, 0 },
    {"no-blocking-io",   0,  POPT_ARG_VAL,    &blocking_io, 0, 0, 0 },
 +  {"source-filter",    0,  POPT_ARG_STRING, &source_filter, 0, 0, 0 },
 +  {"dest-filter",      0,  POPT_ARG_STRING, &dest_filter, 0, 0, 0 },
- #ifdef HAVE_SETVBUF
    {"outbuf",           0,  POPT_ARG_STRING, &outbuf_mode, 0, 0, 0 },
- #endif
-@@ -2360,6 +2369,16 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+   {"remote-option",   'M', POPT_ARG_STRING, 0, 'M', 0, 0 },
+   {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
+@@ -2444,6 +2450,16 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                }
        }
  
@@ -134,7 +117,7 @@ diff --git a/options.c b/options.c
        if (files_from) {
                char *h, *p;
                int q;
-@@ -2730,6 +2749,25 @@ void server_options(char **args, int *argc_p)
+@@ -2852,6 +2868,25 @@ void server_options(char **args, int *argc_p)
        else if (missing_args == 1 && !am_sender)
                args[ac++] = "--ignore-missing-args";
  
@@ -171,7 +154,7 @@ diff --git a/pipe.c b/pipe.c
  extern char *logfile_name;
  extern int remote_option_cnt;
  extern const char **remote_options;
-@@ -178,3 +179,77 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
+@@ -176,3 +177,77 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
  
        return pid;
  }
@@ -252,7 +235,7 @@ diff --git a/pipe.c b/pipe.c
 diff --git a/receiver.c b/receiver.c
 --- a/receiver.c
 +++ b/receiver.c
-@@ -59,6 +59,7 @@ extern BOOL want_progress_now;
+@@ -60,6 +60,7 @@ extern BOOL want_progress_now;
  extern mode_t orig_umask;
  extern struct stats stats;
  extern char *tmpdir;
@@ -260,18 +243,25 @@ diff --git a/receiver.c b/receiver.c
  extern char *partial_dir;
  extern char *basis_dir[MAX_BASIS_DIRS+1];
  extern char sender_file_sum[MAX_DIGEST_LEN];
-@@ -531,6 +532,8 @@ int recv_files(int f_in, int f_out, char *local_name)
+@@ -528,6 +529,7 @@ int recv_files(int f_in, int f_out, char *local_name)
+       char *fnametmp, fnametmpbuf[MAXPATHLEN];
+       char *fnamecmp, *partialptr;
+       char fnamecmpbuf[MAXPATHLEN];
++      char *filter_argv[MAX_FILTER_ARGS + 1];
+       uchar fnamecmp_type;
+       struct file_struct *file;
+       int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
+@@ -538,6 +540,7 @@ int recv_files(int f_in, int f_out, char *local_name)
        const char *parent_dirname = "";
  #endif
-       int ndx, recv_ok;
+       int ndx, recv_ok, one_inplace;
 +      pid_t pid = 0;
-+      char *filter_argv[MAX_FILTER_ARGS + 1];
  
        if (DEBUG_GTE(RECV, 1))
                rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used);
-@@ -538,6 +541,23 @@ int recv_files(int f_in, int f_out, char *local_name)
-       if (delay_updates)
-               delayed_bits = bitbag_create(cur_flist->used + 1);
+@@ -548,6 +551,23 @@ int recv_files(int f_in, int f_out, char *local_name)
+       if (whole_file < 0)
+               whole_file = 0;
  
 +      if (dest_filter) {
 +              char *p;
@@ -293,7 +283,7 @@ diff --git a/receiver.c b/receiver.c
        progress_init();
  
        while (1) {
-@@ -859,6 +879,9 @@ int recv_files(int f_in, int f_out, char *local_name)
+@@ -873,6 +893,9 @@ int recv_files(int f_in, int f_out, char *local_name)
                else if (!am_server && INFO_GTE(NAME, 1) && INFO_EQ(PROGRESS, 1))
                        rprintf(FINFO, "%s\n", fname);
  
@@ -301,9 +291,9 @@ diff --git a/receiver.c b/receiver.c
 +                      pid = run_filter(filter_argv, fd2, &fd2);
 +
                /* recv file data */
-               recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size, fname, fd2, file);
+               recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size, fname, fd2, file, inplace || one_inplace);
  
-@@ -874,6 +897,16 @@ int recv_files(int f_in, int f_out, char *local_name)
+@@ -888,6 +911,16 @@ int recv_files(int f_in, int f_out, char *local_name)
                        exit_cleanup(RERR_FILEIO);
                }
  
@@ -320,10 +310,67 @@ diff --git a/receiver.c b/receiver.c
                if ((recv_ok && (!delay_updates || !partialptr)) || inplace) {
                        if (partialptr == fname)
                                partialptr = NULL;
+diff --git a/rsync.1.md b/rsync.1.md
+--- a/rsync.1.md
++++ b/rsync.1.md
+@@ -504,6 +504,7 @@ has its own detailed description later in this manpage.
+ --contimeout=SECONDS     set daemon connection timeout in seconds
+ --ignore-times, -I       don't skip files that match size and time
+ --size-only              skip files that match in size
++--times-only             skip files that match in mod-time
+ --modify-window=NUM, -@  set the accuracy for mod-time comparisons
+ --temp-dir=DIR, -T       create temporary files in directory DIR
+ --fuzzy, -y              find similar file for basis if no dest file
+@@ -553,6 +554,8 @@ has its own detailed description later in this manpage.
+ --write-batch=FILE       write a batched update to FILE
+ --only-write-batch=FILE  like --write-batch but w/o updating dest
+ --read-batch=FILE        read a batched update from FILE
++--source-filter=COMMAND  filter file through COMMAND at source
++--dest-filter=COMMAND    filter file through COMMAND at destination
+ --protocol=NUM           force an older protocol version to be used
+ --iconv=CONVERT_SPEC     request charset conversion of filenames
+ --checksum-seed=NUM      set block/file checksum seed (advanced)
+@@ -3713,6 +3716,36 @@ expand it.
+     [`--write-batch`](#opt).  If _FILE_ is `-`, the batch data will be read
+     from standard input. See the "BATCH MODE" section for details.
++0.  `--source-filter=COMMAND`
++
++    This option allows the user to specify a filter program that will be
++    applied to the contents of all transferred regular files before the data is
++    sent to destination.  COMMAND will receive the data on its standard input
++    and it should write the filtered data to standard output.  COMMAND should
++    exit non-zero if it cannot process the data or if it encounters an error
++    when writing the data to stdout.
++
++    Example: `--source-filter="gzip -9"` will cause remote files to be
++    compressed.  Use of `--source-filter` automatically enables
++    [`--whole-file`](#opt).  If your filter does not output the same number of
++    bytes that it received on input, you should use `--times-only` to
++    disable size and content checks on subsequent rsync runs.
++
++0.  `--dest-filter=COMMAND`
++
++    This option allows you to specify a filter program that will be applied to
++    the contents of all transferred regular files before the data is written to
++    disk.  COMMAND will receive the data on its standard input and it should
++    write the filtered data to standard output.  COMMAND should exit non-zero
++    if it cannot process the data or if it encounters an error when writing the
++    data to stdout.
++
++    Example: --dest-filter="gzip -9" will cause remote files to be compressed.
++    Use of --dest-filter automatically enables --whole-file.  If your filter
++    does not output the same number of bytes that it received on input, you
++    should use --times-only to disable size and content checks on subsequent
++    rsync runs.
++
+ 0.  `--protocol=NUM`
+     Force an older protocol version to be used.  This is useful for creating a
 diff --git a/rsync.h b/rsync.h
 --- a/rsync.h
 +++ b/rsync.h
-@@ -151,6 +151,7 @@
+@@ -169,6 +169,7 @@
  #define IOERR_DEL_LIMIT (1<<2)
  
  #define MAX_ARGS 1000
@@ -331,72 +378,26 @@ diff --git a/rsync.h b/rsync.h
  #define MAX_BASIS_DIRS 20
  #define MAX_SERVER_ARGS (MAX_BASIS_DIRS*2 + 100)
  
-diff --git a/rsync.yo b/rsync.yo
---- a/rsync.yo
-+++ b/rsync.yo
-@@ -423,6 +423,7 @@ to the detailed description below for a complete description.  verb(
-      --contimeout=SECONDS    set daemon connection timeout in seconds
-  -I, --ignore-times          don't skip files that match size and time
-      --size-only             skip files that match in size
-+     --times-only            skip files that match in mod-time
-  -@, --modify-window=NUM     set the accuracy for mod-time comparisons
-  -T, --temp-dir=DIR          create temporary files in directory DIR
-  -y, --fuzzy                 find similar file for basis if no dest file
-@@ -465,6 +466,8 @@ to the detailed description below for a complete description.  verb(
-      --write-batch=FILE      write a batched update to FILE
-      --only-write-batch=FILE like --write-batch but w/o updating dest
-      --read-batch=FILE       read a batched update from FILE
-+     --source-filter=COMMAND filter file through COMMAND at source
-+     --dest-filter=COMMAND   filter file through COMMAND at destination
-      --protocol=NUM          force an older protocol version to be used
-      --iconv=CONVERT_SPEC    request charset conversion of filenames
-      --checksum-seed=NUM     set block/file checksum seed (advanced)
-@@ -2714,6 +2717,33 @@ file previously generated by bf(--write-batch).
- If em(FILE) is bf(-), the batch data will be read from standard input.
- See the "BATCH MODE" section for details.
-+dit(bf(--source-filter=COMMAND)) This option allows the user to specify a
-+filter program that will be applied to the contents of all transferred
-+regular files before the data is sent to destination.  COMMAND will receive
-+the data on its standard input and it should write the filtered data to
-+standard output.  COMMAND should exit non-zero if it cannot process the
-+data or if it encounters an error when writing the data to stdout.
-+
-+Example: --source-filter="gzip -9" will cause remote files to be
-+compressed.
-+Use of --source-filter automatically enables --whole-file.
-+If your filter does not output the same number of bytes that it received on
-+input, you should use --times-only to disable size and content checks on
-+subsequent rsync runs.
-+
-+dit(bf(--dest-filter=COMMAND)) This option allows you to specify a filter
-+program that will be applied to the contents of all transferred regular
-+files before the data is written to disk.  COMMAND will receive the data on
-+its standard input and it should write the filtered data to standard
-+output.  COMMAND should exit non-zero if it cannot process the data or if
-+it encounters an error when writing the data to stdout.
-+
-+Example: --dest-filter="gzip -9" will cause remote files to be compressed.
-+Use of --dest-filter automatically enables --whole-file.
-+If your filter does not output the same number of bytes that it
-+received on input, you should use --times-only to disable size and
-+content checks on subsequent rsync runs.
-+
- )
- description(
 diff --git a/sender.c b/sender.c
 --- a/sender.c
 +++ b/sender.c
-@@ -46,6 +46,7 @@ extern int batch_fd;
+@@ -21,6 +21,7 @@
+ #include "rsync.h"
+ #include "inums.h"
++#include "ifuncs.h"
+ extern int do_xfers;
+ extern int am_server;
+@@ -50,6 +51,7 @@ extern int batch_fd;
  extern int write_batch;
  extern int file_old_total;
  extern BOOL want_progress_now;
 +extern char *source_filter;
  extern struct stats stats;
  extern struct file_list *cur_flist, *first_flist, *dir_flist;
-@@ -203,6 +204,26 @@ void send_files(int f_in, int f_out)
+ extern char num_dev_ino_buf[4 + 8 + 8];
+@@ -211,6 +213,26 @@ void send_files(int f_in, int f_out)
        int f_xfer = write_batch < 0 ? batch_fd : f_out;
        int save_io_error = io_error;
        int ndx, j;
@@ -423,7 +424,7 @@ diff --git a/sender.c b/sender.c
  
        if (DEBUG_GTE(SEND, 1))
                rprintf(FINFO, "send_files starting\n");
-@@ -339,6 +360,7 @@ void send_files(int f_in, int f_out)
+@@ -348,6 +370,7 @@ void send_files(int f_in, int f_out)
                        exit_cleanup(RERR_PROTOCOL);
                }
  
@@ -431,7 +432,7 @@ diff --git a/sender.c b/sender.c
                fd = do_open(fname, O_RDONLY, 0);
                if (fd == -1) {
                        if (errno == ENOENT) {
-@@ -360,6 +382,33 @@ void send_files(int f_in, int f_out)
+@@ -367,6 +390,33 @@ void send_files(int f_in, int f_out)
                        continue;
                }
  
@@ -465,7 +466,7 @@ diff --git a/sender.c b/sender.c
                /* map the local file */
                if (do_fstat(fd, &st) != 0) {
                        io_error |= IOERR_GENERAL;
-@@ -412,6 +461,8 @@ void send_files(int f_in, int f_out)
+@@ -437,6 +487,8 @@ void send_files(int f_in, int f_out)
                        }
                }
                close(fd);