| 1 | /* 
 | 
|---|
| 2 |    Unix SMB/CIFS implementation.
 | 
|---|
| 3 |    test suite for various lock operations
 | 
|---|
| 4 |    Copyright (C) Andrew Tridgell 2003
 | 
|---|
| 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 "torture/torture.h"
 | 
|---|
| 22 | #include "libcli/raw/libcliraw.h"
 | 
|---|
| 23 | #include "libcli/raw/raw_proto.h"
 | 
|---|
| 24 | #include "system/time.h"
 | 
|---|
| 25 | #include "system/filesys.h"
 | 
|---|
| 26 | #include "libcli/libcli.h"
 | 
|---|
| 27 | #include "torture/util.h"
 | 
|---|
| 28 | #include "libcli/composite/composite.h"
 | 
|---|
| 29 | #include "libcli/smb_composite/smb_composite.h"
 | 
|---|
| 30 | #include "lib/cmdline/popt_common.h"
 | 
|---|
| 31 | #include "param/param.h"
 | 
|---|
| 32 | 
 | 
|---|
| 33 | #define CHECK_STATUS(status, correct) do { \
 | 
|---|
| 34 |         if (!NT_STATUS_EQUAL(status, correct)) { \
 | 
|---|
| 35 |                 torture_result(tctx, TORTURE_FAIL, \
 | 
|---|
| 36 |                         "(%s) Incorrect status %s - should be %s\n", \
 | 
|---|
| 37 |                         __location__, nt_errstr(status), nt_errstr(correct)); \
 | 
|---|
| 38 |                 ret = false; \
 | 
|---|
| 39 |                 goto done; \
 | 
|---|
| 40 |         }} while (0)
 | 
|---|
| 41 | 
 | 
|---|
| 42 | #define CHECK_STATUS_CONT(status, correct) do { \
 | 
|---|
| 43 |         if (!NT_STATUS_EQUAL(status, correct)) { \
 | 
|---|
| 44 |                 torture_result(tctx, TORTURE_FAIL, \
 | 
|---|
| 45 |                         "(%s) Incorrect status %s - should be %s\n", \
 | 
|---|
| 46 |                         __location__, nt_errstr(status), nt_errstr(correct)); \
 | 
|---|
| 47 |                 ret = false; \
 | 
|---|
| 48 |         }} while (0)
 | 
|---|
| 49 | 
 | 
|---|
| 50 | #define CHECK_STATUS_OR(status, correct1, correct2) do { \
 | 
|---|
| 51 |         if ((!NT_STATUS_EQUAL(status, correct1)) && \
 | 
|---|
| 52 |             (!NT_STATUS_EQUAL(status, correct2))) { \
 | 
|---|
| 53 |                 torture_result(tctx, TORTURE_FAIL, \
 | 
|---|
| 54 |                         "(%s) Incorrect status %s - should be %s or %s\n", \
 | 
|---|
| 55 |                         __location__, nt_errstr(status), nt_errstr(correct1), \
 | 
|---|
| 56 |                         nt_errstr(correct2)); \
 | 
|---|
| 57 |                 ret = false; \
 | 
|---|
| 58 |                 goto done; \
 | 
|---|
| 59 |         }} while (0)
 | 
|---|
| 60 | 
 | 
|---|
| 61 | #define CHECK_STATUS_OR_CONT(status, correct1, correct2) do { \
 | 
|---|
| 62 |         if ((!NT_STATUS_EQUAL(status, correct1)) && \
 | 
|---|
| 63 |             (!NT_STATUS_EQUAL(status, correct2))) { \
 | 
|---|
| 64 |                 torture_result(tctx, TORTURE_FAIL, \
 | 
|---|
| 65 |                         "(%s) Incorrect status %s - should be %s or %s\n", \
 | 
|---|
| 66 |                         __location__, nt_errstr(status), nt_errstr(correct1), \
 | 
|---|
| 67 |                         nt_errstr(correct2)); \
 | 
|---|
| 68 |                 ret = false; \
 | 
|---|
| 69 |         }} while (0)
 | 
|---|
| 70 | #define BASEDIR "\\testlock"
 | 
|---|
| 71 | 
 | 
|---|
| 72 | #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
 | 
|---|
| 73 | #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
 | 
|---|
| 74 | #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
 | 
|---|
| 75 | 
 | 
|---|
| 76 | /*
 | 
|---|
| 77 |   test SMBlock and SMBunlock ops
 | 
|---|
| 78 | */
 | 
|---|
| 79 | static bool test_lock(struct torture_context *tctx, struct smbcli_state *cli)
 | 
|---|
| 80 | {
 | 
|---|
| 81 |         union smb_lock io;
 | 
|---|
| 82 |         NTSTATUS status;
 | 
|---|
| 83 |         bool ret = true;
 | 
|---|
| 84 |         int fnum;
 | 
|---|
| 85 |         const char *fname = BASEDIR "\\test.txt";
 | 
|---|
| 86 | 
 | 
|---|
| 87 |         if (!torture_setup_dir(cli, BASEDIR)) {
 | 
|---|
| 88 |                 return false;
 | 
|---|
| 89 |         }
 | 
|---|
| 90 | 
 | 
|---|
| 91 |         torture_comment(tctx, "Testing RAW_LOCK_LOCK\n");
 | 
|---|
| 92 |         io.generic.level = RAW_LOCK_LOCK;
 | 
|---|
| 93 |         
 | 
|---|
| 94 |         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 95 |         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
 | 
|---|
| 96 |                        "Failed to create %s - %s\n",
 | 
|---|
| 97 |                        fname, smbcli_errstr(cli->tree)));
 | 
|---|
| 98 | 
 | 
|---|
| 99 |         torture_comment(tctx, "Trying 0/0 lock\n");
 | 
|---|
| 100 |         io.lock.level = RAW_LOCK_LOCK;
 | 
|---|
| 101 |         io.lock.in.file.fnum = fnum;
 | 
|---|
| 102 |         io.lock.in.count = 0;
 | 
|---|
| 103 |         io.lock.in.offset = 0;
 | 
|---|
| 104 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 105 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 106 |         cli->session->pid++;
 | 
|---|
| 107 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 108 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 109 |         cli->session->pid--;
 | 
|---|
| 110 |         io.lock.level = RAW_LOCK_UNLOCK;
 | 
|---|
| 111 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 112 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 113 | 
 | 
|---|
| 114 |         torture_comment(tctx, "Trying 0/1 lock\n");
 | 
|---|
| 115 |         io.lock.level = RAW_LOCK_LOCK;
 | 
|---|
| 116 |         io.lock.in.file.fnum = fnum;
 | 
|---|
| 117 |         io.lock.in.count = 1;
 | 
|---|
| 118 |         io.lock.in.offset = 0;
 | 
|---|
| 119 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 120 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 121 |         cli->session->pid++;
 | 
|---|
| 122 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 123 |         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 | 
|---|
| 124 |         cli->session->pid--;
 | 
|---|
| 125 |         io.lock.level = RAW_LOCK_UNLOCK;
 | 
|---|
| 126 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 127 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 128 |         io.lock.level = RAW_LOCK_UNLOCK;
 | 
|---|
| 129 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 130 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 131 | 
 | 
|---|
| 132 |         torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
 | 
|---|
| 133 |         io.lock.level = RAW_LOCK_LOCK;
 | 
|---|
| 134 |         io.lock.in.file.fnum = fnum;
 | 
|---|
| 135 |         io.lock.in.count = 4000;
 | 
|---|
| 136 |         io.lock.in.offset = 0xEEFFFFFF;
 | 
|---|
| 137 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 138 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 139 |         cli->session->pid++;
 | 
|---|
| 140 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 141 |         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 | 
|---|
| 142 |         cli->session->pid--;
 | 
|---|
| 143 |         io.lock.level = RAW_LOCK_UNLOCK;
 | 
|---|
| 144 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 145 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 146 |         io.lock.level = RAW_LOCK_UNLOCK;
 | 
|---|
| 147 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 148 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 149 | 
 | 
|---|
| 150 |         torture_comment(tctx, "Trying 0xEF000000 lock\n");
 | 
|---|
| 151 |         io.lock.level = RAW_LOCK_LOCK;
 | 
|---|
| 152 |         io.lock.in.file.fnum = fnum;
 | 
|---|
| 153 |         io.lock.in.count = 4000;
 | 
|---|
| 154 |         io.lock.in.offset = 0xEEFFFFFF;
 | 
|---|
| 155 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 156 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 157 |         cli->session->pid++;
 | 
|---|
| 158 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 159 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 160 |         cli->session->pid--;
 | 
|---|
| 161 |         io.lock.level = RAW_LOCK_UNLOCK;
 | 
|---|
| 162 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 163 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 164 |         io.lock.level = RAW_LOCK_UNLOCK;
 | 
|---|
| 165 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 166 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 167 | 
 | 
|---|
| 168 |         torture_comment(tctx, "Trying max lock\n");
 | 
|---|
| 169 |         io.lock.level = RAW_LOCK_LOCK;
 | 
|---|
| 170 |         io.lock.in.file.fnum = fnum;
 | 
|---|
| 171 |         io.lock.in.count = 4000;
 | 
|---|
| 172 |         io.lock.in.offset = 0xEF000000;
 | 
|---|
| 173 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 174 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 175 |         cli->session->pid++;
 | 
|---|
| 176 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 177 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 178 |         cli->session->pid--;
 | 
|---|
| 179 |         io.lock.level = RAW_LOCK_UNLOCK;
 | 
|---|
| 180 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 181 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 182 |         io.lock.level = RAW_LOCK_UNLOCK;
 | 
|---|
| 183 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 184 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 185 | 
 | 
|---|
| 186 |         torture_comment(tctx, "Trying wrong pid unlock\n");
 | 
|---|
| 187 |         io.lock.level = RAW_LOCK_LOCK;
 | 
|---|
| 188 |         io.lock.in.file.fnum = fnum;
 | 
|---|
| 189 |         io.lock.in.count = 4002;
 | 
|---|
| 190 |         io.lock.in.offset = 10001;
 | 
|---|
| 191 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 192 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 193 |         cli->session->pid++;
 | 
|---|
| 194 |         io.lock.level = RAW_LOCK_UNLOCK;
 | 
|---|
| 195 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 196 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 197 |         cli->session->pid--;
 | 
|---|
| 198 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 199 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 200 | 
 | 
|---|
| 201 | done:
 | 
|---|
| 202 |         smbcli_close(cli->tree, fnum);
 | 
|---|
| 203 |         smb_raw_exit(cli->session);
 | 
|---|
| 204 |         smbcli_deltree(cli->tree, BASEDIR);
 | 
|---|
| 205 |         return ret;
 | 
|---|
| 206 | }
 | 
|---|
| 207 | 
 | 
|---|
| 208 | 
 | 
|---|
| 209 | /*
 | 
|---|
| 210 |   test locking&X ops
 | 
|---|
| 211 | */
 | 
|---|
| 212 | static bool test_lockx(struct torture_context *tctx, struct smbcli_state *cli)
 | 
