r24872: Use torture API a bit more
[kai/samba.git] / source4 / torture / locktest.c
index 99dcf9fd47b61d26741625276bba7720de9f0eb3..ba0ba344d9b3b3264a7423da0a08fa2c800d5493 100644 (file)
@@ -5,7 +5,7 @@
    
    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
+   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,
    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.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "system/filesys.h"
+#include "system/time.h"
+#include "pstring.h"
+#include "auth/credentials/credentials.h"
+#include "auth/gensec/gensec.h"
+#include "libcli/libcli.h"
 
-static fstring password[2];
-static fstring username[2];
-static int got_user;
-static int got_pass;
-static BOOL use_kerberos;
 static int numops = 1000;
 static BOOL showall;
 static BOOL analyze;
 static BOOL hide_unlock_fails;
 static BOOL use_oplocks;
-static unsigned lock_range = 100;
-static unsigned lock_base = 0;
-static unsigned min_length = 0;
+static uint_t lock_range = 100;
+static uint_t lock_base = 0;
+static uint_t min_length = 0;
 static BOOL exact_error_codes;
 static BOOL zero_zero;
 
@@ -47,7 +47,7 @@ static BOOL zero_zero;
 #define NFILES 2
 #define LOCK_TIMEOUT 0
 
-#define NASTY_POSIX_LOCK_HACK 0
+static struct cli_credentials *servers[NSERVERS];
 
 enum lock_op {OP_LOCK, OP_UNLOCK, OP_REOPEN};
 
@@ -57,6 +57,7 @@ struct record {
        char conn, f;
        uint64_t start, len;
        char needed;
+       uint16_t pid;
 };
 
 #define PRESETS 0
@@ -102,12 +103,14 @@ static struct record *recorded;
 /***************************************************** 
 return a connection to a server
 *******************************************************/
