Re: Add the -m (--prune-empty-dirs) option to openrsync

2023-02-22 Thread bukhris

Hello again, Job
Sorry for the recurring formatting and tab issues.
Here's the updated diff.

Index: extern.h
===
RCS file: /cvs/src/usr.bin/rsync/extern.h,v
retrieving revision 1.44
diff -u -p -u -p -r1.44 extern.h
--- extern.h2 Aug 2022 18:09:20 -   1.44
+++ extern.h22 Feb 2023 17:48:04 -
@@ -134,6 +134,7 @@ struct  opts {
int  server;/* --server */
int  recursive; /* -r */
int  dry_run;   /* -n */
+   int  prune_empty_dirs;  /* -m */
int  preserve_times;/* -t */
int  preserve_perms;/* -p */
int  preserve_links;/* -l */
Index: flist.c
===
RCS file: /cvs/src/usr.bin/rsync/flist.c,v
retrieving revision 1.37
diff -u -p -u -p -r1.37 flist.c
--- flist.c 26 Dec 2022 19:16:02 -  1.37
+++ flist.c 22 Feb 2023 17:48:05 -
@@ -802,10 +802,11 @@ static int
 flist_gen_dirent(struct sess *sess, char *root, struct flist **fl, 
size_t *sz,

 size_t *max)
 {
-   char*cargv[2], *cp;
-   int  rc = 0, flag;
-   FTS *fts;
-   FTSENT  *ent;
+   char*cargv[2], *prune_cargv[2], *cp;
+   int rc = 0, flag, empty_chain;
+   FTS *fts, *prunefts;
+   FTSENT  *ent, *prunent;
+
struct flist*f;
size_t   i, flsz = 0, nxdev = 0, stripdir;
dev_t   *newxdev, *xdev = NULL;
@@ -905,6 +906,35 @@ flist_gen_dirent(struct sess *sess, char
if (!flist_fts_check(sess, ent)) {
errno = 0;
continue;
+   }
+
+   /*
+* If -m (prune empty dirs) is enabled, create a new fts
+* to independently traverse directories at once and determine
+* whether we are dealing with a hierarchy of empty
+* directories, if so, skip.
+*/
+
+   if (sess->opts->prune_empty_dirs && ent->fts_info == FTS_D) {
+   prune_cargv[0] = ent->fts_name;
+   prune_cargv[1] = NULL;
+   if ((prunefts = fts_open(prune_cargv,
+   
 FTS_PHYSICAL, NULL)) == NULL) {
+   ERR("fts_open");
+   return 0;
+   }
+   empty_chain = 1;
+   while ((prunent = fts_read(prunefts)) != NULL) {
+   if (prunent->fts_info != FTS_D &&
+   prunent->fts_info != FTS_DP) {
+   empty_chain = 0;
+   break;
+   }
+   }
+   if (empty_chain)
+   continue;
+
+   fts_close(prunefts);
}

/* We don't allow symlinks without -l. */
Index: main.c
===
RCS file: /cvs/src/usr.bin/rsync/main.c,v
retrieving revision 1.66
diff -u -p -u -p -r1.66 main.c
--- main.c  14 Feb 2023 17:15:15 -  1.66
+++ main.c  22 Feb 2023 17:48:05 -
@@ -326,6 +326,7 @@ const struct option  lopts[] = {
 { "perms",   no_argument,_perms,   1 },
 { "no-perms",no_argument,_perms,   0 },
 { "port",required_argument, NULL,OP_PORT },
+   { "prune-empty-dirs", no_argument, _empty_dirs, 1 },
 { "recursive",   no_argument,,1 },
 { "no-recursive",no_argument,,0 },
 { "rsh", required_argument, NULL,'e' },
@@ -362,7 +363,7 @@ main(int argc, char *argv[])

opts.max_size = opts.min_size = -1;

-   while ((c = getopt_long(argc, argv, "Dae:ghlnoprtvxz", lopts, ))
+   while ((c = getopt_long(argc, argv, "Dae:ghlmnoprtvxz", lopts, ))
!= -1) {
switch (c) {
case 'D':
@@ -388,6 +389,9 @@ main(int argc, char *argv[])
case 'l':
opts.preserve_links = 1;
break;
+   case 'm':
+   opts.prune_empty_dirs = 1;
+   break;
case 'n':
opts.dry_run = 1;
break;
@@ -633,7 +637,7 @@ basedir:
exit(rc);
 usage:
fprintf(stderr, "usage: %s"
-   " [-aDglnoprtvx] [-e program] [--address=sourceaddr]\n"
+   " [-aDglmnoprtvx] [-e program] [--address=sourceaddr]\n"
 	  

Re: Add the -m (--prune-empty-dirs) option to openrsync

2023-02-22 Thread Mohamed Bukhris

Hello Job,
Sorry for the formatting issues, here's the fixed version, diffed 
properly via CVS.


Index: extern.h
===
RCS file: /cvs/src/usr.bin/rsync/extern.h,v
retrieving revision 1.44
diff -u -p -u -p -r1.44 extern.h
--- extern.h    2 Aug 2022 18:09:20 - 1.44
+++ extern.h    22 Feb 2023 16:05:24 -
@@ -134,6 +134,7 @@ struct    opts {
 int         server;        /* --server */
 int         recursive;        /* -r */
 int         dry_run;        /* -n */
+    int         prune_empty_dirs;    /* -m */
 int         preserve_times;    /* -t */
 int         preserve_perms;    /* -p */
 int         preserve_links;    /* -l */
Index: flist.c
===
RCS file: /cvs/src/usr.bin/rsync/flist.c,v
retrieving revision 1.37
diff -u -p -u -p -r1.37 flist.c
--- flist.c    26 Dec 2022 19:16:02 - 1.37
+++ flist.c    22 Feb 2023 16:05:24 -
@@ -802,10 +802,11 @@ static int
 flist_gen_dirent(struct sess *sess, char *root, struct flist **fl, 
size_t *sz,

 size_t *max)
 {
-    char        *cargv[2], *cp;
-    int         rc = 0, flag;
-    FTS        *fts;
-    FTSENT        *ent;
+    char    *cargv[2], *prune_cargv[2], *cp;
+    int        rc = 0, flag, empty_chain;
+    FTS        *fts, *prunefts;
+    FTSENT    *ent, *prunent;
+
 struct flist    *f;
 size_t         i, flsz = 0, nxdev = 0, stripdir;
 dev_t        *newxdev, *xdev = NULL;
@@ -905,6 +906,35 @@ flist_gen_dirent(struct sess *sess, char
     if (!flist_fts_check(sess, ent)) {
         errno = 0;
         continue;
+        }
+
+        /*
+         * If -m (prune empty dirs) is enabled, create a new fts
+         * to independently traverse directories at once and determine
+         * whether we are dealing with a hierarchy of empty
+         * directories, if so, skip.
+         */
+
+        if (sess->opts->prune_empty_dirs && ent->fts_info == FTS_D) {
+                prune_cargv[0] = ent->fts_name;
+                prune_cargv[1] = NULL;
+                if ((prunefts = fts_open(prune_cargv,
+  FTS_PHYSICAL, NULL)) == NULL) {
+                ERR("fts_open");
+                return 0;
+            }
+            empty_chain = 1;
+            while ((prunent = fts_read(prunefts)) != NULL) {
+                if (prunent->fts_info != FTS_D &&
+                    prunent->fts_info != FTS_DP) {
+                    empty_chain = 0;
+                    break;
+                }
+            }
+            if (empty_chain)
+                continue;
+
+            fts_close(prunefts);
     }

     /* We don't allow symlinks without -l. */
Index: main.c
===
RCS file: /cvs/src/usr.bin/rsync/main.c,v
retrieving revision 1.66
diff -u -p -u -p -r1.66 main.c
--- main.c    14 Feb 2023 17:15:15 - 1.66
+++ main.c    22 Feb 2023 16:05:24 -
@@ -326,6 +326,7 @@ const struct option  lopts[] = {
 { "perms",        no_argument, _perms,    1 },
 { "no-perms",    no_argument, _perms,    0 },
 { "port",        required_argument, NULL,        OP_PORT },
+     { "prune-empty-dirs", no_argument, _empty_dirs, 1 },
 { "recursive",    no_argument, ,    1 },
 { "no-recursive",    no_argument, ,    0 },
 { "rsh",        required_argument, NULL,        'e' },
@@ -362,7 +363,7 @@ main(int argc, char *argv[])

 opts.max_size = opts.min_size = -1;

-    while ((c = getopt_long(argc, argv, "Dae:ghlnoprtvxz", lopts, ))
+    while ((c = getopt_long(argc, argv, "Dae:ghlmnoprtvxz", lopts, ))
     != -1) {
     switch (c) {
     case 'D':
@@ -388,6 +389,9 @@ main(int argc, char *argv[])
     case 'l':
         opts.preserve_links = 1;
         break;
+        case 'm':
+            opts.prune_empty_dirs = 1;
+            break;
     case 'n':
         opts.dry_run = 1;
         break;
@@ -633,7 +637,7 @@ basedir:
 exit(rc);
 usage:
 fprintf(stderr, "usage: %s"
-        " [-aDglnoprtvx] [-e program] [--address=sourceaddr]\n"
+        " [-aDglmnoprtvx] [-e program] [--address=sourceaddr]\n"
     "\t[--contimeout=seconds] [--compare-dest=dir] [--del] 
[--exclude]\n"

     "\t[--exclude-from=file] [--include] [--include-from=file]\n"
     "\t[--no-motd] [--numeric-ids] [--port=portnumber]\n"
Index: rsync.1
===
RCS file: /cvs/src/usr.bin/rsync/rsync.1,v
retrieving revision 1.30
diff -u -p -u -p -r1.30 rsync.1
--- rsync.1    2 Aug 2022 18:09:20 - 1.30
+++ rsync.1    22 Feb 2023 16:05:24 -
@@ -150,6 +150,8 @@ bytes.
 See
 .Fl -max-size
 on the definition of size.
+.It Fl m , -prune-empty-dirs
+Prune empty directory chains from the file list.
 .It Fl n , -dry-run
 Do not actually modify the destination.
 Mainly useful in combination with

On 2/22/23 10:36, Job Snijders wrote:

Dear 

Re: Add the -m (--prune-empty-dirs) option to openrsync

2023-02-22 Thread Job Snijders
Dear Mohamed,

On Wed, Feb 22, 2023 at 05:42:10AM +, Mohamed Bukhris wrote:
> This patch adds the -m/--prume-empty-dirs option to openrsync
> while keeping said feature compatible with rsync
> this avoids the 27 -> 31 protocol mismatch error by not sharing the -m option 
> to remote
> This was tested locally (openrsync -> openrsync) and remotely (openrsync -> 
> rsync)

I have a few style remarks, see http://man.openbsd.org/style for full
overview of how the code should be formatted to make review &
understanding easier within the context of the OpenBSD project.

Review is slightly easier if you use 'cvs diff -uNp' to generate the
diff. See https://www.openbsd.org/faq/faq5.html#Diff

> diff -ura ../origsync/extern.h ./extern.h
> --- ../origsync/extern.h  2023-02-21 21:43:18.871417908 +0100
> +++ ./extern.h2023-02-21 18:26:12.176316267 +0100
> @@ -134,6 +134,7 @@
>   int  server;/* --server */
>   int  recursive; /* -r */
>   int  dry_run;   /* -n */
> + int  prune_empty_dirs;  /* -m */
>   int  preserve_times;/* -t */
>   int  preserve_perms;/* -p */
>   int  preserve_links;/* -l */
> diff -ura ../origsync/flist.c ./flist.c
> --- ../origsync/flist.c   2023-02-21 21:43:07.778145448 +0100
> +++ ./flist.c 2023-02-22 06:09:51.097975517 +0100
> @@ -907,6 +907,36 @@
>   continue;
>   }
>  
> + /*
> +  * If -m (prune empty dirs) is enabled, create a new fts
> +  * to independently traverse directories at once and determine
> +  * whether we are dealing with a hierarchy of empty
> +  * directories, if so, skip.
> +  */
> +
> + if (sess->opts->prune_empty_dirs && ent->fts_info == FTS_D){

Add a space between ) and {

> + char*prune_cargv[2];
> + prune_cargv[0] = ent->fts_name;
> + prune_cargv[1] = NULL;
> + FTS *prunefts;

Declare FTS *prunefts at the top of flist_gen_dirent() with the rest.

> + if ((prunefts = fts_open(prune_cargv, 
> FTS_PHYSICAL, NULL)) == NULL) {

All code should fit in 80 columns. Add a newline after 'prune_cargv,'
and indent FTS_PHYSICAL with 4 spaces to make it distinct from the if
().

> + ERR("fts_open");
> + return 0;
> + }
> + FTSENT  *prunent;
> + int empty_chain = 1;

Please initiatize variables at the top of flist_gen_dirent().

> + while ((prunent = fts_read(prunefts)) != NULL) {
> + if (prunent->fts_info != FTS_D && 
> prunent->fts_info != FTS_DP){

Above line is too long. Add a space between ) and {

> + empty_chain = 0;
> + break;
> + }
> + }
> + if (empty_chain){
> + continue;
> + }

Add a space between ) and {, and as 'continue' is the only statement
inside this if-block, you can write it like so:

if (empty_chain)
continue;


> + fts_close(prunefts);
> + }
> +
>   /* We don't allow symlinks without -l. */
>  
>   assert(ent->fts_statp != NULL);
> diff -ura ../origsync/main.c ./main.c
> --- ../origsync/main.c2023-02-21 21:43:10.861461862 +0100
> +++ ./main.c  2023-02-22 05:21:15.047310523 +0100
> @@ -340,6 +340,7 @@
>  { "verbose", no_argument,,   1 },
>  { "no-verbose",  no_argument,,   0 },
>  { "version", no_argument,NULL,   OP_VERSION },
> + { "prune-empty-dirs", no_argument, _empty_dirs,  1 },

Align it using spaces like the other lines inside struct option lopts[]
Use semi-alphabetical ordering, move the line to under "port".

>  { NULL,  0,  NULL,   0 }
>  };
>  
> @@ -362,7 +363,7 @@
>  
>   opts.max_size = opts.min_size = -1;
>  
> - while ((c = getopt_long(argc, argv, "Dae:ghlnoprtvxz", lopts, ))
> + while ((c = getopt_long(argc, argv, "Dae:ghlnoprtvxzm", lopts, ))

The optstring argument should be ordered, add 'm' after l' instead.

>   != -1) {
>   switch (c) {
>   case 'D':
> @@ -382,6 +383,9 @@
>   case 'e':
>   opts.ssh_prog = optarg;
>   break;
> + case 'm':
> + opts.prune_empty_dirs = 1;
> + break;
>   case 'g':
>   opts.preserve_gids = 1;
>