torture/masktest.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    mask_match tester
00004    Copyright (C) Andrew Tridgell 1999
00005    
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 #include "includes.h"
00022 
00023 static fstring password;
00024 static fstring username;
00025 static int got_pass;
00026 static int max_protocol = PROTOCOL_NT1;
00027 static BOOL showall = False;
00028 static BOOL old_list = False;
00029 static const char *maskchars = "<>\"?*abc.";
00030 static const char *filechars = "abcdefghijklm.";
00031 static int verbose;
00032 static int die_on_error;
00033 static int NumLoops = 0;
00034 static int ignore_dot_errors = 0;
00035 
00036 extern char *optarg;
00037 extern int optind;
00038 extern BOOL AllowDebugChange;
00039 
00040 /* a test fn for LANMAN mask support */
00041 static int ms_fnmatch_lanman_core(const char *pattern, const char *string)
00042 {
00043         const char *p = pattern, *n = string;
00044         char c;
00045 
00046         if (strcmp(p,"?")==0 && strcmp(n,".")==0) goto match;
00047 
00048         while ((c = *p++)) {
00049                 switch (c) {
00050                 case '.':
00051                         /* if (! *n && ! *p) goto match; */
00052                         if (*n != '.') goto nomatch;
00053                         n++;
00054                         break;
00055 
00056                 case '?':
00057                         if ((*n == '.' && n[1] != '.') || ! *n) goto next;
00058                         n++;
00059                         break;
00060 
00061                 case '>':
00062                         if (n[0] == '.') {
00063                                 if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match;
00064                                 if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
00065                                 goto nomatch;
00066                         }
00067                         if (! *n) goto next;
00068                         n++;
00069                         break;
00070 
00071                 case '*':
00072                         if (! *p) goto match;
00073                         for (; *n; n++) {
00074                                 if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
00075                         }
00076                         break;
00077 
00078                 case '<':
00079                         for (; *n; n++) {
00080                                 if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
00081                                 if (*n == '.' && !strchr_m(n+1,'.')) {
00082                                         n++;
00083                                         break;
00084                                 }
00085                         }
00086                         break;
00087 
00088                 case '"':
00089                         if (*n == 0 && ms_fnmatch_lanman_core(p, n) == 0) goto match;
00090                         if (*n != '.') goto nomatch;
00091                         n++;
00092                         break;
00093 
00094                 default:
00095                         if (c != *n) goto nomatch;
00096                         n++;
00097                 }
00098         }
00099         
00100         if (! *n) goto match;
00101         
00102  nomatch:
00103         if (verbose) printf("NOMATCH pattern=[%s] string=[%s]\n", pattern, string);
00104         return -1;
00105 
00106 next:
00107         if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
00108         goto nomatch;
00109 
00110  match:
00111         if (verbose) printf("MATCH   pattern=[%s] string=[%s]\n", pattern, string);
00112         return 0;
00113 }
00114 
00115 static int ms_fnmatch_lanman(const char *pattern, const char *string)
00116 {
00117         if (!strpbrk(pattern, "?*<>\"")) {
00118                 if (strcmp(string,"..") == 0) 
00119                         string = ".";
00120 
00121                 return strcmp(pattern, string);
00122         }
00123 
00124         if (strcmp(string,"..") == 0 || strcmp(string,".") == 0) {
00125                 return ms_fnmatch_lanman_core(pattern, "..") &&
00126                         ms_fnmatch_lanman_core(pattern, ".");
00127         }
00128 
00129         return ms_fnmatch_lanman_core(pattern, string);
00130 }
00131 
00132 static BOOL reg_match_one(struct cli_state *cli, const char *pattern, const char *file)
00133 {
00134         /* oh what a weird world this is */
00135         if (old_list && strcmp(pattern, "*.*") == 0) return True;
00136 
00137         if (strcmp(pattern,".") == 0) return False;
00138 
00139         if (max_protocol <= PROTOCOL_LANMAN2) {
00140                 return ms_fnmatch_lanman(pattern, file)==0;
00141         }
00142 
00143         if (strcmp(file,"..") == 0) file = ".";
00144 
00145         return ms_fnmatch(pattern, file, cli->protocol, False) == 0;
00146 }
00147 
00148 static char *reg_test(struct cli_state *cli, char *pattern, char *long_name, char *short_name)
00149 {
00150         static fstring ret;
00151         fstrcpy(ret, "---");
00152 
00153         pattern = 1+strrchr_m(pattern,'\\');
00154 
00155         if (reg_match_one(cli, pattern, ".")) ret[0] = '+';
00156         if (reg_match_one(cli, pattern, "..")) ret[1] = '+';
00157         if (reg_match_one(cli, pattern, long_name) || 
00158             (*short_name && reg_match_one(cli, pattern, short_name))) ret[2] = '+';
00159         return ret;
00160 }
00161 
00162 
00163 /***************************************************** 
00164 return a connection to a server
00165 *******************************************************/
00166 static struct cli_state *connect_one(char *share)
00167 {
00168         struct cli_state *c;
00169         struct nmb_name called, calling;
00170         char *server_n;
00171         char *server;
00172         struct in_addr ip;
00173         NTSTATUS status;
00174 
00175         server = share+2;
00176         share = strchr_m(server,'\\');
00177         if (!share) return NULL;
00178         *share = 0;
00179         share++;
00180 
00181         server_n = server;
00182         
00183         zero_ip(&ip);
00184 
00185         make_nmb_name(&calling, "masktest", 0x0);
00186         make_nmb_name(&called , server, 0x20);
00187 
00188  again:
00189         zero_ip(&ip);
00190 
00191         /* have to open a new connection */
00192         if (!(c=cli_initialise())) {
00193                 DEBUG(0,("Connection to %s failed\n", server_n));
00194                 return NULL;
00195         }
00196 
00197         status = cli_connect(c, server_n, &ip);
00198         if (!NT_STATUS_IS_OK(status)) {
00199                 DEBUG(0,("Connection to %s failed. Error %s\n", server_n, nt_errstr(status) ));
00200                 return NULL;
00201         }
00202 
00203         c->protocol = max_protocol;
00204 
00205         if (!cli_session_request(c, &calling, &called)) {
00206                 DEBUG(0,("session request to %s failed\n", called.name));
00207                 cli_shutdown(c);
00208                 if (strcmp(called.name, "*SMBSERVER")) {
00209                         make_nmb_name(&called , "*SMBSERVER", 0x20);
00210                         goto again;
00211                 }
00212                 return NULL;
00213         }
00214 
00215         DEBUG(4,(" session request ok\n"));
00216 
00217         if (!cli_negprot(c)) {
00218                 DEBUG(0,("protocol negotiation failed\n"));
00219                 cli_shutdown(c);
00220                 return NULL;
00221         }
00222 
00223         if (!got_pass) {
00224                 char *pass = getpass("Password: ");
00225                 if (pass) {
00226                         fstrcpy(password, pass);
00227                 }
00228         }
00229 
00230         if (!NT_STATUS_IS_OK(cli_session_setup(c, username, 
00231                                                password, strlen(password),
00232                                                password, strlen(password),
00233                                                lp_workgroup()))) {
00234                 DEBUG(0,("session setup failed: %s\n", cli_errstr(c)));
00235                 return NULL;
00236         }
00237 
00238         /*
00239          * These next two lines are needed to emulate
00240          * old client behaviour for people who have
00241          * scripts based on client output.
00242          * QUESTION ? Do we want to have a 'client compatibility
00243          * mode to turn these on/off ? JRA.
00244          */
00245 
00246         if (*c->server_domain || *c->server_os || *c->server_type)
00247                 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
00248                         c->server_domain,c->server_os,c->server_type));
00249         
00250         DEBUG(4,(" session setup ok\n"));
00251 
00252         if (!cli_send_tconX(c, share, "?????",
00253                             password, strlen(password)+1)) {
00254                 DEBUG(0,("tree connect failed: %s\n", cli_errstr(c)));
00255                 cli_shutdown(c);
00256                 return NULL;
00257         }
00258 
00259         DEBUG(4,(" tconx ok\n"));
00260 
00261         return c;
00262 }
00263 
00264 static char *resultp;
00265 static file_info *f_info;
00266 
00267 static void listfn(const char *mnt, file_info *f, const char *s, void *state)
00268 {
00269         if (strcmp(f->name,".") == 0) {
00270                 resultp[0] = '+';
00271         } else if (strcmp(f->name,"..") == 0) {
00272                 resultp[1] = '+';               
00273         } else {
00274                 resultp[2] = '+';
00275         }
00276         f_info = f;
00277 }
00278 
00279 static void get_real_name(struct cli_state *cli, 
00280                           pstring long_name, fstring short_name)
00281 {
00282         /* nasty hack to force level 260 listings - tridge */
00283         cli->capabilities |= CAP_NT_SMBS;
00284         if (max_protocol <= PROTOCOL_LANMAN1) {
00285                 cli_list_new(cli, "\\masktest\\*.*", aHIDDEN | aDIR, listfn, NULL);
00286         } else {
00287                 cli_list_new(cli, "\\masktest\\*", aHIDDEN | aDIR, listfn, NULL);
00288         }
00289         if (f_info) {
00290                 fstrcpy(short_name, f_info->short_name);
00291                 strlower_m(short_name);
00292                 pstrcpy(long_name, f_info->name);
00293                 strlower_m(long_name);
00294         }
00295 
00296         if (*short_name == 0) {
00297                 fstrcpy(short_name, long_name);
00298         }
00299 
00300 #if 0
00301         if (!strchr_m(short_name,'.')) {
00302                 fstrcat(short_name,".");
00303         }
00304 #endif
00305 }
00306 
00307 static void testpair(struct cli_state *cli, char *mask, char *file)
00308 {
00309         int fnum;
00310         fstring res1;
00311         char *res2;
00312         static int count;
00313         fstring short_name;
00314         pstring long_name;
00315 
00316         count++;
00317 
00318         fstrcpy(res1, "---");
00319 
00320         fnum = cli_open(cli, file, O_CREAT|O_TRUNC|O_RDWR, 0);
00321         if (fnum == -1) {
00322                 DEBUG(0,("Can't create %s\n", file));
00323                 return;
00324         }
00325         cli_close(cli, fnum);
00326 
00327         resultp = res1;
00328         fstrcpy(short_name, "");
00329         f_info = NULL;
00330         get_real_name(cli, long_name, short_name);
00331         f_info = NULL;
00332         fstrcpy(res1, "---");
00333         cli_list(cli, mask, aHIDDEN | aDIR, listfn, NULL);
00334 
00335         res2 = reg_test(cli, mask, long_name, short_name);
00336 
00337         if (showall || 
00338             ((strcmp(res1, res2) && !ignore_dot_errors) ||
00339              (strcmp(res1+2, res2+2) && ignore_dot_errors))) {
00340                 DEBUG(0,("%s %s %d mask=[%s] file=[%s] rfile=[%s/%s]\n",
00341                          res1, res2, count, mask, file, long_name, short_name));
00342                 if (die_on_error) exit(1);
00343         }
00344 
00345         cli_unlink(cli, file);
00346 
00347         if (count % 100 == 0) DEBUG(0,("%d\n", count));
00348 }
00349 
00350 static void test_mask(int argc, char *argv[], 
00351                       struct cli_state *cli)
00352 {
00353         pstring mask, file;
00354         int l1, l2, i, l;
00355         int mc_len = strlen(maskchars);
00356         int fc_len = strlen(filechars);
00357 
00358         cli_mkdir(cli, "\\masktest");
00359 
00360         cli_unlink(cli, "\\masktest\\*");
00361 
00362         if (argc >= 2) {
00363                 while (argc >= 2) {
00364                         pstrcpy(mask,"\\masktest\\");
00365                         pstrcpy(file,"\\masktest\\");
00366                         pstrcat(mask, argv[0]);
00367                         pstrcat(file, argv[1]);
00368                         testpair(cli, mask, file);
00369                         argv += 2;
00370                         argc -= 2;
00371                 }
00372                 goto finished;
00373         }
00374 
00375         while (1) {
00376                 l1 = 1 + random() % 20;
00377                 l2 = 1 + random() % 20;
00378                 pstrcpy(mask,"\\masktest\\");
00379                 pstrcpy(file,"\\masktest\\");
00380                 l = strlen(mask);
00381                 for (i=0;i<l1;i++) {
00382                         mask[i+l] = maskchars[random() % mc_len];
00383                 }
00384                 mask[l+l1] = 0;
00385 
00386                 for (i=0;i<l2;i++) {
00387                         file[i+l] = filechars[random() % fc_len];
00388                 }
00389                 file[l+l2] = 0;
00390 
00391                 if (strcmp(file+l,".") == 0 || 
00392                     strcmp(file+l,"..") == 0 ||
00393                     strcmp(mask+l,"..") == 0) continue;
00394 
00395                 if (strspn(file+l, ".") == strlen(file+l)) continue;
00396 
00397                 testpair(cli, mask, file);
00398                 if (NumLoops && (--NumLoops == 0))
00399                         break;
00400         }
00401 
00402  finished:
00403         cli_rmdir(cli, "\\masktest");
00404 }
00405 
00406 
00407 static void usage(void)
00408 {
00409         printf(
00410 "Usage:\n\
00411   masktest //server/share [options..]\n\
00412   options:\n\
00413         -d debuglevel\n\
00414         -n numloops\n\
00415         -W workgroup\n\
00416         -U user%%pass\n\
00417         -s seed\n\
00418         -M max protocol\n\
00419         -f filechars (default %s)\n\
00420         -m maskchars (default %s)\n\
00421         -v                             verbose mode\n\
00422         -E                             die on error\n\
00423         -a                             show all tests\n\
00424         -i                             ignore . and .. errors\n\
00425 \n\
00426   This program tests wildcard matching between two servers. It generates\n\
00427   random pairs of filenames/masks and tests that they match in the same\n\
00428   way on the servers and internally\n\
00429 ", 
00430   filechars, maskchars);
00431 }
00432 
00433 /****************************************************************************
00434   main program
00435 ****************************************************************************/
00436  int main(int argc,char *argv[])
00437 {
00438         char *share;
00439         struct cli_state *cli;  
00440         int opt;
00441         char *p;
00442         int seed;
00443 
00444         setlinebuf(stdout);
00445 
00446         dbf = x_stderr;
00447 
00448         DEBUGLEVEL = 0;
00449         AllowDebugChange = False;
00450 
00451         if (argc < 2 || argv[1][0] == '-') {
00452                 usage();
00453                 exit(1);
00454         }
00455 
00456         share = argv[1];
00457 
00458         all_string_sub(share,"/","\\",0);
00459 
00460         setup_logging(argv[0],True);
00461 
00462         argc -= 1;
00463         argv += 1;
00464 
00465         lp_load(dyn_CONFIGFILE,True,False,False,True);
00466         load_interfaces();
00467 
00468         if (getenv("USER")) {
00469                 fstrcpy(username,getenv("USER"));
00470         }
00471 
00472         seed = time(NULL);
00473 
00474         while ((opt = getopt(argc, argv, "n:d:U:s:hm:f:aoW:M:vEi")) != EOF) {
00475                 switch (opt) {
00476                 case 'n':
00477                         NumLoops = atoi(optarg);
00478                         break;
00479                 case 'd':
00480                         DEBUGLEVEL = atoi(optarg);
00481                         break;
00482                 case 'E':
00483                         die_on_error = 1;
00484                         break;
00485                 case 'i':
00486                         ignore_dot_errors = 1;
00487                         break;
00488                 case 'v':
00489                         verbose++;
00490                         break;
00491                 case 'M':
00492                         max_protocol = interpret_protocol(optarg, max_protocol);
00493                         break;
00494                 case 'U':
00495                         fstrcpy(username,optarg);
00496                         p = strchr_m(username,'%');
00497                         if (p) {
00498                                 *p = 0;
00499                                 fstrcpy(password, p+1);
00500                                 got_pass = 1;
00501                         }
00502                         break;
00503                 case 's':
00504                         seed = atoi(optarg);
00505                         break;
00506                 case 'h':
00507                         usage();
00508                         exit(1);
00509                 case 'm':
00510                         maskchars = optarg;
00511                         break;
00512                 case 'f':
00513                         filechars = optarg;
00514                         break;
00515                 case 'a':
00516                         showall = 1;
00517                         break;
00518                 case 'o':
00519                         old_list = True;
00520                         break;
00521                 default:
00522                         printf("Unknown option %c (%d)\n", (char)opt, opt);
00523                         exit(1);
00524                 }
00525         }
00526 
00527         argc -= optind;
00528         argv += optind;
00529 
00530 
00531         cli = connect_one(share);
00532         if (!cli) {
00533                 DEBUG(0,("Failed to connect to %s\n", share));
00534                 exit(1);
00535         }
00536 
00537         /* need to init seed after connect as clientgen uses random numbers */
00538         DEBUG(0,("seed=%d\n", seed));
00539         srandom(seed);
00540 
00541         test_mask(argc, argv, cli);
00542 
00543         return(0);
00544 }

Sambaに対してSat Aug 29 21:23:27 2009に生成されました。  doxygen 1.4.7