utils/torture.c: Added one more delete on close test.
[nivanova/samba-autobuild/.git] / source3 / utils / torture.c
index 4267aab118c5d0734272d67d793b3d01b20beede..ac922eed61b5124f1a54e40dfdf8e1b1621e07ce 100644 (file)
@@ -33,6 +33,7 @@ static int procnum; /* records process count number when forking */
 static struct cli_state current_cli;
 static fstring randomfname;
 static BOOL use_oplocks;
+static BOOL use_level_II_oplocks;
 
 static double create_procs(void (*fn)(int));
 
@@ -109,6 +110,7 @@ static BOOL open_nbt_connection(struct cli_state *c)
 
        c->timeout = 120000; /* set a really long timeout (2 minutes) */
        if (use_oplocks) c->use_oplocks = True;
+       if (use_level_II_oplocks) c->use_level_II_oplocks = True;
 
        if (!cli_session_request(c, &calling, &called)) {
                printf("%s rejected the session\n",host);
@@ -1688,7 +1690,7 @@ static void run_randomipc(int dummy)
 
 
 static void browse_callback(const char *sname, uint32 stype, 
-                           const char *comment)
+                           const char *comment, void *state)
 {
        printf("\t%20.20s %08x %s\n", sname, stype, comment);
 }
@@ -1712,12 +1714,12 @@ static void run_browsetest(int dummy)
        printf("domain list:\n");
        cli_NetServerEnum(&cli, cli.server_domain, 
                          SV_TYPE_DOMAIN_ENUM,
-                         browse_callback);
+                         browse_callback, NULL);
 
        printf("machine list:\n");
        cli_NetServerEnum(&cli, cli.server_domain, 
                          SV_TYPE_ALL,
-                         browse_callback);
+                         browse_callback, NULL);
 
        close_connection(&cli);
 
@@ -1885,13 +1887,13 @@ static void run_trans2test(int dummy)
 /*
   this is a harness for some oplock tests
  */