|---|
| 213 | {
 | 
|---|
| 214 |         union smb_lock io;
 | 
|---|
| 215 |         struct smb_lock_entry lock[1];
 | 
|---|
| 216 |         NTSTATUS status;
 | 
|---|
| 217 |         bool ret = true;
 | 
|---|
| 218 |         int fnum;
 | 
|---|
| 219 |         const char *fname = BASEDIR "\\test.txt";
 | 
|---|
| 220 | 
 | 
|---|
| 221 |         if (!torture_setup_dir(cli, BASEDIR)) {
 | 
|---|
| 222 |                 return false;
 | 
|---|
| 223 |         }
 | 
|---|
| 224 | 
 | 
|---|
| 225 |         torture_comment(tctx, "Testing RAW_LOCK_LOCKX\n");
 | 
|---|
| 226 |         io.generic.level = RAW_LOCK_LOCKX;
 | 
|---|
| 227 |         
 | 
|---|
| 228 |         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 229 |         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
 | 
|---|
| 230 |                        "Failed to create %s - %s\n",
 | 
|---|
| 231 |                        fname, smbcli_errstr(cli->tree)));
 | 
|---|
| 232 | 
 | 
|---|
| 233 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 234 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 235 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 236 |         io.lockx.in.timeout = 0;
 | 
|---|
| 237 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 238 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 239 |         lock[0].pid = cli->session->pid;
 | 
|---|
| 240 |         lock[0].offset = 10;
 | 
|---|
| 241 |         lock[0].count = 1;
 | 
|---|
| 242 |         io.lockx.in.locks = &lock[0];
 | 
|---|
| 243 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 244 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 245 | 
 | 
|---|
| 246 | 
 | 
|---|
| 247 |         torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
 | 
|---|
| 248 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 249 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 250 |         lock[0].count = 4000;
 | 
|---|
| 251 |         lock[0].offset = 0xEEFFFFFF;
 | 
|---|
| 252 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 253 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 254 |         lock[0].pid++;
 | 
|---|
| 255 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 256 |         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 | 
|---|
| 257 |         lock[0].pid--;
 | 
|---|
| 258 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 259 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 260 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 261 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 262 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 263 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 264 | 
 | 
|---|
| 265 |         torture_comment(tctx, "Trying 0xEF000000 lock\n");
 | 
|---|
| 266 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 267 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 268 |         lock[0].count = 4000;
 | 
|---|
| 269 |         lock[0].offset = 0xEF000000;
 | 
|---|
| 270 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 271 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 272 |         lock[0].pid++;
 | 
|---|
| 273 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 274 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 275 |         lock[0].pid--;
 | 
|---|
| 276 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 277 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 278 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 279 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 280 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 281 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 282 | 
 | 
|---|
| 283 |         torture_comment(tctx, "Trying zero lock\n");
 | 
|---|
| 284 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 285 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 286 |         lock[0].count = 0;
 | 
|---|
| 287 |         lock[0].offset = ~0;
 | 
|---|
| 288 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 289 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 290 |         lock[0].pid++;
 | 
|---|
| 291 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 292 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 293 |         lock[0].pid--;
 | 
|---|
| 294 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 295 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 296 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 297 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 298 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 299 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 300 | 
 | 
|---|
| 301 |         torture_comment(tctx, "Trying max lock\n");
 | 
|---|
| 302 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 303 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 304 |         lock[0].count = 0;
 | 
|---|
| 305 |         lock[0].offset = ~0;
 | 
|---|
| 306 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 307 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 308 |         lock[0].pid++;
 | 
|---|
| 309 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 310 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 311 |         lock[0].pid--;
 | 
|---|
| 312 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 313 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 314 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 315 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 316 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 317 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 318 | 
 | 
|---|
| 319 |         torture_comment(tctx, "Trying 2^63\n");
 | 
|---|
| 320 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 321 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 322 |         lock[0].count = 1;
 | 
|---|
| 323 |         lock[0].offset = 1;
 | 
|---|
| 324 |         lock[0].offset <<= 63;
 | 
|---|
| 325 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 326 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 327 |         lock[0].pid++;
 | 
|---|
| 328 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 329 |         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 | 
|---|
| 330 |         lock[0].pid--;
 | 
|---|
| 331 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 332 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 333 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 334 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 335 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 336 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 337 | 
 | 
|---|
| 338 |         torture_comment(tctx, "Trying 2^63 - 1\n");
 | 
|---|
| 339 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 340 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 341 |         lock[0].count = 1;
 | 
|---|
| 342 |         lock[0].offset = 1;
 | 
|---|
| 343 |         lock[0].offset <<= 63;
 | 
|---|
| 344 |         lock[0].offset--;
 | 
|---|
| 345 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 346 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 347 |         lock[0].pid++;
 | 
|---|
| 348 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 349 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 350 |         lock[0].pid--;
 | 
|---|
| 351 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 352 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 353 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 354 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 355 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 356 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 357 | 
 | 
|---|
| 358 |         torture_comment(tctx, "Trying max lock 2\n");
 | 
|---|
| 359 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 360 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 361 |         lock[0].count = 1;
 | 
|---|
| 362 |         lock[0].offset = ~0;
 | 
|---|
| 363 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 364 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 365 |         lock[0].pid++;
 | 
|---|
| 366 |         lock[0].count = 2;
 | 
|---|
| 367 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 368 |         if (TARGET_IS_WIN7(tctx))
 | 
|---|
| 369 |                 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
 | 
|---|
| 370 |         else
 | 
|---|
| 371 |                 CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 372 |         lock[0].pid--;
 | 
|---|
| 373 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 374 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 375 |         lock[0].count = 1;
 | 
|---|
| 376 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 377 | 
 | 
|---|
| 378 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 379 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 380 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 381 | 
 | 
|---|
| 382 | done:
 | 
|---|
| 383 |         smbcli_close(cli->tree, fnum);
 | 
|---|
| 384 |         smb_raw_exit(cli->session);
 | 
|---|
| 385 |         smbcli_deltree(cli->tree, BASEDIR);
 | 
|---|
| 386 |         return ret;
 | 
|---|
| 387 | }
 | 
|---|
| 388 | 
 | 
|---|
| 389 | /*
 | 
|---|
| 390 |   test high pid
 | 
|---|
| 391 | */
 | 
|---|
| 392 | static bool test_pidhigh(struct torture_context *tctx, 
 | 
|---|
| 393 |                                                  struct smbcli_state *cli)
 | 
|---|
| 394 | {
 | 
|---|
| 395 |         union smb_lock io;
 | 
|---|
| 396 |         struct smb_lock_entry lock[1];
 | 
|---|
| 397 |         NTSTATUS status;
 | 
|---|
| 398 |         bool ret = true;
 | 
|---|
| 399 |         int fnum;
 | 
|---|
| 400 |         const char *fname = BASEDIR "\\test.txt";
 | 
|---|
| 401 |         uint8_t c = 1;
 | 
|---|
| 402 | 
 | 
|---|
| 403 |         if (!torture_setup_dir(cli, BASEDIR)) {
 | 
|---|
| 404 |                 return false;
 | 
|---|
| 405 |         }
 | 
|---|
| 406 | 
 | 
|---|
| 407 |         torture_comment(tctx, "Testing high pid\n");
 | 
|---|
| 408 |         io.generic.level = RAW_LOCK_LOCKX;
 | 
|---|
| 409 | 
 | 
|---|
| 410 |         cli->session->pid = 1;
 | 
|---|
| 411 |         
 | 
|---|
| 412 |         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 413 |         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
 | 
|---|
| 414 |                        "Failed to create %s - %s\n",
 | 
|---|
| 415 |                        fname, smbcli_errstr(cli->tree)));
 | 
|---|
| 416 | 
 | 
|---|
| 417 |         if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
 | 
|---|
| 418 |                 torture_result(tctx, TORTURE_FAIL,
 | 
|---|
| 419 |                         "Failed to write 1 byte - %s\n",
 | 
|---|
| 420 |                         smbcli_errstr(cli->tree));
 | 
|---|
| 421 |                 ret = false;
 | 
|---|
| 422 |                 goto done;
 | 
|---|
| 423 |         }
 | 
|---|
| 424 | 
 | 
|---|
| 425 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 426 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 427 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 428 |         io.lockx.in.timeout = 0;
 | 
|---|
| 429 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 430 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 431 |         lock[0].pid = cli->session->pid;
 | 
|---|
| 432 |         lock[0].offset = 0;
 | 
|---|
| 433 |         lock[0].count = 0xFFFFFFFF;
 | 
|---|
| 434 |         io.lockx.in.locks = &lock[0];
 | 
|---|
| 435 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 436 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 437 | 
 | 
|---|
| 438 |         if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
 | 
|---|
| 439 |                 torture_result(tctx, TORTURE_FAIL,
 | 
|---|
| 440 |                         "Failed to read 1 byte - %s\n",
 | 
|---|
| 441 |                         smbcli_errstr(cli->tree));
 | 
|---|
| 442 |                 ret = false;
 | 
|---|
| 443 |                 goto done;
 | 
|---|
| 444 |         }
 | 
|---|
| 445 | 
 | 
|---|
| 446 |         cli->session->pid = 2;
 | 
|---|
| 447 | 
 | 
|---|
| 448 |         if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
 | 
|---|
| 449 |                 torture_result(tctx, TORTURE_FAIL,
 | 
|---|
| 450 |                         "pid is incorrect handled for read with lock!\n");
 | 
|---|
| 451 |                 ret = false;
 | 
|---|
| 452 |                 goto done;
 | 
|---|
| 453 |         }
 | 
|---|
| 454 | 
 | 
|---|
| 455 |         cli->session->pid = 0x10001;
 | 
|---|
| 456 | 
 | 
|---|
| 457 |         if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
 | 
|---|
| 458 |                 torture_result(tctx, TORTURE_FAIL,
 | 
|---|
| 459 |                         "High pid is used on this server!\n");
 | 
|---|
| 460 |                 ret = false;
 | 
|---|
| 461 |         } else {
 | 
|---|
| 462 |                 torture_warning(tctx, "High pid is not used on this server (correct)\n");
 | 
|---|
| 463 |         }
 | 
|---|
| 464 | 
 | 
|---|
| 465 | done:
 | 
|---|
| 466 |         smbcli_close(cli->tree, fnum);
 | 
|---|
| 467 |         smb_raw_exit(cli->session);
 | 
|---|
| 468 |         smbcli_deltree(cli->tree, BASEDIR);
 | 
|---|
| 469 |         return ret;
 | 
|---|
| 470 | }
 | 
|---|
| 471 | 
 | 
|---|
| 472 | 
 | 
|---|
| 473 | /*
 | 
|---|
| 474 |   test locking&X async operation
 | 
|---|
| 475 | */
 | 
|---|
| 476 | static bool test_async(struct torture_context *tctx, 
 | 
|---|
| 477 |                                            struct smbcli_state *cli)
 | 
