root/source3/torture/mangle_test.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. test_one
  2. gen_name
  3. torture_mangle

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    SMB torture tester - mangling test
   4    Copyright (C) Andrew Tridgell 2002
   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 
  22 extern int torture_numops;
  23 
  24 static TDB_CONTEXT *tdb;
  25 
  26 #define NAME_LENGTH 20
  27 
  28 static unsigned total, collisions, failures;
  29 
  30 static bool test_one(struct cli_state *cli, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
  31 {
  32         int fnum;
  33         fstring shortname;
  34         fstring name2;
  35         NTSTATUS status;
  36         TDB_DATA data;
  37 
  38         total++;
  39 
  40         fnum = cli_open(cli, name, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
  41         if (fnum == -1) {
  42                 printf("open of %s failed (%s)\n", name, cli_errstr(cli));
  43                 return False;
  44         }
  45 
  46         if (!cli_close(cli, fnum)) {
  47                 printf("close of %s failed (%s)\n", name, cli_errstr(cli));
  48                 return False;
  49         }
  50 
  51         /* get the short name */
  52         status = cli_qpathinfo_alt_name(cli, name, shortname);
  53         if (!NT_STATUS_IS_OK(status)) {
  54                 printf("query altname of %s failed (%s)\n", name, cli_errstr(cli));
  55                 return False;
  56         }
  57 
  58         fstr_sprintf(name2, "\\mangle_test\\%s", shortname);
  59         if (!cli_unlink(cli, name2)) {
  60                 printf("unlink of %s  (%s) failed (%s)\n", 
  61                        name2, name, cli_errstr(cli));
  62                 return False;
  63         }
  64 
  65         /* recreate by short name */
  66         fnum = cli_open(cli, name2, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
  67         if (fnum == -1) {
  68                 printf("open2 of %s failed (%s)\n", name2, cli_errstr(cli));
  69                 return False;
  70         }
  71         if (!cli_close(cli, fnum)) {
  72                 printf("close of %s failed (%s)\n", name, cli_errstr(cli));
  73                 return False;
  74         }
  75 
  76         /* and unlink by long name */
  77         if (!cli_unlink(cli, name)) {
  78                 printf("unlink2 of %s  (%s) failed (%s)\n", 
  79                        name, name2, cli_errstr(cli));
  80                 failures++;
  81                 cli_unlink(cli, name2);
  82                 return True;
  83         }
  84 
  85         /* see if the short name is already in the tdb */
  86         data = tdb_fetch_bystring(tdb, shortname);
  87         if (data.dptr) {
  88                 /* maybe its a duplicate long name? */
  89                 if (!strequal(name, (const char *)data.dptr)) {
  90                         /* we have a collision */
  91                         collisions++;
  92                         printf("Collision between %s and %s   ->  %s "
  93                                 " (coll/tot: %u/%u)\n", 
  94                                 name, data.dptr, shortname, collisions, total);
  95                 }
  96                 free(data.dptr);
  97         } else {
  98                 TDB_DATA namedata;
  99                 /* store it for later */
 100                 namedata.dptr = CONST_DISCARD(uint8 *, name);
 101                 namedata.dsize = strlen(name)+1;
 102                 tdb_store_bystring(tdb, shortname, namedata, TDB_REPLACE);
 103         }
 104 
 105         return True;
 106 }
 107 
 108 
 109 static void gen_name(char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 110 {
 111         const char *chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._-$~... ";
 112         unsigned max_idx = strlen(chars);
 113         unsigned len;
 114         int i;
 115         char *p;
 116 
 117         fstrcpy(name, "\\mangle_test\\");
 118         p = name + strlen(name);
 119 
 120         len = 1 + random() % NAME_LENGTH;
 121         
 122         for (i=0;i<len;i++) {
 123                 p[i] = chars[random() % max_idx];
 124         }
 125 
 126         p[i] = 0;
 127 
 128         if (strcmp(p, ".") == 0 || strcmp(p, "..") == 0) {
 129                 p[0] = '_';
 130         }
 131 
 132         /* have a high probability of a common lead char */
 133         if (random() % 2 == 0) {
 134                 p[0] = 'A';
 135         }
 136 
 137         /* and a medium probability of a common lead string */
 138         if (random() % 10 == 0) {
 139                 if (strlen(p) <= 5) {
 140                         fstrcpy(p, "ABCDE");
 141                 } else {
 142                         /* try not to kill off the null termination */
 143                         memcpy(p, "ABCDE", 5);
 144                 }
 145         }
 146 
 147         /* and a high probability of a good extension length */
 148         if (random() % 2 == 0) {
 149                 char *s = strrchr(p, '.');
 150                 if (s) {
 151                         s[4] = 0;
 152                 }
 153         }
 154 
 155         /* ..... and a 100% proability of a file not ending in "." */
 156         if (p[strlen(p)-1] == '.')
 157                 p[strlen(p)-1] = '_';
 158 }
 159 
 160 
 161 bool torture_mangle(int dummy)
     /* [<][>][^][v][top][bottom][index][help] */
 162 {
 163         static struct cli_state *cli;
 164         int i;
 165         bool ret = True;
 166 
 167         printf("starting mangle test\n");
 168 
 169         if (!torture_open_connection(&cli, 0)) {
 170                 return False;
 171         }
 172 
 173         /* we will use an internal tdb to store the names we have used */
 174         tdb = tdb_open(NULL, 100000, TDB_INTERNAL, 0, 0);
 175         if (!tdb) {
 176                 printf("ERROR: Failed to open tdb\n");
 177                 return False;
 178         }
 179 
 180         cli_unlink(cli, "\\mangle_test\\*");
 181         cli_rmdir(cli, "\\mangle_test");
 182 
 183         if (!cli_mkdir(cli, "\\mangle_test")) {
 184                 printf("ERROR: Failed to make directory\n");
 185                 return False;
 186         }
 187 
 188         for (i=0;i<torture_numops;i++) {
 189                 fstring name;
 190                 ZERO_STRUCT(name);
 191 
 192                 gen_name(name);
 193                 
 194                 if (!test_one(cli, name)) {
 195                         ret = False;
 196                         break;
 197                 }
 198                 if (total && total % 100 == 0) {
 199                         printf("collisions %u/%u  - %.2f%%   (%u failures)\r",
 200                                collisions, total, (100.0*collisions) / total, failures);
 201                 }
 202         }
 203 
 204         cli_unlink(cli, "\\mangle_test\\*");
 205         if (!cli_rmdir(cli, "\\mangle_test")) {
 206                 printf("ERROR: Failed to remove directory\n");
 207                 return False;
 208         }
 209 
 210         printf("\nTotal collisions %u/%u  - %.2f%%   (%u failures)\n",
 211                collisions, total, (100.0*collisions) / total, failures);
 212 
 213         torture_close_connection(cli);
 214 
 215         printf("mangle test finished\n");
 216         return (ret && (failures == 0));
 217 }

/* [<][>][^][v][top][bottom][index][help] */