~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/torture/masktest.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
   mask_match tester
 
4
   Copyright (C) Andrew Tridgell 1999
 
5
   
 
6
   This program is free software; you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by
 
8
   the Free Software Foundation; either version 3 of the License, or
 
9
   (at your option) any later version.
 
10
   
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
   
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
#include "includes.h"
 
21
#include "lib/cmdline/popt_common.h"
 
22
#include "system/filesys.h"
 
23
#include "system/dir.h"
 
24
#include "libcli/libcli.h"
 
25
#include "libcli/raw/libcliraw.h"
 
26
#include "system/time.h"
 
27
#include "auth/credentials/credentials.h"
 
28
#include "auth/gensec/gensec.h"
 
29
#include "param/param.h"
 
30
#include "dynconfig/dynconfig.h"
 
31
#include "libcli/resolve/resolve.h"
 
32
#include "lib/events/events.h"
 
33
 
 
34
static bool showall = false;
 
35
static bool old_list = false;
 
36
static const char *maskchars = "<>\"?*abc.";
 
37
static const char *filechars = "abcdefghijklm.";
 
38
static int die_on_error;
 
39
static int NumLoops = 0;
 
40
static int max_length = 20;
 
41
struct masktest_state {
 
42
        TALLOC_CTX *mem_ctx;
 
43
};
 
44
 
 
45
static bool reg_match_one(struct smbcli_state *cli, const char *pattern, const char *file)
 
46
{
 
47
        /* oh what a weird world this is */
 
48
        if (old_list && strcmp(pattern, "*.*") == 0) return true;
 
49
 
 
50
        if (ISDOT(pattern)) return false;
 
51
 
 
52
        if (ISDOTDOT(file)) file = ".";
 
53
 
 
54
        return ms_fnmatch(pattern, file, cli->transport->negotiate.protocol)==0;
 
55
}
 
56
 
 
57
static char *reg_test(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char *pattern, const char *long_name, const char *short_name)
 
58
{
 
59
        char *ret;
 
60
        ret = talloc_strdup(mem_ctx, "---");
 
61
 
 
62
        pattern = 1+strrchr_m(pattern,'\\');
 
63
 
 
64
        if (reg_match_one(cli, pattern, ".")) ret[0] = '+';
 
65
        if (reg_match_one(cli, pattern, "..")) ret[1] = '+';
 
66
        if (reg_match_one(cli, pattern, long_name) || 
 
67
            (*short_name && reg_match_one(cli, pattern, short_name))) ret[2] = '+';
 
68
        return ret;
 
69
}
 
70
 
 
71
 
 
72
/***************************************************** 
 
73
return a connection to a server
 
74
*******************************************************/
 
75
static struct smbcli_state *connect_one(struct resolve_context *resolve_ctx, 
 
76
                                        struct tevent_context *ev,
 
77
                                        TALLOC_CTX *mem_ctx,
 
78
                                        char *share, const char **ports,
 
79
                                        const char *socket_options,
 
80
                                        struct smbcli_options *options,
 
81
                                        struct smbcli_session_options *session_options,
 
82
                                        struct smb_iconv_convenience *iconv_convenience,
 
83
                                        struct gensec_settings *gensec_settings)
 
84
{
 
85
        struct smbcli_state *c;
 
86
        char *server;
 
87
        NTSTATUS status;
 
88
 
 
89
        server = talloc_strdup(mem_ctx, share+2);
 
90
        share = strchr_m(server,'\\');
 
91
        if (!share) return NULL;
 
92
        *share = 0;
 
93
        share++;
 
94
 
 
95
        cli_credentials_set_workstation(cmdline_credentials, "masktest", CRED_SPECIFIED);
 
96
 
 
97
        status = smbcli_full_connection(NULL, &c,
 
98
                                        server, 
 
99
                                        ports,
 
100
                                        share, NULL,
 
101
                                        socket_options,
 
102
                                        cmdline_credentials, resolve_ctx, ev,
 
103
                                        options, session_options,
 
104
                                        iconv_convenience,
 
105
                                        gensec_settings);
 
106
 
 
107
        if (!NT_STATUS_IS_OK(status)) {
 
108
                return NULL;
 
109
        }
 
110
 
 
111
        return c;
 
112
}
 