|---|
| 478 | {
 | 
|---|
| 479 |         struct smbcli_session *session;
 | 
|---|
| 480 |         struct smb_composite_sesssetup setup;
 | 
|---|
| 481 |         struct smbcli_tree *tree;
 | 
|---|
| 482 |         union smb_tcon tcon;
 | 
|---|
| 483 |         const char *host, *share;
 | 
|---|
| 484 |         union smb_lock io;
 | 
|---|
| 485 |         struct smb_lock_entry lock[2];
 | 
|---|
| 486 |         NTSTATUS status;
 | 
|---|
| 487 |         bool ret = true;
 | 
|---|
| 488 |         int fnum;
 | 
|---|
| 489 |         const char *fname = BASEDIR "\\test.txt";
 | 
|---|
| 490 |         time_t t;
 | 
|---|
| 491 |         struct smbcli_request *req;
 | 
|---|
| 492 |         struct smbcli_session_options options;
 | 
|---|
| 493 | 
 | 
|---|
| 494 |         if (!torture_setup_dir(cli, BASEDIR)) {
 | 
|---|
| 495 |                 return false;
 | 
|---|
| 496 |         }
 | 
|---|
| 497 | 
 | 
|---|
| 498 |         lp_smbcli_session_options(tctx->lp_ctx, &options);
 | 
|---|
| 499 | 
 | 
|---|
| 500 |         torture_comment(tctx, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
 | 
|---|
| 501 |         io.generic.level = RAW_LOCK_LOCKX;
 | 
|---|
| 502 | 
 | 
|---|
| 503 |         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 504 |         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
 | 
|---|
| 505 |                        "Failed to create %s - %s\n",
 | 
|---|
| 506 |                        fname, smbcli_errstr(cli->tree)));
 | 
|---|
| 507 | 
 | 
|---|
| 508 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 509 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 510 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 511 |         io.lockx.in.timeout = 0;
 | 
|---|
| 512 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 513 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 514 |         lock[0].pid = cli->session->pid;
 | 
|---|
| 515 |         lock[0].offset = 100;
 | 
|---|
| 516 |         lock[0].count = 10;
 | 
|---|
| 517 |         io.lockx.in.locks = &lock[0];
 | 
|---|
| 518 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 519 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 520 | 
 | 
|---|
| 521 |         t = time(NULL);
 | 
|---|
| 522 | 
 | 
|---|
| 523 |         torture_comment(tctx, "testing cancel by CANCEL_LOCK\n");
 | 
|---|
| 524 | 
 | 
|---|
| 525 |         /* setup a timed lock */
 | 
|---|
| 526 |         io.lockx.in.timeout = 10000;
 | 
|---|
| 527 |         req = smb_raw_lock_send(cli->tree, &io);
 | 
|---|
| 528 |         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
 | 
|---|
| 529 |                        "Failed to setup timed lock (%s)\n", __location__));
 | 
|---|
| 530 | 
 | 
|---|
| 531 |         /* cancel the wrong range */
 | 
|---|
| 532 |         lock[0].offset = 0;
 | 
|---|
| 533 |         io.lockx.in.timeout = 0;
 | 
|---|
| 534 |         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
 | 
|---|
| 535 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 536 |         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
 | 
|---|
| 537 | 
 | 
|---|
| 538 |         /* cancel with the wrong bits set */
 | 
|---|
| 539 |         lock[0].offset = 100;
 | 
|---|
| 540 |         io.lockx.in.timeout = 0;
 | 
|---|
| 541 |         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
 | 
|---|
| 542 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 543 |         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
 | 
|---|
| 544 | 
 | 
|---|
| 545 |         /* cancel the right range */
 | 
|---|
| 546 |         lock[0].offset = 100;
 | 
|---|
| 547 |         io.lockx.in.timeout = 0;
 | 
|---|
| 548 |         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 549 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 550 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 551 | 
 | 
|---|
| 552 |         /* receive the failed lock request */
 | 
|---|
| 553 |         status = smbcli_request_simple_recv(req);
 | 
|---|
| 554 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 555 | 
 | 
|---|
| 556 |         torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
 | 
|---|
| 557 |                        "lock cancel was not immediate (%s)\n", __location__));
 | 
|---|
| 558 | 
 | 
|---|
| 559 |         torture_comment(tctx, "testing cancel by unlock\n");
 | 
|---|
| 560 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 561 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 562 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 563 |         io.lockx.in.timeout = 0;
 | 
|---|
| 564 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 565 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 566 | 
 | 
|---|
| 567 |         io.lockx.in.timeout = 5000;
 | 
|---|
| 568 |         req = smb_raw_lock_send(cli->tree, &io);
 | 
|---|
| 569 |         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
 | 
|---|
| 570 |                        "Failed to setup timed lock (%s)\n", __location__));
 | 
|---|
| 571 | 
 | 
|---|
| 572 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 573 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 574 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 575 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 576 | 
 | 
|---|
| 577 |         t = time(NULL);
 | 
|---|
| 578 |         status = smbcli_request_simple_recv(req);
 | 
|---|
| 579 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 580 | 
 | 
|---|
| 581 |         torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
 | 
|---|
| 582 |                        "lock cancel by unlock was not immediate (%s) - took %d secs\n",
 | 
|---|
| 583 |                        __location__, (int)(time(NULL)-t)));
 | 
|---|
| 584 | 
 | 
|---|
| 585 |         torture_comment(tctx, "testing cancel by close\n");
 | 
|---|
| 586 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 587 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 588 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 589 |         io.lockx.in.timeout = 0;
 | 
|---|
| 590 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 591 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 592 | 
 | 
|---|
| 593 |         t = time(NULL);
 | 
|---|
| 594 |         io.lockx.in.timeout = 10000;
 | 
|---|
| 595 |         req = smb_raw_lock_send(cli->tree, &io);
 | 
|---|
| 596 |         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
 | 
|---|
| 597 |                        "Failed to setup timed lock (%s)\n", __location__));
 | 
|---|
| 598 | 
 | 
|---|
| 599 |         status = smbcli_close(cli->tree, fnum);
 | 
|---|
| 600 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 601 | 
 | 
|---|
| 602 |         status = smbcli_request_simple_recv(req);
 | 
|---|
| 603 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 604 | 
 | 
|---|
| 605 |         torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
 | 
|---|
| 606 |                        "lock cancel by close was not immediate (%s)\n", __location__));
 | 
|---|
| 607 | 
 | 
|---|
| 608 |         torture_comment(tctx, "create a new sessions\n");
 | 
|---|
| 609 |         session = smbcli_session_init(cli->transport, tctx, false, options);
 | 
|---|
| 610 |         setup.in.sesskey = cli->transport->negotiate.sesskey;
 | 
|---|
| 611 |         setup.in.capabilities = cli->transport->negotiate.capabilities;
 | 
|---|
| 612 |         setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
 | 
|---|
| 613 |         setup.in.credentials = cmdline_credentials;
 | 
|---|
| 614 |         setup.in.gensec_settings = lp_gensec_settings(tctx, tctx->lp_ctx);
 | 
|---|
| 615 |         status = smb_composite_sesssetup(session, &setup);
 | 
|---|
| 616 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 617 |         session->vuid = setup.out.vuid;
 | 
|---|
| 618 | 
 | 
|---|
| 619 |         torture_comment(tctx, "create new tree context\n");
 | 
|---|
| 620 |         share = torture_setting_string(tctx, "share", NULL);
 | 
|---|
| 621 |         host  = torture_setting_string(tctx, "host", NULL);
 | 
|---|
| 622 |         tree = smbcli_tree_init(session, tctx, false);
 | 
|---|
| 623 |         tcon.generic.level = RAW_TCON_TCONX;
 | 
|---|
| 624 |         tcon.tconx.in.flags = 0;
 | 
|---|
| 625 |         tcon.tconx.in.password = data_blob(NULL, 0);
 | 
|---|
| 626 |         tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
 | 
|---|
| 627 |         tcon.tconx.in.device = "A:";
 | 
|---|
| 628 |         status = smb_raw_tcon(tree, tctx, &tcon);
 | 
|---|
| 629 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 630 |         tree->tid = tcon.tconx.out.tid;
 | 
|---|
| 631 | 
 | 
|---|
| 632 |         torture_comment(tctx, "testing cancel by exit\n");
 | 
|---|
| 633 |         fname = BASEDIR "\\test_exit.txt";
 | 
|---|
| 634 |         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 635 |         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
 | 
|---|
| 636 |                        "Failed to reopen %s - %s\n",
 | 
|---|
| 637 |                        fname, smbcli_errstr(tree)));
 | 
|---|
| 638 | 
 | 
|---|
| 639 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 640 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 641 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 642 |         io.lockx.in.timeout = 0;
 | 
|---|
| 643 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 644 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 645 |         lock[0].pid = session->pid;
 | 
|---|
| 646 |         lock[0].offset = 100;
 | 
|---|
| 647 |         lock[0].count = 10;
 | 
|---|
| 648 |         io.lockx.in.locks = &lock[0];
 | 
|---|
| 649 |         status = smb_raw_lock(tree, &io);
 | 
|---|
| 650 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 651 | 
 | 
|---|
| 652 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 653 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 654 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 655 |         io.lockx.in.timeout = 0;
 | 
|---|
| 656 |         status = smb_raw_lock(tree, &io);
 | 
|---|
| 657 |         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 | 
|---|
| 658 | 
 | 
|---|
| 659 |         io.lockx.in.timeout = 10000;
 | 
|---|
| 660 |         t = time(NULL);
 | 
|---|
| 661 |         req = smb_raw_lock_send(tree, &io);
 | 
|---|
| 662 |         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
 | 
|---|
| 663 |                        "Failed to setup timed lock (%s)\n", __location__));
 | 
|---|
| 664 | 
 | 
|---|
| 665 |         status = smb_raw_exit(session);
 | 
|---|
| 666 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 667 | 
 | 
|---|
| 668 |         status = smbcli_request_simple_recv(req);
 | 
|---|
| 669 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 670 | 
 | 
|---|
| 671 |         torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
 | 
|---|
| 672 |                        "lock cancel by exit was not immediate (%s)\n", __location__));
 | 
|---|
| 673 | 
 | 
|---|
| 674 |         torture_comment(tctx, "testing cancel by ulogoff\n");
 | 
|---|
| 675 |         fname = BASEDIR "\\test_ulogoff.txt";
 | 
|---|
| 676 |         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 677 |         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
 | 
|---|
| 678 |                        "Failed to reopen %s - %s\n",
 | 
|---|
| 679 |                        fname, smbcli_errstr(tree)));
 | 
|---|
| 680 | 
 | 
|---|
| 681 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 682 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 683 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 684 |         io.lockx.in.timeout = 0;
 | 
|---|
| 685 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 686 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 687 |         lock[0].pid = session->pid;
 | 
|---|
| 688 |         lock[0].offset = 100;
 | 
|---|
| 689 |         lock[0].count = 10;
 | 
|---|
| 690 |         io.lockx.in.locks = &lock[0];
 | 
|---|
| 691 |         status = smb_raw_lock(tree, &io);
 | 
|---|
| 692 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 693 | 
 | 
|---|
| 694 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 695 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 696 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 697 |         io.lockx.in.timeout = 0;
 | 
|---|
| 698 |         status = smb_raw_lock(tree, &io);
 | 
|---|
| 699 |         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 | 
|---|
| 700 | 
 | 
|---|
| 701 |         io.lockx.in.timeout = 10000;
 | 
