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

Generated by: LCOV version 1.14