LCOV - code coverage report
Current view: top level - source4/torture - locktest.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 191 307 62.2 %
Date: 2021-09-23 10:06:22 Functions: 7 9 77.8 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    randomised byte range lock tester
       4             :    Copyright (C) Andrew Tridgell 1999
       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 "lib/cmdline/cmdline.h"
      22             : #include "lib/events/events.h"
      23             : #include "system/filesys.h"
      24             : #include "system/time.h"
      25             : #include "auth/credentials/credentials.h"
      26             : #include "auth/gensec/gensec.h"
      27             : #include "libcli/libcli.h"
      28             : #include "param/param.h"
      29             : #include "libcli/resolve/resolve.h"
      30             : 
      31             : static int numops = 1000;
      32             : static int showall;
      33             : static int analyze;
      34             : static int hide_unlock_fails;
      35             : static int use_oplocks;
      36             : static unsigned int lock_range = 100;
      37             : static unsigned int lock_base = 0;
      38             : static unsigned int min_length = 0;
      39             : static int exact_error_codes;
      40             : static int zero_zero;
      41             : 
      42             : #define FILENAME "\\locktest.dat"
      43             : 
      44             : #define READ_PCT 50
      45             : #define LOCK_PCT 45
      46             : #define UNLOCK_PCT 70
      47             : #define RANGE_MULTIPLE 1
      48             : #define NSERVERS 2
      49             : #define NCONNECTIONS 2
      50             : #define NFILES 2
      51             : #define LOCK_TIMEOUT 0
      52             : 
      53             : static struct cli_credentials *servers[NSERVERS];
      54             : 
      55             : enum lock_op {OP_LOCK, OP_UNLOCK, OP_REOPEN};
      56             : 
      57             : struct record {
      58             :         enum lock_op lock_op;
      59             :         enum brl_type lock_type;
      60             :         char conn, f;
      61             :         uint64_t start, len;
      62             :         char needed;
      63             :         uint16_t pid;
      64             : };
      65             : 
      66             : #define PRESETS 0
      67             : 
      68             : #if PRESETS
      69             : static struct record preset[] = {
      70             : {OP_LOCK, WRITE_LOCK, 0, 0, 2, 0, 1},
      71             : {OP_LOCK, WRITE_LOCK, 0, 0, 0, 0, 1},
      72             : {OP_LOCK, WRITE_LOCK, 0, 0, 3, 0, 1},
      73             : {OP_UNLOCK, 0       , 0, 0, 2, 0, 1},
      74             : {OP_REOPEN, 0, 0, 0, 0, 0, 1},
      75             : 
      76             : {OP_LOCK, READ_LOCK, 0, 0, 2, 0, 1},
      77             : {OP_LOCK, READ_LOCK, 0, 0, 1, 1, 1},
      78             : {OP_LOCK, WRITE_LOCK, 0, 0, 0, 0, 1},
      79             : {OP_REOPEN, 0, 0, 0, 0, 0, 1},
      80             : 
      81             : {OP_LOCK, READ_LOCK, 0, 0, 2, 0, 1},
      82             : {OP_LOCK, WRITE_LOCK, 0, 0, 3, 1, 1},
      83             : {OP_LOCK, WRITE_LOCK, 0, 0, 0, 0, 1},
      84             : {OP_REOPEN, 0, 0, 0, 0, 0, 1},
      85             : 
      86             : {OP_LOCK, READ_LOCK, 0, 0, 2, 0, 1},
      87             : {OP_LOCK, WRITE_LOCK, 0, 0, 1, 1, 1},
      88             : {OP_LOCK, WRITE_LOCK, 0, 0, 0, 0, 1},
      89             : {OP_REOPEN, 0, 0, 0, 0, 0, 1},
      90             : 
      91             : {OP_LOCK, WRITE_LOCK, 0, 0, 2, 0, 1},
      92             : {OP_LOCK, READ_LOCK, 0, 0, 1, 1, 1},
      93             : {OP_LOCK, WRITE_LOCK, 0, 0, 0, 0, 1},
      94             : {OP_REOPEN, 0, 0, 0, 0, 0, 1},
      95             : 
      96             : {OP_LOCK, WRITE_LOCK, 0, 0, 2, 0, 1},
      97             : {OP_LOCK, READ_LOCK, 0, 0, 3, 1, 1},
      98             : {OP_LOCK, WRITE_LOCK, 0, 0, 0, 0, 1},
      99             : {OP_REOPEN, 0, 0, 0, 0, 0, 1},
     100             : 
     101             : };
     102             : #endif
     103             : 
     104             : static struct record *recorded;
     105             : 
     106             : /***************************************************** 
     107             : return a connection to a server
     108             : *******************************************************/
     109           4 : static struct smbcli_state *connect_one(struct tevent_context *ev,
     110             :                                         struct loadparm_context *lp_ctx,
     111             :                                         TALLOC_CTX *mem_ctx,
     112             :                                         char *share, int snum, int conn)
     113             : {
     114             :         struct smbcli_state *c;
     115             :         char *server, *myname;
     116             :         NTSTATUS status;
     117           4 :         int retries = 10;
     118             :         struct smbcli_options options;
     119             :         struct smbcli_session_options session_options;
     120             : 
     121           4 :         lpcfg_smbcli_options(lp_ctx, &options);
     122           4 :         lpcfg_smbcli_session_options(lp_ctx, &session_options);
     123             : 
     124           4 :         printf("connect_one(%s, %d, %d)\n", share, snum, conn);
     125             : 
     126           4 :         server = talloc_strdup(mem_ctx, share+2);
     127           4 :         share = strchr_m(server,'\\');
     128           4 :         if (!share) return NULL;
     129           4 :         *share = 0;
     130           4 :         share++;
     131             : 
     132           4 :         if (snum == 0) {
     133           2 :                 char **unc_list = NULL;
     134             :                 int num_unc_names;
     135             :                 const char *p;
     136           2 :                 p = lpcfg_parm_string(lp_ctx, NULL, "torture", "unclist");
     137           2 :                 if (p) {
     138             :                         char *h, *s;
     139           0 :                         unc_list = file_lines_load(p, &num_unc_names, 0, NULL);
     140           0 :                         if (!unc_list || num_unc_names <= 0) {
     141           0 :                                 printf("Failed to load unc names list from '%s'\n", p);
     142           0 :                                 exit(1);
     143             :                         }
     144             : 
     145           0 :                         if (!smbcli_parse_unc(unc_list[conn % num_unc_names],
     146             :                                               NULL, &h, &s)) {
     147           0 :                                 printf("Failed to parse UNC name %s\n",
     148           0 :                                        unc_list[conn % num_unc_names]);
     149           0 :                                 exit(1);
     150             :                         }
     151           0 :                         server = talloc_strdup(mem_ctx, h);
     152           0 :                         share = talloc_strdup(mem_ctx, s);
     153             :                 }
     154             :         }
     155             : 
     156             : 
     157           4 :         myname = talloc_asprintf(mem_ctx, "lock-%d-%d", (int) getpid(), snum);
     158           4 :         cli_credentials_set_workstation(servers[snum], myname, CRED_SPECIFIED);
     159             : 
     160             :         do {
     161           4 :                 printf("\\\\%s\\%s\n", server, share);
     162           4 :                 status = smbcli_full_connection(NULL, &c, 
     163             :                                                 server, 
     164             :                                                 lpcfg_smb_ports(lp_ctx),
     165             :                                                 share, NULL,
     166             :                                                 lpcfg_socket_options(lp_ctx),
     167             :                                                 servers[snum], 
     168             :                                                 lpcfg_resolve_context(lp_ctx),
     169             :                                                 ev, &options, &session_options,
     170             :                                                 lpcfg_gensec_settings(mem_ctx, lp_ctx));
     171           4 :                 if (!NT_STATUS_IS_OK(status)) {
     172           0 :                         sleep(2);
     173             :                 }
     174           4 :         } while (!NT_STATUS_IS_OK(status) && retries--);
     175             : 
     176           4 :         if (!NT_STATUS_IS_OK(status)) {
     177           0 :                 return NULL;
     178             :         }
     179             : 
     180           4 :         return c;
     181             : }
     182             : 
     183             : 
     184           1 : static void reconnect(struct tevent_context *ev,
     185             :                       struct loadparm_context *lp_ctx,
     186             :                           TALLOC_CTX *mem_ctx,
     187             :                       struct smbcli_state *cli[NSERVERS][NCONNECTIONS], int fnum[NSERVERS][NCONNECTIONS][NFILES],
     188             :                       char *share[NSERVERS])
     189             : {
     190             :         int server, conn, f;
     191             : 
     192           3 :         for (server=0;server<NSERVERS;server++)
     193           6 :         for (conn=0;conn<NCONNECTIONS;conn++) {
     194           4 :                 if (cli[server][conn]) {
     195           0 :                         for (f=0;f<NFILES;f++) {
     196           0 :                                 if (fnum[server][conn][f] != -1) {
     197           0 :                                         smbcli_close(cli[server][conn]->tree, fnum[server][conn][f]);
     198           0 :                                         fnum[server][conn][f] = -1;
     199             :                                 }
     200             :                         }
     201           0 :                         talloc_free(cli[server][conn]);
     202             :                 }
     203           4 :                 cli[server][conn] = connect_one(ev, lp_ctx, mem_ctx, share[server],
     204             :                                                 server, conn);
     205           4 :                 if (!cli[server][conn]) {
     206           0 :                         DEBUG(0,("Failed to connect to %s\n", share[server]));
     207           0 :                         exit(1);
     208             :                 }
     209             :         }
     210           1 : }
     211             : 
     212             : 
     213             : 
     214         100 : static bool test_one(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], 
     215             :                      int fnum[NSERVERS][NCONNECTIONS][NFILES],
     216             :                      struct record *rec)
     217             : {
     218         100 :         unsigned int conn = rec->conn;
     219         100 :         unsigned int f = rec->f;
     220         100 :         uint64_t start = rec->start;
     221         100 :         uint64_t len = rec->len;
     222         100 :         enum brl_type op = rec->lock_type;
     223             :         int server;
     224             :         /* bool ret[NSERVERS]; */
     225             :         NTSTATUS status[NSERVERS];
     226             : 
     227         100 :         switch (rec->lock_op) {
     228          37 :         case OP_LOCK:
     229             :                 /* set a lock */
     230         111 :                 for (server=0;server<NSERVERS;server++) {
     231             :                         NTSTATUS res;
     232          74 :                         struct smbcli_tree *tree=cli[server][conn]->tree;
     233          74 :                         int fn=fnum[server][conn][f];
     234             : 
     235          74 :                         if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
     236           0 :                                 res=smbcli_lock(tree, fn, start, len, LOCK_TIMEOUT, (enum brl_type) rec->lock_op);
     237             :                         } else {
     238             :                                 union smb_lock parms;
     239             :                                 int ltype;
     240             :                                 struct smb_lock_entry lock[1];
     241             : 
     242          74 :                                 parms.lockx.level = RAW_LOCK_LOCKX;
     243          74 :                                 parms.lockx.in.file.fnum = fn;
     244             :         
     245          74 :                                 ltype = (rec->lock_type == READ_LOCK? 1 : 0);
     246          74 :                                 ltype |= LOCKING_ANDX_LARGE_FILES;
     247          74 :                                 parms.lockx.in.mode = ltype;
     248          74 :                                 parms.lockx.in.timeout = LOCK_TIMEOUT;
     249          74 :                                 parms.lockx.in.ulock_cnt = 0;
     250          74 :                                 parms.lockx.in.lock_cnt = 1;
     251          74 :                                 lock[0].pid = rec->pid;
     252          74 :                                 lock[0].offset = start;
     253          74 :                                 lock[0].count = len;
     254          74 :                                 parms.lockx.in.locks = &lock[0];
     255             : 
     256          74 :                                 res = smb_raw_lock(tree, &parms);
     257             :                         }
     258             : 
     259             :                         /* ret[server] = NT_STATUS_IS_OK(res); */
     260          74 :                         status[server] = res;
     261         148 :                         if (!exact_error_codes && 
     262          74 :                             NT_STATUS_EQUAL(status[server], 
     263             :                                             NT_STATUS_FILE_LOCK_CONFLICT)) {
     264           0 :                                 status[server] = NT_STATUS_LOCK_NOT_GRANTED;
     265             :                         }
     266             :                 }
     267          37 :                 if (showall || !NT_STATUS_EQUAL(status[0],status[1])) {
     268           0 :                         printf("lock   conn=%u f=%u range=%.0f(%.0f) op=%s -> %s:%s\n",
     269             :                                conn, f, 
     270             :                                (double)start, (double)len,
     271             :                                op==READ_LOCK?"READ_LOCK":"WRITE_LOCK",
     272             :                                nt_errstr(status[0]), nt_errstr(status[1]));
     273             :                 }
     274          37 :                 if (!NT_STATUS_EQUAL(status[0],status[1])) return false;
     275          37 :                 break;
     276             :                 
     277          25 :         case OP_UNLOCK:
     278             :                 /* unset a lock */
     279          75 :                 for (server=0;server<NSERVERS;server++) {
     280             :                         NTSTATUS res;
     281          50 :                         struct smbcli_tree *tree=cli[server][conn]->tree;
     282          50 :                         int fn=fnum[server][conn][f];
     283             : 
     284             : 
     285          50 :                         if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
     286           0 :                                 res=smbcli_unlock(tree, fn, start, len);
     287             :                         } else {
     288             :                                 union smb_lock parms;
     289             :                                 struct smb_lock_entry lock[1];
     290             : 
     291          50 :                                 parms.lockx.level = RAW_LOCK_LOCKX;
     292          50 :                                 parms.lockx.in.file.fnum = fn;
     293          50 :                                 parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     294          50 :                                 parms.lockx.in.timeout = 0;
     295          50 :                                 parms.lockx.in.ulock_cnt = 1;
     296          50 :                                 parms.lockx.in.lock_cnt = 0;
     297          50 :                                 lock[0].pid = rec->pid;
     298          50 :                                 lock[0].count = len;
     299          50 :                                 lock[0].offset = start;
     300          50 :                                 parms.lockx.in.locks = &lock[0];
     301             : 
     302          50 :                                 res = smb_raw_lock(tree, &parms);
     303             :                         }
     304             : 
     305             :                         /* ret[server] = NT_STATUS_IS_OK(res); */
     306          50 :                         status[server] = res;
     307             :                 }
     308          50 :                 if (showall || 
     309          50 :                     (!hide_unlock_fails && !NT_STATUS_EQUAL(status[0],status[1]))) {
     310           0 :                         printf("unlock conn=%u f=%u range=%.0f(%.0f)       -> %s:%s\n",
     311             :                                conn, f, 
     312             :                                (double)start, (double)len,
     313             :                                nt_errstr(status[0]), nt_errstr(status[1]));
     314             :                 }
     315          25 :                 if (!hide_unlock_fails && !NT_STATUS_EQUAL(status[0],status[1])) 
     316           0 :                         return false;
     317          25 :                 break;
     318             : 
     319          38 :         case OP_REOPEN:
     320             :                 /* reopen the file */
     321         114 :                 for (server=0;server<NSERVERS;server++) {
     322          76 :                         smbcli_close(cli[server][conn]->tree, fnum[server][conn][f]);
     323          76 :                         fnum[server][conn][f] = -1;
     324             :                 }
     325         114 :                 for (server=0;server<NSERVERS;server++) {
     326          76 :                         fnum[server][conn][f] = smbcli_open(cli[server][conn]->tree, FILENAME,
     327             :                                                          O_RDWR|O_CREAT,
     328             :                                                          DENY_NONE);
     329          76 :                         if (fnum[server][conn][f] == -1) {
     330           0 :                                 printf("failed to reopen on share%d\n", server);
     331           0 :                                 return false;
     332             :                         }
     333             :                 }
     334          38 :                 if (showall) {
     335           0 :                         printf("reopen conn=%u f=%u\n",
     336             :                                conn, f);
     337             :                 }
     338          38 :                 break;
     339             :         }
     340             : 
     341         100 :         return true;
     342             : }
     343             : 
     344           0 : static void close_files(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], 
     345             :                         int fnum[NSERVERS][NCONNECTIONS][NFILES])
     346             : {
     347             :         int server, conn, f; 
     348             : 
     349           0 :         for (server=0;server<NSERVERS;server++)
     350           0 :         for (conn=0;conn<NCONNECTIONS;conn++)
     351           0 :         for (f=0;f<NFILES;f++) {
     352           0 :                 if (fnum[server][conn][f] != -1) {
     353           0 :                         smbcli_close(cli[server][conn]->tree, fnum[server][conn][f]);
     354           0 :                         fnum[server][conn][f] = -1;
     355             :                 }
     356             :         }
     357           0 :         for (server=0;server<NSERVERS;server++) {
     358           0 :                 smbcli_unlink(cli[server][0]->tree, FILENAME);
     359             :         }
     360           0 : }
     361             : 
     362           1 : static void open_files(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], 
     363             :                        int fnum[NSERVERS][NCONNECTIONS][NFILES])
     364             : {
     365             :         int server, conn, f; 
     366             : 
     367           3 :         for (server=0;server<NSERVERS;server++)
     368           6 :         for (conn=0;conn<NCONNECTIONS;conn++)
     369          12 :         for (f=0;f<NFILES;f++) {
     370           8 :                 fnum[server][conn][f] = smbcli_open(cli[server][conn]->tree, FILENAME,
     371             :                                                  O_RDWR|O_CREAT,
     372             :                                                  DENY_NONE);
     373           8 :                 if (fnum[server][conn][f] == -1) {
     374           0 :                         fprintf(stderr,"Failed to open fnum[%u][%u][%u]\n",
     375             :                                 server, conn, f);
     376           0 :                         exit(1);
     377             :                 }
     378             :         }
     379           1 : }
     380             : 
     381             : 
     382           1 : static int retest(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], 
     383             :                    int fnum[NSERVERS][NCONNECTIONS][NFILES],
     384             :                    int n)
     385             : {
     386             :         int i;
     387           1 :         printf("Testing %u ...\n", n);
     388         101 :         for (i=0; i<n; i++) {
     389         100 :                 if (i && i % 100 == 0) {
     390           0 :                         printf("%u\n", i);
     391             :                 }
     392             : 
     393         200 :                 if (recorded[i].needed &&
     394         100 :                     !test_one(cli, fnum, &recorded[i])) return i;
     395             :         }
     396           1 :         return n;
     397             : }
     398             : 
     399             : 
     400             : /* each server has two connections open to it. Each connection has two file
     401             :    descriptors open on the file - 8 file descriptors in total 
     402             : 
     403             :    we then do random locking ops in tamdem on the 4 fnums from each
     404             :    server and ensure that the results match
     405             :  */
     406           1 : static int test_locks(struct tevent_context *ev,
     407             :                       struct loadparm_context *lp_ctx,
     408             :                       TALLOC_CTX *mem_ctx,
     409             :                       char *share[NSERVERS])
     410             : {
     411             :         struct smbcli_state *cli[NSERVERS][NCONNECTIONS];
     412             :         int fnum[NSERVERS][NCONNECTIONS][NFILES];
     413             :         int n, i, n1, skip, r1, r2; 
     414             : 
     415           1 :         ZERO_STRUCT(fnum);
     416           1 :         ZERO_STRUCT(cli);
     417             : 
     418           1 :         recorded = malloc_array_p(struct record, numops);
     419             : 
     420         101 :         for (n=0; n<numops; n++) {
     421             : #if PRESETS
     422             :                 if (n < sizeof(preset) / sizeof(preset[0])) {
     423             :                         recorded[n] = preset[n];
     424             :                 } else {
     425             : #endif
     426         100 :                         recorded[n].conn = random() % NCONNECTIONS;
     427         100 :                         recorded[n].f = random() % NFILES;
     428         100 :                         recorded[n].start = lock_base + ((unsigned int)random() % (lock_range-1));
     429         200 :                         recorded[n].len =  min_length +
     430         100 :                                 random() % (lock_range-(recorded[n].start-lock_base));
     431         100 :                         recorded[n].start *= RANGE_MULTIPLE;
     432         100 :                         recorded[n].len *= RANGE_MULTIPLE;
     433         100 :                         recorded[n].pid = random()%3;
     434         100 :                         if (recorded[n].pid == 2) {
     435          34 :                                 recorded[n].pid = 0xFFFF; /* see if its magic */
     436             :                         }
     437         100 :                         r1 = random() % 100;
     438         100 :                         r2 = random() % 100;
     439         100 :                         if (r1 < READ_PCT) {
     440          48 :                                 recorded[n].lock_type = READ_LOCK;
     441             :                         } else {
     442          52 :                                 recorded[n].lock_type = WRITE_LOCK;
     443             :                         }
     444         100 :                         if (r2 < LOCK_PCT) {
     445          37 :                                 recorded[n].lock_op = OP_LOCK;
     446          63 :                         } else if (r2 < UNLOCK_PCT) {
     447          25 :                                 recorded[n].lock_op = OP_UNLOCK;
     448             :                         } else {
     449          38 :                                 recorded[n].lock_op = OP_REOPEN;
     450             :                         }
     451         100 :                         recorded[n].needed = true;
     452         100 :                         if (!zero_zero && recorded[n].start==0 && recorded[n].len==0) {
     453           0 :                                 recorded[n].len = 1;
     454             :                         }
     455             : #if PRESETS
     456             :                 }
     457             : #endif
     458             :         }
     459             : 
     460           1 :         reconnect(ev, lp_ctx, mem_ctx, cli, fnum, share);
     461           1 :         open_files(cli, fnum);
     462           1 :         n = retest(cli, fnum, numops);
     463             : 
     464           1 :         if (n == numops || !analyze) {
     465           1 :                 if (n != numops) {
     466           0 :                         return 1;
     467             :                 }
     468           1 :                 return 0;
     469             :         }
     470           0 :         n++;
     471             : 
     472           0 :         skip = n/2;
     473             : 
     474             :         while (1) {
     475           0 :                 n1 = n;
     476             : 
     477           0 :                 close_files(cli, fnum);
     478           0 :                 reconnect(ev, lp_ctx, mem_ctx, cli, fnum, share);
     479           0 :                 open_files(cli, fnum);
     480             : 
     481           0 :                 for (i=0;i<n-skip;i+=skip) {
     482             :                         int m, j;
     483           0 :                         printf("excluding %d-%d\n", i, i+skip-1);
     484           0 :                         for (j=i;j<i+skip;j++) {
     485           0 :                                 recorded[j].needed = false;
     486             :                         }
     487             : 
     488           0 :                         close_files(cli, fnum);
     489           0 :                         open_files(cli, fnum);
     490             : 
     491           0 :                         m = retest(cli, fnum, n);
     492           0 :                         if (m == n) {
     493           0 :                                 for (j=i;j<i+skip;j++) {
     494           0 :                                         recorded[j].needed = true;
     495             :                                 }
     496             :                         } else {
     497           0 :                                 if (i+(skip-1) < m) {
     498           0 :                                         memmove(&recorded[i], &recorded[i+skip],
     499           0 :                                                 (m-(i+skip-1))*sizeof(recorded[0]));
     500             :                                 }
     501           0 :                                 n = m-(skip-1);
     502           0 :                                 i--;
     503             :                         }
     504             :                 }
     505             : 
     506           0 :                 if (skip > 1) {
     507           0 :                         skip = skip/2;
     508           0 :                         printf("skip=%d\n", skip);
     509           0 :                         continue;
     510             :                 }
     511             : 
     512           0 :                 if (n1 == n) break;
     513             :         }
     514             : 
     515           0 :         close_files(cli, fnum);
     516           0 :         reconnect(ev, lp_ctx, mem_ctx, cli, fnum, share);
     517           0 :         open_files(cli, fnum);
     518           0 :         showall = true;
     519           0 :         n1 = retest(cli, fnum, n);
     520           0 :         if (n1 != n-1) {
     521           0 :                 printf("ERROR - inconsistent result (%u %u)\n", n1, n);
     522             :         }
     523           0 :         close_files(cli, fnum);
     524             : 
     525           0 :         for (i=0;i<n;i++) {
     526           0 :                 printf("{%d, %d, %u, %u, %.0f, %.0f, %u},\n",
     527           0 :                        recorded[i].lock_op,
     528           0 :                        recorded[i].lock_type,
     529           0 :                        recorded[i].conn,
     530           0 :                        recorded[i].f,
     531           0 :                        (double)recorded[i].start,
     532           0 :                        (double)recorded[i].len,
     533           0 :                        recorded[i].needed);
     534             :         }       
     535             : 
     536           0 :         return 1;
     537             : }
     538             : 
     539             : 
     540             : 
     541           0 : static void usage(poptContext pc)
     542             : {
     543           0 :         printf("Usage:\n\tlocktest //server1/share1 //server2/share2 [options..]\n");
     544           0 :         poptPrintUsage(pc, stdout, 0);
     545           0 : }
     546             : 
     547             : /****************************************************************************
     548             :   main program
     549             : ****************************************************************************/
     550           1 : int main(int argc, const char *argv[])
     551             : {
     552             :         char *share[NSERVERS];
     553             :         int opt;
     554             :         int seed, server;
     555           1 :         int username_count=0;
     556             :         struct tevent_context *ev;
     557             :         struct loadparm_context *lp_ctx;
     558             :         poptContext pc;
     559             :         int argc_new, i;
     560             :         char **argv_new;
     561             :         enum {
     562             :                 OPT_UNCLIST=1000,
     563             :                 OPT_USER1,
     564             :                 OPT_USER2,
     565             :         };
     566           6 :         struct poptOption long_options[] = {
     567             :                 POPT_AUTOHELP
     568             :                 {"seed",        0, POPT_ARG_INT,  &seed,  0,      "Seed to use for randomizer",         NULL},
     569             :                 {"num-ops",     0, POPT_ARG_INT,  &numops,        0,      "num ops",    NULL},
     570             :                 {"lockrange",     0, POPT_ARG_INT,  &lock_range,0,      "locking range", NULL},
     571             :                 {"lockbase",      0, POPT_ARG_INT,  &lock_base, 0,      "locking base", NULL},
     572             :                 {"minlength",     0, POPT_ARG_INT,  &min_length,0,      "min lock length", NULL},
     573             :                 {"hidefails",     0, POPT_ARG_NONE, &hide_unlock_fails,0,"hide unlock fails", NULL},
     574             :                 {"oplocks",       0, POPT_ARG_NONE, &use_oplocks,0,      "use oplocks", NULL},
     575             :                 {"showall",       0, POPT_ARG_NONE, &showall,    0,      "display all operations", NULL},
     576             :                 {"analyse",       0, POPT_ARG_NONE, &analyze,    0,      "do backtrack analysis", NULL},
     577             :                 {"zerozero",      0, POPT_ARG_NONE, &zero_zero,    0,      "do zero/zero lock", NULL},
     578             :                 {"exacterrors",   0, POPT_ARG_NONE, &exact_error_codes,0,"use exact error codes", NULL},
     579             :                 {"unclist",     0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",    NULL},
     580             :                 {"user1",         0, POPT_ARG_STRING, NULL, OPT_USER1, "Set first network username", "[DOMAIN/]USERNAME[%PASSWORD]" },
     581             :                 {"user2",         0, POPT_ARG_STRING, NULL, OPT_USER2, "Set second network username", "[DOMAIN/]USERNAME[%PASSWORD]" },
     582           1 :                 POPT_COMMON_SAMBA
     583           1 :                 POPT_COMMON_CONNECTION
     584           1 :                 POPT_COMMON_CREDENTIALS
     585           1 :                 POPT_COMMON_VERSION
     586           1 :                 POPT_LEGACY_S4
     587             :                 POPT_TABLEEND
     588             :         };
     589           1 :         TALLOC_CTX *mem_ctx = NULL;
     590           1 :         int ret = -1;
     591             :         bool ok;
     592             : 
     593           1 :         setlinebuf(stdout);
     594           1 :         seed = time(NULL);
     595             : 
     596           1 :         mem_ctx = talloc_named_const(NULL, 0, "locktest_ctx");
     597           1 :         if (mem_ctx == NULL) {
     598           0 :                 printf("Unable to allocate locktest_ctx\n");
     599           0 :                 exit(1);
     600             :         }
     601             : 
     602           1 :         ok = samba_cmdline_init(mem_ctx,
     603             :                                 SAMBA_CMDLINE_CONFIG_CLIENT,
     604             :                                 false /* require_smbconf */);
     605           1 :         if (!ok) {
     606           0 :                 DBG_ERR("Failed to init cmdline parser!\n");
     607           0 :                 TALLOC_FREE(mem_ctx);
     608           0 :                 exit(1);
     609             :         }
     610             : 
     611             : 
     612           1 :         pc = samba_popt_get_context("locktest",
     613             :                                     argc,
     614             :                                     argv,
     615             :                                     long_options,
     616             :                                     POPT_CONTEXT_KEEP_FIRST);
     617           1 :         if (pc == NULL) {
     618           0 :                 DBG_ERR("Failed to setup popt context!\n");
     619           0 :                 TALLOC_FREE(mem_ctx);
     620           0 :                 exit(1);
     621             :         }
     622             : 
     623           1 :         poptSetOtherOptionHelp(pc, "<unc1> <unc2>");
     624             : 
     625           1 :         lp_ctx = samba_cmdline_get_lp_ctx();
     626             : 
     627           1 :         servers[0] = cli_credentials_init(mem_ctx);
     628           1 :         servers[1] = cli_credentials_init(mem_ctx);
     629           1 :         cli_credentials_guess(servers[0], lp_ctx);
     630           1 :         cli_credentials_guess(servers[1], lp_ctx);
     631             : 
     632           1 :         while((opt = poptGetNextOpt(pc)) != -1) {
     633           1 :                 switch (opt) {
     634           0 :                 case OPT_UNCLIST:
     635           0 :                         lpcfg_set_cmdline(lp_ctx, "torture:unclist", poptGetOptArg(pc));
     636           0 :                         break;
     637           1 :                 case OPT_USER1:
     638           1 :                         cli_credentials_parse_string(servers[0],
     639           1 :                                                      poptGetOptArg(pc),
     640             :                                                      CRED_SPECIFIED);
     641           1 :                         username_count++;
     642           1 :                         break;
     643           0 :                 case OPT_USER2:
     644           0 :                         cli_credentials_parse_string(servers[1],
     645           0 :                                                      poptGetOptArg(pc),
     646             :                                                      CRED_SPECIFIED);
     647           0 :                         username_count++;
     648           0 :                         break;
     649           0 :                 case POPT_ERROR_BADOPT:
     650           0 :                         fprintf(stderr, "\nInvalid option %s: %s\n\n",
     651             :                                 poptBadOption(pc, 0), poptStrerror(opt));
     652           0 :                         poptPrintUsage(pc, stderr, 0);
     653           0 :                         exit(1);
     654             :                 }
     655             :         }
     656             : 
     657           1 :         argv_new = discard_const_p(char *, poptGetArgs(pc));
     658           1 :         argc_new = argc;
     659           4 :         for (i=0; i<argc; i++) {
     660           4 :                 if (argv_new[i] == NULL) {
     661           1 :                         argc_new = i;
     662           1 :                         break;
     663             :                 }
     664             :         }
     665             : 
     666           1 :         if (!(argc_new >= 3)) {
     667           0 :                 usage(pc);
     668           0 :                 exit(1);
     669             :         }
     670             : 
     671           1 :         setup_logging("locktest", DEBUG_STDOUT);
     672             : 
     673           3 :         for (server=0;server<NSERVERS;server++) {
     674           2 :                 share[server] = argv_new[1+server];
     675           2 :                 all_string_sub(share[server],"/","\\",0);
     676             :         }
     677             : 
     678           1 :         if (username_count == 0) {
     679           0 :                 usage(pc);
     680           0 :                 poptFreeContext(pc);
     681           0 :                 return -1;
     682             :         }
     683           1 :         if (username_count == 1) {
     684           1 :                 servers[1] = servers[0];
     685             :         }
     686             : 
     687           1 :         ev = s4_event_context_init(mem_ctx);
     688             : 
     689           1 :         gensec_init();
     690             : 
     691           1 :         DEBUG(0,("seed=%u base=%d range=%d min_length=%d\n", 
     692             :                  seed, lock_base, lock_range, min_length));
     693           1 :         srandom(seed);
     694             : 
     695           1 :         ret = test_locks(ev, lp_ctx, NULL, share);
     696           1 :         poptFreeContext(pc);
     697           1 :         talloc_free(mem_ctx);
     698           1 :         return ret;
     699             : }
     700             : 

Generated by: LCOV version 1.13