|---|
| 702 |         t = time(NULL);
 | 
|---|
| 703 |         req = smb_raw_lock_send(tree, &io);
 | 
|---|
| 704 |         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
 | 
|---|
| 705 |                        "Failed to setup timed lock (%s)\n", __location__));
 | 
|---|
| 706 | 
 | 
|---|
| 707 |         status = smb_raw_ulogoff(session);
 | 
|---|
| 708 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 709 | 
 | 
|---|
| 710 |         status = smbcli_request_simple_recv(req);
 | 
|---|
| 711 |         if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
 | 
|---|
| 712 |                 torture_result(tctx, TORTURE_FAIL,
 | 
|---|
| 713 |                         "lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
 | 
|---|
| 714 |                         nt_errstr(status));
 | 
|---|
| 715 |                 smb_tree_disconnect(tree);
 | 
|---|
| 716 |                 smb_raw_exit(session);
 | 
|---|
| 717 |                 goto done;
 | 
|---|
| 718 |         }
 | 
|---|
| 719 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 720 | 
 | 
|---|
| 721 |         torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
 | 
|---|
| 722 |                        "lock cancel by ulogoff was not immediate (%s)\n", __location__));
 | 
|---|
| 723 | 
 | 
|---|
| 724 |         torture_comment(tctx, "testing cancel by tdis\n");
 | 
|---|
| 725 |         tree->session = cli->session;
 | 
|---|
| 726 | 
 | 
|---|
| 727 |         fname = BASEDIR "\\test_tdis.txt";
 | 
|---|
| 728 |         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 729 |         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
 | 
|---|
| 730 |                        "Failed to reopen %s - %s\n",
 | 
|---|
| 731 |                        fname, smbcli_errstr(tree)));
 | 
|---|
| 732 | 
 | 
|---|
| 733 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 734 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 735 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 736 |         io.lockx.in.timeout = 0;
 | 
|---|
| 737 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 738 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 739 |         lock[0].pid = cli->session->pid;
 | 
|---|
| 740 |         lock[0].offset = 100;
 | 
|---|
| 741 |         lock[0].count = 10;
 | 
|---|
| 742 |         io.lockx.in.locks = &lock[0];
 | 
|---|
| 743 |         status = smb_raw_lock(tree, &io);
 | 
|---|
| 744 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 745 | 
 | 
|---|
| 746 |         status = smb_raw_lock(tree, &io);
 | 
|---|
| 747 |         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 | 
|---|
| 748 | 
 | 
|---|
| 749 |         io.lockx.in.timeout = 10000;
 | 
|---|
| 750 |         t = time(NULL);
 | 
|---|
| 751 |         req = smb_raw_lock_send(tree, &io);
 | 
|---|
| 752 |         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
 | 
|---|
| 753 |                        "Failed to setup timed lock (%s)\n", __location__));
 | 
|---|
| 754 | 
 | 
|---|
| 755 |         status = smb_tree_disconnect(tree);
 | 
|---|
| 756 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 757 | 
 | 
|---|
| 758 |         status = smbcli_request_simple_recv(req);
 | 
|---|
| 759 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 760 | 
 | 
|---|
| 761 |         torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
 | 
|---|
| 762 |                        "lock cancel by tdis was not immediate (%s)\n", __location__));
 | 
|---|
| 763 | 
 | 
|---|
| 764 | done:
 | 
|---|
| 765 |         smb_raw_exit(cli->session);
 | 
|---|
| 766 |         smbcli_deltree(cli->tree, BASEDIR);
 | 
|---|
| 767 |         return ret;
 | 
|---|
| 768 | }
 | 
|---|
| 769 | 
 | 
|---|
| 770 | /*
 | 
|---|
| 771 |   test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
 | 
|---|
| 772 | */
 | 
|---|
| 773 | static bool test_errorcode(struct torture_context *tctx, 
 | 
|---|
| 774 |                                                    struct smbcli_state *cli)
 | 
|---|
| 775 | {
 | 
|---|
| 776 |         union smb_lock io;
 | 
|---|
| 777 |         union smb_open op;
 | 
|---|
| 778 |         struct smb_lock_entry lock[2];
 | 
|---|
| 779 |         NTSTATUS status;
 | 
|---|
| 780 |         bool ret = true;
 | 
|---|
| 781 |         int fnum, fnum2;
 | 
|---|
| 782 |         const char *fname;
 | 
|---|
| 783 |         struct smbcli_request *req;
 | 
|---|
| 784 |         time_t start;
 | 
|---|
| 785 |         int t;
 | 
|---|
| 786 |         int delay;
 | 
|---|
| 787 | 
 | 
|---|
| 788 |         if (!torture_setup_dir(cli, BASEDIR)) {
 | 
|---|
| 789 |                 return false;
 | 
|---|
| 790 |         }
 | 
|---|
| 791 | 
 | 
|---|
| 792 |         torture_comment(tctx, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
 | 
|---|
| 793 | 
 | 
|---|
| 794 |         torture_comment(tctx, "testing with timeout = 0\n");
 | 
|---|
| 795 |         fname = BASEDIR "\\test0.txt";
 | 
|---|
| 796 |         t = 0;
 | 
|---|
| 797 | 
 | 
|---|
| 798 |         /*
 | 
|---|
| 799 |          * the first run is with t = 0,
 | 
|---|
| 800 |          * the second with t > 0 (=1)
 | 
|---|
| 801 |          */
 | 
|---|
| 802 | next_run:
 | 
|---|
| 803 |         /* 
 | 
|---|
| 804 |          * use the DENY_DOS mode, that creates two fnum's of one low-level file handle,
 | 
|---|
| 805 |          * this demonstrates that the cache is per fnum
 | 
|---|
| 806 |          */
 | 
|---|
| 807 |         op.openx.level = RAW_OPEN_OPENX;
 | 
|---|
| 808 |         op.openx.in.fname = fname;
 | 
|---|
| 809 |         op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
 | 
|---|
| 810 |         op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_DOS;
 | 
|---|
| 811 |         op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
 | 
|---|
| 812 |         op.openx.in.search_attrs = 0;
 | 
|---|
| 813 |         op.openx.in.file_attrs = 0;
 | 
|---|
| 814 |         op.openx.in.write_time = 0;
 | 
|---|
| 815 |         op.openx.in.size = 0;
 | 
|---|
| 816 |         op.openx.in.timeout = 0;
 | 
|---|
| 817 | 
 | 
|---|
| 818 |         status = smb_raw_open(cli->tree, tctx, &op);
 | 
|---|
| 819 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 820 |         fnum = op.openx.out.file.fnum;
 | 
|---|
| 821 | 
 | 
|---|
| 822 |         status = smb_raw_open(cli->tree, tctx, &op);
 | 
|---|
| 823 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 824 |         fnum2 = op.openx.out.file.fnum;
 | 
|---|
| 825 | 
 | 
|---|
| 826 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 827 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 828 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 829 |         io.lockx.in.timeout = t;
 | 
|---|
| 830 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 831 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 832 |         lock[0].pid = cli->session->pid;
 | 
|---|
| 833 |         lock[0].offset = 100;
 | 
|---|
| 834 |         lock[0].count = 10;
 | 
|---|
| 835 |         io.lockx.in.locks = &lock[0];
 | 
|---|
| 836 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 837 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 838 | 
 | 
|---|
| 839 |         /*
 | 
|---|
| 840 |          * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
 | 
|---|
| 841 |          * this also demonstrates that the error code cache is per file handle
 | 
|---|
| 842 |          * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
 | 
|---|
| 843 |          */
 | 
|---|
| 844 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 845 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 846 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 847 | 
 | 
|---|
| 848 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 849 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 850 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 851 | 
 | 
|---|
| 852 |         /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
 | 
|---|
| 853 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 854 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 855 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 856 | 
 | 
|---|
| 857 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 858 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 859 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 860 | 
 | 
|---|
| 861 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 862 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 863 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 864 | 
 | 
|---|
| 865 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 866 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 867 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 868 | 
 | 
|---|
| 869 |         /* demonstrate that the smbpid doesn't matter */
 | 
|---|
| 870 |         lock[0].pid++;
 | 
|---|
| 871 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 872 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 873 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 874 | 
 | 
|---|
| 875 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 876 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 877 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 878 |         lock[0].pid--;
 | 
|---|
| 879 | 
 | 
|---|
| 880 |         /* 
 | 
|---|
| 881 |          * demonstrate the a successful lock with count = 0 and the same offset,
 | 
|---|
| 882 |          * doesn't reset the error cache
 | 
|---|
| 883 |          */
 | 
|---|
| 884 |         lock[0].offset = 100;
 | 
|---|
| 885 |         lock[0].count = 0;
 | 
|---|
| 886 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 887 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 888 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 889 | 
 | 
|---|
| 890 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 891 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 892 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 893 | 
 | 
|---|
| 894 |         lock[0].offset = 100;
 | 
|---|
| 895 |         lock[0].count = 10;
 | 
|---|
| 896 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 897 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 898 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 899 | 
 | 
|---|
| 900 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 901 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 902 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 903 | 
 | 
|---|
| 904 |         /* 
 | 
|---|
| 905 |          * demonstrate the a successful lock with count = 0 and outside the locked range,
 | 
|---|
| 906 |          * doesn't reset the error cache
 | 
|---|
| 907 |          */
 | 
|---|
| 908 |         lock[0].offset = 110;
 | 
|---|
| 909 |         lock[0].count = 0;
 | 
|---|
| 910 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 911 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 912 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 913 | 
 | 
|---|
| 914 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 915 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 916 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 917 | 
 | 
|---|
| 918 |         lock[0].offset = 100;
 | 
|---|
| 919 |         lock[0].count = 10;
 | 
|---|
| 920 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 921 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 922 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 923 | 
 | 
|---|
| 924 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 925 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 926 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 927 | 
 | 
|---|
| 928 |         lock[0].offset = 99;
 | 
|---|
| 929 |         lock[0].count = 0;
 | 
|---|
| 930 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 931 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 932 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 933 | 
 | 
|---|
| 934 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 935 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 936 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 937 | 
 | 
|---|
| 938 |         lock[0].offset = 100;
 | 
|---|
| 939 |         lock[0].count = 10;
 | 
|---|
| 940 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 941 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 942 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 943 | 
 | 
|---|
| 944 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 945 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 946 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 947 | 
 | 
|---|
| 948 |         /* demonstrate that a changing count doesn't reset the error cache */
 | 
|---|
| 949 |         lock[0].offset = 100;
 | 
|---|
| 950 |         lock[0].count = 5;
 | 
|---|
| 951 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 952 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 953 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 954 | 
 | 
|---|
| 955 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 956 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 957 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 958 | 
 | 
|---|
| 959 |         lock[0].offset = 100;
 | 
|---|
| 960 |         lock[0].count = 15;
 | 
|---|
| 961 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 962 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 963 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 964 | 
 | 
|---|
| 965 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 966 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 967 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 968 | 
 | 
|---|
| 969 |         /* 
 | 
|---|
| 970 |          * demonstrate the a lock with count = 0 and inside the locked range,
 | 
|---|
| 971 |          * fails and resets the error cache
 | 
|---|
| 972 |          */
 | 
|---|
| 973 |         lock[0].offset = 101;
 | 
|---|
| 974 |         lock[0].count = 0;
 | 
|---|
| 975 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 976 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 977 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 978 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 979 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 980 | 
 | 
|---|
| 981 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 982 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 983 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 984 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 985 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 986 | 
 | 
|---|
| 987 |         lock[0].offset = 100;
 | 
|---|
| 988 |         lock[0].count = 10;
 | 
|---|
| 989 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 990 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 991 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 992 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 993 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 994 | 
 | 
|---|
| 995 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 996 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 997 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 998 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 999 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1000 | 
 | 
|---|
| 1001 |         /* demonstrate the a changing offset, resets the error cache */
 | 
|---|
| 1002 |         lock[0].offset = 105;
 | 
|---|
| 1003 |         lock[0].count = 10;
 | 
|---|
| 1004 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 1005 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1006 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 1007 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1008 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1009 | 
 | 
|---|
| 1010 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 1011 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1012 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 1013 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1014 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1015 | 
 | 
|---|
| 1016 |         lock[0].offset = 100;
 | 
|---|
| 1017 |         lock[0].count = 10;
 | 
|---|
| 1018 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 1019 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1020 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 1021 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1022 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1023 | 
 | 
|---|
| 1024 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 1025 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1026 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 1027 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1028 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1029 | 
 | 
|---|
| 1030 |         lock[0].offset = 95;
 | 
|---|
| 1031 |         lock[0].count = 9;
 | 
|---|
| 1032 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 1033 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1034 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 1035 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1036 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1037 | 
 | 
|---|
| 1038 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 1039 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1040 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 1041 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1042 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1043 | 
 | 
|---|
| 1044 |         lock[0].offset = 100;
 | 
|---|
| 1045 |         lock[0].count = 10;
 | 
|---|
| 1046 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 1047 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1048 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 1049 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1050 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1051 | 
 | 
|---|
| 1052 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 1053 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1054 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 1055 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1056 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1057 | 
 | 
|---|
| 1058 |         /* 
 | 
|---|
| 1059 |          * demonstrate the a successful lock in a different range, 
 | 
|---|
| 1060 |          * doesn't reset the cache, the failing lock on the 2nd handle
 | 
|---|
| 1061 |          * resets the resets the cache
 | 
|---|
| 1062 |          */
 | 
|---|
| 1063 |         lock[0].offset = 120;
 | 
|---|
| 1064 |         lock[0].count = 15;
 | 
|---|
| 1065 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 1066 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1067 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1068 | 
 | 
|---|
| 1069 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 1070 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1071 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 1072 | 
 | 
|---|
| 1073 |         lock[0].offset = 100;
 | 
|---|
| 1074 |         lock[0].count = 10;
 | 
|---|
| 1075 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 1076 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1077 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1078 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1079 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1080 | 
 | 
|---|
| 1081 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 1082 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1083 |         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 | 
|---|
| 1084 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1085 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1086 | 
 | 
|---|
| 1087 |         /* end of the loop */
 | 
|---|
| 1088 |         if (t == 0) {
 | 
|---|
| 1089 |                 smb_raw_exit(cli->session);
 | 
|---|
| 1090 |                 t = 1;
 | 
|---|
| 1091 |                 torture_comment(tctx, "testing with timeout > 0 (=%d)\n",
 | 
|---|
| 1092 |                                 t);
 | 
|---|
| 1093 |                 fname = BASEDIR "\\test1.txt";
 | 
|---|
| 1094 |                 goto next_run;
 | 
|---|
| 1095 |         }
 | 
|---|
| 1096 | 
 | 
|---|
| 1097 |         t = 4000;
 | 
|---|
| 1098 |         torture_comment(tctx, "testing special cases with timeout > 0 (=%d)\n",
 | 
|---|
| 1099 |                         t);
 | 
|---|
| 1100 | 
 | 
|---|
| 1101 |         /*
 | 
|---|
| 1102 |          * the following 3 test sections demonstrate that
 | 
|---|
| 1103 |          * the cache is only set when the error is reported
 | 
|---|
| 1104 |          * to the client (after the timeout went by)
 | 
|---|
| 1105 |          */
 | 
|---|
| 1106 |         smb_raw_exit(cli->session);
 | 
|---|
| 1107 |         torture_comment(tctx, "testing a conflict while a lock is pending\n");
 | 
|---|
| 1108 |         fname = BASEDIR "\\test2.txt";
 | 
|---|
| 1109 |         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 1110 |         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
 | 
|---|
| 1111 |                        "Failed to reopen %s - %s\n",
 | 
|---|
| 1112 |                        fname, smbcli_errstr(cli->tree)));
 | 