-static void run_oplock(int dummy)
+static void run_oplock1(int dummy)
 {
        static struct cli_state cli1;
        char *fname = "\\lockt1.lck";
        int fnum1;
 
-       printf("starting oplock test\n");
+       printf("starting oplock test 1\n");
 
        if (!open_connection(&cli1)) {
                return;
@@ -1927,11 +1929,532 @@ static void run_oplock(int dummy)
 
        close_connection(&cli1);
 
-       printf("finished oplock test\n");
+       printf("finished oplock test 1\n");
 }
 
+static void run_oplock2(int dummy)
+{
+       static struct cli_state cli1, cli2;
+       char *fname = "\\lockt2.lck";
+       int fnum1, fnum2;
+       int saved_use_oplocks = use_oplocks;
+       char buf[4];
+
+       use_level_II_oplocks = True;
+       use_oplocks = True;
+
+       printf("starting oplock test 2\n");
+
+       if (!open_connection(&cli1)) {
+               use_level_II_oplocks = False;
+               use_oplocks = saved_use_oplocks;
+               return;
+       }
+
+       cli1.use_oplocks = True;
+       cli1.use_level_II_oplocks = True;
+
+       if (!open_connection(&cli2)) {
+               use_level_II_oplocks = False;
+               use_oplocks = saved_use_oplocks;
+               return;
+       }
+
+       cli2.use_oplocks = True;
+       cli2.use_level_II_oplocks = True;
+
+       cli_unlink(&cli1, fname);
+
+       cli_sockopt(&cli1, sockops);
+       cli_sockopt(&cli2, sockops);
+
+       fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
+       if (fnum1 == -1) {
+               printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return;
+       }
+
+       /* Don't need the globals any more. */
+       use_level_II_oplocks = False;
+       use_oplocks = saved_use_oplocks;
+
+       if (fork() == 0) {
+               /* Child code */
+               fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
+               if (fnum2 == -1) {
+                       printf("second open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+                       exit(0);
+               }
+
+               sleep(2);
+
+               if (!cli_close(&cli2, fnum2)) {
+                       printf("close2 failed (%s)\n", cli_errstr(&cli1));
+               }
+
+               exit(0);
+       }
+
+       sleep(2);
+
+       /* Ensure cli1 processes the break. */
+
+       if (cli_read(&cli1, fnum1, buf, 0, 4) != 4) {
+               printf("read on fnum1 failed (%s)\n", cli_errstr(&cli1));
+       }
+
+       /* Should now be at level II. */
+       /* Test if sending a write locks causes a break to none. */
+
+       if (!cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK)) {
+               printf("lock failed (%s)\n", cli_errstr(&cli1));
+       }
+
+       cli_unlock(&cli1, fnum1, 0, 4);
+
+       sleep(2);
+
+       if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
+               printf("lock failed (%s)\n", cli_errstr(&cli1));
+       }
+
+       cli_unlock(&cli1, fnum1, 0, 4);
+
+       sleep(2);
+
+       cli_read(&cli1, fnum1, buf, 0, 4);
+
+#if 0
+       if (cli_write(&cli1, fnum1, 0, buf, 0, 4) != 4) {
+               printf("write on fnum1 failed (%s)\n", cli_errstr(&cli1));
+       }
+#endif
+
+       if (!cli_close(&cli1, fnum1)) {
+               printf("close1 failed (%s)\n", cli_errstr(&cli1));
+       }
+
+       sleep(4);
+
+       if (!cli_unlink(&cli1, fname)) {
+               printf("unlink failed (%s)\n", cli_errstr(&cli1));
+       }
+
+       close_connection(&cli1);
+
+       printf("finished oplock test 2\n");
+}
+
+/*
+  Test delete on close semantics.
+ */
+static void run_deletetest(int dummy)
+{
+    static struct cli_state cli1;
+    static struct cli_state cli2;
+    char *fname = "\\delete.file";
+    int fnum1, fnum2;
+
+    printf("starting delete test\n");
+
+    if (!open_connection(&cli1)) {
+        return;
+    }
+
+       cli_sockopt(&cli1, sockops);
+
+       /* Test 1 - this should *NOT* delete the file on close. */
+
+       cli_setatr(&cli1, fname, 0, 0);
+       cli_unlink(&cli1, fname);
+
+       fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
+                       FILE_SHARE_DELETE, FILE_OVERWRITE_IF, DELETE_ON_CLOSE_FLAG);
+
+       if (fnum1 == -1) {
+               printf("[1] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return;
+       }
+
+    if (!cli_close(&cli1, fnum1)) {
+        printf("[1] close failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+    fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
+    if (fnum1 == -1) {
+        printf("[1] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+        return;
+    }
+
+    if (!cli_close(&cli1, fnum1)) {
+        printf("[1] close failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+       printf("first delete on close test succeeded.\n");
+
+       /* Test 2 - this should delete the file on close. */
+
+       cli_setatr(&cli1, fname, 0, 0);
+       cli_unlink(&cli1, fname);
+
+       fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS,
+                       FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0);
+
+       if (fnum1 == -1) {
+               printf("[2] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return;
+       }
+
+       if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
+        printf("[2] setting delete_on_close failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+    if (!cli_close(&cli1, fnum1)) {
+        printf("[2] close failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+    fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
+    if (fnum1 != -1) {
+               printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
+               if (!cli_close(&cli1, fnum1)) {
+                       printf("[2] close failed (%s)\n", cli_errstr(&cli1));
+               }
+               cli_unlink(&cli1, fname);
+    } else
+               printf("second delete on close test succeeded.\n");
+
+
+       /* Test 3 - ... */
+       cli_setatr(&cli1, fname, 0, 0);
+       cli_unlink(&cli1, fname);
+
+       fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0);
+
+       if (fnum1 == -1) {
+               printf("[3] open - 1 of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return;
+       }
+
+       /* This should fail with a sharing violation - open for delete is only compatible
+          with SHARE_DELETE. */
+
+       fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0);
+
+       if (fnum2 != -1) {
+               printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
+               return;
+       }
+
+       /* This should succeed. */
+
+       fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
+
+       if (fnum2 == -1) {
+               printf("[3] open  - 2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return;
+       }
+
+       if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
+        printf("[3] setting delete_on_close failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+    if (!cli_close(&cli1, fnum1)) {
+        printf("[3] close 1 failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+    if (!cli_close(&cli1, fnum2)) {
+        printf("[3] close 2 failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+       /* This should fail - file should no longer be there. */
+
+    fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
+    if (fnum1 != -1) {
+               printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
+               if (!cli_close(&cli1, fnum1)) {
+                       printf("[3] close failed (%s)\n", cli_errstr(&cli1));
+               }
+               cli_unlink(&cli1, fname);
+    } else
+               printf("third delete on close test succeeded.\n");
+
+       /* Test 4 ... */
+       cli_setatr(&cli1, fname, 0, 0);
+       cli_unlink(&cli1, fname);
+
+       fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
+                       FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0);
+                                                               
+       if (fnum1 == -1) {
+               printf("[4] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return;
+       }
+
+       /* This should succeed. */
+       fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS,
+                       FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
+       if (fnum2 == -1) {
+               printf("[4] open  - 2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return;
+       }
+
+    if (!cli_close(&cli1, fnum2)) {
+        printf("[4] close - 1 failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+       if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
+        printf("[4] setting delete_on_close failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+       /* This should fail - no more opens once delete on close set. */
+       fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS,
+                       FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
+       if (fnum2 != -1) {
+               printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
+               return;
+    } else
+               printf("fourth delete on close test succeeded.\n");
+
+    if (!cli_close(&cli1, fnum1)) {
+        printf("[4] close - 2 failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+       /* Test 5 ... */
+       cli_setatr(&cli1, fname, 0, 0);
+       cli_unlink(&cli1, fname);
+
+    fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT, DENY_NONE);
+       if (fnum1 == -1) {
+               printf("[5] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return;
+       }
+
+       /* This should fail - only allowed on NT opens with DELETE access. */
+
+       if (cli_nt_delete_on_close(&cli1, fnum1, True)) {
+        printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
+        return;
+    }
+
+    if (!cli_close(&cli1, fnum1)) {
+        printf("[5] close - 2 failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+       printf("fifth delete on close test succeeded.\n");
+
+       /* Test 6 ... */
+       cli_setatr(&cli1, fname, 0, 0);
+       cli_unlink(&cli1, fname);
+
+       fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA,
+                       FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+                       FILE_OVERWRITE_IF, 0);
+                                                               
+       if (fnum1 == -1) {
+               printf("[6] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return;
+       }
+
+       /* This should fail - only allowed on NT opens with DELETE access. */
+
+       if (cli_nt_delete_on_close(&cli1, fnum1, True)) {
+        printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
+        return;
+    }
+
+    if (!cli_close(&cli1, fnum1)) {
+        printf("[6] close - 2 failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+       printf("sixth delete on close test succeeded.\n");
+
+       /* Test 7 ... */
+       cli_setatr(&cli1, fname, 0, 0);
+       cli_unlink(&cli1, fname);
+
+       fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
+                       FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0);
+                                                               
+       if (fnum1 == -1) {
+               printf("[7] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return;
+       }
+
+       if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
+        printf("[7] setting delete_on_close on file failed !\n");
+        return;
+    }
+
+       if (!cli_nt_delete_on_close(&cli1, fnum1, False)) {
+        printf("[7] unsetting delete_on_close on file failed !\n");
+        return;
+    }
+
+    if (!cli_close(&cli1, fnum1)) {
+        printf("[7] close - 2 failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+       /* This next open should succeed - we reset the flag. */
+
+    fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
+       if (fnum1 == -1) {
+               printf("[5] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return;
+       }
+
+    if (!cli_close(&cli1, fnum1)) {
+        printf("[7] close - 2 failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+       printf("seventh delete on close test succeeded.\n");
+
+       /* Test 7 ... */
+       cli_setatr(&cli1, fname, 0, 0);
+       cli_unlink(&cli1, fname);
+
+    if (!open_connection(&cli2)) {
+               printf("[8] failed to open second connection.\n");
+        return;
+    }
+
+       cli_sockopt(&cli1, sockops);
+
+       fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
+                       FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0);
+                                                               
+       if (fnum1 == -1) {
+               printf("[8] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return;
+       }
+
+       fnum2 = cli_nt_create_full(&cli2, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
+                       FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
+                                                               
+       if (fnum2 == -1) {
+               printf("[8] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return;
+       }
+
+       if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
+        printf("[8] setting delete_on_close on file failed !\n");
+        return;
+    }
+
+    if (!cli_close(&cli1, fnum1)) {
+        printf("[8] close - 1 failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+    if (!cli_close(&cli2, fnum2)) {
+        printf("[8] close - 2 failed (%s)\n", cli_errstr(&cli2));
+        return;
+    }
+
+       /* This should fail.. */
+    fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
+    if (fnum1 != -1) {
+               printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
+               if (!cli_close(&cli1, fnum1)) {
+                       printf("[8] close failed (%s)\n", cli_errstr(&cli1));
+               }
+               cli_unlink(&cli1, fname);
+    } else
+               printf("eighth delete on close test succeeded.\n");
+
+    printf("finished delete test\n");
+
+       cli_setatr(&cli1, fname, 0, 0);
+       cli_unlink(&cli1, fname);
+
+    close_connection(&cli1);
+    close_connection(&cli2);
+}
+
+/*
+  Test open mode returns on read-only files.
+ */
+static void run_opentest(int dummy)
+{
+    static struct cli_state cli1;
+    char *fname = "\\readonly.file";
+    int fnum1, fnum2;
+       uint8 eclass;
+       uint32 errnum;
+
+    printf("starting open test\n");
+
+    if (!open_connection(&cli1)) {
+        return;
+    }
+
+       cli_setatr(&cli1, fname, 0, 0);
+    cli_unlink(&cli1, fname);
+
+    cli_sockopt(&cli1, sockops);
+
+    fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
+    if (fnum1 == -1) {
+        printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+        return;
+    }
+
+    if (!cli_close(&cli1, fnum1)) {
+        printf("close2 failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+       if (!cli_setatr(&cli1, fname, aRONLY, 0)) {
+               printf("cli_setatr failed (%s)\n", cli_errstr(&cli1));
+               return;
+       }
+
+    fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_WRITE);
+    if (fnum1 == -1) {
+        printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
+        return;
+    }
+
+       /* This will fail - but the error should be ERRnoaccess, not ERRshare. */
+    fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_ALL);
+
+       cli_error( &cli1, &eclass, &errnum, NULL);
+
+       if (eclass != ERRDOS || errnum != ERRnoaccess) {
+               printf("wrong error code (%x,%x) = %s\n", (unsigned int)eclass,
+                               (unsigned int)errnum, cli_errstr(&cli1) );
+       } else {
+               printf("correct error code ERRDOS/ERRnoaccess returned\n");
+       }
+
+       
+       cli_close(&cli1, fnum1);
+
+       cli_setatr(&cli1, fname, 0, 0);
+       cli_unlink(&cli1, fname);
+
+    close_connection(&cli1);
+
+    printf("finished open test 1\n");
+}
 
-static void list_fn(file_info *finfo, const char *name)
+static void list_fn(file_info *finfo, const char *name, void *state)
 {
        
 }
@@ -1968,9 +2491,9 @@ static void run_dirtest(int dummy)
 
        t1 = end_timer();
 
-       printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn));
-       printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn));
-       printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn));
+       printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn, NULL));
+       printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn, NULL));
+       printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn, NULL));
 
        printf("dirtest core %g seconds\n", end_timer() - t1);
 
@@ -2089,13 +2612,16 @@ static struct {
        {"NEGNOWAIT", run_negprot_nowait, 0},
        {"NBW95",  run_nbw95, 0},
        {"NBWNT",  run_nbwnt, 0},
-       {"OPLOCK",  run_oplock, 0},
+       {"OPLOCK1",  run_oplock1, 0},
+       {"OPLOCK2",  run_oplock2, 0},
        {"DIR",  run_dirtest, 0},
        {"DENY1",  run_denytest1, 0},
        {"DENY2",  run_denytest2, 0},
        {"TCON",  run_tcon_test, 0},
        {"RW1",  run_readwritetest, 0},
        {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
+       {"OPEN", run_opentest, 0},
+       {"DELETE", run_deletetest, 0},
        {NULL, NULL, 0}};