s3-masktest: Fix cli_errstr() usage (part of bug #7864)
[idra/samba.git] / source3 / torture / masktest.c
index 0e0b531080ff0913477377f1ef751bf40b45685a..887910284441c5553f55afd0f36d9f587fc02e0f 100644 (file)
@@ -5,7 +5,7 @@
    
    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 2 of the License, or
+   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,
    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, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#define NO_SYSLOG
-
 #include "includes.h"
 
 static fstring password;
 static fstring username;
 static int got_pass;
 static int max_protocol = PROTOCOL_NT1;
-static BOOL showall = False;
-static BOOL old_list = False;
-static char *maskchars = "<>\"?*abc.";
-static char *filechars = "abcdefghijklm.";
+static bool showall = False;
+static bool old_list = False;
+static const char *maskchars = "<>\"?*abc.";
+static const char *filechars = "abcdefghijklm.";
 static int verbose;
 static int die_on_error;
+static int NumLoops = 0;
+static int ignore_dot_errors = 0;
+
+extern char *optarg;
+extern int optind;
 
 /* a test fn for LANMAN mask support */
-int ms_fnmatch_lanman_core(char *pattern, char *string)
+static int ms_fnmatch_lanman_core(const char *pattern, const char *string)
 {
-       char *p = pattern, *n = string;
+       const char *p = pattern, *n = string;
        char c;
 
        if (strcmp(p,"?")==0 && strcmp(n,".")==0) goto match;
@@ -92,9 +94,9 @@ int ms_fnmatch_lanman_core(char *pattern, char *string)
                        n++;
                }
        }
-       
+
        if (! *n) goto match;
-       
+
  nomatch:
        if (verbose) printf("NOMATCH pattern=[%s] string=[%s]\n", pattern, string);
        return -1;
@@ -108,10 +110,12 @@ next:
        return 0;
 }
 
-int ms_fnmatch_lanman(char *pattern, char *string)
+static int ms_fnmatch_lanman(const char *pattern, const char *string)
 {
        if (!strpbrk(pattern, "?*<>\"")) {
-               if (strcmp(string,"..") == 0) string = ".";
+               if (strcmp(string,"..") == 0) 
+                       string = ".";
+
                return strcmp(pattern, string);
        }
 
@@ -123,7 +127,7 @@ int ms_fnmatch_lanman(char *pattern, char *string)
        return ms_fnmatch_lanman_core(pattern, string);
 }
 
-static BOOL reg_match_one(struct cli_state *cli, char *pattern, char *file)
+static bool reg_match_one(struct cli_state *cli, const char *pattern, const char *file)
 {
        /* oh what a weird world this is */
        if (old_list && strcmp(pattern, "*.*") == 0) return True;
@@ -136,20 +140,19 @@ static BOOL reg_match_one(struct cli_state *cli, char *pattern, char *file)
 
        if (strcmp(file,"..") == 0) file = ".";
 
-       return ms_fnmatch(pattern, file, cli->protocol)==0;
+       return ms_fnmatch(pattern, file, cli->protocol, False) == 0;
 }
 
-static char *reg_test(struct cli_state *cli, char *pattern, char *long_name, char *short_name)
+static char *reg_test(struct cli_state *cli, const char *pattern, const char *long_name, const char *short_name)
 {
        static fstring ret;
-       fstrcpy(ret, "---");
+       const char *new_pattern = 1+strrchr_m(pattern,'\\');
 
-       pattern = 1+strrchr_m(pattern,'\\');
-
-       if (reg_match_one(cli, pattern, ".")) ret[0] = '+';
-       if (reg_match_one(cli, pattern, "..")) ret[1] = '+';
-       if (reg_match_one(cli, pattern, long_name) || 
-           (*short_name && reg_match_one(cli, pattern, short_name))) ret[2] = '+';
+       fstrcpy(ret, "---");
+       if (reg_match_one(cli, new_pattern, ".")) ret[0] = '+';
+       if (reg_match_one(cli, new_pattern, "..")) ret[1] = '+';
+       if (reg_match_one(cli, new_pattern, long_name) ||
+           (*short_name && reg_match_one(cli, new_pattern, short_name))) ret[2] = '+';
        return ret;
 }
 
