home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / samba-1.9.18p7.tar.gz / samba-1.9.18p7.tar / samba-1.9.18p7 / source / torture.c < prev    next >
C/C++ Source or Header  |  1998-05-12  |  19KB  |  920 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    SMB torture tester
  5.    Copyright (C) Andrew Tridgell 1997-1998
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #ifdef SYSLOG
  23. #undef SYSLOG
  24. #endif
  25.  
  26. #include "includes.h"
  27.  
  28. static fstring host, workgroup, share, password, username, myname;
  29. static int max_protocol = PROTOCOL_NT1;
  30. static char *sockops="";
  31.  
  32.  
  33. static struct timeval tp1,tp2;
  34.  
  35. static void start_timer()
  36. {
  37.     gettimeofday(&tp1,NULL);
  38. }
  39.  
  40. static double end_timer()
  41. {
  42.     gettimeofday(&tp2,NULL);
  43.     return((tp2.tv_sec - tp1.tv_sec) + 
  44.            (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
  45. }
  46.  
  47.  
  48. static BOOL open_connection(struct cli_state *c)
  49. {
  50.     if (!cli_initialise(c) || !cli_connect(c, host, NULL)) {
  51.         printf("Failed to connect with %s\n", host);
  52.         return False;
  53.     }
  54.  
  55.     if (!cli_session_request(c, host, 0x20, myname)) {
  56.         printf("%s rejected the session\n",host);
  57.         cli_shutdown(c);
  58.         return False;
  59.     }
  60.  
  61.     c->protocol = max_protocol;
  62.  
  63.     if (!cli_negprot(c)) {
  64.         printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
  65.         cli_shutdown(c);
  66.         return False;
  67.     }
  68.  
  69.     if (!cli_session_setup(c, username, password, strlen(password),
  70.                    "", 0, workgroup)) {
  71.         printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
  72.         cli_shutdown(c);
  73.         return False;
  74.     }
  75.  
  76.     if (!cli_send_tconX(c, share, "A:", password, strlen(password)+1)) {
  77.         printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
  78.         cli_shutdown(c);
  79.         return False;
  80.     }
  81.  
  82.     return True;
  83. }
  84.  
  85.  
  86.  
  87. static void close_connection(struct cli_state *c)
  88. {
  89.     if (!cli_tdis(c)) {
  90.         printf("tdis failed (%s)\n", cli_errstr(c));
  91.     }
  92.  
  93.     cli_shutdown(c);
  94. }
  95.  
  96.  
  97. static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
  98. {
  99.     while (!cli_lock(c, fnum, offset, len, -1)) {
  100.         int eclass, num;
  101.         cli_error(c, &eclass, &num);
  102.         if (eclass != ERRDOS || num != ERRlock) {
  103.             printf("lock failed (%s)\n", 
  104.                    cli_errstr(c));
  105.             return False;
  106.         }
  107.     }
  108.     return True;
  109. }
  110.  
  111.  
  112. static BOOL rw_torture(struct cli_state *c, int numops)
  113. {
  114.     char *lockfname = "\\torture.lck";
  115.     fstring fname;
  116.     int fnum;
  117.     int fnum2;
  118.     int pid2, pid = getpid();
  119.     int i;
  120.  
  121.     fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
  122.              DENY_NONE);
  123.     if (fnum2 == -1)
  124.         fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
  125.     if (fnum2 == -1) {
  126.         printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
  127.         return False;
  128.     }
  129.  
  130.  
  131.     for (i=0;i<numops;i++) {
  132.         unsigned n = (unsigned)random()%10;
  133.         if (i % 10 == 0) {
  134.             printf("%d\r", i); fflush(stdout);
  135.         }
  136.         slprintf(fname,sizeof(fstring)-1,"\\torture.%u", n);
  137.  
  138.         if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
  139.             return False;
  140.         }
  141.  
  142.         fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
  143.         if (fnum == -1) {
  144.             printf("open failed (%s)\n", cli_errstr(c));
  145.             break;
  146.         }
  147.  
  148.         if (cli_write(c, fnum, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
  149.             printf("write failed (%s)\n", cli_errstr(c));
  150.         }
  151.  
  152.         pid2 = 0;
  153.  
  154.         if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
  155.             printf("read failed (%s)\n", cli_errstr(c));
  156.         }
  157.  
  158.         if (pid2 != pid) {
  159.             printf("data corruption!\n");
  160.         }
  161.  
  162.         if (!cli_close(c, fnum)) {
  163.             printf("close failed (%s)\n", cli_errstr(c));
  164.         }
  165.  
  166.         if (!cli_unlink(c, fname)) {
  167.             printf("unlink failed (%s)\n", cli_errstr(c));
  168.         }
  169.  
  170.         if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int), -1)) {
  171.             printf("unlock failed (%s)\n", cli_errstr(c));
  172.         }
  173.     }
  174.  
  175.     cli_close(c, fnum2);
  176.     cli_unlink(c, lockfname);
  177.  
  178.     printf("%d\n", i);
  179.  
  180.     return True;
  181. }
  182.  
  183. static void usage(void)
  184. {
  185.     printf("Usage: smbtorture \\\\server\\share <options>\n");
  186.  
  187.     printf("\t-U user%%pass\n");
  188.     printf("\t-N numprocs\n");
  189.     printf("\t-n my_netbios_name\n");
  190.     printf("\t-W workgroup\n");
  191.     printf("\t-o num_operations\n");
  192.     printf("\t-O socket_options\n");
  193.     printf("\t-m maximum protocol\n");
  194.     printf("\n");
  195.  
  196.     exit(1);
  197. }
  198.  
  199.  
  200.  
  201. static void run_torture(int numops)
  202. {
  203.     static struct cli_state cli;
  204.  
  205.     if (open_connection(&cli)) {
  206.         cli_sockopt(&cli, sockops);
  207.  
  208.         printf("pid %d OK\n", getpid());
  209.  
  210.         rw_torture(&cli, numops);
  211.  
  212.         close_connection(&cli);
  213.     }
  214. }
  215.  
  216. /*
  217.   This test checks for two things:
  218.  
  219.   1) correct support for retaining locks over a close (ie. the server
  220.      must not use posix semantics)
  221.   2) support for lock timeouts
  222.  */
  223. static void run_locktest1(void)
  224. {
  225.     static struct cli_state cli1, cli2;
  226.     char *fname = "\\locktest.lck";
  227.     int fnum1, fnum2, fnum3;
  228.     time_t t1, t2;
  229.  
  230.     if (!open_connection(&cli1) || !open_connection(&cli2)) {
  231.         return;
  232.     }
  233.     cli_sockopt(&cli1, sockops);
  234.     cli_sockopt(&cli2, sockops);
  235.  
  236.     printf("starting locktest1\n");
  237.  
  238.     cli_unlink(&cli1, fname);
  239.  
  240.     fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
  241.     if (fnum1 == -1) {
  242.         printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
  243.         return;
  244.     }
  245.     fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
  246.     if (fnum2 == -1) {
  247.         printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
  248.         return;
  249.     }
  250.     fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
  251.     if (fnum3 == -1) {
  252.         printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
  253.         return;
  254.     }
  255.  
  256.     if (!cli_lock(&cli1, fnum1, 0, 4, 0)) {
  257.         printf("lock1 failed (%s)\n", cli_errstr(&cli1));
  258.         return;
  259.     }
  260.  
  261.  
  262.     if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
  263.         printf("lock2 succeeded! This is a locking bug\n");
  264.         return;
  265.     } else {
  266.         int eclass, num;
  267.         cli_error(&cli2, &eclass, &num);
  268.         if (eclass != ERRDOS || num != ERRlock) {
  269.             printf("error should have been ERRDOS/ERRlock (%s)\n", 
  270.                    cli_errstr(&cli2));
  271.             return;
  272.         }
  273.     }
  274.  
  275.  
  276.     printf("Testing lock timeouts\n");
  277.     t1 = time(NULL);
  278.     if (cli_lock(&cli2, fnum3, 0, 4, 10*1000)) {
  279.         printf("lock3 succeeded! This is a locking bug\n");
  280.         return;
  281.     } else {
  282.         int eclass, num;
  283.         cli_error(&cli2, &eclass, &num);
  284.         if (eclass != ERRDOS || num != ERRlock) {
  285.             printf("error should have been ERRDOS/ERRlock (%s)\n", 
  286.                    cli_errstr(&cli2));
  287.             return;
  288.         }
  289.     }
  290.     t2 = time(NULL);
  291.  
  292.     if (t2 - t1 < 5) {
  293.         printf("error: This server appears not to support timed lock requests\n");
  294.     }
  295.  
  296.     if (!cli_close(&cli1, fnum2)) {
  297.         printf("close1 failed (%s)\n", cli_errstr(&cli1));
  298.         return;
  299.     }
  300.  
  301.     if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
  302.         printf("lock4 succeeded! This is a locking bug\n");
  303.         return;
  304.     } else {
  305.         int eclass, num;
  306.         cli_error(&cli2, &eclass, &num);
  307.         if (eclass != ERRDOS || num != ERRlock) {
  308.             printf("error should have been ERRDOS/ERRlock (%s)\n", 
  309.                    cli_errstr(&cli2));
  310.             return;
  311.         }
  312.     }
  313.  
  314.     if (!cli_close(&cli1, fnum1)) {
  315.         printf("close2 failed (%s)\n", cli_errstr(&cli1));
  316.         return;
  317.     }
  318.  
  319.     if (!cli_close(&cli2, fnum3)) {
  320.         printf("close3 failed (%s)\n", cli_errstr(&cli2));
  321.         return;
  322.     }
  323.  
  324.     if (!cli_unlink(&cli1, fname)) {
  325.         printf("unlink failed (%s)\n", cli_errstr(&cli1));
  326.         return;
  327.     }
  328.  
  329.  
  330.     close_connection(&cli1);
  331.     close_connection(&cli2);
  332.  
  333.     printf("Passed locktest1\n");
  334. }
  335.  
  336.  
  337. /*
  338.   This test checks that 
  339.  
  340.   1) the server supports multiple locking contexts on the one SMB
  341.   connection, distinguished by PID.  
  342.  
  343.   2) the server correctly fails overlapping locks made by the same PID (this
  344.      goes against POSIX behaviour, which is why it is tricky to implement)
  345.  
  346.   3) the server denies unlock requests by an incorrect client PID
  347. */
  348. static void run_locktest2(void)
  349. {
  350.     static struct cli_state cli;
  351.     char *fname = "\\locktest.lck";
  352.     int fnum1, fnum2, fnum3;
  353.  
  354.     if (!open_connection(&cli)) {
  355.         return;
  356.     }
  357.  
  358.     cli_sockopt(&cli, sockops);
  359.  
  360.     printf("starting locktest2\n");
  361.  
  362.     cli_unlink(&cli, fname);
  363.  
  364.     cli_setpid(&cli, 1);
  365.  
  366.     fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
  367.     if (fnum1 == -1) {
  368.         printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
  369.         return;
  370.     }
  371.  
  372.     fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
  373.     if (fnum2 == -1) {
  374.         printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
  375.         return;
  376.     }
  377.  
  378.     cli_setpid(&cli, 2);
  379.  
  380.     fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
  381.     if (fnum3 == -1) {
  382.         printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
  383.         return;
  384.     }
  385.  
  386.     cli_setpid(&cli, 1);
  387.  
  388.     if (!cli_lock(&cli, fnum1, 0, 4, 0)) {
  389.         printf("lock1 failed (%s)\n", cli_errstr(&cli));
  390.         return;
  391.     }
  392.  
  393.     if (cli_lock(&cli, fnum2, 0, 4, 0)) {
  394.         printf("lock2 succeeded! This is a locking bug\n");
  395.     } else {
  396.         int eclass, num;
  397.         cli_error(&cli, &eclass, &num);
  398.         if (eclass != ERRDOS || num != ERRlock) {
  399.             printf("error should have been ERRDOS/ERRlock (%s)\n", 
  400.                    cli_errstr(&cli));
  401.             return;
  402.         }
  403.     }
  404.  
  405.     cli_setpid(&cli, 2);
  406.  
  407.     if (cli_unlock(&cli, fnum1, 0, 4, 0)) {
  408.         printf("unlock1 succeeded! This is a locking bug\n");
  409.     }
  410.  
  411.     if (cli_lock(&cli, fnum3, 0, 4, 0)) {
  412.         printf("lock3 succeeded! This is a locking bug\n");
  413.     } else {
  414.         int eclass, num;
  415.         cli_error(&cli, &eclass, &num);
  416.         if (eclass != ERRDOS || num != ERRlock) {
  417.             printf("error should have been ERRDOS/ERRlock (%s)\n", 
  418.                    cli_errstr(&cli));
  419.             return;
  420.         }
  421.     }
  422.  
  423.     cli_setpid(&cli, 1);
  424.  
  425.     if (!cli_close(&cli, fnum1)) {
  426.         printf("close1 failed (%s)\n", cli_errstr(&cli));
  427.         return;
  428.     }
  429.  
  430.     if (!cli_close(&cli, fnum2)) {
  431.         printf("close2 failed (%s)\n", cli_errstr(&cli));
  432.         return;
  433.     }
  434.  
  435.     if (!cli_close(&cli, fnum3)) {
  436.         printf("close3 failed (%s)\n", cli_errstr(&cli));
  437.         return;
  438.     }
  439.  
  440.     close_connection(&cli);
  441.  
  442.     printf("locktest2 finished\n");
  443. }
  444.  
  445.  
  446. /*
  447.   This test checks that 
  448.  
  449.   1) the server supports the full offset range in lock requests
  450. */
  451. static void run_locktest3(int numops)
  452. {
  453.     static struct cli_state cli1, cli2;
  454.     char *fname = "\\locktest.lck";
  455.     int fnum1, fnum2, i;
  456.     uint32 offset;
  457.  
  458. #define NEXT_OFFSET offset += (~(uint32)0) / numops
  459.  
  460.     if (!open_connection(&cli1) || !open_connection(&cli2)) {
  461.         return;
  462.     }
  463.     cli_sockopt(&cli1, sockops);
  464.     cli_sockopt(&cli2, sockops);
  465.  
  466.     printf("starting locktest3\n");
  467.  
  468.     cli_unlink(&cli1, fname);
  469.  
  470.     fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
  471.     if (fnum1 == -1) {
  472.         printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
  473.         return;
  474.     }
  475.     fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
  476.     if (fnum2 == -1) {
  477.         printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
  478.         return;
  479.     }
  480.  
  481.     for (offset=i=0;i<numops;i++) {
  482.         NEXT_OFFSET;
  483.         if (!cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
  484.             printf("lock1 %d failed (%s)\n", 
  485.                    i,
  486.                    cli_errstr(&cli1));
  487.             return;
  488.         }
  489.  
  490.         if (!cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
  491.             printf("lock2 %d failed (%s)\n", 
  492.                    i,
  493.                    cli_errstr(&cli1));
  494.             return;
  495.         }
  496.     }
  497.  
  498.     for (offset=i=0;i<numops;i++) {
  499.         NEXT_OFFSET;
  500.  
  501.         if (cli_lock(&cli1, fnum1, offset-2, 1, 0)) {
  502.             printf("error: lock1 %d succeeded!\n", i);
  503.             return;
  504.         }
  505.  
  506.         if (cli_lock(&cli2, fnum2, offset-1, 1, 0)) {
  507.             printf("error: lock2 %d succeeded!\n", i);
  508.             return;
  509.         }
  510.  
  511.         if (cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
  512.             printf("error: lock3 %d succeeded!\n", i);
  513.             return;
  514.         }
  515.  
  516.         if (cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
  517.             printf("error: lock4 %d succeeded!\n", i);
  518.             return;
  519.         }
  520.     }
  521.  
  522.     for (offset=i=0;i<numops;i++) {
  523.         NEXT_OFFSET;
  524.  
  525.         if (!cli_unlock(&cli1, fnum1, offset-1, 1, 0)) {
  526.             printf("unlock1 %d failed (%s)\n", 
  527.                    i,
  528.                    cli_errstr(&cli1));
  529.             return;
  530.         }
  531.  
  532.         if (!cli_unlock(&cli2, fnum2, offset-2, 1, 0)) {
  533.             printf("unlock2 %d failed (%s)\n", 
  534.                    i,
  535.                    cli_errstr(&cli1));
  536.             return;
  537.         }
  538.     }
  539.  
  540.     if (!cli_close(&cli1, fnum1)) {
  541.         printf("close1 failed (%s)\n", cli_errstr(&cli1));
  542.     }
  543.  
  544.     if (!cli_close(&cli2, fnum2)) {
  545.         printf("close2 failed (%s)\n", cli_errstr(&cli2));
  546.     }
  547.  
  548.     if (!cli_unlink(&cli1, fname)) {
  549.         printf("unlink failed (%s)\n", cli_errstr(&cli1));
  550.         return;
  551.     }
  552.  
  553.     close_connection(&cli1);
  554.     close_connection(&cli2);
  555.  
  556.     printf("finished locktest3\n");
  557. }
  558.  
  559.  
  560. /*
  561.   This test checks that 
  562.  
  563.   1) the server does not allow an unlink on a file that is open
  564. */
  565. static void run_unlinktest(void)
  566. {
  567.     static struct cli_state cli;
  568.     char *fname = "\\unlink.tst";
  569.     int fnum;
  570.  
  571.     if (!open_connection(&cli)) {
  572.         return;
  573.     }
  574.  
  575.     cli_sockopt(&cli, sockops);
  576.  
  577.     printf("starting unlink test\n");
  578.  
  579.     cli_unlink(&cli, fname);
  580.  
  581.     cli_setpid(&cli, 1);
  582.  
  583.     fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
  584.     if (fnum == -1) {
  585.         printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
  586.         return;
  587.     }
  588.  
  589.     if (cli_unlink(&cli, fname)) {
  590.         printf("error: server allowed unlink on an open file\n");
  591.     }
  592.  
  593.     cli_close(&cli, fnum);
  594.     cli_unlink(&cli, fname);
  595.  
  596.     close_connection(&cli);
  597.  
  598.     printf("unlink test finished\n");
  599. }
  600.  
  601.  
  602.  
  603. static void browse_callback(char *sname, uint32 stype, char *comment)
  604. {
  605.     printf("\t%20.20s %08x %s\n", sname, stype, comment);
  606. }
  607.  
  608.  
  609. /*
  610.   This test checks the browse list code
  611.  
  612. */
  613. static void run_browsetest(void)
  614. {
  615.     static struct cli_state cli;
  616.  
  617.     printf("starting browse test\n");
  618.  
  619.     if (!open_connection(&cli)) {
  620.         return;
  621.     }
  622.  
  623.     printf("domain list:\n");
  624.     cli_NetServerEnum(&cli, workgroup, 
  625.               SV_TYPE_DOMAIN_ENUM,
  626.               browse_callback);
  627.  
  628.     printf("machine list:\n");
  629.     cli_NetServerEnum(&cli, workgroup, 
  630.               SV_TYPE_ALL,
  631.               browse_callback);
  632.  
  633.     close_connection(&cli);
  634.  
  635.     printf("browse test finished\n");
  636. }
  637.  
  638.  
  639. /*
  640.   This checks how the getatr calls works
  641. */
  642. static void run_attrtest(void)
  643. {
  644.     static struct cli_state cli;
  645.     int fnum;
  646.     time_t t, t2;
  647.     char *fname = "\\attrib.tst";
  648.  
  649.     printf("starting attrib test\n");
  650.  
  651.     if (!open_connection(&cli)) {
  652.         return;
  653.     }
  654.  
  655.     cli_unlink(&cli, fname);
  656.     fnum = cli_open(&cli, fname, 
  657.             O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
  658.     cli_close(&cli, fnum);
  659.     if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
  660.         printf("getatr failed (%s)\n", cli_errstr(&cli));
  661.     }
  662.  
  663.     if (abs(t - time(NULL)) > 2) {
  664.         printf("ERROR: SMBgetatr bug. time is %s",
  665.                ctime(&t));
  666.         t = time(NULL);
  667.     }
  668.  
  669.     t2 = t-60*60*24; /* 1 day ago */
  670.  
  671.     if (!cli_setatr(&cli, fname, 0, t2)) {
  672.         printf("setatr failed (%s)\n", cli_errstr(&cli));
  673.     }
  674.  
  675.     if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
  676.         printf("getatr failed (%s)\n", cli_errstr(&cli));
  677.     }
  678.  
  679.     if (t != t2) {
  680.         printf("ERROR: getatr/setatr bug. times are\n%s",
  681.                ctime(&t));
  682.         printf("%s", ctime(&t2));
  683.     }
  684.  
  685.     cli_unlink(&cli, fname);
  686.  
  687.     close_connection(&cli);
  688.  
  689.     printf("attrib test finished\n");
  690. }
  691.  
  692.  
  693. /*
  694.   This checks a couple of trans2 calls
  695. */
  696. static void run_trans2test(void)
  697. {
  698.     static struct cli_state cli;
  699.     int fnum;
  700.     uint32 size;
  701.     time_t c_time, a_time, m_time, w_time, m_time2;
  702.     char *fname = "\\trans2.tst";
  703.     char *dname = "\\trans2";
  704.     char *fname2 = "\\trans2\\trans2.tst";
  705.  
  706.     printf("starting trans2 test\n");
  707.  
  708.     if (!open_connection(&cli)) {
  709.         return;
  710.     }
  711.  
  712.     cli_unlink(&cli, fname);
  713.     fnum = cli_open(&cli, fname, 
  714.             O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
  715.     if (!cli_qfileinfo(&cli, fnum, &c_time, &a_time, &m_time, &size)) {
  716.         printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
  717.     }
  718.     cli_close(&cli, fnum);
  719.  
  720.     sleep(2);
  721.  
  722.     cli_unlink(&cli, fname);
  723.     fnum = cli_open(&cli, fname, 
  724.             O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
  725.     cli_close(&cli, fnum);
  726.  
  727.     if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size)) {
  728.         printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
  729.     } else {
  730.         if (c_time != m_time) {
  731.             printf("create time=%s", ctime(&c_time));
  732.             printf("modify time=%s", ctime(&m_time));
  733.             printf("This system appears to have sticky create times\n");
  734.         }
  735.         if (a_time % (60*60) == 0) {
  736.             printf("access time=%s", ctime(&a_time));
  737.             printf("This system appears to set a midnight access time\n");
  738.         }
  739.  
  740.         if (abs(m_time - time(NULL)) > 60*60*24*7) {
  741.             printf("ERROR: totally incorrect times - maybe word reversed?\n");
  742.         }
  743.     }
  744.  
  745.  
  746.     cli_unlink(&cli, fname);
  747.     fnum = cli_open(&cli, fname, 
  748.             O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
  749.     cli_close(&cli, fnum);
  750.     if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time, 
  751.                 &w_time, &size)) {
  752.         printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
  753.     } else {
  754.         if (w_time < 60*60*24*2) {
  755.             printf("write time=%s", ctime(&w_time));
  756.             printf("This system appears to set a initial 0 write time\n");
  757.         }
  758.     }
  759.  
  760.     cli_unlink(&cli, fname);
  761.  
  762.  
  763.     /* check if the server updates the directory modification time
  764.            when creating a new file */
  765.     if (!cli_mkdir(&cli, dname)) {
  766.         printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
  767.     }
  768.     sleep(3);
  769.     if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time, 
  770.                 &w_time, &size)) {
  771.         printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
  772.     }
  773.  
  774.     fnum = cli_open(&cli, fname2, 
  775.             O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
  776.     cli_write(&cli, fnum,  (char *)&fnum, 0, sizeof(fnum));
  777.     cli_close(&cli, fnum);
  778.     if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2, 
  779.                 &w_time, &size)) {
  780.         printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
  781.     } else {
  782.         if (m_time2 == m_time)
  783.             printf("This system does not update directory modification times\n");
  784.     }
  785.     cli_unlink(&cli, fname2);
  786.     cli_rmdir(&cli, dname);
  787.  
  788.  
  789.     close_connection(&cli);
  790.  
  791.     printf("trans2 test finished\n");
  792. }
  793.  
  794.  
  795. static void create_procs(int nprocs, int numops)
  796. {
  797.     int i, status;
  798.  
  799.     for (i=0;i<nprocs;i++) {
  800.         if (fork() == 0) {
  801.             int mypid = getpid();
  802.             srandom(mypid ^ time(NULL));
  803.             run_torture(numops);
  804.             _exit(0);
  805.         }
  806.     }
  807.  
  808.     for (i=0;i<nprocs;i++)
  809.         waitpid(0, &status, 0);
  810. }
  811.  
  812.  
  813.  
  814. /****************************************************************************
  815.   main program
  816. ****************************************************************************/
  817.  int main(int argc,char *argv[])
  818. {
  819.     int nprocs=1, numops=100;
  820.     int opt;
  821.     char *p;
  822.     int gotpass = 0;
  823.     extern char *optarg;
  824.     extern int optind;
  825.     extern FILE *dbf;
  826.  
  827.     dbf = stdout;
  828.  
  829.     charset_initialise();
  830.  
  831.     if (argc < 2) {
  832.         usage();
  833.     }
  834.  
  835.     if (strncmp(argv[1], "\\\\", 2)) {
  836.         usage();
  837.     }
  838.  
  839.     fstrcpy(host, &argv[1][2]);
  840.     p = strchr(&host[2],'\\');
  841.     if (!p) {
  842.         usage();
  843.     }
  844.     *p = 0;
  845.     fstrcpy(share, p+1);
  846.  
  847.     get_myname(myname,NULL);
  848.  
  849.     if (*username == 0 && getenv("LOGNAME")) {
  850.       pstrcpy(username,getenv("LOGNAME"));
  851.     }
  852.  
  853.     argc--;
  854.     argv++;
  855.  
  856.  
  857.     while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:")) != EOF) {
  858.         switch (opt) {
  859.         case 'W':
  860.             fstrcpy(workgroup,optarg);
  861.             break;
  862.         case 'm':
  863.             max_protocol = interpret_protocol(optarg, max_protocol);
  864.             break;
  865.         case 'N':
  866.             nprocs = atoi(optarg);
  867.             break;
  868.         case 'o':
  869.             numops = atoi(optarg);
  870.             break;
  871.         case 'O':
  872.             sockops = optarg;
  873.             break;
  874.         case 'n':
  875.             fstrcpy(myname, optarg);
  876.             break;
  877.         case 'U':
  878.             pstrcpy(username,optarg);
  879.             p = strchr(username,'%');
  880.             if (p) {
  881.                 *p = 0;
  882.                 pstrcpy(password, p+1);
  883.                 gotpass = 1;
  884.             }
  885.             break;
  886.         default:
  887.             printf("Unknown option %c (%d)\n", (char)opt, opt);
  888.             usage();
  889.         }
  890.     }
  891.  
  892.  
  893.     while (!gotpass) {
  894.         p = getpass("Password:");
  895.         if (p) {
  896.             pstrcpy(password, p);
  897.             gotpass = 1;
  898.         }
  899.     }
  900.  
  901.     printf("host=%s share=%s user=%s myname=%s\n", 
  902.            host, share, username, myname);
  903.  
  904.     start_timer();
  905.     create_procs(nprocs, numops);
  906.     printf("rw_torture: %g secs\n", end_timer());
  907.  
  908.     run_locktest1();
  909.     run_locktest2();
  910.     run_locktest3(numops);
  911.     run_unlinktest();
  912.     run_browsetest();
  913.     run_attrtest();
  914.     run_trans2test();
  915.  
  916.     return(0);
  917. }
  918.  
  919.  
  920.