summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2002-04-12 03:26:19 +0000
committerAndrew Tridgell <tridge@samba.org>2002-04-12 03:26:19 +0000
commit3067ec21fb34f46fd1683aad6d455e7d6da8f52e (patch)
tree4bfbb894a9ebda5c99ad6df8c45916b95883276d
parent4c0399915cde591cb06f99b50acd5e5bf48bc6cb (diff)
downloadsamba-3067ec21fb34f46fd1683aad6d455e7d6da8f52e.tar.gz
samba-3067ec21fb34f46fd1683aad6d455e7d6da8f52e.tar.bz2
samba-3067ec21fb34f46fd1683aad6d455e7d6da8f52e.zip
- added a mangling test suite that measures the collision rate on
randomised filenames - fixed several mangling bugs that the test suite pointed out (This used to be commit 858fa7efc34f6e7cdf8500900aed3f7943c91348)
-rw-r--r--source3/Makefile.in2
-rw-r--r--source3/smbd/mangle_hash2.c14
-rw-r--r--source3/torture/mangle_test.c162
-rw-r--r--source3/torture/torture.c28
4 files changed, 194 insertions, 12 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 54e3238fba..476997512f 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -364,7 +364,7 @@ NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(UBIQX_OBJ) \
$(LIBSMB_OBJ) $(LIB_OBJ)
SMBTORTURE_OBJ = torture/torture.o torture/nbio.o torture/scanner.o torture/utable.o \
- torture/denytest.o \
+ torture/denytest.o torture/mangle_test.o \
$(LIBSMB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
MASKTEST_OBJ = torture/masktest.o $(LIBSMB_OBJ) $(PARAM_OBJ) \
diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c
index 96ca7360b8..959a93e07b 100644
--- a/source3/smbd/mangle_hash2.c
+++ b/source3/smbd/mangle_hash2.c
@@ -344,6 +344,7 @@ static BOOL check_cache(char *name)
/* we found it - construct the full name */
strncpy(extension, name+9, 3);
+ extension[3] = 0;
if (extension[0]) {
M_DEBUG(0,("check_cache: %s -> %s.%s\n", name, prefix, extension));
@@ -435,6 +436,19 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83)
/* find the '.' if any */
dot_p = strrchr(name, '.');
+ if (dot_p) {
+ /* if the extension contains any illegal characters or
+ is too long or zero length then we treat it as part
+ of the prefix */
+ for (i=0; i<4 && dot_p[i+1]; i++) {
+ if (! FLAG_CHECK(dot_p[i+1], FLAG_ASCII)) {
+ dot_p = NULL;
+ break;
+ }
+ }
+ if (i == 0 || i == 4) dot_p = NULL;
+ }
+
/* the leading character in the mangled name is taken from
the first character of the name, if it is ascii
otherwise '_' is used
diff --git a/source3/torture/mangle_test.c b/source3/torture/mangle_test.c
new file mode 100644
index 0000000000..9024925beb
--- /dev/null
+++ b/source3/torture/mangle_test.c
@@ -0,0 +1,162 @@
+/*
+ Unix SMB/CIFS implementation.
+ SMB torture tester - mangling test
+ Copyright (C) Andrew Tridgell 2002
+
+ 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
+ (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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+static TDB_CONTEXT *tdb;
+
+#define NAME_LENGTH 30
+
+static unsigned total, collisions;
+
+static BOOL test_one(struct cli_state *cli, const char *name)
+{
+ int fnum;
+ fstring shortname;
+ fstring name2;
+ NTSTATUS status;
+ TDB_DATA data;
+
+ total++;
+
+ fnum = cli_open(cli, name, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
+ if (fnum == -1) {
+ printf("open of %s failed (%s)\n", name, cli_errstr(cli));
+ return False;
+ }
+
+ if (!cli_close(cli, fnum)) {
+ printf("close of %s failed (%s)\n", name, cli_errstr(cli));
+ return False;
+ }
+
+ /* get the short name */
+ status = cli_qpathinfo_alt_name(cli, name, shortname);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("query altname of %s failed (%s)\n", name, cli_errstr(cli));
+ return False;
+ }
+
+ snprintf(name2, sizeof(name2), "\\mangle_test\\%s", shortname);
+ if (!cli_unlink(cli, name2)) {
+ printf("unlink of %s (%s) failed (%s)\n",
+ name2, name, cli_errstr(cli));
+ return False;
+ }
+
+ /* see if the short name is already in the tdb */
+ data = tdb_fetch_by_string(tdb, shortname);
+ if (data.dptr) {
+ /* maybe its a duplicate long name? */
+ if (strcasecmp(name, data.dptr) != 0) {
+ /* we have a collision */
+ collisions++;
+ printf("Collision between %s and %s -> %s\n",
+ name, data.dptr, shortname);
+ }
+ free(data.dptr);
+ } else {
+ /* store it for later */
+ tdb_store_by_string(tdb, shortname, name, strlen(name)+1);
+ }
+
+ return True;
+}
+
+
+static void gen_name(char *name)
+{
+ const char *chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._-$~";
+ unsigned max_idx = strlen(chars);
+ unsigned len;
+ int i;
+ char *p;
+
+ fstrcpy(name, "\\mangle_test\\");
+ p = name + strlen(name);
+
+ len = 1 + random() % NAME_LENGTH;
+
+ for (i=0;i<len;i++) {
+ p[i] = chars[random() % max_idx];
+ }
+
+ p[i] = 0;
+
+ if (strcmp(p, ".") == 0 || strcmp(p, "..") == 0) {
+ p[0] = '_';
+ }
+}
+
+
+BOOL torture_mangle(int dummy)
+{
+ extern int torture_numops;
+ static struct cli_state cli;
+ int i;
+
+ printf("starting mangle test\n");
+
+ if (!torture_open_connection(&cli)) {
+ return False;
+ }
+
+ /* we will use an internal tdb to store the names we have used */
+ tdb = tdb_open(NULL, 100000, TDB_INTERNAL, 0, 0);
+ if (!tdb) {
+ printf("ERROR: Failed to open tdb\n");
+ return False;
+ }
+
+ cli_unlink(&cli, "\\mangle_test\\*");
+ cli_rmdir(&cli, "\\mangle_test");
+
+ if (!cli_mkdir(&cli, "\\mangle_test")) {
+ printf("ERROR: Failed to make directory\n");
+ return False;
+ }
+
+ for (i=0;i<torture_numops;i++) {
+ fstring name;
+
+ gen_name(name);
+
+ if (!test_one(&cli, name)) {
+ break;
+ }
+ if (total && total % 100 == 0) {
+ printf("collisions %u/%u - %.2f%%\r",
+ collisions, total, (100.0*collisions) / total);
+ }
+ }
+
+ if (!cli_rmdir(&cli, "\\mangle_test")) {
+ printf("ERROR: Failed to remove directory\n");
+ return False;
+ }
+
+ printf("\nTotal collisions %u/%u - %.2f%%\n",
+ collisions, total, (100.0*collisions) / total);
+
+ torture_close_connection(&cli);
+
+ printf("mangle test finished\n");
+ return True;
+}
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 29eeb802ff..23624d0733 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -25,7 +25,8 @@
static fstring host, workgroup, share, password, username, myname;
static int max_protocol = PROTOCOL_NT1;
static char *sockops="TCP_NODELAY";
-static int nprocs=1, numops=100;
+static int nprocs=1;
+int torture_numops=100;
static int procnum; /* records process count number when forking */
static struct cli_state current_cli;
static fstring randomfname;
@@ -239,7 +240,7 @@ static BOOL rw_torture(struct cli_state *c)
}
- for (i=0;i<numops;i++) {
+ for (i=0;i<torture_numops;i++) {
unsigned n = (unsigned)sys_random()%10;
if (i % 10 == 0) {
printf("%d\r", i); fflush(stdout);
@@ -456,7 +457,7 @@ static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2)
return False;
}
- for (i=0;i<numops;i++)
+ for (i=0;i<torture_numops;i++)
{
size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
if (i % 10 == 0) {
@@ -1112,7 +1113,7 @@ static BOOL run_locktest3(int dummy)
uint32 offset;
BOOL correct = True;
-#define NEXT_OFFSET offset += (~(uint32)0) / numops
+#define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
return False;
@@ -1135,7 +1136,7 @@ static BOOL run_locktest3(int dummy)
return False;
}
- for (offset=i=0;i<numops;i++) {
+ for (offset=i=0;i<torture_numops;i++) {
NEXT_OFFSET;
if (!cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
printf("lock1 %d failed (%s)\n",
@@ -1152,7 +1153,7 @@ static BOOL run_locktest3(int dummy)
}
}
- for (offset=i=0;i<numops;i++) {
+ for (offset=i=0;i<torture_numops;i++) {
NEXT_OFFSET;
if (cli_lock(&cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
@@ -1176,7 +1177,7 @@ static BOOL run_locktest3(int dummy)
}
}
- for (offset=i=0;i<numops;i++) {
+ for (offset=i=0;i<torture_numops;i++) {
NEXT_OFFSET;
if (!cli_unlock(&cli1, fnum1, offset-1, 1)) {
@@ -3419,7 +3420,7 @@ static BOOL run_dirtest(int dummy)
cli_sockopt(&cli, sockops);
srandom(0);
- for (i=0;i<numops;i++) {
+ for (i=0;i<torture_numops;i++) {
fstring fname;
slprintf(fname, sizeof(fname), "\\%x", (int)random());
fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
@@ -3439,7 +3440,7 @@ static BOOL run_dirtest(int dummy)
printf("dirtest core %g seconds\n", end_timer() - t1);
srandom(0);
- for (i=0;i<numops;i++) {
+ for (i=0;i<torture_numops;i++) {
fstring fname;
slprintf(fname, sizeof(fname), "\\%x", (int)random());
cli_unlink(&cli, fname);
@@ -3693,6 +3694,7 @@ static struct {
{"RENAME", run_rename, 0},
{"DELETE", run_deletetest, 0},
{"PROPERTIES", run_properties, 0},
+ {"MANGLE", torture_mangle, 0},
{"W2K", run_w2ktest, 0},
{"TRANS2SCAN", torture_trans2_scan, 0},
{"NTTRANSSCAN", torture_nttrans_scan, 0},
@@ -3764,6 +3766,7 @@ static void usage(void)
printf("\t-L use oplocks\n");
printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
printf("\t-A showall\n");
+ printf("\t-s seed\n");
printf("\n\n");
printf("tests are:");
@@ -3834,8 +3837,11 @@ static void usage(void)
fstrcpy(workgroup, lp_workgroup());
- while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:Ld:Ac:k")) != EOF) {
+ while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:Ld:Ac:ks:")) != EOF) {
switch (opt) {
+ case 's':
+ srandom(atoi(optarg));
+ break;
case 'W':
fstrcpy(workgroup,optarg);
break;
@@ -3846,7 +3852,7 @@ static void usage(void)
nprocs = atoi(optarg);
break;
case 'o':
- numops = atoi(optarg);
+ torture_numops = atoi(optarg);
break;
case 'd':
DEBUGLEVEL = atoi(optarg);