|---|
| 1113 | 
 | 
|---|
| 1114 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 1115 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 1116 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 1117 |         io.lockx.in.timeout = 0;
 | 
|---|
| 1118 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1119 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1120 |         lock[0].pid = cli->session->pid;
 | 
|---|
| 1121 |         lock[0].offset = 100;
 | 
|---|
| 1122 |         lock[0].count = 10;
 | 
|---|
| 1123 |         io.lockx.in.locks = &lock[0];
 | 
|---|
| 1124 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1125 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1126 | 
 | 
|---|
| 1127 |         start = time(NULL);
 | 
|---|
| 1128 |         io.lockx.in.timeout = t;
 | 
|---|
| 1129 |         req = smb_raw_lock_send(cli->tree, &io);
 | 
|---|
| 1130 |         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
 | 
|---|
| 1131 |                        "Failed to setup timed lock (%s)\n", __location__));
 | 
|---|
| 1132 | 
 | 
|---|
| 1133 |         io.lockx.in.timeout = 0;
 | 
|---|
| 1134 |         lock[0].offset = 105;
 | 
|---|
| 1135 |         lock[0].count = 10;
 | 
|---|
| 1136 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1137 |         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 | 
|---|
| 1138 | 
 | 
|---|
| 1139 |         status = smbcli_request_simple_recv(req);
 | 
|---|
| 1140 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1141 | 
 | 
|---|
| 1142 |         delay = t / 1000;
 | 
|---|
| 1143 |         if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
 | 
|---|
| 1144 |                 delay /= 2;
 | 
|---|
| 1145 |         }
 | 
|---|
| 1146 | 
 | 
|---|
| 1147 |         torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
 | 
|---|
| 1148 |                        "lock comes back to early timeout[%d] delay[%d]"
 | 
|---|
| 1149 |                        "(%s)\n", t, delay, __location__));
 | 
|---|
| 1150 | 
 | 
|---|
| 1151 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1152 |         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 | 
|---|
| 1153 | 
 | 
|---|
| 1154 |         smbcli_close(cli->tree, fnum);
 | 
|---|
| 1155 |         fname = BASEDIR "\\test3.txt";
 | 
|---|
| 1156 |         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 1157 |         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
 | 
|---|
| 1158 |                        "Failed to reopen %s - %s\n",
 | 
|---|
| 1159 |                        fname, smbcli_errstr(cli->tree)));
 | 
|---|
| 1160 | 
 | 
|---|
| 1161 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 1162 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 1163 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 1164 |         io.lockx.in.timeout = 0;
 | 
|---|
| 1165 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1166 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1167 |         lock[0].pid = cli->session->pid;
 | 
|---|
| 1168 |         lock[0].offset = 100;
 | 
|---|
| 1169 |         lock[0].count = 10;
 | 
|---|
| 1170 |         io.lockx.in.locks = &lock[0];
 | 
|---|
| 1171 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1172 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1173 | 
 | 
|---|
| 1174 |         start = time(NULL);
 | 
|---|
| 1175 |         io.lockx.in.timeout = t;
 | 
|---|
| 1176 |         req = smb_raw_lock_send(cli->tree, &io);
 | 
|---|
| 1177 |         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
 | 
|---|
| 1178 |                        "Failed to setup timed lock (%s)\n", __location__));
 | 
|---|
| 1179 | 
 | 
|---|
| 1180 |         io.lockx.in.timeout = 0;
 | 
|---|
| 1181 |         lock[0].offset = 105;
 | 
|---|
| 1182 |         lock[0].count = 10;
 | 
|---|
| 1183 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1184 |         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 | 
|---|
| 1185 | 
 | 
|---|
| 1186 |         status = smbcli_request_simple_recv(req);
 | 
|---|
| 1187 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1188 | 
 | 
|---|
| 1189 |         delay = t / 1000;
 | 
|---|
| 1190 |         if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
 | 
|---|
| 1191 |                 delay /= 2;
 | 
|---|
| 1192 |         }
 | 
|---|
| 1193 | 
 | 
|---|
| 1194 |         torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
 | 
|---|
| 1195 |                        "lock comes back to early timeout[%d] delay[%d]"
 | 
|---|
| 1196 |                        "(%s)\n", t, delay, __location__));
 | 
|---|
| 1197 | 
 | 
|---|
| 1198 |         lock[0].offset = 100;
 | 
|---|
| 1199 |         lock[0].count = 10;
 | 
|---|
| 1200 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1201 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1202 | 
 | 
|---|
| 1203 |         smbcli_close(cli->tree, fnum);
 | 
|---|
| 1204 |         fname = BASEDIR "\\test4.txt";
 | 
|---|
| 1205 |         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 1206 |         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
 | 
|---|
| 1207 |                        "Failed to reopen %s - %s\n",
 | 
|---|
| 1208 |                        fname, smbcli_errstr(cli->tree)));
 | 
|---|
| 1209 | 
 | 
|---|
| 1210 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 1211 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 1212 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 | 
|---|
| 1213 |         io.lockx.in.timeout = 0;
 | 
|---|
| 1214 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1215 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1216 |         lock[0].pid = cli->session->pid;
 | 
|---|
| 1217 |         lock[0].offset = 100;
 | 
|---|
| 1218 |         lock[0].count = 10;
 | 
|---|
| 1219 |         io.lockx.in.locks = &lock[0];
 | 
|---|
| 1220 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1221 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1222 | 
 | 
|---|
| 1223 |         start = time(NULL);
 | 
|---|
| 1224 |         io.lockx.in.timeout = t;
 | 
|---|
| 1225 |         req = smb_raw_lock_send(cli->tree, &io);
 | 
|---|
| 1226 |         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
 | 
|---|
| 1227 |                        "Failed to setup timed lock (%s)\n", __location__));
 | 
|---|
| 1228 | 
 | 
|---|
| 1229 |         io.lockx.in.timeout = 0;
 | 
|---|
| 1230 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1231 |         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 | 
|---|
| 1232 | 
 | 
|---|
| 1233 |         status = smbcli_request_simple_recv(req);
 | 
|---|
| 1234 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1235 | 
 | 
|---|
| 1236 |         delay = t / 1000;
 | 
|---|
| 1237 |         if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
 | 
|---|
| 1238 |                 delay /= 2;
 | 
|---|
| 1239 |         }
 | 
|---|
| 1240 | 
 | 
|---|
| 1241 |         torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
 | 
|---|
| 1242 |                        "lock comes back to early timeout[%d] delay[%d]"
 | 
|---|
| 1243 |                        "(%s)\n", t, delay, __location__));
 | 
|---|
| 1244 | 
 | 