113
 
 
114
static char *resultp;
 
115
static struct {
 
116
        char *long_name;
 
117
        char *short_name;
 
118
} last_hit;
 
119
static bool f_info_hit;
 
120
 
 
121
static void listfn(struct clilist_file_info *f, const char *s, void *state)
 
122
{
 
123
        struct masktest_state *m = (struct masktest_state *)state;
 
124
 
 
125
        if (ISDOT(f->name)) {
 
126
                resultp[0] = '+';
 
127
        } else if (ISDOTDOT(f->name)) {
 
128
                resultp[1] = '+';
 
129
        } else {
 
130
                resultp[2] = '+';
 
131
        }
 
132
 
 
133
        last_hit.long_name = talloc_strdup(m->mem_ctx, f->name);
 
134
        last_hit.short_name = talloc_strdup(m->mem_ctx, f->short_name);
 
135
        f_info_hit = true;
 
136
}
 
137
 
 
138
static void get_real_name(TALLOC_CTX *mem_ctx, struct smbcli_state *cli,
 
139
                          char **long_name, char **short_name)
 
140
{
 
141
        const char *mask;
 
142
        struct masktest_state state;
 
143
 
 
144
        if (cli->transport->negotiate.protocol <= PROTOCOL_LANMAN1) {
 
145
                mask = "\\masktest\\*.*";
 
146
        } else {
 
147
                mask = "\\masktest\\*";
 
148
        }
 
149
 
 
150
        f_info_hit = false;
 
151
 
 
152
        state.mem_ctx = mem_ctx;
 
153
 
 
154
        smbcli_list_new(cli->tree, mask,
 
155
                        FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY,
 
156
                        RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO,
 
157
                        listfn, &state);
 
158
 
 
159
        if (f_info_hit) {
 
160
                *short_name = talloc_strdup(mem_ctx, last_hit.short_name);
 
161
                strlower(*short_name);
 
162
                *long_name = talloc_strdup(mem_ctx, last_hit.long_name);
 
163
                strlower(*long_name);
 
164
        }
 
165
 
 
166
        if (*short_name == '\0') {
 
167
                *short_name = talloc_strdup(mem_ctx, *long_name);
 
168
        }
 
169
}
 
170
 
 
171
static void testpair(TALLOC_CTX *mem_ctx, struct smbcli_state *cli, char *mask,
 
172
                char *file)
 
173
{
 
174
        int fnum;
 
175
        char res1[256];
 
176
        char *res2;
 
177
        static int count;
 
178
        char *short_name = NULL;
 
179
        char *long_name = NULL;
 
180
        struct masktest_state state;
 
181
 
 
182
        count++;
 
183
 
 
184
        safe_strcpy(res1, "---", sizeof(res1));
 
185
 
 
186
        state.mem_ctx = mem_ctx;
 
187
 
 
188
        fnum = smbcli_open(cli->tree, file, O_CREAT|O_TRUNC|O_RDWR, 0);
 
189
        if (fnum == -1) {
 
190
                DEBUG(0,("Can't create %s\n", file));
 
191
                return;
 
192
        }
 
193
        smbcli_close(cli->tree, fnum);
 
194
 
 
195
        resultp = res1;
 
196
        short_name = talloc_strdup(mem_ctx, "");
 
197
        get_real_name(mem_ctx, cli, &long_name, &short_name);
 
198
        safe_strcpy(res1, "---", sizeof(res1));
 
199
        smbcli_list_new(cli->tree, mask,
 
200
                        FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY,
 
201
                        RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO,
 
202
                        listfn, &state);
 
203
 
 
204
        res2 = reg_test(cli, mem_ctx, mask, long_name, short_name);
 
205
 
 
206
        if (showall || strcmp(res1, res2)) {
 
207
                d_printf("%s %s %d mask=[%s] file=[%s] rfile=[%s/%s]\n",
 
208
                         res1, res2, count, mask, file, long_name, short_name);
 
209
                if (die_on_error) exit(1);
 
210
        }
 
211
 
 
212
        smbcli_unlink(cli->tree, file);
 
213
 
 
214
        if (count % 100 == 0) DEBUG(0,("%d\n", count));
 
215
 
 
216
        resultp = NULL;
 
217
}
 
