/* 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 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 . */ #include "includes.h" #include "system/filesys.h" #include "torture/proto.h" #include "libsmb/libsmb.h" #include "libsmb/clirap.h" #include "util_tdb.h" extern int torture_numops; static TDB_CONTEXT *tdb; #define NAME_LENGTH 20 static unsigned total, collisions, failures; static bool test_one(struct cli_state *cli, const char *name) { uint16_t fnum; fstring shortname; fstring name2; NTSTATUS status; TDB_DATA data; total++; status = cli_openx(cli, name, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum); if (!NT_STATUS_IS_OK(status)) { printf("open of %s failed (%s)\n", name, nt_errstr(status)); return False; } status = cli_close(cli, fnum); if (!NT_STATUS_IS_OK(status)) { printf("close of %s failed (%s)\n", name, nt_errstr(status)); 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, nt_errstr(status)); return False; } fstr_sprintf(name2, "\\mangle_test\\%s", shortname); status = cli_unlink(cli, name2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); if (!NT_STATUS_IS_OK(status)) { printf("unlink of %s (%s) failed (%s)\n", name2, name, nt_errstr(status)); return False; } /* recreate by short name */ status = cli_openx(cli, name2, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum); if (!NT_STATUS_IS_OK(status)) { printf("open2 of %s failed (%s)\n", name2, nt_errstr(status)); return False; } status = cli_close(cli, fnum); if (!NT_STATUS_IS_OK(status)) { printf("close of %s failed (%s)\n", name, nt_errstr(status)); return False; } /* and unlink by long name */ status = cli_unlink(cli, name, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); if (!NT_STATUS_IS_OK(status)) { printf("unlink2 of %s (%s) failed (%s)\n", name, name2, nt_errstr(status)); failures++; cli_unlink(cli, name2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); return True; } /* see if the short name is already in the tdb */ data = tdb_fetch_bystring(tdb, shortname); if (data.dptr) { /* maybe its a duplicate long name? */ if (!strequal(name, (const char *)data.dptr)) { /* we have a collision */ collisions++; printf("Collision between %s and %s -> %s " " (coll/tot: %u/%u)\n", name, data.dptr, shortname, collisions, total); } free(data.dptr); } else { TDB_DATA namedata; /* store it for later */ namedata.dptr = discard_const_p(uint8_t, name); namedata.dsize = strlen(name)+1; tdb_store_bystring(tdb, shortname, namedata, TDB_REPLACE); } 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