|---|
| 1245 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1246 |         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1247 | 
 | 
|---|
| 1248 | done:
 | 
|---|
| 1249 |         smb_raw_exit(cli->session);
 | 
|---|
| 1250 |         smbcli_deltree(cli->tree, BASEDIR);
 | 
|---|
| 1251 |         return ret;
 | 
|---|
| 1252 | }
 | 
|---|
| 1253 | 
 | 
|---|
| 1254 | 
 | 
|---|
| 1255 | /*
 | 
|---|
| 1256 |   test LOCKING_ANDX_CHANGE_LOCKTYPE
 | 
|---|
| 1257 | */
 | 
|---|
| 1258 | static bool test_changetype(struct torture_context *tctx, 
 | 
|---|
| 1259 |                                                         struct smbcli_state *cli)
 | 
|---|
| 1260 | {
 | 
|---|
| 1261 |         union smb_lock io;
 | 
|---|
| 1262 |         struct smb_lock_entry lock[2];
 | 
|---|
| 1263 |         NTSTATUS status;
 | 
|---|
| 1264 |         bool ret = true;
 | 
|---|
| 1265 |         int fnum;
 | 
|---|
| 1266 |         uint8_t c = 0;
 | 
|---|
| 1267 |         const char *fname = BASEDIR "\\test.txt";
 | 
|---|
| 1268 | 
 | 
|---|
| 1269 |         if (!torture_setup_dir(cli, BASEDIR)) {
 | 
|---|
| 1270 |                 return false;
 | 
|---|
| 1271 |         }
 | 
|---|
| 1272 | 
 | 
|---|
| 1273 |         torture_comment(tctx, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
 | 
|---|
| 1274 |         io.generic.level = RAW_LOCK_LOCKX;
 | 
|---|
| 1275 |         
 | 
|---|
| 1276 |         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 1277 |         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
 | 
|---|
| 1278 |                        "Failed to create %s - %s\n",
 | 
|---|
| 1279 |                        fname, smbcli_errstr(cli->tree)));
 | 
|---|
| 1280 | 
 | 
|---|
| 1281 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 1282 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 1283 |         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
 | 
|---|
| 1284 |         io.lockx.in.timeout = 0;
 | 
|---|
| 1285 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1286 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1287 |         lock[0].pid = cli->session->pid;
 | 
|---|
| 1288 |         lock[0].offset = 100;
 | 
|---|
| 1289 |         lock[0].count = 10;
 | 
|---|
| 1290 |         io.lockx.in.locks = &lock[0];
 | 
|---|
| 1291 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1292 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1293 | 
 | 
|---|
| 1294 |         if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
 | 
|---|
| 1295 |                 torture_result(tctx, TORTURE_FAIL,
 | 
|---|
| 1296 |                         "allowed write on read locked region (%s)\n", __location__);
 | 
|---|
| 1297 |                 ret = false;
 | 
|---|
| 1298 |                 goto done;
 | 
|---|
| 1299 |         }
 | 
|---|
| 1300 | 
 | 
|---|
| 1301 |         /* windows server don't seem to support this */
 | 
|---|
| 1302 |         io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
 | 
|---|
| 1303 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1304 |         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
 | 
|---|
| 1305 | 
 | 
|---|
| 1306 |         if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
 | 
|---|
| 1307 |                 torture_result(tctx, TORTURE_FAIL,
 | 
|---|
| 1308 |                         "allowed write after lock change (%s)\n", __location__);
 | 
|---|
| 1309 |                 ret = false;
 | 
|---|
| 1310 |                 goto done;
 | 
|---|
| 1311 |         }
 | 
|---|
| 1312 | 
 | 
|---|
| 1313 | done:
 | 
|---|
| 1314 |         smbcli_close(cli->tree, fnum);
 | 
|---|
| 1315 |         smb_raw_exit(cli->session);
 | 
|---|
| 1316 |         smbcli_deltree(cli->tree, BASEDIR);
 | 
|---|
| 1317 |         return ret;
 | 
|---|
| 1318 | }
 | 
|---|
| 1319 | 
 | 
|---|
| 1320 | struct double_lock_test {
 | 
|---|
| 1321 |         struct smb_lock_entry lock1;
 | 
|---|
| 1322 |         struct smb_lock_entry lock2;
 | 
|---|
| 1323 |         NTSTATUS exp_status;
 | 
|---|
| 1324 | };
 | 
|---|
| 1325 | 
 | 
|---|
| 1326 | /**
 | 
|---|
| 1327 |  * Tests zero byte locks.
 | 
|---|
| 1328 |  */
 | 
|---|
| 1329 | static const struct double_lock_test zero_byte_tests[] = {
 | 
|---|
| 1330 |         /* {pid, offset, count}, {pid, offset, count}, status */
 | 
|---|
| 1331 | 
 | 
|---|
| 1332 |         /** First, takes a zero byte lock at offset 10. Then:
 | 
|---|
| 1333 |         *   - Taking 0 byte lock at 10 should succeed.
 | 
|---|
| 1334 |         *   - Taking 1 byte locks at 9,10,11 should succeed.
 | 
|---|
| 1335 |         *   - Taking 2 byte lock at 9 should fail.
 | 
|---|
| 1336 |         *   - Taking 2 byte lock at 10 should succeed.
 | 
|---|
| 1337 |         *   - Taking 3 byte lock at 9 should fail.
 | 
|---|
| 1338 |         */
 | 
|---|
| 1339 |         {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK},
 | 
|---|
| 1340 |         {{1000, 10, 0}, {1001, 9, 1},  NT_STATUS_OK},
 | 
|---|
| 1341 |         {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK},
 | 
|---|
| 1342 |         {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK},
 | 
|---|
| 1343 |         {{1000, 10, 0}, {1001, 9, 2},  NT_STATUS_LOCK_NOT_GRANTED},
 | 
|---|
| 1344 |         {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK},
 | 
|---|
| 1345 |         {{1000, 10, 0}, {1001, 9, 3},  NT_STATUS_LOCK_NOT_GRANTED},
 | 
|---|
| 1346 | 
 | 
|---|
| 1347 |         /** Same, but opposite order. */
 | 
|---|
| 1348 |         {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK},
 | 
|---|
| 1349 |         {{1001, 9, 1},  {1000, 10, 0}, NT_STATUS_OK},
 | 
|---|
| 1350 |         {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK},
 | 
|---|
| 1351 |         {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK},
 | 
|---|
| 1352 |         {{1001, 9, 2},  {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
 | 
|---|
| 1353 |         {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK},
 | 
|---|
| 1354 |         {{1001, 9, 3},  {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
 | 
|---|
| 1355 | 
 | 
|---|
| 1356 |         /** Zero zero case. */
 | 
|---|
| 1357 |         {{1000, 0, 0},  {1001, 0, 0},  NT_STATUS_OK},
 | 
|---|
| 1358 | };
 | 
|---|
| 1359 | 
 | 
|---|
| 1360 | static bool test_zerobytelocks(struct torture_context *tctx, struct smbcli_state *cli)
 | 
|---|
| 1361 | {
 | 
|---|
| 1362 |         union smb_lock io;
 | 
|---|
| 1363 |         NTSTATUS status;
 | 
|---|
| 1364 |         bool ret = true;
 | 
|---|
| 1365 |         int fnum, i;
 | 
|---|
| 1366 |         const char *fname = BASEDIR "\\zero.txt";
 | 
|---|
| 1367 | 
 | 
|---|
| 1368 |         torture_comment(tctx, "Testing zero length byte range locks:\n");
 | 
|---|
| 1369 | 
 | 
|---|
| 1370 |         if (!torture_setup_dir(cli, BASEDIR)) {
 | 
|---|
| 1371 |                 return false;
 | 
|---|
| 1372 |         }
 | 
|---|
| 1373 | 
 | 
|---|
| 1374 |         io.generic.level = RAW_LOCK_LOCKX;
 | 
|---|
| 1375 | 
 | 
|---|
| 1376 |         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 1377 |         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
 | 
|---|
| 1378 |                        "Failed to create %s - %s\n",
 | 
|---|
| 1379 |                        fname, smbcli_errstr(cli->tree)));
 | 
|---|
| 1380 | 
 | 
|---|
| 1381 |         /* Setup initial parameters */
 | 
|---|
| 1382 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 1383 |         io.lockx.in.file.fnum = fnum;
 | 
|---|
| 1384 |         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; /* Exclusive */
 | 
|---|
| 1385 |         io.lockx.in.timeout = 0;
 | 
|---|
| 1386 | 
 | 
|---|
| 1387 |         /* Try every combination of locks in zero_byte_tests. The first lock is
 | 
|---|
| 1388 |          * assumed to succeed. The second lock may contend, depending on the
 | 
|---|
| 1389 |          * expected status. */
 | 
|---|
| 1390 |         for (i = 0;
 | 
|---|
| 1391 |              i < ARRAY_SIZE(zero_byte_tests);
 | 
|---|
| 1392 |              i++) {
 | 
|---|
| 1393 |                 torture_comment(tctx, "  ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
 | 
|---|
| 1394 |                     zero_byte_tests[i].lock1.pid,
 | 
|---|
| 1395 |                     zero_byte_tests[i].lock1.offset,
 | 
|---|
| 1396 |                     zero_byte_tests[i].lock1.count,
 | 
|---|
| 1397 |                     zero_byte_tests[i].lock2.pid,
 | 
|---|
| 1398 |                     zero_byte_tests[i].lock2.offset,
 | 
|---|
| 1399 |                     zero_byte_tests[i].lock2.count,
 | 
|---|
| 1400 |                     nt_errstr(zero_byte_tests[i].exp_status));
 | 
|---|
| 1401 | 
 | 
|---|
| 1402 |                 /* Lock both locks. */
 | 
|---|
| 1403 |                 io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1404 |                 io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1405 | 
 | 
|---|
| 1406 |                 io.lockx.in.locks = &zero_byte_tests[i].lock1;
 | 
|---|
| 1407 |                 status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1408 |                 CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1409 | 
 | 
|---|
| 1410 |                 io.lockx.in.locks = &zero_byte_tests[i].lock2;
 | 
|---|
| 1411 |                 status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1412 | 
 | 
|---|
| 1413 |                 if (NT_STATUS_EQUAL(zero_byte_tests[i].exp_status,
 | 
|---|
| 1414 |                         NT_STATUS_LOCK_NOT_GRANTED)) {
 | 
|---|
| 1415 |                         /* Allow either of the failure messages and keep going
 | 
|---|
| 1416 |                          * if we see the wrong status. */
 | 
|---|
| 1417 |                         CHECK_STATUS_OR_CONT(status,
 | 
|---|
| 1418 |                             NT_STATUS_LOCK_NOT_GRANTED,
 | 
|---|
| 1419 |                             NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1420 | 
 | 
|---|
| 1421 |                 } else {
 | 
|---|
| 1422 |                         CHECK_STATUS_CONT(status,
 | 
|---|
| 1423 |                             zero_byte_tests[i].exp_status);
 | 
|---|
| 1424 |                 }
 | 
|---|
| 1425 | 
 | 
|---|
| 1426 |                 /* Unlock both locks. */
 | 
|---|
| 1427 |                 io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 1428 |                 io.lockx.in.lock_cnt = 0;
 | 
|---|
| 1429 | 
 | 
|---|
| 1430 |                 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
 | 
|---|
| 1431 |                         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1432 |                         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1433 |                 }
 | 
|---|
| 1434 | 
 | 
|---|
| 1435 |                 io.lockx.in.locks = &zero_byte_tests[i].lock1;
 | 
|---|
| 1436 |                 status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1437 |                 CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1438 |         }
 | 
|---|
| 1439 | 
 | 
|---|
| 1440 | done:
 | 
|---|
| 1441 |         smbcli_close(cli->tree, fnum);
 | 
|---|
| 1442 |         smb_raw_exit(cli->session);
 | 
|---|
| 1443 |         smbcli_deltree(cli->tree, BASEDIR);
 | 
|---|
| 1444 |         return ret;
 | 
|---|
| 1445 | }
 | 
|---|
| 1446 | 
 | 
|---|
| 1447 | static bool test_unlock(struct torture_context *tctx, struct smbcli_state *cli)
 | 
|---|
| 1448 | {
 | 
|---|
| 1449 |         union smb_lock io;
 | 
|---|
| 1450 |         NTSTATUS status;
 | 
|---|
| 1451 |         bool ret = true;
 | 
|---|
| 1452 |         int fnum1, fnum2;
 | 
|---|
| 1453 |         const char *fname = BASEDIR "\\unlock.txt";
 | 
|---|
| 1454 |         struct smb_lock_entry lock1;
 | 
|---|
| 1455 |         struct smb_lock_entry lock2;
 | 
|---|
| 1456 | 
 | 
|---|
| 1457 |         torture_comment(tctx, "Testing LOCKX unlock:\n");
 | 
|---|
| 1458 | 
 | 
|---|
| 1459 |         if (!torture_setup_dir(cli, BASEDIR)) {
 | 
|---|
| 1460 |                 return false;
 | 
|---|
| 1461 |         }
 | 
|---|
| 1462 | 
 | 
|---|
| 1463 |         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 1464 |         torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
 | 
|---|
| 1465 |                        "Failed to create %s - %s\n",
 | 
|---|
| 1466 |                        fname, smbcli_errstr(cli->tree)));
 | 
|---|
| 1467 | 
 | 
|---|
| 1468 |         fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 1469 |         torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
 | 
|---|
| 1470 |                        "Failed to create %s - %s\n",
 | 
|---|
| 1471 |                        fname, smbcli_errstr(cli->tree)));
 | 