218
 
 
219
static void test_mask(int argc, char *argv[],
 
220
                                          TALLOC_CTX *mem_ctx,
 
221
                      struct smbcli_state *cli)
 
222
{
 
223
        char *mask, *file;
 
224
        int l1, l2, i, l;
 
225
        int mc_len = strlen(maskchars);
 
226
        int fc_len = strlen(filechars);
 
227
 
 
228
        smbcli_mkdir(cli->tree, "\\masktest");
 
229
 
 
230
        smbcli_unlink(cli->tree, "\\masktest\\*");
 
231
 
 
232
        if (argc >= 2) {
 
233
                while (argc >= 2) {
 
234
                        mask = talloc_strdup(mem_ctx, "\\masktest\\");
 
235
                        file = talloc_strdup(mem_ctx, "\\masktest\\");
 
236
                        mask = talloc_strdup_append(mask, argv[0]);
 
237
                        file = talloc_strdup_append(file, argv[1]);
 
238
                        testpair(mem_ctx, cli, mask, file);
 
239
                        argv += 2;
 
240
                        argc -= 2;
 
241
                }
 
242
                goto finished;
 
243
        }
 
244
 
 
245
        while (1) {
 
246
                l1 = 1 + random() % max_length;
 
247
                l2 = 1 + random() % max_length;
 
248
                mask = talloc_strdup(mem_ctx, "\\masktest\\");
 
249
                file = talloc_strdup(mem_ctx, "\\masktest\\");
 
250
                mask = talloc_realloc_size(mem_ctx, mask, strlen(mask)+l1+1);
 
251
                file = talloc_realloc_size(mem_ctx, file, strlen(file)+l2+1);
 
252
                l = strlen(mask);
 
253
                for (i=0;i<l1;i++) {
 
254
                        mask[i+l] = maskchars[random() % mc_len];
 
255
                }
 
256
                mask[l+l1] = 0;
 
257
 
 
258
                for (i=0;i<l2;i++) {
 
259
                        file[i+l] = filechars[random() % fc_len];
 
260
                }
 
261
                file[l+l2] = 0;
 
262
 
 
263
                if (ISDOT(file+l) || ISDOTDOT(file+l) || ISDOTDOT(mask+l)) {
 
264
                        continue;
 
265
                }
 
266
 
 
267
                if (strspn(file+l, ".") == strlen(file+l)) continue;
 
268
 
 
269
                testpair(mem_ctx, cli, mask, file);
 
270
                if (NumLoops && (--NumLoops == 0))
 
271
                        break;
 
272
        }
 
273
 
 
274
 finished:
 
275
        smbcli_rmdir(cli->tree, "\\masktest");
 
276
        talloc_free(mem_ctx);
 
277
}
 
278
 
 
279
 
 
280
static void usage(poptContext pc)
 