-static struct cli_state *connect_one(char *share, int snum)
+static struct smbcli_state *connect_one(char *share, int snum, int conn)
 {
-       struct cli_state *c;
+       struct smbcli_state *c;
        fstring server, myname;
-       uint_t flags = 0;
        NTSTATUS status;
+       int retries = 10;
+
+       printf("connect_one(%s, %d, %d)\n", share, snum, conn);
 
        fstrcpy(server,share+2);
        share = strchr_m(server,'\\');
@@ -115,16 +118,44 @@ static struct cli_state *connect_one(char *share, int snum)
        *share = 0;
        share++;
 
-       slprintf(myname,sizeof(myname), "lock-%u-%u", getpid(), snum);
+       if (snum == 0) {
+               char **unc_list = NULL;
+               int num_unc_names;
+               const char *p;
+               p = lp_parm_string(-1, "torture", "unclist");
+               if (p) {
+                       char *h, *s;
+                       unc_list = file_lines_load(p, &num_unc_names, NULL);
+                       if (!unc_list || num_unc_names <= 0) {
+                               printf("Failed to load unc names list from '%s'\n", p);
+                               exit(1);
+                       }
+
+                       if (!smbcli_parse_unc(unc_list[conn % num_unc_names],
+                                             NULL, &h, &s)) {
+                               printf("Failed to parse UNC name %s\n",
+                                      unc_list[conn % num_unc_names]);
+                               exit(1);
+                       }
+                       fstrcpy(server, h);
+                       fstrcpy(share, s);
+               }
+       }
 
-       if (use_kerberos)
-               flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
-       
-       status = cli_full_connection(&c, myname,
-                                    server, NULL,  
-                                    share, "?????", 
-                                    username[snum], lp_workgroup(), 
-                                    password[snum], flags, NULL);
+
+       slprintf(myname,sizeof(myname), "lock-%u-%u", getpid(), snum);
+       cli_credentials_set_workstation(servers[snum], myname, CRED_SPECIFIED);
+
+       do {
+               printf("\\\\%s\\%s\n", server, share);
+               status = smbcli_full_connection(NULL, &c, 
+                                               server, 
+                                               share, NULL,
+                                               servers[snum], NULL);
+               if (!NT_STATUS_IS_OK(status)) {
+                       sleep(2);
+               }
+       } while (!NT_STATUS_IS_OK(status) && retries--);
 
        if (!NT_STATUS_IS_OK(status)) {
                return NULL;
@@ -134,7 +165,7 @@ static struct cli_state *connect_one(char *share, int snum)
 }
 
 
-static void reconnect(struct cli_state *cli[NSERVERS][NCONNECTIONS], int fnum[NSERVERS][NCONNECTIONS][NFILES],
+static void reconnect(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], int fnum[NSERVERS][NCONNECTIONS][NFILES],
                      char *share[NSERVERS])
 {
        int server, conn, f;
@@ -144,13 +175,13 @@ static void reconnect(struct cli_state *cli[NSERVERS][NCONNECTIONS], int fnum[NS
                if (cli[server][conn]) {
                        for (f=0;f<NFILES;f++) {
                                if (fnum[server][conn][f] != -1) {
-                                       cli_close(cli[server][conn]->tree, fnum[server][conn][f]);
+                                       smbcli_close(cli[server][conn]->tree, fnum[server][conn][f]);
                                        fnum[server][conn][f] = -1;
                                }
                        }
-                       cli_shutdown(cli[server][conn]);
+                       talloc_free(cli[server][conn]);
                }
-               cli[server][conn] = connect_one(share[server], server);
+               cli[server][conn] = connect_one(share[server], server, conn);
                if (!cli[server][conn]) {
                        DEBUG(0,("Failed to connect to %s\n", share[server]));
                        exit(1);
@@ -160,12 +191,12 @@ static void reconnect(struct cli_state *cli[NSERVERS][NCONNECTIONS], int fnum[NS
 
 
 
-static BOOL test_one(struct cli_state *cli[NSERVERS][NCONNECTIONS], 
+static bool test_one(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], 
                     int fnum[NSERVERS][NCONNECTIONS][NFILES],
                     struct record *rec)
 {
-       unsigned conn = rec->conn;
-       unsigned f = rec->f;
+       uint_t conn = rec->conn;
+       uint_t f = rec->f;
        uint64_t start = rec->start;
        uint64_t len = rec->len;
        enum brl_type op = rec->lock_type;
@@ -177,10 +208,36 @@ static BOOL test_one(struct cli_state *cli[NSERVERS][NCONNECTIONS],
        case OP_LOCK:
                /* set a lock */
                for (server=0;server<NSERVERS;server++) {
-                       ret[server] = NT_STATUS_IS_OK(cli_lock64(cli[server][conn]->tree, 
-                                                fnum[server][conn][f],
-                                                start, len, LOCK_TIMEOUT, op));
-                       status[server] = cli_nt_error(cli[server][conn]->tree);
+                       NTSTATUS res;
+                       struct smbcli_tree *tree=cli[server][conn]->tree;
+                       int fn=fnum[server][conn][f];
+
+                       if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
+                               res=smbcli_lock(tree, fn, start, len, LOCK_TIMEOUT, rec->lock_op);
+                       } else {
+                               union smb_lock parms;
+                               int ltype;
+                               struct smb_lock_entry lock[1];
+
+                               parms.lockx.level = RAW_LOCK_LOCKX;
+                               parms.lockx.in.file.fnum = fn;
+       
+                               ltype = (rec->lock_op == READ_LOCK? 1 : 0);
+                               ltype |= LOCKING_ANDX_LARGE_FILES;
+                               parms.lockx.in.mode = ltype;
+                               parms.lockx.in.timeout = LOCK_TIMEOUT;
+                               parms.lockx.in.ulock_cnt = 0;
+                               parms.lockx.in.lock_cnt = 1;
+                               lock[0].pid = rec->pid;
+                               lock[0].offset = start;
+                               lock[0].count = len;
+                               parms.lockx.in.locks = &lock[0];
+
+                               res = smb_raw_lock(tree, &parms);
+                       }
+
+                       ret[server] = NT_STATUS_IS_OK(res); 
+                       status[server] = smbcli_nt_error(cli[server][conn]->tree);
                        if (!exact_error_codes && 
                            NT_STATUS_EQUAL(status[server], 
                                            NT_STATUS_FILE_LOCK_CONFLICT)) {
@@ -200,10 +257,33 @@ static BOOL test_one(struct cli_state *cli[NSERVERS][NCONNECTIONS],
        case OP_UNLOCK:
                /* unset a lock */
                for (server=0;server<NSERVERS;server++) {
-                       ret[server] = NT_STATUS_IS_OK(cli_unlock64(cli[server][conn]->tree, 
-                                                  fnum[server][conn][f],
-                                                  start, len));
-                       status[server] = cli_nt_error(cli[server][conn]->tree);
+                       NTSTATUS res;
+                       struct smbcli_tree *tree=cli[server][conn]->tree;
+                       int fn=fnum[server][conn][f];
+
+
+                       if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
+                               res=smbcli_unlock(tree, fn, start, len);
+                       } else {
+                               union smb_lock parms;
+                               struct smb_lock_entry lock[1];
+
+                               parms.lockx.level = RAW_LOCK_LOCKX;
+                               parms.lockx.in.file.fnum = fn;
+                               parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
+                               parms.lockx.in.timeout = 0;
+                               parms.lockx.in.ulock_cnt = 1;
+                               parms.lockx.in.lock_cnt = 0;
+                               lock[0].pid = rec->pid;
+                               lock[0].count = len;
+                               lock[0].offset = start;
+                               parms.lockx.in.locks = &lock[0];
+
+                               res = smb_raw_lock(tree, &parms);
+                       }
+
+                       ret[server] = NT_STATUS_IS_OK(res);
+                       status[server] = smbcli_nt_error(cli[server][conn]->tree);
                }
                if (showall || 
                    (!hide_unlock_fails && !NT_STATUS_EQUAL(status[0],status[1]))) {
@@ -219,11 +299,11 @@ static BOOL test_one(struct cli_state *cli[NSERVERS][NCONNECTIONS],
        case OP_REOPEN:
                /* reopen the file */
                for (server=0;server<NSERVERS;server++) {
-                       cli_close(cli[server][conn]->tree, fnum[server][conn][f]);
+                       smbcli_close(cli[server][conn]->tree, fnum[server][conn][f]);
                        fnum[server][conn][f] = -1;
                }
                for (server=0;server<NSERVERS;server++) {
-                       fnum[server][conn][f] = cli_open(cli[server][conn]->tree, FILENAME,
+                       fnum[server][conn][f] = smbcli_open(cli[server][conn]->tree, FILENAME,
                                                         O_RDWR|O_CREAT,
                                                         DENY_NONE);
                        if (fnum[server][conn][f] == -1) {
@@ -241,7 +321,7 @@ static BOOL test_one(struct cli_state *cli[NSERVERS][NCONNECTIONS],
        return True;
 }
 
-static void close_files(struct cli_state *cli[NSERVERS][NCONNECTIONS], 
+static void close_files(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], 
                        int fnum[NSERVERS][NCONNECTIONS][NFILES])
 {
        int server, conn, f; 
@@ -250,16 +330,16 @@ static void close_files(struct cli_state *cli[NSERVERS][NCONNECTIONS],
        for (conn=0;conn<NCONNECTIONS;conn++)
        for (f=0;f<NFILES;f++) {
                if (fnum[server][conn][f] != -1) {
-                       cli_close(cli[server][conn]->tree, fnum[server][conn][f]);
+                       smbcli_close(cli[server][conn]->tree, fnum[server][conn][f]);
                        fnum[server][conn][f] = -1;
                }
        }
        for (server=0;server<NSERVERS;server++) {
-               cli_unlink(cli[server][0]->tree, FILENAME);
+               smbcli_unlink(cli[server][0]->tree, FILENAME);
        }
 }
 
-static void open_files(struct cli_state *cli[NSERVERS][NCONNECTIONS], 
+static void open_files(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], 
                       int fnum[NSERVERS][NCONNECTIONS][NFILES])
 {
        int server, conn, f; 
@@ -267,7 +347,7 @@ static void open_files(struct cli_state *cli[NSERVERS][NCONNECTIONS],
        for (server=0;server<NSERVERS;server++)
        for (conn=0;conn<NCONNECTIONS;conn++)
        for (f=0;f<NFILES;f++) {
-               fnum[server][conn][f] = cli_open(cli[server][conn]->tree, FILENAME,
+               fnum[server][conn][f] = smbcli_open(cli[server][conn]->tree, FILENAME,
                                                 O_RDWR|O_CREAT,
                                                 DENY_NONE);
                if (fnum[server][conn][f] == -1) {
@@ -279,7 +359,7 @@ static void open_files(struct cli_state *cli[NSERVERS][NCONNECTIONS],
 }
 
 
-static int retest(struct cli_state *cli[NSERVERS][NCONNECTIONS], 
+static int retest(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], 
                   int fnum[NSERVERS][NCONNECTIONS][NFILES],
                   int n)
 {
@@ -305,14 +385,14 @@ static int retest(struct cli_state *cli[NSERVERS][NCONNECTIONS],
  */
 static void test_locks(char *share[NSERVERS])
 {
-       struct cli_state *cli[NSERVERS][NCONNECTIONS];
+       struct smbcli_state *cli[NSERVERS][NCONNECTIONS];
        int fnum[NSERVERS][NCONNECTIONS][NFILES];
        int n, i, n1, skip, r1, r2; 
 
        ZERO_STRUCT(fnum);
        ZERO_STRUCT(cli);
 
-       recorded = (struct record *)malloc(sizeof(*recorded) * numops);
+       recorded = malloc_array_p(struct record, numops);
 
        for (n=0; n<numops; n++) {
 #if PRESETS
@@ -322,11 +402,15 @@ static void test_locks(char *share[NSERVERS])
 #endif
                        recorded[n].conn = random() % NCONNECTIONS;
                        recorded[n].f = random() % NFILES;
-                       recorded[n].start = lock_base + ((unsigned)random() % (lock_range-1));
+                       recorded[n].start = lock_base + ((uint_t)random() % (lock_range-1));
                        recorded[n].len =  min_length +
                                random() % (lock_range-(recorded[n].start-lock_base));
                        recorded[n].start *= RANGE_MULTIPLE;
                        recorded[n].len *= RANGE_MULTIPLE;
+                       recorded[n].pid = random()%3;
+                       if (recorded[n].pid == 2) {
+                               recorded[n].pid = 0xFFFF; /* see if its magic */
+                       }
                        r1 = random() % 100;
                        r2 = random() % 100;
                        if (r1 < READ_PCT) {
@@ -431,7 +515,6 @@ static void usage(void)
   locktest //server1/share1 //server2/share2 [options..]\n\
   options:\n\
         -U user%%pass        (may be specified twice)\n\
-        -k               use kerberos\n\
         -s seed\n\
         -o numops\n\
         -u          hide unlock fails\n\
@@ -443,6 +526,7 @@ static void usage(void)
         -R range    set lock range\n\
         -B base     set lock base\n\
         -M min      set min lock length\n\
+        -l filename unclist file\n\
 ");
 }
 
@@ -453,8 +537,8 @@ static void usage(void)
 {
        char *share[NSERVERS];
        int opt;
-       char *p;
        int seed, server;
+       int username_count=0;
 
        setlinebuf(stdout);
 
@@ -475,39 +559,25 @@ static void usage(void)
        argc -= NSERVERS;
        argv += NSERVERS;
 
-       lp_load(dyn_CONFIGFILE,True,False,False);
-       load_interfaces();
+       lp_load();
 
-       if (getenv("USER")) {
-               fstrcpy(username[0],getenv("USER"));
-               fstrcpy(username[1],getenv("USER"));
-       }
+       servers[0] = cli_credentials_init(talloc_autofree_context());
+       servers[1] = cli_credentials_init(talloc_autofree_context());
+       cli_credentials_guess(servers[0]);
+       cli_credentials_guess(servers[1]);
 
        seed = time(NULL);
 
-       while ((opt = getopt(argc, argv, "U:s:ho:aAW:OkR:B:M:EZ")) != EOF) {
+       while ((opt = getopt(argc, argv, "U:s:ho:aAW:OR:B:M:EZW:l:")) != EOF) {
                switch (opt) {
-               case 'k':
-#ifdef HAVE_KRB5
-                       use_kerberos = True;
-#else
-                       d_printf("No kerberos support compiled in\n");
-                       exit(1);
-#endif
-                       break;
                case 'U':
-                       got_user = 1;
-                       if (got_pass == 2) {
-                               d_printf("Max of 2 usernames\n");
+                       if (username_count == 2) {
+                               usage();
                                exit(1);
                        }
-                       fstrcpy(username[got_pass],optarg);
-                       p = strchr_m(username[got_pass],'%');
-                       if (p) {
-                               *p = 0;
-                               fstrcpy(password[got_pass], p+1);
-                               got_pass++;
-                       }
+                       cli_credentials_parse_string(servers[username_count], 
+                                                    optarg, CRED_SPECIFIED);
+                       username_count++;
                        break;
                case 'R':
                        lock_range = strtol(optarg, NULL, 0);
@@ -542,6 +612,12 @@ static void usage(void)
                case 'E':
                        exact_error_codes = True;
                        break;
+               case 'l':
+                       lp_set_cmdline("torture:unclist", optarg);
+                       break;
+               case 'W':
+                       lp_set_cmdline("workgroup", optarg);
+                       break;
                case 'h':
                        usage();
                        exit(1);
@@ -551,7 +627,15 @@ static void usage(void)
                }
        }
 
-       if(use_kerberos && !got_user) got_pass = True;
+       if (username_count == 0) {
+               usage();
+               return -1;
+       }
+       if (username_count == 1) {
+               servers[1] = servers[0];
+       }
+
+       gensec_init();
 
        argc -= optind;
        argv += optind;
@@ -564,3 +648,4 @@ static void usage(void)
 
        return(0);
 }
+