@@ -157,13 +160,14 @@ static char *reg_test(struct cli_state *cli, char *pattern, char *long_name, cha
 /***************************************************** 
 return a connection to a server
 *******************************************************/
-struct cli_state *connect_one(char *share)
+static struct cli_state *connect_one(char *share)
 {
        struct cli_state *c;
        struct nmb_name called, calling;
        char *server_n;
        char *server;
-       struct in_addr ip;
+       struct sockaddr_storage ss;
+       NTSTATUS status;
 
        server = share+2;
        share = strchr_m(server,'\\');
@@ -172,21 +176,27 @@ struct cli_state *connect_one(char *share)
        share++;
 
        server_n = server;
-       
-        zero_ip(&ip);
+
+       zero_sockaddr(&ss);
 
        make_nmb_name(&calling, "masktest", 0x0);
        make_nmb_name(&called , server, 0x20);
 
  again:
-        zero_ip(&ip);
+        zero_sockaddr(&ss);
 
        /* have to open a new connection */
-       if (!(c=cli_initialise(NULL)) || !cli_connect(c, server_n, &ip)) {
+       if (!(c=cli_initialise())) {
                DEBUG(0,("Connection to %s failed\n", server_n));
                return NULL;
        }
 
+       status = cli_connect(c, server_n, &ss);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("Connection to %s failed. Error %s\n", server_n, nt_errstr(status) ));
+               return NULL;
+       }
+
        c->protocol = max_protocol;
 
        if (!cli_session_request(c, &calling, &called)) {
@@ -201,8 +211,10 @@ struct cli_state *connect_one(char *share)
 
        DEBUG(4,(" session request ok\n"));
 
-       if (!cli_negprot(c)) {
-               DEBUG(0,("protocol negotiation failed\n"));
+       status = cli_negprot(c);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("protocol negotiation failed: %s\n",
+                         nt_errstr(status)));
                cli_shutdown(c);
                return NULL;
        }
@@ -210,15 +222,16 @@ struct cli_state *connect_one(char *share)
        if (!got_pass) {
                char *pass = getpass("Password: ");
                if (pass) {
-                       pstrcpy(password, pass);
+                       fstrcpy(password, pass);
                }
        }
 
-       if (!cli_session_setup(c, username, 
-                              password, strlen(password),
-                              password, strlen(password),
-                              lp_workgroup())) {
-               DEBUG(0,("session setup failed: %s\n", cli_errstr(c)));
+       status = cli_session_setup(c, username,
+                                  password, strlen(password),
+                                  password, strlen(password),
+                                  lp_workgroup());
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("session setup failed: %s\n", nt_errstr(status)));
                return NULL;
        }
 
@@ -233,12 +246,13 @@ struct cli_state *connect_one(char *share)
        if (*c->server_domain || *c->server_os || *c->server_type)
                DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
                        c->server_domain,c->server_os,c->server_type));
-       
+
        DEBUG(4,(" session setup ok\n"));
 
-       if (!cli_send_tconX(c, share, "?????",
-                           password, strlen(password)+1)) {
-               DEBUG(0,("tree connect failed: %s\n", cli_errstr(c)));
+       status = cli_tcon_andx(c, share, "?????", password,
+                              strlen(password)+1);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("tree connect failed: %s\n", nt_errstr(status)));
                cli_shutdown(c);
                return NULL;
        }
@@ -249,39 +263,64 @@ struct cli_state *connect_one(char *share)
 }
 
 static char *resultp;
-static file_info *f_info;
 