281
{
 
282
        printf(
 
283
"Usage:\n\
 
284
  masktest //server/share [options..]\n\
 
285
\n\
 
286
  This program tests wildcard matching between two servers. It generates\n\
 
287
  random pairs of filenames/masks and tests that they match in the same\n\
 
288
  way on the servers and internally\n");
 
289
        poptPrintUsage(pc, stdout, 0);
 
290
}
 
291
 
 
292
/****************************************************************************
 
293
  main program
 
294
****************************************************************************/
 
295
 int main(int argc,char *argv[])
 
296
{
 
297
        char *share;
 
298
        struct smbcli_state *cli;       
 
299
        int opt;
 
300
        int seed;
 
301
        struct tevent_context *ev;
 
302
        struct loadparm_context *lp_ctx;
 
303
        struct smbcli_options options;
 
304
        struct smbcli_session_options session_options;
 
305
        poptContext pc;
 
306
        int argc_new, i;
 
307
        char **argv_new;
 
308
        TALLOC_CTX *mem_ctx;
 
309
        enum {OPT_UNCLIST=1000};
 
310
        struct poptOption long_options[] = {
 
311
                POPT_AUTOHELP
 
312
                {"seed",          0, POPT_ARG_INT,  &seed,      0,      "Seed to use for randomizer",   NULL},
 
313
                {"num-ops",       0, POPT_ARG_INT,  &NumLoops,  0,      "num ops",      NULL},
 
314
                {"maxlength",     0, POPT_ARG_INT,  &max_length,0,      "maximum length",       NULL},
 
315
                {"dieonerror",    0, POPT_ARG_NONE, &die_on_error, 0,   "die on errors", NULL},
 
316
                {"showall",       0, POPT_ARG_NONE, &showall,    0,      "display all operations", NULL},
 
317
                {"oldlist",       0, POPT_ARG_NONE, &old_list,    0,     "use old list call", NULL},
 
318
                {"maskchars",     0, POPT_ARG_STRING,   &maskchars,    0,"mask characters",     NULL},
 
319
                {"filechars",     0, POPT_ARG_STRING,   &filechars,    0,"file characters",     NULL},
 
320
                POPT_COMMON_SAMBA
 
321
                POPT_COMMON_CONNECTION
 
322
                POPT_COMMON_CREDENTIALS
 
323
                POPT_COMMON_VERSION
 
324
                { NULL }
 
325
        };
 
326
 
 
327
        setlinebuf(stdout);
 
328
        seed = time(NULL);
 
329
 
 
330
        pc = poptGetContext("locktest", argc, (const char **) argv, long_options, 
 
331
                            POPT_CONTEXT_KEEP_FIRST);
 
332
 
 
333
        poptSetOtherOptionHelp(pc, "<unc>");
 
334
 
 
335
        while((opt = poptGetNextOpt(pc)) != -1) {
 
336
                switch (opt) {
 
337
                case OPT_UNCLIST:
 
338
                        lp_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
 
339
                        break;
 
340
                }
 
341
        }
 
342
 
 
343
        argv_new = discard_const_p(char *, poptGetArgs(pc));
 
344
        argc_new = argc;
 
345
        for (i=0; i<argc; i++) {
 
346
                if (argv_new[i] == NULL) {
 
347
                        argc_new = i;
 
348
                        break;
 
349
                }
 
350
        }
 
351
 
 
352
        if (!(argc_new >= 2)) {
 
353
                usage(pc);
 
354
                exit(1);
 
355
        }
 
356
 
 
357
        setup_logging("masktest", DEBUG_STDOUT);
 
358
 
 
359
        share = argv_new[1];
 
360
 
 
361
        all_string_sub(share,"/","\\",0);
 
362
 
 
363
        lp_ctx = cmdline_lp_ctx;
 
364
 
 
365
        mem_ctx = talloc_autofree_context();
 
366
 
 
367
        ev = s4_event_context_init(mem_ctx);
 
368
 
 
369
        gensec_init(lp_ctx);
 
370
 
 
371
        lp_smbcli_options(lp_ctx, &options);
 
372
        lp_smbcli_session_options(lp_ctx, &session_options);
 
373
 
 
374
        cli = connect_one(lp_resolve_context(lp_ctx), ev, mem_ctx, share, 
 
375
                          lp_smb_ports(lp_ctx), lp_socket_options(lp_ctx), 
 
376
                          &options, &session_options,
 
377
                          lp_iconv_convenience(lp_ctx),
 
378
                          lp_gensec_settings(mem_ctx, lp_ctx));
 
379
        if (!cli) {
 
380
                DEBUG(0,("Failed to connect to %s\n", share));
 
381
                exit(1);
 
382
        }
 
383
 
 
384
        /* need to init seed after connect as clientgen uses random numbers */
 
385
        DEBUG(0,("seed=%d     format --- --- (server, correct)\n", seed));
 
386
        srandom(seed);
 
387
 
 
388
        test_mask(argc_new-1, argv_new+1, mem_ctx, cli);
 
389
 
 
390
        return(0);
 
391
}