implement argument parsing, split client_proto.h
authorAurélien Aptel <aurelien.aptel@gmail.com>
Mon, 8 Jul 2013 16:09:47 +0000 (18:09 +0200)
committerAndreas Schneider <asn@samba.org>
Wed, 19 Feb 2014 17:22:26 +0000 (18:22 +0100)
Signed-off-by: Aurélien Aptel <aurelien.aptel@gmail.com>
Reviewed-by: David Disseldorp <ddiss@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
source3/client/client.c
source3/client/client_proto.h
source3/client/clitar.c
source3/client/clitar_proto.h [new file with mode: 0644]

index e039a470cb6a2d13e47a04d6faab02e4a0d22000..4fc285f08cf8c971ac07da1dc4c7270593d4c760 100644 (file)
@@ -26,6 +26,7 @@
 #include "popt_common.h"
 #include "rpc_client/cli_pipe.h"
 #include "client/client_proto.h"
+#include "client/clitar_proto.h"
 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
 #include "../lib/util/select.h"
 #include "system/readline.h"
@@ -5513,12 +5514,14 @@ static int do_message_op(struct user_auth_info *a_info)
                         * position of the -T option in the raw argv[]. */
                        {
                                int i;
+                               extern struct tar tar_ctx;
+
                                for (i = 1; i < argc; i++) {
                                        if (strncmp("-T", argv[i],2)==0)
                                                break;
                                }
                                i++;
-                               if (!tar_parseargs(argc, argv, poptGetOptArg(pc), i)) {
+                               if (!tar_parse_args(&tar_ctx, poptGetOptArg(pc), argv + i, argc - i)) {
                                        poptPrintUsage(pc, stderr, 0);
                                        exit(1);
                                }
index d119014abdc79372232fa6ff47fa2269513b5a0b..3e91ff0fb356cba4a9bd9a28120ec838ed8cc9da 100644 (file)
@@ -38,15 +38,6 @@ NTSTATUS do_list(const char *mask,
                        bool dirs);
 int cmd_iosize(void);
 
-/* The following definitions come from client/clitar.c  */
-
-int cmd_block(void);
-int cmd_tarmode(void);
-int cmd_setmode(void);
-int cmd_tar(void);
-int process_tar(void);
-int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind);
-
 /* The following definitions come from client/dnsbrowse.c  */
 
 int do_smb_browse(void);
index 0750e324aae6536edfcc9beee6cbc43c12d38d68..c2a80d2ed9297c6ac01771ef0f609ef247ec6048 100644 (file)
@@ -20,6 +20,7 @@
 #include "includes.h"
 #include "system/filesys.h"
 #include "client/client_proto.h"
+#include "client/clitar_proto.h"
 #include "libsmb/libsmb.h"
 #include <archive.h>
 
@@ -67,14 +68,17 @@ struct tar {
     /* path to tar archive name */
     char *tar_path;
 
-    /* path to file list (F flag) */
-    char *list_path;
+    /* file descriptor of tar file */
+    int tar_fd;
+
+    /* list of path to include or exclude */
+    char **path_list;
 
     /* archive handle */
     struct archive *archive;
 };
 
-static struct tar tar_ctx = {
+struct tar tar_ctx = {
     .mode.selection   = TAR_INCLUDE,
     .mode.blocksize   = 20,
     .mode.hidden      = True,
@@ -109,6 +113,29 @@ static bool tar_set_newer_than(struct tar *t, char *filename)
     return 1;
 }
 
+static bool tar_read_inclusion_file (struct tar *t, const char* filename)
+{
+    char *line;
+    const char **list;
+    TALLOC_CTX *ctx = talloc_tos();
+    int fd = open(filename, O_RDONLY);
+
+    if (fd < 0) {
+        DEBUG(0, ("Can't open inclusion file '%s': %s\n", filename, strerror(errno)));
+        return 0;
+    }
+
+    list = str_list_make_empty(ctx);
+
+    while ((line = afdgets(fd, ctx, 0))) {
+        list = str_list_add(list, line);
+    }
+
+    close(fd);
+    t->path_list = list;
+    return 1;
+}
+
 /**
  * cmd_block - interactive command to change tar blocksize
  *
@@ -293,10 +320,11 @@ int cmd_setmode(void)
 }
 
 
-/****************************************************************************
-Principal command for creating / extracting
-***************************************************************************/
-
+/**
+ * cmd_tar - interactive command to start a tar backup/restoration
+ *
+ * Check presence of argument, parse them and handle the request.
+ */
 int cmd_tar(void)
 {
     return 0;
@@ -311,123 +339,146 @@ int process_tar(void)
     return 0;
 }
 
-/****************************************************************************
-Parse tar arguments. Sets tar_type, tar_excl, etc.
-***************************************************************************/
-
-int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind)
+/**
+ * tar_parse_args - parse and set tar command line arguments
+ * @flag: string pointing to tar options
+ * @val: number of tar arguments
+ * @valsize: table of arguments after the flags (number of element in val)
+ *
+ * tar arguments work in a weird way. For each flag f that takes a
+ * value v, the user is supposed to type:
+ *
+ * on the CLI:
+ *   -Tf1f2f3 v1 v2 v3 TARFILE PATHS...
+ *
+ * in the interactive session:
+ *   tar f1f2f3 v1 v2 v3 TARFILE PATHS...
+ *
+ * opt has only flags (eg. "f1f2f3") and val has the arguments
+ * (values) following them (eg. ["v1", "v2", "v3", "TARFILE", "PATH1",
+ * "PATH2"]).
+ *
+ * There are only 2 flags that take an arg: b and N. The other flags
+ * just change the semantic of PATH or TARFILE.
+ *
+ * PATH can be a list of included/excluded paths, the path to a file
+ * containing a list of included/excluded paths to use (F flag). If no
+ * PATH is provided, the whole share is used (/).
+ */
+int tar_parse_args(struct tar* t, const char *flag, const char **val, int valsize)
 {
-       int newOptind = Optind;
+    TALLOC_CTX *ctx = talloc_tos();
+
+    /* index of next value to use */
+    int ival = 0;
 
     /*
      * Reset back some options - could be from interactive version
         * all other modes are left as they are
         */
-    tar_ctx.mode.operation = TAR_NO_OPERATION;
-    tar_ctx.mode.selection = TAR_NO_SELECTION;
-    tar_ctx.mode.dry = False;
+    t->mode.operation = TAR_NO_OPERATION;
+    t->mode.selection = TAR_NO_SELECTION;
+    t->mode.dry = False;
 
-    while (*Optarg) {
-        switch(*Optarg++) {
+    while (*flag) {
+        switch(*flag++) {
         /* operation */
         case 'c':
-            if (tar_ctx.mode.operation != TAR_NO_OPERATION) {
+            if (t->mode.operation != TAR_NO_OPERATION) {
                 printf("Tar must be followed by only one of c or x.\n");
                 return 0;
             }
-            tar_ctx.mode.operation = TAR_CREATE;
+            t->mode.operation = TAR_CREATE;
             break;
         case 'x':
-            if (tar_ctx.mode.operation != TAR_NO_OPERATION) {
+            if (t->mode.operation != TAR_NO_OPERATION) {
                 printf("Tar must be followed by only one of c or x.\n");
                 return 0;
             }
-            tar_ctx.mode.operation = TAR_CREATE;
+            t->mode.operation = TAR_CREATE;
             break;
 
         /* selection  */
         case 'I':
-            if (tar_ctx.mode.selection != TAR_NO_SELECTION) {
+            if (t->mode.selection != TAR_NO_SELECTION) {
                 DEBUG(0,("Only one of I,X,F must be specified\n"));
                 return 0;
             }
-            tar_ctx.mode.selection = TAR_INCLUDE;
+            t->mode.selection = TAR_INCLUDE;
             break;
         case 'X':
-            if (tar_ctx.mode.selection != TAR_NO_SELECTION) {
+            if (t->mode.selection != TAR_NO_SELECTION) {
                 DEBUG(0,("Only one of I,X,F must be specified\n"));
                 return 0;
             }
-            tar_ctx.mode.selection = TAR_EXCLUDE;
+            t->mode.selection = TAR_EXCLUDE;
             break;
         case 'F':
-            if (tar_ctx.mode.selection != TAR_NO_SELECTION) {
+            if (t->mode.selection != TAR_NO_SELECTION) {
                 DEBUG(0,("Only one of I,X,F must be specified\n"));
                 return 0;
             }
-            tar_ctx.mode.selection = TAR_INCLUDE_LIST;
+            t->mode.selection = TAR_INCLUDE_LIST;
             break;
 
         /* blocksize */
         case 'b':
-            if (Optind >= argc) {
+            if (ival >= valsize) {
                 DEBUG(0, ("Option b must be followed by a blocksize\n"));
                 return 0;
             }
 
-            if (!tar_set_blocksize(&tar_ctx, atoi(argv[Optind]))) {
+            if (!tar_set_blocksize(t, atoi(val[ival]))) {
                 DEBUG(0, ("Option b must be followed by a valid blocksize\n"));
                 return 0;
             }
 
-            Optind++;
-            newOptind++;
+            ival++;
             break;
 
          /* incremental mode */
         case 'g':
-            tar_ctx.mode.incremental = True;
+            t->mode.incremental = True;
             break;
 
         /* newer than */
         case 'N':
-            if (Optind >= argc) {
+            if (ival >= valsize) {
                 DEBUG(0, ("Option N must be followed by valid file name\n"));
                 return 0;
             }
 
-            if (!tar_set_newer_than(&tar_ctx, argv[Optind])) {
+            if (!tar_set_newer_than(t, val[ival])) {
                 DEBUG(0,("Error setting newer-than time\n"));
                 return 0;
             }
 
-            newOptind++;
-            Optind++;
+            ival++;
             break;
 
         /* reset mode */
         case 'a':
-            tar_ctx.mode.reset = True;
+            t->mode.reset = True;
             break;
 
         /* verbose */
         case 'q':
-            tar_ctx.mode.verbose = True;
+            t->mode.verbose = True;
             break;
 
         /* regex match  */
         case 'r':
-            tar_ctx.mode.regex = True;
+            t->mode.regex = True;
             break;
 
         /* dry run mode */
         case 'n':
-            if (tar_ctx.mode.operation != TAR_CREATE) {
+            if (t->mode.operation != TAR_CREATE) {
                 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
                 return 0;
             }
 
-            tar_ctx.mode.dry = True;
+            t->mode.dry = True;
             DEBUG(0, ("dry_run set\n"));
             break;
 
@@ -437,21 +488,43 @@ int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind)
         }
     }
 
-    /* default operation is include */
-    if (tar_ctx.mode.operation == TAR_NO_OPERATION) {
-        tar_ctx.mode.operation = TAR_INCLUDE;
+    /* no operation given? default operation is include */
+    if (t->mode.operation == TAR_NO_OPERATION) {
+        t->mode.operation = TAR_INCLUDE;
     }
 
-    if (tar_ctx.mode.selection == TAR_INCLUDE_LIST) {
-        if (argc - Optind - 1 != 1) {
+    if (valsize - ival < 1) {
+        DEBUG(0, ("No tar file given.\n"));
+        return 0;
+    }
+
+    /* handle TARFILE */
+    t->tar_path = talloc_strdup(ctx, val[ival]);
+    ival++;
+
+    /* handle PATHs... */
+    tar_ctx.path_list = str_list_make_empty(ctx);
+
+    /* flag F -> read file list */
+    if (t->mode.selection == TAR_INCLUDE_LIST) {
+        if (valsize - ival != 1) {
             DEBUG(0,("Option F must be followed by exactly one filename.\n"));
             return 0;
         }
-        newOptind++;
-        /* Optind points at the tar output file, Optind+1 at the inclusion file. */
-        printf("tar: %s list: %s\n", argv[Optind], argv[Optind+1]);
+
+        if(!tar_read_inclusion_file(t, val[ival])) {
+            return 0;
+        }
+        ival++;
     }
 
-    return newOptind;
+    /* otherwise store all the PATHs on the command line */
+    else {
+        int i;
+        for (i = ival; i < valsize; i++) {
+            t->path_list = str_list_add(t->path_list, val[i]);
+        }
+    }
 
+    return 1;
 }
diff --git a/source3/client/clitar_proto.h b/source3/client/clitar_proto.h
new file mode 100644 (file)
index 0000000..e66c9f9
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Tar backup command extension
+ * Copyright (C) Aurélien Aptel 2013
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CLITAR_PROTO_H_
+#define _CLITAR_PROTO_H_
+
+struct tar;
+
+int cmd_block(void);
+int cmd_tarmode(void);
+int cmd_setmode(void);
+int cmd_tar(void);
+int process_tar(void);
+int tar_parse_args(struct tar *tar, const char *flag, const char **val, int valsize);
+
+#endif /* _CLITAR_PROTO_H_ */