-void listfn(file_info *f, const char *s, void *state)
+struct rn_state {
+       char **pp_long_name;
+       char *short_name;
+};
+
+static NTSTATUS listfn(const char *mnt, struct file_info *f, const char *s,
+                  void *private_data)
 {
+       struct rn_state *state = (struct rn_state *)private_data;
        if (strcmp(f->name,".") == 0) {
                resultp[0] = '+';
        } else if (strcmp(f->name,"..") == 0) {
-               resultp[1] = '+';               
+               resultp[1] = '+';
        } else {
                resultp[2] = '+';
        }
-       f_info = f;
+
+       if (state == NULL) {
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
+       if (ISDOT(f->name) || ISDOTDOT(f->name))  {
+               return NT_STATUS_OK;
+       }
+
+       fstrcpy(state->short_name, f->short_name);
+       strlower_m(state->short_name);
+       *state->pp_long_name = SMB_STRDUP(f->name);
+       if (!*state->pp_long_name) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       strlower_m(*state->pp_long_name);
+       return NT_STATUS_OK;
 }
 
-static void get_real_name(struct cli_state *cli, 
-                         pstring long_name, fstring short_name)
+static void get_real_name(struct cli_state *cli,
+                         char **pp_long_name, fstring short_name)
 {
+       struct rn_state state;
+
+       state.pp_long_name = pp_long_name;
+       state.short_name = short_name;
+
+       *pp_long_name = NULL;
        /* nasty hack to force level 260 listings - tridge */
-       cli->capabilities |= CAP_NT_SMBS;
        if (max_protocol <= PROTOCOL_LANMAN1) {
-               cli_list_new(cli, "\\masktest\\*.*", aHIDDEN | aDIR, listfn, NULL);
+               cli_list_trans(cli, "\\masktest\\*.*", aHIDDEN | aDIR,
+                              SMB_FIND_FILE_BOTH_DIRECTORY_INFO, listfn,
+                              &state);
        } else {
-               cli_list_new(cli, "\\masktest\\*", aHIDDEN | aDIR, listfn, NULL);
-       }
-       if (f_info) {
-               fstrcpy(short_name, f_info->short_name);
-               strlower(short_name);
-               pstrcpy(long_name, f_info->name);
-               strlower(long_name);
+               cli_list_trans(cli, "\\masktest\\*", aHIDDEN | aDIR,
+                              SMB_FIND_FILE_BOTH_DIRECTORY_INFO,
+                              listfn, &state);
        }
 
        if (*short_name == 0) {
-               fstrcpy(short_name, long_name);
+               fstrcpy(short_name, *pp_long_name);
        }
 
 #if 0
@@ -291,21 +330,20 @@ static void get_real_name(struct cli_state *cli,
 #endif
 }
 
-static void testpair(struct cli_state *cli, char *mask, char *file)
+static void testpair(struct cli_state *cli, const char *mask, const char *file)
 {
-       int fnum;
+       uint16_t fnum;
        fstring res1;
        char *res2;
        static int count;
        fstring short_name;
-       pstring long_name;
+       char *long_name = NULL;
 
        count++;
 
        fstrcpy(res1, "---");
 
-       fnum = cli_open(cli, file, O_CREAT|O_TRUNC|O_RDWR, 0);
-       if (fnum == -1) {
+       if (!NT_STATUS_IS_OK(cli_open(cli, file, O_CREAT|O_TRUNC|O_RDWR, 0, &fnum))) {
                DEBUG(0,("Can't create %s\n", file));
                return;
        }
@@ -313,43 +351,53 @@ static void testpair(struct cli_state *cli, char *mask, char *file)
 
        resultp = res1;
        fstrcpy(short_name, "");
-       f_info = NULL;
-       get_real_name(cli, long_name, short_name);
-       f_info = NULL;
+       get_real_name(cli, &long_name, short_name);
+       if (!long_name) {
+               return;
+       }
        fstrcpy(res1, "---");
        cli_list(cli, mask, aHIDDEN | aDIR, listfn, NULL);
 
        res2 = reg_test(cli, mask, long_name, short_name);
 
-       if (showall || strcmp(res1, res2)) {
+       if (showall ||
+           ((strcmp(res1, res2) && !ignore_dot_errors) ||
+            (strcmp(res1+2, res2+2) && ignore_dot_errors))) {
                DEBUG(0,("%s %s %d mask=[%s] file=[%s] rfile=[%s/%s]\n",
                         res1, res2, count, mask, file, long_name, short_name));
                if (die_on_error) exit(1);
        }
 
-       cli_unlink(cli, file);
+       cli_unlink(cli, file, aSYSTEM | aHIDDEN);
 
        if (count % 100 == 0) DEBUG(0,("%d\n", count));
+       SAFE_FREE(long_name);
 }
 
-static void test_mask(int argc, char *argv[], 
+static void test_mask(int argc, char *argv[],
                      struct cli_state *cli)
 {
-       pstring mask, file;
+       char *mask, *file;
        int l1, l2, i, l;
        int mc_len = strlen(maskchars);
        int fc_len = strlen(filechars);
+       TALLOC_CTX *ctx = talloc_tos();
 
        cli_mkdir(cli, "\\masktest");
 
-       cli_unlink(cli, "\\masktest\\*");
+       cli_unlink(cli, "\\masktest\\*", aSYSTEM | aHIDDEN);
 
        if (argc >= 2) {
                while (argc >= 2) {
-                       pstrcpy(mask,"\\masktest\\");
-                       pstrcpy(file,"\\masktest\\");
-                       pstrcat(mask, argv[0]);
-                       pstrcat(file, argv[1]);
+                       mask = talloc_asprintf(ctx,
+                                       "\\masktest\\%s",
+                                       argv[0]);
+                       file = talloc_asprintf(ctx,
+                                       "\\masktest\\%s",
+                                       argv[1]);
+                       if (!mask || !file) {
+                               goto finished;
+                       }
                        testpair(cli, mask, file);
                        argv += 2;
                        argc -= 2;
@@ -360,8 +408,13 @@ static void test_mask(int argc, char *argv[],
        while (1) {
                l1 = 1 + random() % 20;
                l2 = 1 + random() % 20;
-               pstrcpy(mask,"\\masktest\\");
-               pstrcpy(file,"\\masktest\\");
+               mask = TALLOC_ARRAY(ctx, char, strlen("\\masktest\\")+1+22);
+               file = TALLOC_ARRAY(ctx, char, strlen("\\masktest\\")+1+22);
+               if (!mask || !file) {
+                       goto finished;
+               }
+               memcpy(mask,"\\masktest\\",strlen("\\masktest\\")+1);
+               memcpy(file,"\\masktest\\",strlen("\\masktest\\")+1);
                l = strlen(mask);
                for (i=0;i<l1;i++) {
                        mask[i+l] = maskchars[random() % mc_len];
@@ -380,6 +433,10 @@ static void test_mask(int argc, char *argv[],
                if (strspn(file+l, ".") == strlen(file+l)) continue;
 
                testpair(cli, mask, file);
+               if (NumLoops && (--NumLoops == 0))
+                       break;
+               TALLOC_FREE(mask);
+               TALLOC_FREE(file);
        }
 
  finished:
@@ -394,6 +451,7 @@ static void usage(void)
   masktest //server/share [options..]\n\
   options:\n\
        -d debuglevel\n\
+       -n numloops\n\
         -W workgroup\n\
         -U user%%pass\n\
         -s seed\n\
@@ -403,6 +461,7 @@ static void usage(void)
        -v                             verbose mode\n\
        -E                             die on error\n\
         -a                             show all tests\n\
+        -i                             ignore . and .. errors\n\
 \n\
   This program tests wildcard matching between two servers. It generates\n\
   random pairs of filenames/masks and tests that they match in the same\n\
@@ -417,20 +476,15 @@ static void usage(void)
  int main(int argc,char *argv[])
 {
        char *share;
-       struct cli_state *cli;  
-       extern char *optarg;
-       extern int optind;
-       extern BOOL AllowDebugChange;
+       struct cli_state *cli;
        int opt;
        char *p;
        int seed;
+       TALLOC_CTX *frame = talloc_stackframe();
 
        setlinebuf(stdout);
 
-       dbf = x_stderr;
-
-       DEBUGLEVEL = 0;
-       AllowDebugChange = False;
+       lp_set_cmdline("log level", "0");
 
        if (argc < 2 || argv[1][0] == '-') {
                usage();
@@ -441,28 +495,35 @@ static void usage(void)
 
        all_string_sub(share,"/","\\",0);
 
-       setup_logging(argv[0],True);
+       setup_logging(argv[0], DEBUG_STDERR);
 
        argc -= 1;
        argv += 1;
 
-       lp_load(dyn_CONFIGFILE,True,False,False);
+       load_case_tables();
+       lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
        load_interfaces();
 
        if (getenv("USER")) {
-               pstrcpy(username,getenv("USER"));
+               fstrcpy(username,getenv("USER"));
        }
 
        seed = time(NULL);
 
-       while ((opt = getopt(argc, argv, "d:U:s:hm:f:aoW:M:vE")) != EOF) {
+       while ((opt = getopt(argc, argv, "n:d:U:s:hm:f:aoW:M:vEi")) != EOF) {
                switch (opt) {
+               case 'n':
+                       NumLoops = atoi(optarg);
+                       break;
                case 'd':
-                       DEBUGLEVEL = atoi(optarg);
+                       lp_set_cmdline("log level", optarg);
                        break;
                case 'E':
                        die_on_error = 1;
                        break;
+               case 'i':
+                       ignore_dot_errors = 1;
+                       break;
                case 'v':
                        verbose++;
                        break;
@@ -470,11 +531,11 @@ static void usage(void)
                        max_protocol = interpret_protocol(optarg, max_protocol);
                        break;
                case 'U':
-                       pstrcpy(username,optarg);
+                       fstrcpy(username,optarg);
                        p = strchr_m(username,'%');
                        if (p) {
                                *p = 0;
-                               pstrcpy(password, p+1);
+                               fstrcpy(password, p+1);
                                got_pass = 1;
                        }
                        break;
@@ -518,5 +579,6 @@ static void usage(void)
 
        test_mask(argc, argv, cli);
 
+       TALLOC_FREE(frame);
        return(0);
 }