2 Unix SMB/CIFS implementation.
3 basic raw test suite for change notify
4 Copyright (C) Andrew Tridgell 2003
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.
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.
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/>.
21 #include "libcli/raw/libcliraw.h"
22 #include "libcli/raw/raw_proto.h"
23 #include "libcli/libcli.h"
24 #include "system/filesys.h"
25 #include "torture/util.h"
26 #include "torture/raw/proto.h"
28 #define BASEDIR "\\test_notify"
30 #define CHECK_WSTR(tctx, field, value, flags) \
32 torture_assert_str_equal(tctx, field.s, value, "values don't match"); \
33 torture_assert(tctx, \
34 !wire_bad_flags(&field, STR_UNICODE, cli->transport), \
39 basic testing of change notify on directories
41 static bool test_notify_dir(struct torture_context
*tctx
,
42 struct smbcli_state
*cli
,
43 struct smbcli_state
*cli2
)
47 union smb_notify notify
;
50 int i
, count
, fnum
, fnum2
;
51 struct smbcli_request
*req
, *req2
;
52 extern int torture_numops
;
54 torture_comment(tctx
, "TESTING CHANGE NOTIFY ON DIRECTORIES\n");
56 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
),
57 "Failed to setup up test directory: " BASEDIR
);
60 get a handle on the directory
62 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
63 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
64 io
.ntcreatex
.in
.flags
= 0;
65 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
66 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
67 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
68 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
69 io
.ntcreatex
.in
.alloc_size
= 0;
70 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
71 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
72 io
.ntcreatex
.in
.security_flags
= 0;
73 io
.ntcreatex
.in
.fname
= BASEDIR
;
75 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
76 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
78 fnum
= io
.ntcreatex
.out
.file
.fnum
;
80 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
81 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
83 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
85 /* ask for a change notify,
86 on file or directory name changes */
87 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
88 notify
.nttrans
.in
.buffer_size
= 1000;
89 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
90 notify
.nttrans
.in
.file
.fnum
= fnum
;
91 notify
.nttrans
.in
.recursive
= true;
93 torture_comment(tctx
, "Testing notify cancel\n");
95 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
96 smb_raw_ntcancel(req
);
97 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
98 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_CANCELLED
,
100 "smb_raw_changenotify_recv");
102 torture_comment(tctx
, "Testing notify mkdir\n");
104 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
105 smbcli_mkdir(cli2
->tree
, BASEDIR
"\\subdir-name");
107 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
108 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
109 "smb_raw_changenotify_recv");
111 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
112 1, ret
, done
, "more than one change");
113 torture_assert_int_equal_goto(tctx
,
114 notify
.nttrans
.out
.changes
[0].action
,
115 NOTIFY_ACTION_ADDED
, ret
, done
,
116 "wrong action (exp: ADDED)");
117 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subdir-name",
120 torture_comment(tctx
, "Testing notify rmdir\n");
122 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
123 smbcli_rmdir(cli2
->tree
, BASEDIR
"\\subdir-name");
125 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
126 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
127 "smb_raw_changenotify_recv");
128 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
129 1, ret
, done
, "more than one change");
130 torture_assert_int_equal_goto(tctx
,
131 notify
.nttrans
.out
.changes
[0].action
,
132 NOTIFY_ACTION_REMOVED
, ret
, done
,
133 "wrong action (exp: REMOVED)");
134 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subdir-name",
137 torture_comment(tctx
, "Testing notify mkdir - rmdir - mkdir - rmdir\n");
139 smbcli_mkdir(cli2
->tree
, BASEDIR
"\\subdir-name");
140 smbcli_rmdir(cli2
->tree
, BASEDIR
"\\subdir-name");
141 smbcli_mkdir(cli2
->tree
, BASEDIR
"\\subdir-name");
142 smbcli_rmdir(cli2
->tree
, BASEDIR
"\\subdir-name");
144 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
145 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
146 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
147 "smb_raw_changenotify_recv");
148 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
149 4, ret
, done
, "wrong number of changes");
150 torture_assert_int_equal_goto(tctx
,
151 notify
.nttrans
.out
.changes
[0].action
,
152 NOTIFY_ACTION_ADDED
, ret
, done
,
153 "wrong action (exp: ADDED)");
154 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subdir-name",
156 torture_assert_int_equal_goto(tctx
,
157 notify
.nttrans
.out
.changes
[1].action
,
158 NOTIFY_ACTION_REMOVED
, ret
, done
,
159 "wrong action (exp: REMOVED)");
160 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[1].name
, "subdir-name",
162 torture_assert_int_equal_goto(tctx
,
163 notify
.nttrans
.out
.changes
[2].action
,
164 NOTIFY_ACTION_ADDED
, ret
, done
,
165 "wrong action (exp: ADDED)");
166 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[2].name
, "subdir-name",
168 torture_assert_int_equal_goto(tctx
,
169 notify
.nttrans
.out
.changes
[3].action
,
170 NOTIFY_ACTION_REMOVED
, ret
, done
,
171 "wrong action (exp: REMOVED)");
172 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[3].name
, "subdir-name",
175 count
= torture_numops
;
176 torture_comment(tctx
, "Testing buffered notify on create of %d files\n", count
);
177 for (i
=0;i
<count
;i
++) {
178 char *fname
= talloc_asprintf(cli
, BASEDIR
"\\test%d.txt", i
);
179 int fnum3
= smbcli_open(cli
->tree
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
);
180 torture_assert_int_not_equal_goto(tctx
, fnum3
, -1, ret
, done
,
181 talloc_asprintf(tctx
, "Failed to create %s - %s",
182 fname
, smbcli_errstr(cli
->tree
)));
184 smbcli_close(cli
->tree
, fnum3
);
187 /* (1st notify) setup a new notify on a different directory handle.
188 This new notify won't see the events above. */
189 notify
.nttrans
.in
.file
.fnum
= fnum2
;
190 req2
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
192 /* (2nd notify) whereas this notify will see the above buffered events,
193 and it directly returns the buffered events */
194 notify
.nttrans
.in
.file
.fnum
= fnum
;
195 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
197 status
= smbcli_unlink(cli
->tree
, BASEDIR
"\\nonexistent.txt");
198 torture_assert_ntstatus_equal_goto(tctx
, status
,
199 NT_STATUS_OBJECT_NAME_NOT_FOUND
,
203 /* (1st unlink) as the 2nd notify directly returns,
204 this unlink is only seen by the 1st notify and
205 the 3rd notify (later) */
206 torture_comment(tctx
, "Testing notify on unlink for the first file\n");
207 status
= smbcli_unlink(cli2
->tree
, BASEDIR
"\\test0.txt");
208 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
211 /* receive the reply from the 2nd notify */
212 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
213 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
214 "smb_raw_changenotify_recv");
216 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
218 "wrong number of changes");
219 for (i
=1;i
<count
;i
++) {
220 torture_assert_int_equal_goto(tctx
,
221 notify
.nttrans
.out
.changes
[i
].action
,
222 NOTIFY_ACTION_ADDED
, ret
, done
,
223 "wrong action (exp: ADDED)");
225 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "test0.txt",
228 torture_comment(tctx
, "and now from the 1st notify\n");
229 status
= smb_raw_changenotify_recv(req2
, tctx
, ¬ify
);
230 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
231 "smb_raw_changenotify_recv");
232 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
233 1, ret
, done
, "wrong number of changes");
234 torture_assert_int_equal_goto(tctx
,
235 notify
.nttrans
.out
.changes
[0].action
,
236 NOTIFY_ACTION_REMOVED
, ret
, done
,
237 "wrong action (exp: REMOVED)");
238 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "test0.txt",
241 torture_comment(tctx
, "(3rd notify) this notify will only see the 1st unlink\n");
242 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
244 status
= smbcli_unlink(cli
->tree
, BASEDIR
"\\nonexistent.txt");
245 torture_assert_ntstatus_equal_goto(tctx
, status
,
246 NT_STATUS_OBJECT_NAME_NOT_FOUND
,
250 torture_comment(tctx
, "Testing notify on wildcard unlink for %d files\n", count
-1);
251 /* (2nd unlink) do a wildcard unlink */
252 status
= smbcli_unlink(cli2
->tree
, BASEDIR
"\\test*.txt");
253 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
254 "smb_raw_changenotify_recv");
256 /* receive the 3rd notify */
257 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
258 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
259 "smb_raw_changenotify_recv");
260 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
261 1, ret
, done
, "wrong number of changes");
262 torture_assert_int_equal_goto(tctx
,
263 notify
.nttrans
.out
.changes
[0].action
,
264 NOTIFY_ACTION_REMOVED
, ret
, done
,
265 "wrong action (exp: REMOVED)");
266 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "test0.txt",
269 /* and we now see the rest of the unlink calls on both directory handles */
270 notify
.nttrans
.in
.file
.fnum
= fnum
;
272 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
273 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
274 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
275 "smb_raw_changenotify_recv");
276 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
277 count
- 1, ret
, done
,
278 "wrong number of changes");
279 for (i
=0;i
<notify
.nttrans
.out
.num_changes
;i
++) {
280 torture_assert_int_equal_goto(tctx
,
281 notify
.nttrans
.out
.changes
[i
].action
,
282 NOTIFY_ACTION_REMOVED
, ret
, done
,
283 "wrong action (exp: REMOVED)");
285 notify
.nttrans
.in
.file
.fnum
= fnum2
;
286 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
287 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
288 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
289 "smb_raw_changenotify_recv");
290 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
291 count
- 1, ret
, done
,
292 "wrong number of changes");
293 for (i
=0;i
<notify
.nttrans
.out
.num_changes
;i
++) {
294 torture_assert_int_equal_goto(tctx
,
295 notify
.nttrans
.out
.changes
[i
].action
,
296 NOTIFY_ACTION_REMOVED
, ret
, done
,
297 "wrong action (exp: REMOVED)");
300 torture_comment(tctx
, "Testing if a close() on the dir handle triggers the notify reply\n");
302 notify
.nttrans
.in
.file
.fnum
= fnum
;
303 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
305 cl
.close
.level
= RAW_CLOSE_CLOSE
;
306 cl
.close
.in
.file
.fnum
= fnum
;
307 cl
.close
.in
.write_time
= 0;
308 status
= smb_raw_close(cli
->tree
, &cl
);
309 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
312 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
313 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
314 "smb_raw_changenotify_recv");
315 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
316 0, ret
, done
, "no changes expected");
319 smb_raw_exit(cli
->session
);
320 smbcli_deltree(cli
->tree
, BASEDIR
);
325 * Check notify reply for a rename action. Not sure if this is a valid thing
326 * to do, but depending on timing between inotify and messaging we get the
327 * add/remove/modify in any order. This routines tries to find the action/name
328 * pair in any of the three following notify_changes.
331 static bool check_rename_reply(struct torture_context
*tctx
,
332 struct smbcli_state
*cli
,
334 struct notify_changes
*actions
,
335 uint32_t action
, const char *name
)
339 for (i
=0; i
<3; i
++) {
340 if (actions
[i
].action
== action
) {
341 CHECK_WSTR(tctx
, actions
[i
].name
, name
, STR_UNICODE
);
346 torture_result(tctx
, TORTURE_FAIL
,
347 __location__
": (%d) expected action %d, not found\n",
353 testing of recursive change notify
355 static bool test_notify_recursive(struct torture_context
*tctx
,
356 struct smbcli_state
*cli
,
357 struct smbcli_state
*cli2
)
361 union smb_notify notify
;
364 struct smbcli_request
*req1
, *req2
;
366 torture_comment(tctx
, "TESTING CHANGE NOTIFY WITH RECURSION\n");
368 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
),
369 "Failed to setup up test directory: " BASEDIR
);
372 get a handle on the directory
374 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
375 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
376 io
.ntcreatex
.in
.flags
= 0;
377 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
378 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
379 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
380 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
381 io
.ntcreatex
.in
.alloc_size
= 0;
382 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
383 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
384 io
.ntcreatex
.in
.security_flags
= 0;
385 io
.ntcreatex
.in
.fname
= BASEDIR
;
387 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
388 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
390 fnum
= io
.ntcreatex
.out
.file
.fnum
;
392 /* ask for a change notify, on file or directory name
393 changes. Setup both with and without recursion */
394 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
395 notify
.nttrans
.in
.buffer_size
= 1000;
396 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
| FILE_NOTIFY_CHANGE_ATTRIBUTES
| FILE_NOTIFY_CHANGE_CREATION
;
397 notify
.nttrans
.in
.file
.fnum
= fnum
;
399 notify
.nttrans
.in
.recursive
= true;
400 req1
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
402 notify
.nttrans
.in
.recursive
= false;
403 req2
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
405 /* cancel initial requests so the buffer is setup */
406 smb_raw_ntcancel(req1
);
407 status
= smb_raw_changenotify_recv(req1
, tctx
, ¬ify
);
408 torture_assert_ntstatus_equal_goto(tctx
, status
,
411 "smb_raw_changenotify_recv");
413 smb_raw_ntcancel(req2
);
414 status
= smb_raw_changenotify_recv(req2
, tctx
, ¬ify
);
415 torture_assert_ntstatus_equal_goto(tctx
, status
,
418 "smb_raw_changenotify_recv");
421 * Make notifies a bit more interesting in a cluster by doing
422 * the changes against different nodes with --unclist
424 smbcli_mkdir(cli
->tree
, BASEDIR
"\\subdir-name");
425 smbcli_mkdir(cli2
->tree
, BASEDIR
"\\subdir-name\\subname1");
426 smbcli_close(cli
->tree
,
427 smbcli_open(cli
->tree
, BASEDIR
"\\subdir-name\\subname2", O_CREAT
, 0));
428 smbcli_rename(cli2
->tree
, BASEDIR
"\\subdir-name\\subname1",
429 BASEDIR
"\\subdir-name\\subname1-r");
430 smbcli_rename(cli
->tree
, BASEDIR
"\\subdir-name\\subname2", BASEDIR
"\\subname2-r");
431 smbcli_rename(cli2
->tree
, BASEDIR
"\\subname2-r",
432 BASEDIR
"\\subname3-r");
434 notify
.nttrans
.in
.completion_filter
= 0;
435 notify
.nttrans
.in
.recursive
= true;
437 req1
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
439 smbcli_rmdir(cli
->tree
, BASEDIR
"\\subdir-name\\subname1-r");
440 smbcli_rmdir(cli2
->tree
, BASEDIR
"\\subdir-name");
441 smbcli_unlink(cli
->tree
, BASEDIR
"\\subname3-r");
444 notify
.nttrans
.in
.recursive
= false;
445 req2
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
447 status
= smb_raw_changenotify_recv(req1
, tctx
, ¬ify
);
448 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
449 "smb_raw_changenotify_recv");
451 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
452 11, ret
, done
, "wrong number of changes");
453 torture_assert_int_equal_goto(tctx
,
454 notify
.nttrans
.out
.changes
[0].action
,
455 NOTIFY_ACTION_ADDED
, ret
, done
,
456 "wrong action (exp: ADDED)");
457 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subdir-name",
459 torture_assert_int_equal_goto(tctx
,
460 notify
.nttrans
.out
.changes
[1].action
,
461 NOTIFY_ACTION_ADDED
, ret
, done
,
462 "wrong action (exp: ADDED)");
463 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[1].name
,
464 "subdir-name\\subname1", STR_UNICODE
);
465 torture_assert_int_equal_goto(tctx
,
466 notify
.nttrans
.out
.changes
[2].action
,
467 NOTIFY_ACTION_ADDED
, ret
, done
,
468 "wrong action (exp: ADDED)");
469 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[2].name
,
470 "subdir-name\\subname2", STR_UNICODE
);
471 torture_assert_int_equal_goto(tctx
,
472 notify
.nttrans
.out
.changes
[3].action
,
473 NOTIFY_ACTION_OLD_NAME
, ret
, done
,
474 "wrong action (exp: OLD_NAME)");
475 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[3].name
,
476 "subdir-name\\subname1", STR_UNICODE
);
477 torture_assert_int_equal_goto(tctx
,
478 notify
.nttrans
.out
.changes
[4].action
,
479 NOTIFY_ACTION_NEW_NAME
, ret
, done
,
480 "wrong action (exp: NEW_NAME)");
481 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[4].name
,
482 "subdir-name\\subname1-r", STR_UNICODE
);
484 ret
&= check_rename_reply(tctx
,
485 cli
, __LINE__
, ¬ify
.nttrans
.out
.changes
[5],
486 NOTIFY_ACTION_ADDED
, "subname2-r");
487 ret
&= check_rename_reply(tctx
,
488 cli
, __LINE__
, ¬ify
.nttrans
.out
.changes
[5],
489 NOTIFY_ACTION_REMOVED
, "subdir-name\\subname2");
490 ret
&= check_rename_reply(tctx
,
491 cli
, __LINE__
, ¬ify
.nttrans
.out
.changes
[5],
492 NOTIFY_ACTION_MODIFIED
, "subname2-r");
494 ret
&= check_rename_reply(tctx
,
495 cli
, __LINE__
, ¬ify
.nttrans
.out
.changes
[8],
496 NOTIFY_ACTION_OLD_NAME
, "subname2-r");
497 ret
&= check_rename_reply(tctx
,
498 cli
, __LINE__
, ¬ify
.nttrans
.out
.changes
[8],
499 NOTIFY_ACTION_NEW_NAME
, "subname3-r");
500 ret
&= check_rename_reply(tctx
,
501 cli
, __LINE__
, ¬ify
.nttrans
.out
.changes
[8],
502 NOTIFY_ACTION_MODIFIED
, "subname3-r");
508 status
= smb_raw_changenotify_recv(req2
, tctx
, ¬ify
);
509 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
510 "smb_raw_changenotify_recv");
512 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
513 3, ret
, done
, "wrong number of changes");
514 torture_assert_int_equal_goto(tctx
,
515 notify
.nttrans
.out
.changes
[0].action
,
516 NOTIFY_ACTION_REMOVED
, ret
, done
,
517 "wrong action (exp: REMOVED)");
518 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
,
519 "subdir-name\\subname1-r", STR_UNICODE
);
520 torture_assert_int_equal_goto(tctx
,
521 notify
.nttrans
.out
.changes
[1].action
,
522 NOTIFY_ACTION_REMOVED
, ret
, done
,
523 "wrong action (exp: REMOVED)");
524 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[1].name
, "subdir-name",
526 torture_assert_int_equal_goto(tctx
,
527 notify
.nttrans
.out
.changes
[2].action
,
528 NOTIFY_ACTION_REMOVED
, ret
, done
,
529 "wrong action (exp: REMOVED)");
530 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[2].name
, "subname3-r",
534 smb_raw_exit(cli
->session
);
535 smbcli_deltree(cli
->tree
, BASEDIR
);
540 testing of change notify mask change
542 static bool test_notify_mask_change(struct torture_context
*tctx
,
543 struct smbcli_state
*cli
)
547 union smb_notify notify
;
550 struct smbcli_request
*req1
, *req2
;
552 torture_comment(tctx
, "TESTING CHANGE NOTIFY WITH MASK CHANGE\n");
554 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
),
555 "Failed to setup up test directory: " BASEDIR
);
558 get a handle on the directory
560 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
561 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
562 io
.ntcreatex
.in
.flags
= 0;
563 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
564 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
565 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
566 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
567 io
.ntcreatex
.in
.alloc_size
= 0;
568 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
569 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
570 io
.ntcreatex
.in
.security_flags
= 0;
571 io
.ntcreatex
.in
.fname
= BASEDIR
;
573 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
574 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
576 fnum
= io
.ntcreatex
.out
.file
.fnum
;
578 /* ask for a change notify, on file or directory name
579 changes. Setup both with and without recursion */
580 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
581 notify
.nttrans
.in
.buffer_size
= 1000;
582 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ATTRIBUTES
;
583 notify
.nttrans
.in
.file
.fnum
= fnum
;
585 notify
.nttrans
.in
.recursive
= true;
586 req1
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
588 notify
.nttrans
.in
.recursive
= false;
589 req2
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
591 /* cancel initial requests so the buffer is setup */
592 smb_raw_ntcancel(req1
);
593 status
= smb_raw_changenotify_recv(req1
, tctx
, ¬ify
);
594 torture_assert_ntstatus_equal_goto(tctx
, status
,
597 "smb_raw_changenotify_recv");
599 smb_raw_ntcancel(req2
);
600 status
= smb_raw_changenotify_recv(req2
, tctx
, ¬ify
);
601 torture_assert_ntstatus_equal_goto(tctx
, status
,
604 "smb_raw_changenotify_recv");
606 notify
.nttrans
.in
.recursive
= true;
607 req1
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
609 /* Set to hidden then back again. */
610 smbcli_close(cli
->tree
, smbcli_open(cli
->tree
, BASEDIR
"\\tname1", O_CREAT
, 0));
611 smbcli_setatr(cli
->tree
, BASEDIR
"\\tname1", FILE_ATTRIBUTE_HIDDEN
, 0);
612 smbcli_unlink(cli
->tree
, BASEDIR
"\\tname1");
614 status
= smb_raw_changenotify_recv(req1
, tctx
, ¬ify
);
615 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
616 "smb_raw_changenotify_recv");
618 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
619 1, ret
, done
, "wrong number of changes");
620 torture_assert_int_equal_goto(tctx
,
621 notify
.nttrans
.out
.changes
[0].action
,
622 NOTIFY_ACTION_MODIFIED
, ret
, done
,
623 "wrong action (exp: MODIFIED)");
624 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "tname1",
627 /* Now try and change the mask to include other events.
628 * This should not work - once the mask is set on a directory
629 * fnum it seems to be fixed until the fnum is closed. */
631 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
| FILE_NOTIFY_CHANGE_ATTRIBUTES
| FILE_NOTIFY_CHANGE_CREATION
;
632 notify
.nttrans
.in
.recursive
= true;
633 req1
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
635 notify
.nttrans
.in
.recursive
= false;
636 req2
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
638 smbcli_mkdir(cli
->tree
, BASEDIR
"\\subdir-name");
639 smbcli_mkdir(cli
->tree
, BASEDIR
"\\subdir-name\\subname1");
640 smbcli_close(cli
->tree
,
641 smbcli_open(cli
->tree
, BASEDIR
"\\subdir-name\\subname2", O_CREAT
, 0));
642 smbcli_rename(cli
->tree
, BASEDIR
"\\subdir-name\\subname1", BASEDIR
"\\subdir-name\\subname1-r");
643 smbcli_rename(cli
->tree
, BASEDIR
"\\subdir-name\\subname2", BASEDIR
"\\subname2-r");
644 smbcli_rename(cli
->tree
, BASEDIR
"\\subname2-r", BASEDIR
"\\subname3-r");
646 smbcli_rmdir(cli
->tree
, BASEDIR
"\\subdir-name\\subname1-r");
647 smbcli_rmdir(cli
->tree
, BASEDIR
"\\subdir-name");
648 smbcli_unlink(cli
->tree
, BASEDIR
"\\subname3-r");
650 status
= smb_raw_changenotify_recv(req1
, tctx
, ¬ify
);
651 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
652 "smb_raw_changenotify_recv");
654 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
655 1, ret
, done
, "wrong number of changes");
656 torture_assert_int_equal_goto(tctx
,
657 notify
.nttrans
.out
.changes
[0].action
,
658 NOTIFY_ACTION_MODIFIED
, ret
, done
,
659 "wrong action (exp: MODIFIED)");
660 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subname2-r",
663 status
= smb_raw_changenotify_recv(req2
, tctx
, ¬ify
);
664 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
665 "smb_raw_changenotify_recv");
667 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
668 1, ret
, done
, "wrong number of changes");
669 torture_assert_int_equal_goto(tctx
,
670 notify
.nttrans
.out
.changes
[0].action
,
671 NOTIFY_ACTION_MODIFIED
, ret
, done
,
672 "wrong action (exp: MODIFIED)");
673 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subname3-r",
677 smb_raw_exit(cli
->session
);
678 smbcli_deltree(cli
->tree
, BASEDIR
);
684 testing of mask bits for change notify
686 static bool test_notify_mask(struct torture_context
*tctx
,
687 struct smbcli_state
*cli
,
688 struct smbcli_state
*cli2
)
692 union smb_notify notify
;
694 union smb_chkpath chkpath
;
702 torture_comment(tctx
, "TESTING CHANGE NOTIFY COMPLETION FILTERS\n");
704 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
),
705 "Failed to setup up test directory: " BASEDIR
);
707 tv
= timeval_current_ofs(1000, 0);
708 t
= timeval_to_nttime(&tv
);
711 get a handle on the directory
713 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
714 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
715 io
.ntcreatex
.in
.flags
= 0;
716 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
717 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
718 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
719 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
720 io
.ntcreatex
.in
.alloc_size
= 0;
721 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
722 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
723 io
.ntcreatex
.in
.security_flags
= 0;
724 io
.ntcreatex
.in
.fname
= BASEDIR
;
726 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
727 notify
.nttrans
.in
.buffer_size
= 1000;
728 notify
.nttrans
.in
.recursive
= true;
730 chkpath
.chkpath
.in
.path
= "\\";
732 #define NOTIFY_MASK_TEST(test_name, setup, op, cleanup, Action, expected, nchanges) \
734 smbcli_getatr(cli->tree, test_name, NULL, NULL, NULL); \
735 for (mask=i=0;i<32;i++) { \
736 struct smbcli_request *req; \
737 status = smb_raw_open(cli->tree, tctx, &io); \
738 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, \
740 fnum = io.ntcreatex.out.file.fnum; \
742 notify.nttrans.in.file.fnum = fnum; \
743 notify.nttrans.in.completion_filter = (1<<i); \
744 req = smb_raw_changenotify_send(cli->tree, ¬ify); \
745 smb_raw_chkpath(cli->tree, &chkpath); \
747 smb_msleep(200); smb_raw_ntcancel(req); \
748 status = smb_raw_changenotify_recv(req, tctx, ¬ify); \
750 smbcli_close(cli->tree, fnum); \
751 if (NT_STATUS_EQUAL(status, NT_STATUS_CANCELLED)) continue; \
752 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, \
754 /* special case to cope with file rename behaviour */ \
755 if (nchanges == 2 && notify.nttrans.out.num_changes == 1 && \
756 notify.nttrans.out.changes[0].action == NOTIFY_ACTION_MODIFIED && \
757 ((expected) & FILE_NOTIFY_CHANGE_ATTRIBUTES) && \
758 Action == NOTIFY_ACTION_OLD_NAME) { \
759 torture_comment(tctx, "(rename file special handling OK)\n"); \
761 torture_assert_int_equal_goto(tctx, \
762 notify.nttrans.out.num_changes,\
763 nchanges, ret, done, \
764 talloc_asprintf(tctx, \
765 "nchanges=%d expected=%d action=%d " \
767 notify.nttrans.out.num_changes, \
769 notify.nttrans.out.changes[0].action, \
770 notify.nttrans.in.completion_filter)); \
771 torture_assert_int_equal_goto(tctx, \
772 notify.nttrans.out.changes[0].action, \
774 talloc_asprintf(tctx, \
775 "nchanges=%d action=%d " \
776 "expectedAction=%d filter=0x%08x\n", \
777 notify.nttrans.out.num_changes, \
778 notify.nttrans.out.changes[0].action, \
780 notify.nttrans.in.completion_filter)); \
781 torture_assert_str_equal_goto(tctx, \
782 notify.nttrans.out.changes[0].name.s, \
783 "tname1", ret, done, \
784 talloc_asprintf(tctx, \
785 "nchanges=%d action=%d filter=0x%08x " \
786 "name=%s expected_name=tname1\n", \
787 notify.nttrans.out.num_changes, \
788 notify.nttrans.out.changes[0].action, \
789 notify.nttrans.in.completion_filter, \
790 notify.nttrans.out.changes[0].name.s));\
794 if ((expected) != mask) { \
795 torture_assert_int_not_equal_goto(tctx, ((expected) & ~mask), \
796 0, ret, done, "Too few bits"); \
797 torture_comment(tctx, "WARNING: trigger on too many bits. mask=0x%08x expected=0x%08x\n", \
802 torture_comment(tctx
, "Testing mkdir\n");
803 NOTIFY_MASK_TEST("Testing mkdir",;,
804 smbcli_mkdir(cli
->tree
, BASEDIR
"\\tname1");,
805 smbcli_rmdir(cli2
->tree
, BASEDIR
"\\tname1");,
807 FILE_NOTIFY_CHANGE_DIR_NAME
, 1);
809 torture_comment(tctx
, "Testing create file\n");
810 NOTIFY_MASK_TEST("Testing create file",;,
811 smbcli_close(cli
->tree
, smbcli_open(cli
->tree
, BASEDIR
"\\tname1", O_CREAT
, 0));,
812 smbcli_unlink(cli2
->tree
, BASEDIR
"\\tname1");,
814 FILE_NOTIFY_CHANGE_FILE_NAME
, 1);
816 torture_comment(tctx
, "Testing unlink\n");
817 NOTIFY_MASK_TEST("Testing unlink",
818 smbcli_close(cli
->tree
, smbcli_open(cli
->tree
, BASEDIR
"\\tname1", O_CREAT
, 0));,
819 smbcli_unlink(cli2
->tree
, BASEDIR
"\\tname1");,
821 NOTIFY_ACTION_REMOVED
,
822 FILE_NOTIFY_CHANGE_FILE_NAME
, 1);
824 torture_comment(tctx
, "Testing rmdir\n");
825 NOTIFY_MASK_TEST("Testing rmdir",
826 smbcli_mkdir(cli
->tree
, BASEDIR
"\\tname1");,
827 smbcli_rmdir(cli2
->tree
, BASEDIR
"\\tname1");,
829 NOTIFY_ACTION_REMOVED
,
830 FILE_NOTIFY_CHANGE_DIR_NAME
, 1);
832 torture_comment(tctx
, "Testing rename file\n");
833 NOTIFY_MASK_TEST("Testing rename file",
834 smbcli_close(cli
->tree
, smbcli_open(cli
->tree
, BASEDIR
"\\tname1", O_CREAT
, 0));,
835 smbcli_rename(cli2
->tree
, BASEDIR
"\\tname1", BASEDIR
"\\tname2");,
836 smbcli_unlink(cli
->tree
, BASEDIR
"\\tname2");,
837 NOTIFY_ACTION_OLD_NAME
,
838 FILE_NOTIFY_CHANGE_FILE_NAME
|FILE_NOTIFY_CHANGE_ATTRIBUTES
|FILE_NOTIFY_CHANGE_CREATION
, 2);
840 torture_comment(tctx
, "Testing rename dir\n");
841 NOTIFY_MASK_TEST("Testing rename dir",
842 smbcli_mkdir(cli
->tree
, BASEDIR
"\\tname1");,
843 smbcli_rename(cli2
->tree
, BASEDIR
"\\tname1", BASEDIR
"\\tname2");,
844 smbcli_rmdir(cli
->tree
, BASEDIR
"\\tname2");,
845 NOTIFY_ACTION_OLD_NAME
,
846 FILE_NOTIFY_CHANGE_DIR_NAME
, 2);
848 torture_comment(tctx
, "Testing set path attribute\n");
849 NOTIFY_MASK_TEST("Testing set path attribute",
850 smbcli_close(cli
->tree
, smbcli_open(cli
->tree
, BASEDIR
"\\tname1", O_CREAT
, 0));,
851 smbcli_setatr(cli2
->tree
, BASEDIR
"\\tname1", FILE_ATTRIBUTE_HIDDEN
, 0);,
852 smbcli_unlink(cli
->tree
, BASEDIR
"\\tname1");,
853 NOTIFY_ACTION_MODIFIED
,
854 FILE_NOTIFY_CHANGE_ATTRIBUTES
, 1);
856 torture_comment(tctx
, "Testing set path write time\n");
857 NOTIFY_MASK_TEST("Testing set path write time",
858 smbcli_close(cli
->tree
, smbcli_open(cli
->tree
, BASEDIR
"\\tname1", O_CREAT
, 0));,
859 smbcli_setatr(cli2
->tree
, BASEDIR
"\\tname1", FILE_ATTRIBUTE_NORMAL
, 1000);,
860 smbcli_unlink(cli
->tree
, BASEDIR
"\\tname1");,
861 NOTIFY_ACTION_MODIFIED
,
862 FILE_NOTIFY_CHANGE_LAST_WRITE
, 1);
864 torture_comment(tctx
, "Testing set file attribute\n");
865 NOTIFY_MASK_TEST("Testing set file attribute",
866 fnum2
= create_complex_file(cli2
, tctx
, BASEDIR
"\\tname1");,
867 smbcli_fsetatr(cli2
->tree
, fnum2
, FILE_ATTRIBUTE_HIDDEN
, 0, 0, 0, 0);,
868 (smbcli_close(cli2
->tree
, fnum2
), smbcli_unlink(cli2
->tree
, BASEDIR
"\\tname1"));,
869 NOTIFY_ACTION_MODIFIED
,
870 FILE_NOTIFY_CHANGE_ATTRIBUTES
, 1);
872 if (torture_setting_bool(tctx
, "samba3", false)) {
873 torture_comment(tctx
, "Samba3 does not yet support create times "
877 torture_comment(tctx
, "Testing set file create time\n");
878 NOTIFY_MASK_TEST("Testing set file create time",
879 fnum2
= create_complex_file(cli
, tctx
,
880 BASEDIR
"\\tname1");,
881 smbcli_fsetatr(cli
->tree
, fnum2
, 0, t
, 0, 0, 0);,
882 (smbcli_close(cli
->tree
, fnum2
),
883 smbcli_unlink(cli
->tree
, BASEDIR
"\\tname1"));,
884 NOTIFY_ACTION_MODIFIED
,
885 FILE_NOTIFY_CHANGE_CREATION
, 1);
888 torture_comment(tctx
, "Testing set file access time\n");
889 NOTIFY_MASK_TEST("Testing set file access time",
890 fnum2
= create_complex_file(cli
, tctx
, BASEDIR
"\\tname1");,
891 smbcli_fsetatr(cli
->tree
, fnum2
, 0, 0, t
, 0, 0);,
892 (smbcli_close(cli
->tree
, fnum2
), smbcli_unlink(cli
->tree
, BASEDIR
"\\tname1"));,
893 NOTIFY_ACTION_MODIFIED
,
894 FILE_NOTIFY_CHANGE_LAST_ACCESS
, 1);
896 torture_comment(tctx
, "Testing set file write time\n");
897 NOTIFY_MASK_TEST("Testing set file write time",
898 fnum2
= create_complex_file(cli
, tctx
, BASEDIR
"\\tname1");,
899 smbcli_fsetatr(cli
->tree
, fnum2
, 0, 0, 0, t
, 0);,
900 (smbcli_close(cli
->tree
, fnum2
), smbcli_unlink(cli
->tree
, BASEDIR
"\\tname1"));,
901 NOTIFY_ACTION_MODIFIED
,
902 FILE_NOTIFY_CHANGE_LAST_WRITE
, 1);
904 torture_comment(tctx
, "Testing set file change time\n");
905 NOTIFY_MASK_TEST("Testing set file change time",
906 fnum2
= create_complex_file(cli
, tctx
, BASEDIR
"\\tname1");,
907 smbcli_fsetatr(cli
->tree
, fnum2
, 0, 0, 0, 0, t
);,
908 (smbcli_close(cli
->tree
, fnum2
), smbcli_unlink(cli
->tree
, BASEDIR
"\\tname1"));,
909 NOTIFY_ACTION_MODIFIED
,
913 torture_comment(tctx
, "Testing write\n");
914 NOTIFY_MASK_TEST("Testing write",
915 fnum2
= create_complex_file(cli2
, tctx
, BASEDIR
"\\tname1");,
916 smbcli_write(cli2
->tree
, fnum2
, 1, &c
, 10000, 1);,
917 (smbcli_close(cli2
->tree
, fnum2
), smbcli_unlink(cli
->tree
, BASEDIR
"\\tname1"));,
918 NOTIFY_ACTION_MODIFIED
,
921 torture_comment(tctx
, "Testing truncate\n");
922 NOTIFY_MASK_TEST("Testing truncate",
923 fnum2
= create_complex_file(cli2
, tctx
, BASEDIR
"\\tname1");,
924 smbcli_ftruncate(cli2
->tree
, fnum2
, 10000);,
925 (smbcli_close(cli2
->tree
, fnum2
), smbcli_unlink(cli2
->tree
, BASEDIR
"\\tname1"));,
926 NOTIFY_ACTION_MODIFIED
,
927 FILE_NOTIFY_CHANGE_SIZE
| FILE_NOTIFY_CHANGE_ATTRIBUTES
, 1);
930 smb_raw_exit(cli
->session
);
931 smbcli_deltree(cli
->tree
, BASEDIR
);
936 basic testing of change notify on files
938 static bool test_notify_file(struct torture_context
*tctx
,
939 struct smbcli_state
*cli
)
945 union smb_notify notify
;
946 struct smbcli_request
*req
;
948 const char *fname
= BASEDIR
"\\file.txt";
950 torture_comment(tctx
, "TESTING CHANGE NOTIFY ON FILES\n");
952 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
),
953 "Failed to setup up test directory: " BASEDIR
);
955 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
956 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
957 io
.ntcreatex
.in
.flags
= 0;
958 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
959 io
.ntcreatex
.in
.create_options
= 0;
960 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
961 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
962 io
.ntcreatex
.in
.alloc_size
= 0;
963 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
964 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
965 io
.ntcreatex
.in
.security_flags
= 0;
966 io
.ntcreatex
.in
.fname
= fname
;
967 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
968 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
970 fnum
= io
.ntcreatex
.out
.file
.fnum
;
972 /* ask for a change notify,
973 on file or directory name changes */
974 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
975 notify
.nttrans
.in
.file
.fnum
= fnum
;
976 notify
.nttrans
.in
.buffer_size
= 1000;
977 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_STREAM_NAME
;
978 notify
.nttrans
.in
.recursive
= false;
980 torture_comment(tctx
, "Testing if notifies on file handles are invalid (should be)\n");
982 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
983 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
984 torture_assert_ntstatus_equal_goto(tctx
, status
,
985 NT_STATUS_INVALID_PARAMETER
,
987 "smb_raw_changenotify_recv");
989 cl
.close
.level
= RAW_CLOSE_CLOSE
;
990 cl
.close
.in
.file
.fnum
= fnum
;
991 cl
.close
.in
.write_time
= 0;
992 status
= smb_raw_close(cli
->tree
, &cl
);
993 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
996 status
= smbcli_unlink(cli
->tree
, fname
);
997 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1001 smb_raw_exit(cli
->session
);
1002 smbcli_deltree(cli
->tree
, BASEDIR
);
1007 basic testing of change notifies followed by a tdis
1009 static bool test_notify_tdis(struct torture_context
*tctx
,
1010 struct smbcli_state
*cli1
)
1014 union smb_notify notify
;
1017 struct smbcli_request
*req
;
1018 struct smbcli_state
*cli
= NULL
;
1020 torture_comment(tctx
, "TESTING CHANGE NOTIFY FOLLOWED BY TDIS\n");
1022 torture_assert(tctx
, torture_setup_dir(cli1
, BASEDIR
),
1023 "Failed to setup up test directory: " BASEDIR
);
1025 torture_assert(tctx
, torture_open_connection(&cli
, tctx
, 0),
1026 "Failed to open connection.");
1029 get a handle on the directory
1031 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1032 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1033 io
.ntcreatex
.in
.flags
= 0;
1034 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
1035 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1036 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1037 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1038 io
.ntcreatex
.in
.alloc_size
= 0;
1039 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1040 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1041 io
.ntcreatex
.in
.security_flags
= 0;
1042 io
.ntcreatex
.in
.fname
= BASEDIR
;
1044 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1045 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1047 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1049 /* ask for a change notify,
1050 on file or directory name changes */
1051 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
1052 notify
.nttrans
.in
.buffer_size
= 1000;
1053 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1054 notify
.nttrans
.in
.file
.fnum
= fnum
;
1055 notify
.nttrans
.in
.recursive
= true;
1057 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1059 status
= smbcli_tdis(cli
);
1060 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1064 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1065 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1066 "smb_raw_changenotify_recv");
1067 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
1068 0, ret
, done
, "no changes expected");
1071 torture_close_connection(cli
);
1072 smbcli_deltree(cli1
->tree
, BASEDIR
);
1077 basic testing of change notifies followed by a exit
1079 static bool test_notify_exit(struct torture_context
*tctx
,
1080 struct smbcli_state
*cli1
)
1084 union smb_notify notify
;
1087 struct smbcli_request
*req
;
1088 struct smbcli_state
*cli
= NULL
;
1090 torture_comment(tctx
, "TESTING CHANGE NOTIFY FOLLOWED BY EXIT\n");
1092 torture_assert(tctx
, torture_setup_dir(cli1
, BASEDIR
),
1093 "Failed to setup up test directory: " BASEDIR
);
1095 torture_assert(tctx
, torture_open_connection(&cli
, tctx
, 0),
1096 "Failed to open connection.");
1099 get a handle on the directory
1101 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1102 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1103 io
.ntcreatex
.in
.flags
= 0;
1104 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
1105 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1106 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1107 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1108 io
.ntcreatex
.in
.alloc_size
= 0;
1109 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1110 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1111 io
.ntcreatex
.in
.security_flags
= 0;
1112 io
.ntcreatex
.in
.fname
= BASEDIR
;
1114 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1115 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1117 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1119 /* ask for a change notify,
1120 on file or directory name changes */
1121 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
1122 notify
.nttrans
.in
.buffer_size
= 1000;
1123 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1124 notify
.nttrans
.in
.file
.fnum
= fnum
;
1125 notify
.nttrans
.in
.recursive
= true;
1127 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1129 status
= smb_raw_exit(cli
->session
);
1130 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1133 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1134 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1135 "smb_raw_changenotify_recv");
1136 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
1137 0, ret
, done
, "no changes expected");
1140 torture_close_connection(cli
);
1141 smbcli_deltree(cli1
->tree
, BASEDIR
);
1146 basic testing of change notifies followed by a ulogoff
1148 static bool test_notify_ulogoff(struct torture_context
*tctx
,
1149 struct smbcli_state
*cli1
)
1153 union smb_notify notify
;
1156 struct smbcli_request
*req
;
1157 struct smbcli_state
*cli
= NULL
;
1159 torture_comment(tctx
, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
1161 torture_assert(tctx
, torture_setup_dir(cli1
, BASEDIR
),
1162 "Failed to setup up test directory: " BASEDIR
);
1164 torture_assert(tctx
, torture_open_connection(&cli
, tctx
, 0),
1165 "Failed to open connection.");
1168 get a handle on the directory
1170 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1171 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1172 io
.ntcreatex
.in
.flags
= 0;
1173 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
1174 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1175 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1176 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1177 io
.ntcreatex
.in
.alloc_size
= 0;
1178 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1179 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1180 io
.ntcreatex
.in
.security_flags
= 0;
1181 io
.ntcreatex
.in
.fname
= BASEDIR
;
1183 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1184 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1186 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1188 /* ask for a change notify,
1189 on file or directory name changes */
1190 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
1191 notify
.nttrans
.in
.buffer_size
= 1000;
1192 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1193 notify
.nttrans
.in
.file
.fnum
= fnum
;
1194 notify
.nttrans
.in
.recursive
= true;
1196 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1198 status
= smb_raw_ulogoff(cli
->session
);
1199 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1202 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1203 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1204 "smb_raw_changenotify_recv");
1205 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
1206 0, ret
, done
, "no changes expected");
1209 torture_close_connection(cli
);
1210 smbcli_deltree(cli1
->tree
, BASEDIR
);
1214 static void tcp_dis_handler(struct smbcli_transport
*t
, void *p
)
1216 struct smbcli_state
*cli
= (struct smbcli_state
*)p
;
1217 smbcli_transport_dead(cli
->transport
, NT_STATUS_LOCAL_DISCONNECT
);
1218 cli
->transport
= NULL
;
1222 basic testing of change notifies followed by tcp disconnect
1224 static bool test_notify_tcp_dis(struct torture_context
*tctx
,
1225 struct smbcli_state
*cli1
)
1229 union smb_notify notify
;
1232 struct smbcli_request
*req
;
1233 struct smbcli_state
*cli
= NULL
;
1235 torture_comment(tctx
, "TESTING CHANGE NOTIFY FOLLOWED BY TCP DISCONNECT\n");
1237 torture_assert(tctx
, torture_setup_dir(cli1
, BASEDIR
),
1238 "Failed to setup up test directory: " BASEDIR
);
1240 torture_assert(tctx
, torture_open_connection(&cli
, tctx
, 0),
1241 "Failed to open connection.");
1244 get a handle on the directory
1246 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1247 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1248 io
.ntcreatex
.in
.flags
= 0;
1249 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
1250 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1251 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1252 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1253 io
.ntcreatex
.in
.alloc_size
= 0;
1254 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1255 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1256 io
.ntcreatex
.in
.security_flags
= 0;
1257 io
.ntcreatex
.in
.fname
= BASEDIR
;
1259 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1260 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1262 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1264 /* ask for a change notify,
1265 on file or directory name changes */
1266 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
1267 notify
.nttrans
.in
.buffer_size
= 1000;
1268 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1269 notify
.nttrans
.in
.file
.fnum
= fnum
;
1270 notify
.nttrans
.in
.recursive
= true;
1272 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1274 smbcli_transport_idle_handler(cli
->transport
, tcp_dis_handler
, 250, cli
);
1276 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1277 torture_assert_ntstatus_equal_goto(tctx
, status
,
1278 NT_STATUS_LOCAL_DISCONNECT
,
1280 "smb_raw_changenotify_recv");
1283 torture_close_connection(cli
);
1284 smbcli_deltree(cli1
->tree
, BASEDIR
);
1289 test setting up two change notify requests on one handle
1291 static bool test_notify_double(struct torture_context
*tctx
,
1292 struct smbcli_state
*cli
)
1296 union smb_notify notify
;
1299 struct smbcli_request
*req1
, *req2
;
1301 torture_comment(tctx
, "TESTING CHANGE NOTIFY TWICE ON ONE DIRECTORY\n");
1303 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
),
1304 "Failed to setup up test directory: " BASEDIR
);
1307 get a handle on the directory
1309 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1310 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1311 io
.ntcreatex
.in
.flags
= 0;
1312 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
1313 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1314 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1315 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1316 io
.ntcreatex
.in
.alloc_size
= 0;
1317 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1318 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1319 io
.ntcreatex
.in
.security_flags
= 0;
1320 io
.ntcreatex
.in
.fname
= BASEDIR
;
1322 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1323 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1325 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1327 /* ask for a change notify,
1328 on file or directory name changes */
1329 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
1330 notify
.nttrans
.in
.buffer_size
= 1000;
1331 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1332 notify
.nttrans
.in
.file
.fnum
= fnum
;
1333 notify
.nttrans
.in
.recursive
= true;
1335 req1
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1336 req2
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1338 smbcli_mkdir(cli
->tree
, BASEDIR
"\\subdir-name");
1340 status
= smb_raw_changenotify_recv(req1
, tctx
, ¬ify
);
1341 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1342 "smb_raw_changenotify_recv");
1343 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
1344 1, ret
, done
, "wrong number of changes");
1345 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subdir-name",
1348 smbcli_mkdir(cli
->tree
, BASEDIR
"\\subdir-name2");
1350 status
= smb_raw_changenotify_recv(req2
, tctx
, ¬ify
);
1351 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1352 "smb_raw_changenotify_recv");
1353 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
1354 1, ret
, done
, "wrong number of changes");
1355 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subdir-name2",
1359 smb_raw_exit(cli
->session
);
1360 smbcli_deltree(cli
->tree
, BASEDIR
);
1366 test multiple change notifies at different depths and with/without recursion
1368 static bool test_notify_tree(struct torture_context
*tctx
,
1369 struct smbcli_state
*cli
,
1370 struct smbcli_state
*cli2
)
1373 union smb_notify notify
;
1375 struct smbcli_request
*req
;
1385 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 30 },
1386 {BASEDIR
"\\zqy", true, FILE_NOTIFY_CHANGE_NAME
, 8 },
1387 {BASEDIR
"\\atsy", true, FILE_NOTIFY_CHANGE_NAME
, 4 },
1388 {BASEDIR
"\\abc\\foo", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1389 {BASEDIR
"\\abc\\blah", true, FILE_NOTIFY_CHANGE_NAME
, 13 },
1390 {BASEDIR
"\\abc\\blah", false, FILE_NOTIFY_CHANGE_NAME
, 7 },
1391 {BASEDIR
"\\abc\\blah\\a", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1392 {BASEDIR
"\\abc\\blah\\b", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1393 {BASEDIR
"\\abc\\blah\\c", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1394 {BASEDIR
"\\abc\\fooblah", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1395 {BASEDIR
"\\zqy\\xx", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1396 {BASEDIR
"\\zqy\\yyy", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1397 {BASEDIR
"\\zqy\\..", true, FILE_NOTIFY_CHANGE_NAME
, 40 },
1398 {BASEDIR
, true, FILE_NOTIFY_CHANGE_NAME
, 40 },
1399 {BASEDIR
, false,FILE_NOTIFY_CHANGE_NAME
, 6 },
1400 {BASEDIR
"\\atsy", false,FILE_NOTIFY_CHANGE_NAME
, 4 },
1401 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 24 },
1402 {BASEDIR
"\\abc", false,FILE_NOTIFY_CHANGE_FILE_NAME
, 0 },
1403 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_FILE_NAME
, 0 },
1404 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 24 },
1408 bool all_done
= false;
1410 torture_comment(tctx
, "TESTING CHANGE NOTIFY FOR DIFFERENT DEPTHS\n");
1412 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
),
1413 "Failed to setup up test directory: " BASEDIR
);
1415 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1416 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1417 io
.ntcreatex
.in
.flags
= 0;
1418 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
1419 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1420 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1421 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1422 io
.ntcreatex
.in
.alloc_size
= 0;
1423 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1424 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1425 io
.ntcreatex
.in
.security_flags
= 0;
1427 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
1428 notify
.nttrans
.in
.buffer_size
= 20000;
1431 setup the directory tree, and the notify buffer on each directory
1433 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1434 io
.ntcreatex
.in
.fname
= dirs
[i
].path
;
1435 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1436 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1438 dirs
[i
].fnum
= io
.ntcreatex
.out
.file
.fnum
;
1440 notify
.nttrans
.in
.completion_filter
= dirs
[i
].filter
;
1441 notify
.nttrans
.in
.file
.fnum
= dirs
[i
].fnum
;
1442 notify
.nttrans
.in
.recursive
= dirs
[i
].recursive
;
1443 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1444 smb_raw_ntcancel(req
);
1445 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1446 torture_assert_ntstatus_equal_goto(tctx
, status
,
1447 NT_STATUS_CANCELLED
,
1449 "smb_raw_changenotify_recv");
1452 /* trigger 2 events in each dir */
1453 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1454 char *path
= talloc_asprintf(tctx
, "%s\\test.dir", dirs
[i
].path
);
1456 * Make notifies a bit more interesting in a cluster
1457 * by doing the changes against different nodes with
1460 smbcli_mkdir(cli
->tree
, path
);
1461 smbcli_rmdir(cli2
->tree
, path
);
1465 /* give a bit of time for the events to propogate */
1466 tv
= timeval_current();
1469 /* count events that have happened in each dir */
1470 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1471 notify
.nttrans
.in
.file
.fnum
= dirs
[i
].fnum
;
1472 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1473 smb_raw_ntcancel(req
);
1474 notify
.nttrans
.out
.num_changes
= 0;
1475 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1476 dirs
[i
].counted
+= notify
.nttrans
.out
.num_changes
;
1481 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1482 if (dirs
[i
].counted
!= dirs
[i
].expected
) {
1486 } while (!all_done
&& timeval_elapsed(&tv
) < 20);
1488 torture_comment(tctx
, "took %.4f seconds to propogate all events\n", timeval_elapsed(&tv
));
1490 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1491 torture_assert_int_equal_goto(tctx
,
1492 dirs
[i
].counted
, dirs
[i
].expected
, ret
, done
,
1493 talloc_asprintf(tctx
,
1494 "unexpected number of events for '%s'",
1499 run from the back, closing and deleting
1501 for (i
=ARRAY_SIZE(dirs
)-1;i
>=0;i
--) {
1502 smbcli_close(cli
->tree
, dirs
[i
].fnum
);
1503 smbcli_rmdir(cli
->tree
, dirs
[i
].path
);
1507 smb_raw_exit(cli
->session
);
1508 smbcli_deltree(cli
->tree
, BASEDIR
);
1513 Test response when cached server events exceed single NT NOTFIY response
1516 static bool test_notify_overflow(struct torture_context
*tctx
,
1517 struct smbcli_state
*cli
)
1521 union smb_notify notify
;
1525 struct smbcli_request
*req1
;
1528 torture_comment(tctx
, "TESTING CHANGE NOTIFY EVENT OVERFLOW\n");
1530 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
),
1531 "Failed to setup up test directory: " BASEDIR
);
1533 /* get a handle on the directory */
1534 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1535 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1536 io
.ntcreatex
.in
.flags
= 0;
1537 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
1538 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1539 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1540 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1541 NTCREATEX_SHARE_ACCESS_WRITE
;
1542 io
.ntcreatex
.in
.alloc_size
= 0;
1543 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1544 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1545 io
.ntcreatex
.in
.security_flags
= 0;
1546 io
.ntcreatex
.in
.fname
= BASEDIR
;
1548 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1549 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1551 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1553 /* ask for a change notify, on name changes. */
1554 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
1555 notify
.nttrans
.in
.buffer_size
= 1000;
1556 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1557 notify
.nttrans
.in
.file
.fnum
= fnum
;
1559 notify
.nttrans
.in
.recursive
= true;
1560 req1
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1562 /* cancel initial requests so the buffer is setup */
1563 smb_raw_ntcancel(req1
);
1564 status
= smb_raw_changenotify_recv(req1
, tctx
, ¬ify
);
1565 torture_assert_ntstatus_equal_goto(tctx
, status
,
1566 NT_STATUS_CANCELLED
,
1568 "smb_raw_changenotify_recv");
1570 /* open a lot of files, filling up the server side notify buffer */
1571 torture_comment(tctx
, "Testing overflowed buffer notify on create of %d files\n",
1573 for (i
=0;i
<count
;i
++) {
1574 char *fname
= talloc_asprintf(cli
, BASEDIR
"\\test%d.txt", i
);
1575 int fnum2
= smbcli_open(cli
->tree
, fname
, O_CREAT
|O_RDWR
,
1577 torture_assert_int_not_equal_goto(tctx
, fnum2
, -1, ret
, done
,
1578 talloc_asprintf(tctx
, "Failed to create %s - %s",
1579 fname
, smbcli_errstr(cli
->tree
)));
1581 smbcli_close(cli
->tree
, fnum2
);
1584 /* expect that 0 events will be returned with NT_STATUS_OK */
1585 req1
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1586 status
= smb_raw_changenotify_recv(req1
, tctx
, ¬ify
);
1587 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1588 "smb_raw_changenotify_recv");
1589 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
1590 0, ret
, done
, "no changes expected");
1593 smb_raw_exit(cli
->session
);
1594 smbcli_deltree(cli
->tree
, BASEDIR
);
1599 Test if notifications are returned for changes to the base directory.
1602 static bool test_notify_basedir(struct torture_context
*tctx
,
1603 struct smbcli_state
*cli
)
1607 union smb_notify notify
;
1610 struct smbcli_request
*req1
;
1612 torture_comment(tctx
, "TESTING CHANGE NOTIFY BASEDIR EVENTS\n");
1614 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
),
1615 "Failed to setup up test directory: " BASEDIR
);
1617 /* get a handle on the directory */
1618 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1619 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1620 io
.ntcreatex
.in
.flags
= 0;
1621 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
1622 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1623 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1624 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1625 NTCREATEX_SHARE_ACCESS_WRITE
;
1626 io
.ntcreatex
.in
.alloc_size
= 0;
1627 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1628 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1629 io
.ntcreatex
.in
.security_flags
= 0;
1630 io
.ntcreatex
.in
.fname
= BASEDIR
;
1632 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1633 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1635 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1637 /* create a test file that will also be modified */
1638 smbcli_close(cli
->tree
, smbcli_open(cli
->tree
, BASEDIR
"\\tname1",
1641 /* ask for a change notify, on attribute changes. */
1642 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
1643 notify
.nttrans
.in
.buffer_size
= 1000;
1644 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ATTRIBUTES
;
1645 notify
.nttrans
.in
.file
.fnum
= fnum
;
1646 notify
.nttrans
.in
.recursive
= true;
1648 req1
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1650 /* set attribute on the base dir */
1651 smbcli_setatr(cli
->tree
, BASEDIR
, FILE_ATTRIBUTE_HIDDEN
, 0);
1653 /* set attribute on a file to assure we receive a notification */
1654 smbcli_setatr(cli
->tree
, BASEDIR
"\\tname1", FILE_ATTRIBUTE_HIDDEN
, 0);
1657 /* check how many responses were given, expect only 1 for the file */
1658 status
= smb_raw_changenotify_recv(req1
, tctx
, ¬ify
);
1659 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1660 "smb_raw_changenotify_recv");
1661 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
1662 1, ret
, done
, "wrong number of changes");
1663 torture_assert_int_equal_goto(tctx
,
1664 notify
.nttrans
.out
.changes
[0].action
,
1665 NOTIFY_ACTION_MODIFIED
, ret
, done
,
1666 "wrong action (exp: MODIFIED)");
1667 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "tname1",
1671 smb_raw_exit(cli
->session
);
1672 smbcli_deltree(cli
->tree
, BASEDIR
);
1678 create a secondary tree connect - used to test for a bug in Samba3 messaging
1681 static struct smbcli_tree
*secondary_tcon(struct smbcli_state
*cli
,
1682 struct torture_context
*tctx
)
1685 const char *share
, *host
;
1686 struct smbcli_tree
*tree
;
1687 union smb_tcon tcon
;
1689 share
= torture_setting_string(tctx
, "share", NULL
);
1690 host
= torture_setting_string(tctx
, "host", NULL
);
1692 torture_comment(tctx
, "create a second tree context on the same session\n");
1693 tree
= smbcli_tree_init(cli
->session
, tctx
, false);
1695 tcon
.generic
.level
= RAW_TCON_TCONX
;
1696 tcon
.tconx
.in
.flags
= TCONX_FLAG_EXTENDED_RESPONSE
;
1697 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
1698 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
1699 tcon
.tconx
.in
.device
= "A:";
1700 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
1701 if (!NT_STATUS_IS_OK(status
)) {
1703 torture_comment(tctx
, "Failed to create secondary tree\n");
1707 tree
->tid
= tcon
.tconx
.out
.tid
;
1708 torture_comment(tctx
, "tid1=%d tid2=%d\n", cli
->tree
->tid
, tree
->tid
);
1715 very simple change notify test
1717 static bool test_notify_tcon(struct torture_context
*tctx
,
1718 struct smbcli_state
*cli
)
1722 union smb_notify notify
;
1725 struct smbcli_request
*req
;
1726 extern int torture_numops
;
1727 struct smbcli_tree
*tree
= NULL
;
1729 torture_comment(tctx
, "TESTING SIMPLE CHANGE NOTIFY\n");
1731 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
),
1732 "Failed to setup up test directory: " BASEDIR
);
1735 get a handle on the directory
1737 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1738 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1739 io
.ntcreatex
.in
.flags
= 0;
1740 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
1741 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1742 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1743 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1744 io
.ntcreatex
.in
.alloc_size
= 0;
1745 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1746 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1747 io
.ntcreatex
.in
.security_flags
= 0;
1748 io
.ntcreatex
.in
.fname
= BASEDIR
;
1750 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1751 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1753 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1755 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1756 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1759 /* ask for a change notify,
1760 on file or directory name changes */
1761 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
1762 notify
.nttrans
.in
.buffer_size
= 1000;
1763 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1764 notify
.nttrans
.in
.file
.fnum
= fnum
;
1765 notify
.nttrans
.in
.recursive
= true;
1767 torture_comment(tctx
, "Testing notify mkdir\n");
1768 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1769 smbcli_mkdir(cli
->tree
, BASEDIR
"\\subdir-name");
1771 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1772 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1773 "smb_raw_changenotify_recv");
1775 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
1776 1, ret
, done
, "wrong number of changes");
1777 torture_assert_int_equal_goto(tctx
,
1778 notify
.nttrans
.out
.changes
[0].action
,
1779 NOTIFY_ACTION_ADDED
, ret
, done
,
1780 "wrong action (exp: ADDED)");
1781 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subdir-name",
1784 torture_comment(tctx
, "Testing notify rmdir\n");
1785 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1786 smbcli_rmdir(cli
->tree
, BASEDIR
"\\subdir-name");
1788 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1789 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1790 "smb_raw_changenotify_recv");
1791 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
1792 1, ret
, done
, "wrong number of changes");
1793 torture_assert_int_equal_goto(tctx
,
1794 notify
.nttrans
.out
.changes
[0].action
,
1795 NOTIFY_ACTION_REMOVED
, ret
, done
,
1796 "wrong action (exp: REMOVED)");
1797 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subdir-name",
1800 torture_comment(tctx
, "SIMPLE CHANGE NOTIFY OK\n");
1802 torture_comment(tctx
, "TESTING WITH SECONDARY TCON\n");
1803 tree
= secondary_tcon(cli
, tctx
);
1804 torture_assert_not_null_goto(tctx
, tree
, ret
, done
,
1805 "failed to create secondary tcon");
1807 torture_comment(tctx
, "Testing notify mkdir\n");
1808 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1809 smbcli_mkdir(cli
->tree
, BASEDIR
"\\subdir-name");
1811 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1812 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1813 "smb_raw_changenotify_recv");
1815 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
1816 1, ret
, done
, "wrong number of changes");
1817 torture_assert_int_equal_goto(tctx
,
1818 notify
.nttrans
.out
.changes
[0].action
,
1819 NOTIFY_ACTION_ADDED
, ret
, done
,
1820 "wrong action (exp: ADDED)");
1821 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subdir-name",
1824 torture_comment(tctx
, "Testing notify rmdir\n");
1825 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1826 smbcli_rmdir(cli
->tree
, BASEDIR
"\\subdir-name");
1828 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1829 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1830 "smb_raw_changenotify_recv");
1831 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
1832 1, ret
, done
, "wrong number of changes");
1833 torture_assert_int_equal_goto(tctx
,
1834 notify
.nttrans
.out
.changes
[0].action
,
1835 NOTIFY_ACTION_REMOVED
, ret
, done
,
1836 "wrong action (exp: REMOVED)");
1837 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subdir-name",
1840 torture_comment(tctx
, "CHANGE NOTIFY WITH TCON OK\n");
1842 torture_comment(tctx
, "Disconnecting secondary tree\n");
1843 status
= smb_tree_disconnect(tree
);
1844 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1845 "smb_tree_disconnect");
1848 torture_comment(tctx
, "Testing notify mkdir\n");
1849 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1850 smbcli_mkdir(cli
->tree
, BASEDIR
"\\subdir-name");
1852 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1853 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1854 "smb_raw_changenotify_recv");
1856 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
1857 1, ret
, done
, "wrong number of changes");
1858 torture_assert_int_equal_goto(tctx
,
1859 notify
.nttrans
.out
.changes
[0].action
,
1860 NOTIFY_ACTION_ADDED
, ret
, done
,
1861 "wrong action (exp: ADDED)");
1862 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subdir-name",
1865 torture_comment(tctx
, "Testing notify rmdir\n");
1866 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1867 smbcli_rmdir(cli
->tree
, BASEDIR
"\\subdir-name");
1869 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1870 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
1871 "smb_raw_changenotify_recv");
1872 torture_assert_int_equal_goto(tctx
, notify
.nttrans
.out
.num_changes
,
1873 1, ret
, done
, "wrong number of changes");
1874 torture_assert_int_equal_goto(tctx
,
1875 notify
.nttrans
.out
.changes
[0].action
,
1876 NOTIFY_ACTION_REMOVED
, ret
, done
,
1877 "wrong action (exp: REMOVED)");
1878 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[0].name
, "subdir-name",
1881 torture_comment(tctx
, "CHANGE NOTIFY WITH TDIS OK\n");
1883 smb_raw_exit(cli
->session
);
1884 smbcli_deltree(cli
->tree
, BASEDIR
);
1890 testing alignment of multiple change notify infos
1892 static bool test_notify_alignment(struct torture_context
*tctx
,
1893 struct smbcli_state
*cli
)
1896 union smb_notify notify
;
1899 struct smbcli_request
*req
;
1900 const char *fname
= BASEDIR
"\\starter";
1901 const char *fnames
[] = { "a",
1905 int num_names
= ARRAY_SIZE(fnames
);
1908 torture_comment(tctx
, "TESTING CHANGE NOTIFY REPLY ALIGNMENT\n");
1910 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
),
1911 "Failed to setup up test directory: " BASEDIR
);
1913 /* get a handle on the directory */
1914 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1915 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1916 io
.ntcreatex
.in
.flags
= 0;
1917 io
.ntcreatex
.in
.access_mask
= SEC_FILE_ALL
;
1918 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1919 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1920 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1921 NTCREATEX_SHARE_ACCESS_WRITE
;
1922 io
.ntcreatex
.in
.alloc_size
= 0;
1923 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1924 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1925 io
.ntcreatex
.in
.security_flags
= 0;
1926 io
.ntcreatex
.in
.fname
= BASEDIR
;
1928 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1929 torture_assert_ntstatus_ok(tctx
, status
, "smb_raw_open");
1930 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1932 /* ask for a change notify, on file creation */
1933 notify
.nttrans
.level
= RAW_NOTIFY_NTTRANS
;
1934 notify
.nttrans
.in
.buffer_size
= 1000;
1935 notify
.nttrans
.in
.completion_filter
= FILE_NOTIFY_CHANGE_FILE_NAME
;
1936 notify
.nttrans
.in
.file
.fnum
= fnum
;
1937 notify
.nttrans
.in
.recursive
= false;
1939 /* start change tracking */
1940 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1942 fnum2
= smbcli_open(cli
->tree
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
);
1943 torture_assert(tctx
, fnum2
!= -1, smbcli_errstr(cli
->tree
));
1944 smbcli_close(cli
->tree
, fnum2
);
1946 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1947 torture_assert_ntstatus_ok(tctx
, status
, "smb_raw_changenotify_recv");
1949 /* create 4 files that will cause CHANGE_NOTIFY_INFO structures
1950 * to be returned in the same packet with all possible 4-byte padding
1951 * permutations. As per MS-CIFS 2.2.7.4.2 these structures should be
1952 * 4-byte aligned. */
1954 for (i
= 0; i
< num_names
; i
++) {
1955 fpath
= talloc_asprintf(tctx
, "%s\\%s", BASEDIR
, fnames
[i
]);
1956 fnum2
= smbcli_open(cli
->tree
, fpath
,
1957 O_CREAT
|O_RDWR
, DENY_NONE
);
1958 torture_assert(tctx
, fnum2
!= -1, smbcli_errstr(cli
->tree
));
1959 smbcli_close(cli
->tree
, fnum2
);
1963 /* We send a notify packet, and let smb_raw_changenotify_recv() do
1964 * the alignment checking for us. */
1965 req
= smb_raw_changenotify_send(cli
->tree
, ¬ify
);
1966 status
= smb_raw_changenotify_recv(req
, tctx
, ¬ify
);
1967 torture_assert_ntstatus_ok(tctx
, status
, "smb_raw_changenotify_recv");
1969 /* Do basic checking for correctness. */
1970 torture_assert(tctx
, notify
.nttrans
.out
.num_changes
== num_names
, "");
1971 for (i
= 0; i
< num_names
; i
++) {
1972 torture_assert(tctx
, notify
.nttrans
.out
.changes
[i
].action
==
1973 NOTIFY_ACTION_ADDED
, "");
1974 CHECK_WSTR(tctx
, notify
.nttrans
.out
.changes
[i
].name
, fnames
[i
],
1978 smb_raw_exit(cli
->session
);
1979 smbcli_deltree(cli
->tree
, BASEDIR
);
1983 struct torture_suite
*torture_raw_notify(TALLOC_CTX
*mem_ctx
)
1985 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "notify");
1987 torture_suite_add_1smb_test(suite
, "tcon", test_notify_tcon
);
1988 torture_suite_add_2smb_test(suite
, "dir", test_notify_dir
);
1989 torture_suite_add_2smb_test(suite
, "mask", test_notify_mask
);
1990 torture_suite_add_2smb_test(suite
, "recursive", test_notify_recursive
);
1991 torture_suite_add_1smb_test(suite
, "mask_change",
1992 test_notify_mask_change
);
1993 torture_suite_add_1smb_test(suite
, "file", test_notify_file
);
1994 torture_suite_add_1smb_test(suite
, "tdis", test_notify_tdis
);
1995 torture_suite_add_1smb_test(suite
, "exit", test_notify_exit
);
1996 torture_suite_add_1smb_test(suite
, "ulogoff", test_notify_ulogoff
);
1997 torture_suite_add_1smb_test(suite
, "tcp_dis", test_notify_tcp_dis
);
1998 torture_suite_add_1smb_test(suite
, "double", test_notify_double
);
1999 torture_suite_add_2smb_test(suite
, "tree", test_notify_tree
);
2000 torture_suite_add_1smb_test(suite
, "overflow", test_notify_overflow
);
2001 torture_suite_add_1smb_test(suite
, "basedir", test_notify_basedir
);
2002 torture_suite_add_1smb_test(suite
, "alignment", test_notify_alignment
);