Add --one-file-system, which prevents openrsync to cross filesystem
boundaries. Option and behaviour is the same as GPL rsync.

OK?


diff --git usr.bin/rsync/extern.h usr.bin/rsync/extern.h
index 12aceae566c..602cd24cede 100644
--- usr.bin/rsync/extern.h
+++ usr.bin/rsync/extern.h
@@ -117,6 +117,7 @@ struct      opts {
        int              devices;               /* --devices */
        int              specials;              /* --specials */
        int              numeric_ids;           /* --numeric-ids */
+       int              one_file_system;       /* --one-file-system or -x */
        char            *rsync_path;            /* --rsync-path */
        char            *ssh_prog;              /* --rsh or -e */
        char            *port;                  /* --port */
diff --git usr.bin/rsync/flist.c usr.bin/rsync/flist.c
index b39599583e3..7f18966d85d 100644
--- usr.bin/rsync/flist.c
+++ usr.bin/rsync/flist.c
@@ -804,7 +804,7 @@ flist_gen_dirent(struct sess *sess, char *root, struct 
flist **fl, size_t *sz,
     size_t *max)
 {
        char            *cargv[2], *cp;
-       int              rc = 0;
+       int              rc = 0, xdev = 0;
        FTS             *fts;
        FTSENT          *ent;
        struct flist    *f;
@@ -890,9 +890,15 @@ flist_gen_dirent(struct sess *sess, char *root, struct 
flist **fl, size_t *sz,
         * files and directory components, so use fts(3).
         * Copying the information file-by-file into the flstat.
         * We'll make sense of it in flist_send.
+        * If one-file-system is used, prevent fts(3) from descending
+        * into directories that have a different device number than
+        * the file from which the descent began.
         */
 
-       if ((fts = fts_open(cargv, FTS_PHYSICAL, NULL)) == NULL) {
+       if (sess->opts->one_file_system)
+               xdev = FTS_XDEV;
+
+       if ((fts = fts_open(cargv, FTS_PHYSICAL | xdev, NULL)) == NULL) {
                ERR(sess, "fts_open");
                return 0;
        }
@@ -1129,7 +1135,7 @@ flist_gen_dels(struct sess *sess, const char *root, 
struct flist **fl,
     size_t *sz,        const struct flist *wfl, size_t wflsz)
 {
        char            **cargv = NULL;
-       int               rc = 0, c;
+       int               rc = 0, c, xdev = 0;
        FTS              *fts = NULL;
        FTSENT           *ent;
        struct flist     *f;
@@ -1235,9 +1241,15 @@ flist_gen_dels(struct sess *sess, const char *root, 
struct flist **fl,
         * Now we're going to try to descend into all of the top-level
         * directories stipulated by the file list.
         * If the directories don't exist, it's ok.
+        * If one-file-system is used, prevent fts(3) from descending
+        * into directories that have a different device number than
+        * the file from which the descent began.
         */
 
-       if ((fts = fts_open(cargv, FTS_PHYSICAL, NULL)) == NULL) {
+       if (sess->opts->one_file_system)
+               xdev = FTS_XDEV;
+
+       if ((fts = fts_open(cargv, FTS_PHYSICAL | xdev, NULL)) == NULL) {
                ERR(sess, "fts_open");
                goto out;
        }
diff --git usr.bin/rsync/main.c usr.bin/rsync/main.c
index dd598d93eb2..3dbf6dd6028 100644
--- usr.bin/rsync/main.c
+++ usr.bin/rsync/main.c
@@ -305,6 +305,7 @@ main(int argc, char *argv[])
                { "no-times",   no_argument,    &opts.preserve_times,   0 },
                { "verbose",    no_argument,    &opts.verbose,          1 },
                { "no-verbose", no_argument,    &opts.verbose,          0 },
+               { "one-file-system", no_argument, NULL,                 'x' },
                { NULL,         0,              NULL,                   0 }};
 
        /* Global pledge. */
@@ -315,7 +316,7 @@ main(int argc, char *argv[])
 
        memset(&opts, 0, sizeof(struct opts));
 
-       while ((c = getopt_long(argc, argv, "Dae:ghlnoprtvz", lopts, NULL))
+       while ((c = getopt_long(argc, argv, "Dae:ghlnoprtvxz", lopts, NULL))
            != -1) {
                switch (c) {
                case 'D':
@@ -359,6 +360,9 @@ main(int argc, char *argv[])
                case 'v':
                        opts.verbose++;
                        break;
+               case 'x':
+                       opts.one_file_system = 1;
+                       break;
                case 'z':
                        fprintf(stderr, "%s: -z not supported yet\n", 
getprogname());
                        break;
diff --git usr.bin/rsync/rsync.1 usr.bin/rsync/rsync.1
index c16168fff8f..911c848da7e 100644
--- usr.bin/rsync/rsync.1
+++ usr.bin/rsync/rsync.1
@@ -141,6 +141,8 @@ Increase verbosity.
 Specify once for files being transferred, twice for specific status,
 thrice for per-file transfer information, and four times for per-file
 breakdowns.
+.It Fl x , -one-file-system
+Do not cross filesystem boundaries.
 .It Fl -version
 Print version and exit.
 .El

Reply via email to