root/source4/torture/raw/unlink.c

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

DEFINITIONS

This source file includes following definitions.
  1. test_unlink
  2. test_delete_on_close
  3. torture_raw_unlink

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    unlink test suite
   4    Copyright (C) Andrew Tridgell 2003
   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 "torture/torture.h"
  22 #include "system/filesys.h"
  23 #include "libcli/raw/libcliraw.h"
  24 #include "libcli/raw/raw_proto.h"
  25 #include "libcli/libcli.h"
  26 #include "torture/util.h"
  27 
  28 #define CHECK_STATUS(status, correct) do { \
  29         if (!NT_STATUS_EQUAL(status, correct)) { \
  30                 printf("(%s) Incorrect status %s - should be %s\n", \
  31                        __location__, nt_errstr(status), nt_errstr(correct)); \
  32                 ret = false; \
  33                 goto done; \
  34         }} while (0)
  35 
  36 #define BASEDIR "\\testunlink"
  37 
  38 /*
  39   test unlink ops
  40 */
  41 static bool test_unlink(struct torture_context *tctx, struct smbcli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
  42 {
  43         union smb_unlink io;
  44         NTSTATUS status;
  45         bool ret = true;
  46         const char *fname = BASEDIR "\\test.txt";
  47 
  48         if (!torture_setup_dir(cli, BASEDIR)) {
  49                 return false;
  50         }
  51 
  52         printf("Trying non-existant file\n");
  53         io.unlink.in.pattern = fname;
  54         io.unlink.in.attrib = 0;
  55         status = smb_raw_unlink(cli->tree, &io);
  56         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
  57 
  58         smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
  59 
  60         io.unlink.in.pattern = fname;
  61         io.unlink.in.attrib = 0;
  62         status = smb_raw_unlink(cli->tree, &io);
  63         CHECK_STATUS(status, NT_STATUS_OK);
  64 
  65         printf("Trying a hidden file\n");
  66         smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
  67         torture_set_file_attribute(cli->tree, fname, FILE_ATTRIBUTE_HIDDEN);
  68 
  69         io.unlink.in.pattern = fname;
  70         io.unlink.in.attrib = 0;
  71         status = smb_raw_unlink(cli->tree, &io);
  72         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
  73 
  74         io.unlink.in.pattern = fname;
  75         io.unlink.in.attrib = FILE_ATTRIBUTE_HIDDEN;
  76         status = smb_raw_unlink(cli->tree, &io);
  77         CHECK_STATUS(status, NT_STATUS_OK);
  78 
  79         io.unlink.in.pattern = fname;
  80         io.unlink.in.attrib = FILE_ATTRIBUTE_HIDDEN;
  81         status = smb_raw_unlink(cli->tree, &io);
  82         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
  83 
  84         printf("Trying a directory\n");
  85         io.unlink.in.pattern = BASEDIR;
  86         io.unlink.in.attrib = 0;
  87         status = smb_raw_unlink(cli->tree, &io);
  88         CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
  89 
  90         io.unlink.in.pattern = BASEDIR;
  91         io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
  92         status = smb_raw_unlink(cli->tree, &io);
  93         CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
  94 
  95         printf("Trying a bad path\n");
  96         io.unlink.in.pattern = "..";
  97         io.unlink.in.attrib = 0;
  98         status = smb_raw_unlink(cli->tree, &io);
  99         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
 100 
 101         io.unlink.in.pattern = "\\..";
 102         io.unlink.in.attrib = 0;
 103         status = smb_raw_unlink(cli->tree, &io);
 104         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
 105 
 106         io.unlink.in.pattern = BASEDIR "\\..\\..";
 107         io.unlink.in.attrib = 0;
 108         status = smb_raw_unlink(cli->tree, &io);
 109         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
 110 
 111         io.unlink.in.pattern = BASEDIR "\\..";
 112         io.unlink.in.attrib = 0;
 113         status = smb_raw_unlink(cli->tree, &io);
 114         CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
 115 
 116         printf("Trying wildcards\n");
 117         smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
 118         io.unlink.in.pattern = BASEDIR "\\t*.t";
 119         io.unlink.in.attrib = 0;
 120         status = smb_raw_unlink(cli->tree, &io);
 121         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
 122 
 123         io.unlink.in.pattern = BASEDIR "\\z*";
 124         io.unlink.in.attrib = 0;
 125         status = smb_raw_unlink(cli->tree, &io);
 126         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
 127 
 128         io.unlink.in.pattern = BASEDIR "\\z*";
 129         io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
 130         status = smb_raw_unlink(cli->tree, &io);
 131 
 132         if (torture_setting_bool(tctx, "samba3", false)) {
 133                 /*
 134                  * In Samba3 we gave up upon getting the error codes in
 135                  * wildcard unlink correct. Trying gentest showed that this is
 136                  * irregular beyond our capabilities. So for
 137                  * FILE_ATTRIBUTE_DIRECTORY we always return NAME_INVALID.
 138                  * Tried by jra and vl. If others feel like solving this
 139                  * puzzle, please tell us :-)
 140                  */
 141                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
 142         }
 143         else {
 144                 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
 145         }
 146 
 147         io.unlink.in.pattern = BASEDIR "\\*";
 148         io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
 149         status = smb_raw_unlink(cli->tree, &io);
 150         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
 151 
 152         io.unlink.in.pattern = BASEDIR "\\?";
 153         io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
 154         status = smb_raw_unlink(cli->tree, &io);
 155         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
 156 
 157         io.unlink.in.pattern = BASEDIR "\\t*";
 158         io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
 159         status = smb_raw_unlink(cli->tree, &io);
 160         if (torture_setting_bool(tctx, "samba3", false)) {
 161                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
 162         }
 163         else {
 164                 CHECK_STATUS(status, NT_STATUS_OK);
 165         }
 166 
 167         smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
 168 
 169         io.unlink.in.pattern = BASEDIR "\\*.dat";
 170         io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
 171         status = smb_raw_unlink(cli->tree, &io);
 172         if (torture_setting_bool(tctx, "samba3", false)) {
 173                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
 174         }
 175         else {
 176                 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
 177         }
 178 
 179         io.unlink.in.pattern = BASEDIR "\\*.tx?";
 180         io.unlink.in.attrib = 0;
 181         status = smb_raw_unlink(cli->tree, &io);
 182         if (torture_setting_bool(tctx, "samba3", false)) {
 183                 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
 184         }
 185         else {
 186                 CHECK_STATUS(status, NT_STATUS_OK);
 187         }
 188 
 189         status = smb_raw_unlink(cli->tree, &io);
 190         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
 191 
 192 
 193 done:
 194         smb_raw_exit(cli->session);
 195         smbcli_deltree(cli->tree, BASEDIR);
 196         return ret;
 197 }
 198 
 199 
 200 /*
 201   test delete on close 
 202 */
 203 static bool test_delete_on_close(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 204                                                                  struct smbcli_state *cli)
 205 {
 206         union smb_open op;
 207         union smb_unlink io;
 208         struct smb_rmdir dio;
 209         NTSTATUS status;
 210         bool ret = true;
 211         int fnum, fnum2;
 212         const char *fname = BASEDIR "\\test.txt";
 213         const char *dname = BASEDIR "\\test.dir";
 214         const char *inside = BASEDIR "\\test.dir\\test.txt";
 215         union smb_setfileinfo sfinfo;
 216 
 217         if (!torture_setup_dir(cli, BASEDIR)) {
 218                 return false;
 219         }
 220 
 221         dio.in.path = dname;
 222 
 223         io.unlink.in.pattern = fname;
 224         io.unlink.in.attrib = 0;
 225         status = smb_raw_unlink(cli->tree, &io);
 226         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 227 
 228         printf("Testing with delete_on_close 0\n");
 229         fnum = create_complex_file(cli, tctx, fname);
 230 
 231         sfinfo.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
 232         sfinfo.disposition_info.in.file.fnum = fnum;
 233         sfinfo.disposition_info.in.delete_on_close = 0;
 234         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
 235         CHECK_STATUS(status, NT_STATUS_OK);
 236 
 237         smbcli_close(cli->tree, fnum);
 238 
 239         status = smb_raw_unlink(cli->tree, &io);
 240         CHECK_STATUS(status, NT_STATUS_OK);
 241 
 242         printf("Testing with delete_on_close 1\n");
 243         fnum = create_complex_file(cli, tctx, fname);
 244         sfinfo.disposition_info.in.file.fnum = fnum;
 245         sfinfo.disposition_info.in.delete_on_close = 1;
 246         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
 247         CHECK_STATUS(status, NT_STATUS_OK);
 248 
 249         smbcli_close(cli->tree, fnum);
 250 
 251         status = smb_raw_unlink(cli->tree, &io);
 252         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 253 
 254 
 255         printf("Testing with directory and delete_on_close 0\n");
 256         status = create_directory_handle(cli->tree, dname, &fnum);
 257         CHECK_STATUS(status, NT_STATUS_OK);
 258 
 259         sfinfo.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
 260         sfinfo.disposition_info.in.file.fnum = fnum;
 261         sfinfo.disposition_info.in.delete_on_close = 0;
 262         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
 263         CHECK_STATUS(status, NT_STATUS_OK);
 264 
 265         smbcli_close(cli->tree, fnum);
 266 
 267         status = smb_raw_rmdir(cli->tree, &dio);
 268         CHECK_STATUS(status, NT_STATUS_OK);
 269 
 270         printf("Testing with directory delete_on_close 1\n");
 271         status = create_directory_handle(cli->tree, dname, &fnum);
 272         CHECK_STATUS(status, NT_STATUS_OK);
 273         
 274         sfinfo.disposition_info.in.file.fnum = fnum;
 275         sfinfo.disposition_info.in.delete_on_close = 1;
 276         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
 277         CHECK_STATUS(status, NT_STATUS_OK);
 278 
 279         smbcli_close(cli->tree, fnum);
 280 
 281         status = smb_raw_rmdir(cli->tree, &dio);
 282         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 283 
 284 
 285         if (!torture_setting_bool(tctx, "samba3", false)) {
 286 
 287                 /*
 288                  * Known deficiency, also skipped in base-delete.
 289                  */
 290 
 291                 printf("Testing with non-empty directory delete_on_close\n");
 292                 status = create_directory_handle(cli->tree, dname, &fnum);
 293                 CHECK_STATUS(status, NT_STATUS_OK);
 294 
 295                 fnum2 = create_complex_file(cli, tctx, inside);
 296 
 297                 sfinfo.disposition_info.in.file.fnum = fnum;
 298                 sfinfo.disposition_info.in.delete_on_close = 1;
 299                 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
 300                 CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
 301 
 302                 sfinfo.disposition_info.in.file.fnum = fnum2;
 303                 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
 304                 CHECK_STATUS(status, NT_STATUS_OK);
 305 
 306                 sfinfo.disposition_info.in.file.fnum = fnum;
 307                 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
 308                 CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
 309 
 310                 smbcli_close(cli->tree, fnum2);
 311 
 312                 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
 313                 CHECK_STATUS(status, NT_STATUS_OK);
 314 
 315                 smbcli_close(cli->tree, fnum);
 316 
 317                 status = smb_raw_rmdir(cli->tree, &dio);
 318                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 319         }
 320 
 321         printf("Testing open dir with delete_on_close\n");
 322         status = create_directory_handle(cli->tree, dname, &fnum);
 323         CHECK_STATUS(status, NT_STATUS_OK);
 324         
 325         smbcli_close(cli->tree, fnum);
 326         fnum2 = create_complex_file(cli, tctx, inside);
 327         smbcli_close(cli->tree, fnum2);
 328 
 329         op.generic.level = RAW_OPEN_NTCREATEX;
 330         op.ntcreatex.in.root_fid = 0;
 331         op.ntcreatex.in.flags = 0;
 332         op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
 333         op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
 334         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
 335         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
 336         op.ntcreatex.in.alloc_size = 0;
 337         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
 338         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
 339         op.ntcreatex.in.security_flags = 0;
 340         op.ntcreatex.in.fname = dname;
 341 
 342         status = smb_raw_open(cli->tree, tctx, &op);
 343         CHECK_STATUS(status, NT_STATUS_OK);
 344         fnum = op.ntcreatex.out.file.fnum;
 345 
 346         smbcli_close(cli->tree, fnum);
 347 
 348         status = smb_raw_rmdir(cli->tree, &dio);
 349         CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
 350 
 351         smbcli_deltree(cli->tree, dname);
 352 
 353         printf("Testing double open dir with second delete_on_close\n");
 354         status = create_directory_handle(cli->tree, dname, &fnum);
 355         CHECK_STATUS(status, NT_STATUS_OK);
 356         smbcli_close(cli->tree, fnum);
 357         
 358         fnum2 = create_complex_file(cli, tctx, inside);
 359         smbcli_close(cli->tree, fnum2);
 360 
 361         op.generic.level = RAW_OPEN_NTCREATEX;
 362         op.ntcreatex.in.root_fid = 0;
 363         op.ntcreatex.in.flags = 0;
 364         op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
 365         op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
 366         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
 367         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
 368         op.ntcreatex.in.alloc_size = 0;
 369         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
 370         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
 371         op.ntcreatex.in.security_flags = 0;
 372         op.ntcreatex.in.fname = dname;
 373 
 374         status = smb_raw_open(cli->tree, tctx, &op);
 375         CHECK_STATUS(status, NT_STATUS_OK);
 376         fnum2 = op.ntcreatex.out.file.fnum;
 377 
 378         smbcli_close(cli->tree, fnum2);
 379 
 380         status = smb_raw_rmdir(cli->tree, &dio);
 381         CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
 382 
 383         smbcli_deltree(cli->tree, dname);
 384 
 385         printf("Testing pre-existing open dir with second delete_on_close\n");
 386         status = create_directory_handle(cli->tree, dname, &fnum);
 387         CHECK_STATUS(status, NT_STATUS_OK);
 388         
 389         smbcli_close(cli->tree, fnum);
 390 
 391         fnum = create_complex_file(cli, tctx, inside);
 392         smbcli_close(cli->tree, fnum);
 393 
 394         /* we have a dir with a file in it, no handles open */
 395 
 396         op.generic.level = RAW_OPEN_NTCREATEX;
 397         op.ntcreatex.in.root_fid = 0;
 398         op.ntcreatex.in.flags = 0;
 399         op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
 400         op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
 401         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
 402         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
 403         op.ntcreatex.in.alloc_size = 0;
 404         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
 405         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
 406         op.ntcreatex.in.security_flags = 0;
 407         op.ntcreatex.in.fname = dname;
 408 
 409         status = smb_raw_open(cli->tree, tctx, &op);
 410         CHECK_STATUS(status, NT_STATUS_OK);
 411         fnum = op.ntcreatex.out.file.fnum;
 412 
 413         /* open without delete on close */
 414         op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
 415         status = smb_raw_open(cli->tree, tctx, &op);
 416         CHECK_STATUS(status, NT_STATUS_OK);
 417         fnum2 = op.ntcreatex.out.file.fnum;
 418 
 419         /* close 2nd file handle */
 420         smbcli_close(cli->tree, fnum2);
 421 
 422         status = smb_raw_rmdir(cli->tree, &dio);
 423         CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
 424         
 425 
 426         smbcli_close(cli->tree, fnum);
 427 
 428         status = smb_raw_rmdir(cli->tree, &dio);
 429         CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
 430         
 431 done:
 432         smb_raw_exit(cli->session);
 433         smbcli_deltree(cli->tree, BASEDIR);
 434         return ret;
 435 }
 436 
 437 
 438 /* 
 439    basic testing of unlink calls
 440 */
 441 struct torture_suite *torture_raw_unlink(TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 442 {
 443         struct torture_suite *suite = torture_suite_create(mem_ctx, "UNLINK");
 444 
 445         torture_suite_add_1smb_test(suite, "unlink", test_unlink);
 446         torture_suite_add_1smb_test(suite, "delete_on_close", test_delete_on_close);
 447 
 448         return suite;
 449 }

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