|---|
| 1472 | 
 | 
|---|
| 1473 |         /* Setup initial parameters */
 | 
|---|
| 1474 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 1475 |         io.lockx.in.timeout = 0;
 | 
|---|
| 1476 | 
 | 
|---|
| 1477 |         lock1.pid = cli->session->pid;
 | 
|---|
| 1478 |         lock1.offset = 0;
 | 
|---|
| 1479 |         lock1.count = 10;
 | 
|---|
| 1480 |         lock2.pid = cli->session->pid - 1;
 | 
|---|
| 1481 |         lock2.offset = 0;
 | 
|---|
| 1482 |         lock2.count = 10;
 | 
|---|
| 1483 | 
 | 
|---|
| 1484 |         /**
 | 
|---|
| 1485 |          * Take exclusive lock, then unlock it with a shared-unlock call.
 | 
|---|
| 1486 |          */
 | 
|---|
| 1487 |         torture_comment(tctx, "  taking exclusive lock.\n");
 | 
|---|
| 1488 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1489 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1490 |         io.lockx.in.mode = 0;
 | 
|---|
| 1491 |         io.lockx.in.file.fnum = fnum1;
 | 
|---|
| 1492 |         io.lockx.in.locks = &lock1;
 | 
|---|
| 1493 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1494 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1495 | 
 | 
|---|
| 1496 |         torture_comment(tctx, "  unlock the exclusive with a shared unlock call.\n");
 | 
|---|
| 1497 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 1498 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 1499 |         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
 | 
|---|
| 1500 |         io.lockx.in.file.fnum = fnum1;
 | 
|---|
| 1501 |         io.lockx.in.locks = &lock1;
 | 
|---|
| 1502 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1503 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1504 | 
 | 
|---|
| 1505 |         torture_comment(tctx, "  try shared lock on pid2/fnum2, testing the unlock.\n");
 | 
|---|
| 1506 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1507 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1508 |         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
 | 
|---|
| 1509 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 1510 |         io.lockx.in.locks = &lock2;
 | 
|---|
| 1511 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1512 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1513 | 
 | 
|---|
| 1514 |         /**
 | 
|---|
| 1515 |          * Unlock a shared lock with an exclusive-unlock call.
 | 
|---|
| 1516 |          */
 | 
|---|
| 1517 |         torture_comment(tctx, "  unlock new shared lock with exclusive unlock call.\n");
 | 
|---|
| 1518 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 1519 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 1520 |         io.lockx.in.mode = 0;
 | 
|---|
| 1521 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 1522 |         io.lockx.in.locks = &lock2;
 | 
|---|
| 1523 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1524 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1525 | 
 | 
|---|
| 1526 |         torture_comment(tctx, "  try exclusive lock on pid1, testing the unlock.\n");
 | 
|---|
| 1527 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1528 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1529 |         io.lockx.in.mode = 0;
 | 
|---|
| 1530 |         io.lockx.in.file.fnum = fnum1;
 | 
|---|
| 1531 |         io.lockx.in.locks = &lock1;
 | 
|---|
| 1532 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1533 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1534 | 
 | 
|---|
| 1535 |         /* cleanup */
 | 
|---|
| 1536 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 1537 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 1538 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1539 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1540 | 
 | 
|---|
| 1541 |         /**
 | 
|---|
| 1542 |          * Test unlocking of 0-byte locks.
 | 
|---|
| 1543 |          */
 | 
|---|
| 1544 | 
 | 
|---|
| 1545 |         torture_comment(tctx, "  lock shared and exclusive 0-byte locks, testing that Windows "
 | 
|---|
| 1546 |             "always unlocks the exclusive first.\n");
 | 
|---|
| 1547 |         lock1.pid = cli->session->pid;
 | 
|---|
| 1548 |         lock1.offset = 10;
 | 
|---|
| 1549 |         lock1.count = 0;
 | 
|---|
| 1550 |         lock2.pid = cli->session->pid;
 | 
|---|
| 1551 |         lock2.offset = 5;
 | 
|---|
| 1552 |         lock2.count = 10;
 | 
|---|
| 1553 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1554 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1555 |         io.lockx.in.file.fnum = fnum1;
 | 
|---|
| 1556 |         io.lockx.in.locks = &lock1;
 | 
|---|
| 1557 | 
 | 
|---|
| 1558 |         /* lock 0-byte shared
 | 
|---|
| 1559 |          * Note: Order of the shared/exclusive locks doesn't matter. */
 | 
|---|
| 1560 |         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
 | 
|---|
| 1561 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1562 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1563 | 
 | 
|---|
| 1564 |         /* lock 0-byte exclusive */
 | 
|---|
| 1565 |         io.lockx.in.mode = 0;
 | 
|---|
| 1566 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1567 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1568 | 
 | 
|---|
| 1569 |         /* test contention */
 | 
|---|
| 1570 |         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
 | 
|---|
| 1571 |         io.lockx.in.locks = &lock2;
 | 
|---|
| 1572 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 1573 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1574 |         CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
 | 
|---|
| 1575 |             NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1576 | 
 | 
|---|
| 1577 |         /* unlock */
 | 
|---|
| 1578 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 1579 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 1580 |         io.lockx.in.file.fnum = fnum1;
 | 
|---|
| 1581 |         io.lockx.in.locks = &lock1;
 | 
|---|
| 1582 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1583 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1584 | 
 | 
|---|
| 1585 |         /* test - can we take a shared lock? */
 | 
|---|
| 1586 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1587 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1588 |         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
 | 
|---|
| 1589 |         io.lockx.in.file.fnum = fnum2;
 | 
|---|
| 1590 |         io.lockx.in.locks = &lock2;
 | 
|---|
| 1591 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1592 | 
 | 
|---|
| 1593 |         /* XXX Samba 3 will fail this test. This is temporary(because this isn't
 | 
|---|
| 1594 |          * new to Win7, it succeeds in WinXP too), until I can come to a
 | 
|---|
| 1595 |          * resolution as to whether Samba should support this or not. There is
 | 
|---|
| 1596 |          * code to preference unlocking exclusive locks before shared locks,
 | 
|---|
| 1597 |          * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
 | 
|---|
| 1598 |         if (TARGET_IS_SAMBA3(tctx)) {
 | 
|---|
| 1599 |                 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
 | 
|---|
| 1600 |                     NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1601 |         } else {
 | 
|---|
| 1602 |                 CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1603 |         }
 | 
|---|
| 1604 | 
 | 
|---|
| 1605 |         /* cleanup */
 | 
|---|
| 1606 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 1607 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 1608 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1609 | 
 | 
|---|
| 1610 |         /* XXX Same as above. */
 | 
|---|
| 1611 |         if (TARGET_IS_SAMBA3(tctx)) {
 | 
|---|
| 1612 |                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 1613 |         } else {
 | 
|---|
| 1614 |                 CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1615 |         }
 | 
|---|
| 1616 | 
 | 
|---|
| 1617 |         io.lockx.in.file.fnum = fnum1;
 | 
|---|
| 1618 |         io.lockx.in.locks = &lock1;
 | 
|---|
| 1619 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1620 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1621 | 
 | 
|---|
| 1622 | done:
 | 
|---|
| 1623 |         smbcli_close(cli->tree, fnum1);
 | 
|---|
| 1624 |         smbcli_close(cli->tree, fnum2);
 | 
|---|
| 1625 |         smb_raw_exit(cli->session);
 | 
|---|
| 1626 |         smbcli_deltree(cli->tree, BASEDIR);
 | 
|---|
| 1627 |         return ret;
 | 
|---|
| 1628 | }
 | 
|---|
| 1629 | 
 | 
|---|
| 1630 | static bool test_multiple_unlock(struct torture_context *tctx, struct smbcli_state *cli)
 | 
|---|
| 1631 | {
 | 
|---|
| 1632 |         union smb_lock io;
 | 
|---|
| 1633 |         NTSTATUS status;
 | 
|---|
| 1634 |         bool ret = true;
 | 
|---|
| 1635 |         int fnum1;
 | 
|---|
| 1636 |         const char *fname = BASEDIR "\\unlock_multiple.txt";
 | 
|---|
| 1637 |         struct smb_lock_entry lock1;
 | 
|---|
| 1638 |         struct smb_lock_entry lock2;
 | 
|---|
| 1639 |         struct smb_lock_entry locks[2];
 | 
|---|
| 1640 | 
 | 
|---|
| 1641 |         torture_comment(tctx, "Testing LOCKX multiple unlock:\n");
 | 
|---|
| 1642 | 
 | 
|---|
| 1643 |         if (!torture_setup_dir(cli, BASEDIR)) {
 | 
|---|
| 1644 |                 return false;
 | 
|---|
| 1645 |         }
 | 
|---|
| 1646 | 
 | 
|---|
| 1647 |         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 1648 |         torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
 | 
|---|
| 1649 |                        "Failed to create %s - %s\n",
 | 
|---|
| 1650 |                        fname, smbcli_errstr(cli->tree)));
 | 
|---|
| 1651 | 
 | 
|---|
| 1652 |         /* Setup initial parameters */
 | 
|---|
| 1653 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 1654 |         io.lockx.in.timeout = 0;
 | 
|---|
| 1655 | 
 | 
|---|
| 1656 |         lock1.pid = cli->session->pid;
 | 
|---|
| 1657 |         lock1.offset = 0;
 | 
|---|
| 1658 |         lock1.count = 10;
 | 
|---|
| 1659 |         lock2.pid = cli->session->pid;
 | 
|---|
| 1660 |         lock2.offset = 10;
 | 
|---|
| 1661 |         lock2.count = 10;
 | 
|---|
| 1662 | 
 | 
|---|
| 1663 |         locks[0] = lock1;
 | 
|---|
| 1664 |         locks[1] = lock2;
 | 
|---|
| 1665 | 
 | 
|---|
| 1666 |         io.lockx.in.file.fnum = fnum1;
 | 
|---|
| 1667 |         io.lockx.in.mode = 0; /* exclusive */
 | 
|---|
| 1668 | 
 | 
|---|
| 1669 |         /** Test1: Take second lock, but not first. */
 | 
|---|
| 1670 |         torture_comment(tctx, "  unlock 2 locks, first one not locked. Expect no locks "
 | 
|---|
| 1671 |             "unlocked. \n");
 | 
|---|
| 1672 | 
 | 
|---|
| 1673 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1674 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1675 |         io.lockx.in.locks = &lock2;
 | 
|---|
| 1676 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1677 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1678 | 
 | 
|---|
| 1679 |         /* Try to unlock both locks. */
 | 
|---|
| 1680 |         io.lockx.in.ulock_cnt = 2;
 | 
|---|
| 1681 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 1682 |         io.lockx.in.locks = locks;
 | 
|---|
| 1683 | 
 | 
|---|
| 1684 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1685 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 1686 | 
 | 
|---|
| 1687 |         /* Second lock should not be unlocked. */
 | 
|---|
| 1688 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1689 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1690 |         io.lockx.in.locks = &lock2;
 | 
|---|
| 1691 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1692 |         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 | 
|---|
| 1693 | 
 | 
|---|
| 1694 |         /* cleanup */
 | 
|---|
| 1695 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 1696 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 1697 |         io.lockx.in.locks = &lock2;
 | 
|---|
| 1698 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1699 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1700 | 
 | 
|---|
| 1701 |         /** Test2: Take first lock, but not second. */
 | 
|---|
| 1702 |         torture_comment(tctx, "  unlock 2 locks, second one not locked. Expect first lock "
 | 
|---|
| 1703 |             "unlocked.\n");
 | 
|---|
| 1704 | 
 | 
|---|
| 1705 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1706 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1707 |         io.lockx.in.locks = &lock1;
 | 
|---|
| 1708 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1709 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1710 | 
 | 
|---|
| 1711 |         /* Try to unlock both locks. */
 | 
|---|
| 1712 |         io.lockx.in.ulock_cnt = 2;
 | 
|---|
| 1713 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 1714 |         io.lockx.in.locks = locks;
 | 
|---|
| 1715 | 
 | 
|---|
| 1716 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1717 |         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 | 
|---|
| 1718 | 
 | 
|---|
| 1719 |         /* First lock should be unlocked. */
 | 
|---|
| 1720 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1721 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1722 |         io.lockx.in.locks = &lock1;
 | 
|---|
| 1723 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1724 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1725 | 
 | 
|---|
| 1726 |         /* cleanup */
 | 
|---|
| 1727 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 1728 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 1729 |         io.lockx.in.locks = &lock1;
 | 
|---|
| 1730 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1731 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1732 | 
 | 
|---|
| 1733 | done:
 | 
|---|
| 1734 |         smbcli_close(cli->tree, fnum1);
 | 
|---|
| 1735 |         smb_raw_exit(cli->session);
 | 
|---|
| 1736 |         smbcli_deltree(cli->tree, BASEDIR);
 | 
|---|
| 1737 |         return ret;
 | 
|---|
| 1738 | }
 | 
|---|
| 1739 | 
 | 
|---|
| 1740 | /**
 | 
|---|
| 1741 |  * torture_locktest5 covers stacking pretty well, but its missing two tests:
 | 
|---|
| 1742 |  * - stacking an exclusive on top of shared fails
 | 
|---|
| 1743 |  * - stacking two exclusives fail
 | 
|---|
| 1744 |  */
 | 
|---|
| 1745 | static bool test_stacking(struct torture_context *tctx, struct smbcli_state *cli)
 | 
|---|
| 1746 | {
 | 
|---|
| 1747 |         union smb_lock io;
 | 
|---|
| 1748 |         NTSTATUS status;
 | 
|---|
| 1749 |         bool ret = true;
 | 
|---|
| 1750 |         int fnum1;
 | 
|---|
| 1751 |         const char *fname = BASEDIR "\\stacking.txt";
 | 
|---|
| 1752 |         struct smb_lock_entry lock1;
 | 
|---|
| 1753 |         struct smb_lock_entry lock2;
 | 
|---|
| 1754 | 
 | 
|---|
| 1755 |         torture_comment(tctx, "Testing stacking:\n");
 | 
|---|
| 1756 | 
 | 
|---|
| 1757 |         if (!torture_setup_dir(cli, BASEDIR)) {
 | 
|---|
| 1758 |                 return false;
 | 
|---|
| 1759 |         }
 | 
|---|
| 1760 | 
 | 
|---|
| 1761 |         io.generic.level = RAW_LOCK_LOCKX;
 | 
|---|
| 1762 | 
 | 
|---|
| 1763 |         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 | 
|---|
| 1764 |         torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
 | 
|---|
| 1765 |                        "Failed to create %s - %s\n",
 | 
|---|
| 1766 |                        fname, smbcli_errstr(cli->tree)));
 | 
|---|
| 1767 | 
 | 
|---|
| 1768 |         /* Setup initial parameters */
 | 
|---|
| 1769 |         io.lockx.level = RAW_LOCK_LOCKX;
 | 
|---|
| 1770 |         io.lockx.in.timeout = 0;
 | 
|---|
| 1771 | 
 | 
|---|
| 1772 |         lock1.pid = cli->session->pid;
 | 
|---|
| 1773 |         lock1.offset = 0;
 | 
|---|
| 1774 |         lock1.count = 10;
 | 
|---|
| 1775 |         lock2.pid = cli->session->pid - 1;
 | 
|---|
| 1776 |         lock2.offset = 0;
 | 
|---|
| 1777 |         lock2.count = 10;
 | 
|---|
| 1778 | 
 | 
|---|
| 1779 |         /**
 | 
|---|
| 1780 |          * Try to take a shared lock, then stack an exclusive.
 | 
|---|
| 1781 |          */
 | 
|---|
| 1782 |         torture_comment(tctx, "  stacking an exclusive on top of a shared lock fails.\n");
 | 
|---|
| 1783 |         io.lockx.in.file.fnum = fnum1;
 | 
|---|
| 1784 |         io.lockx.in.locks = &lock1;
 | 
|---|
| 1785 | 
 | 
|---|
| 1786 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1787 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1788 |         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
 | 
|---|
| 1789 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1790 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1791 | 
 | 
|---|
| 1792 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1793 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1794 |         io.lockx.in.mode = 0;
 | 
|---|
| 1795 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1796 |         CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
 | 
|---|
| 1797 |             NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1798 | 
 | 
|---|
| 1799 |         /* cleanup */
 | 
|---|
| 1800 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 1801 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 1802 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1803 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1804 | 
 | 
|---|
| 1805 |         /**
 | 
|---|
| 1806 |          * Prove that two exclusive locks do not stack.
 | 
|---|
| 1807 |          */
 | 
|---|
| 1808 |         torture_comment(tctx, "  two exclusive locks do not stack.\n");
 | 
|---|
| 1809 |         io.lockx.in.ulock_cnt = 0;
 | 
|---|
| 1810 |         io.lockx.in.lock_cnt = 1;
 | 
|---|
| 1811 |         io.lockx.in.mode = 0;
 | 
|---|
| 1812 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1813 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1814 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1815 |         CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
 | 
|---|
| 1816 |             NT_STATUS_FILE_LOCK_CONFLICT);
 | 
|---|
| 1817 | 
 | 
|---|
| 1818 |         /* cleanup */
 | 
|---|
| 1819 |         io.lockx.in.ulock_cnt = 1;
 | 
|---|
| 1820 |         io.lockx.in.lock_cnt = 0;
 | 
|---|
| 1821 |         status = smb_raw_lock(cli->tree, &io);
 | 
|---|
| 1822 |         CHECK_STATUS(status, NT_STATUS_OK);
 | 
|---|
| 1823 | 
 | 
|---|
| 1824 | done:
 | 
|---|
| 1825 |         smbcli_close(cli->tree, fnum1);
 | 
|---|
| 1826 |         smb_raw_exit(cli->session);
 | 
|---|
| 1827 |         smbcli_deltree(cli->tree, BASEDIR);
 | 
|---|
| 1828 |         return ret;
 | 
|---|
| 1829 | }
 | 
|---|
| 1830 | 
 | 
|---|
| 1831 | /* 
 | 
|---|
| 1832 |    basic testing of lock calls
 | 
|---|
| 1833 | */
 | 
|---|
| 1834 | struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
 | 
|---|
| 1835 | {
 | 
|---|
| 1836 |         struct torture_suite *suite = torture_suite_create(mem_ctx, "LOCK");
 | 
|---|
| 1837 | 
 | 
|---|
| 1838 |         torture_suite_add_1smb_test(suite, "lockx", test_lockx);
 | 
|---|
| 1839 |         torture_suite_add_1smb_test(suite, "lock", test_lock);
 | 
|---|
| 1840 |         torture_suite_add_1smb_test(suite, "pidhigh", test_pidhigh);
 | 
|---|
| 1841 |         torture_suite_add_1smb_test(suite, "async", test_async);
 | 
|---|
| 1842 |         torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
 | 
|---|
| 1843 |         torture_suite_add_1smb_test(suite, "changetype", test_changetype);
 | 
|---|
| 1844 | 
 | 
|---|
| 1845 |         torture_suite_add_1smb_test(suite, "stacking", test_stacking);
 | 
|---|
| 1846 |         torture_suite_add_1smb_test(suite, "unlock", test_unlock);
 | 
|---|
| 1847 |         torture_suite_add_1smb_test(suite, "multiple_unlock",
 | 
|---|
| 1848 |             test_multiple_unlock);
 | 
|---|
| 1849 |         torture_suite_add_1smb_test(suite, "zerobytelocks",
 | 
|---|
| 1850 |             test_zerobytelocks);
 | 
|---|
| 1851 | 
 | 
|---|
| 1852 |         return suite;
 | 
|---|
| 1853 | }
 | 
|---|