1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

r16980: - make struct smb_notify a union and add levels RAW_NOTIFY_NTTRANS,RAW_NOTIFY_SMB2

- parse SMB2 Notify reponse

metze
(This used to be commit de50e0ccdd)
This commit is contained in:
Stefan Metzmacher 2006-07-12 14:25:50 +00:00 committed by Gerald (Jerry) Carter
parent e6b29409a2
commit a8958391e8
12 changed files with 322 additions and 252 deletions

View File

@ -2128,23 +2128,60 @@ struct smb_nttrans {
} out;
};
enum smb_notify_level {
RAW_NOTIFY_NTTRANS,
RAW_NOTIFY_SMB2
};
/* struct for nttrans change notify call */
struct smb_notify {
union smb_notify {
/* struct for nttrans change notify call */
struct {
union smb_handle file;
uint32_t buffer_size;
uint32_t completion_filter;
BOOL recursive;
} in;
enum smb_notify_level level;
struct {
uint32_t num_changes;
struct notify_changes {
uint32_t action;
struct smb_wire_string name;
} *changes;
} out;
struct {
union smb_handle file;
uint32_t buffer_size;
uint32_t completion_filter;
BOOL recursive;
} in;
struct {
uint32_t num_changes;
struct notify_changes {
uint32_t action;
struct smb_wire_string name;
} *changes;
} out;
} nttrans;
struct smb2_notify {
enum smb_notify_level level;
struct {
union smb_handle file;
/* static body buffer 32 (0x20) bytes */
/* uint16_t buffer_code; 0x32 */
uint16_t recursive;
uint32_t buffer_size;
/*struct smb2_handle file;*/
uint32_t completion_filter;
uint32_t unknown;
} in;
struct {
/* static body buffer 8 (0x08) bytes */
/* uint16_t buffer_code; 0x09 = 0x08 + 1 */
/* uint16_t blob_ofs; */
/* uint16_t blob_size; */
/* dynamic body */
/*DATA_BLOB blob;*/
/* DATA_BLOB content */
uint32_t num_changes;
struct notify_changes *changes;
} out;
} smb2;
};
enum smb_search_level {

View File

@ -25,19 +25,23 @@
/****************************************************************************
change notify (async send)
****************************************************************************/
struct smbcli_request *smb_raw_changenotify_send(struct smbcli_tree *tree, struct smb_notify *parms)
struct smbcli_request *smb_raw_changenotify_send(struct smbcli_tree *tree, union smb_notify *parms)
{
struct smb_nttrans nt;
uint16_t setup[4];
if (parms->nttrans.level != RAW_NOTIFY_NTTRANS) {
return NULL;
}
nt.in.max_setup = 0;
nt.in.max_param = parms->in.buffer_size;
nt.in.max_param = parms->nttrans.in.buffer_size;
nt.in.max_data = 0;
nt.in.setup_count = 4;
nt.in.setup = setup;
SIVAL(setup, 0, parms->in.completion_filter);
SSVAL(setup, 4, parms->in.file.fnum);
SSVAL(setup, 6, parms->in.recursive);
SIVAL(setup, 0, parms->nttrans.in.completion_filter);
SSVAL(setup, 4, parms->nttrans.in.file.fnum);
SSVAL(setup, 6, parms->nttrans.in.recursive);
nt.in.function = NT_TRANSACT_NOTIFY_CHANGE;
nt.in.params = data_blob(NULL, 0);
nt.in.data = data_blob(NULL, 0);
@ -49,41 +53,45 @@ struct smbcli_request *smb_raw_changenotify_send(struct smbcli_tree *tree, struc
change notify (async recv)
****************************************************************************/
NTSTATUS smb_raw_changenotify_recv(struct smbcli_request *req,
TALLOC_CTX *mem_ctx, struct smb_notify *parms)
TALLOC_CTX *mem_ctx, union smb_notify *parms)
{
struct smb_nttrans nt;
NTSTATUS status;
uint32_t ofs, i;
struct smbcli_session *session = req?req->session:NULL;
if (parms->nttrans.level != RAW_NOTIFY_NTTRANS) {
return NT_STATUS_INVALID_LEVEL;
}
status = smb_raw_nttrans_recv(req, mem_ctx, &nt);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
parms->out.changes = NULL;
parms->out.num_changes = 0;
parms->nttrans.out.changes = NULL;
parms->nttrans.out.num_changes = 0;
/* count them */
for (ofs=0; nt.out.params.length - ofs > 12; ) {
uint32_t next = IVAL(nt.out.params.data, ofs);
parms->out.num_changes++;
parms->nttrans.out.num_changes++;
if (next == 0 ||
ofs + next >= nt.out.params.length) break;
ofs += next;
}
/* allocate array */
parms->out.changes = talloc_array(mem_ctx, struct notify_changes, parms->out.num_changes);
if (!parms->out.changes) {
parms->nttrans.out.changes = talloc_array(mem_ctx, struct notify_changes, parms->nttrans.out.num_changes);
if (!parms->nttrans.out.changes) {
return NT_STATUS_NO_MEMORY;
}
for (i=ofs=0; i<parms->out.num_changes; i++) {
parms->out.changes[i].action = IVAL(nt.out.params.data, ofs+4);
for (i=ofs=0; i<parms->nttrans.out.num_changes; i++) {
parms->nttrans.out.changes[i].action = IVAL(nt.out.params.data, ofs+4);
smbcli_blob_pull_string(session, mem_ctx, &nt.out.params,
&parms->out.changes[i].name,
ofs+8, ofs+12, STR_UNICODE);
&parms->nttrans.out.changes[i].name,
ofs+8, ofs+12, STR_UNICODE);
ofs += IVAL(nt.out.params.data, ofs);
}

View File

@ -56,19 +56,46 @@ NTSTATUS smb2_notify_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
struct smb2_notify *io)
{
NTSTATUS status;
DATA_BLOB blob;
uint32_t ofs, i;
if (!smb2_request_receive(req) ||
smb2_request_is_error(req)) {
!smb2_request_is_ok(req)) {
return smb2_request_destroy(req);
}
SMB2_CHECK_PACKET_RECV(req, 0x08, True);
status = smb2_pull_o16s32_blob(&req->in, mem_ctx, req->in.body+0x02, &io->out.blob);
status = smb2_pull_o16s32_blob(&req->in, mem_ctx, req->in.body+0x02, &blob);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
io->out.changes = NULL;
io->out.num_changes = 0;
/* count them */
for (ofs=0; blob.length - ofs > 12; ) {
uint32_t next = IVAL(blob.data, ofs);
io->out.num_changes++;
if (next == 0 || (ofs + next) >= blob.length) break;
ofs += next;
}
/* allocate array */
io->out.changes = talloc_array(mem_ctx, struct notify_changes, io->out.num_changes);
if (!io->out.changes) {
return NT_STATUS_NO_MEMORY;
}
for (i=ofs=0; i<io->out.num_changes; i++) {
io->out.changes[i].action = IVAL(blob.data, ofs+4);
smbcli_blob_pull_string(NULL, mem_ctx, &blob,
&io->out.changes[i].name,
ofs+8, ofs+12, STR_UNICODE);
ofs += IVAL(blob.data, ofs);
}
return smb2_request_destroy(req);
}

View File

@ -94,28 +94,6 @@ struct smb2_setinfo {
} in;
};
struct smb2_notify {
struct {
/* static body buffer 32 (0x20) bytes */
/* uint16_t buffer_code; 0x32 */
uint16_t recursive;
uint32_t buffer_size;
union smb_handle file;
uint32_t completion_filter;
uint32_t unknown;
} in;
struct {
/* static body buffer 8 (0x08) bytes */
/* uint16_t buffer_code; 0x09 = 0x08 + 1 */
/* uint16_t blob_ofs; */
/* uint16_t blob_size; */
/* dynamic body */
DATA_BLOB blob;
} out;
};
struct cli_credentials;
struct event_context;
#include "libcli/smb2/smb2_proto.h"

View File

@ -1000,18 +1000,22 @@ static void async_changenotify(struct smbcli_request *c_req)
/* change notify request - always async */
static NTSTATUS cvfs_notify(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
struct smb_notify *io)
union smb_notify *io)
{
struct cvfs_private *private = ntvfs->private_data;
struct smbcli_request *c_req;
int saved_timeout = private->transport->options.request_timeout;
struct cvfs_file *f;
if (io->nttrans.level != RAW_NOTIFY_NTTRANS) {
return NT_STATUS_NOT_IMPLEMENTED;
}
SETUP_PID;
f = ntvfs_handle_get_backend_data(io->in.file.ntvfs, ntvfs);
f = ntvfs_handle_get_backend_data(io->nttrans.in.file.ntvfs, ntvfs);
if (!f) return NT_STATUS_INVALID_HANDLE;
io->in.file.fnum = f->fnum;
io->nttrans.in.file.fnum = f->fnum;
/* this request doesn't make sense unless its async */
if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {

View File

@ -139,7 +139,7 @@ struct ntvfs_ops {
/* change notify request */
NTSTATUS (*notify)(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
struct smb_notify *info);
union smb_notify *info);
/* cancel - cancels any pending async request */
NTSTATUS (*cancel)(struct ntvfs_module_context *ntvfs,

View File

@ -313,7 +313,7 @@ _PUBLIC_ NTSTATUS ntvfs_exit(struct ntvfs_request *req)
/*
change notify request
*/
_PUBLIC_ NTSTATUS ntvfs_notify(struct ntvfs_request *req, struct smb_notify *info)
_PUBLIC_ NTSTATUS ntvfs_notify(struct ntvfs_request *req, union smb_notify *info)
{
struct ntvfs_module_context *ntvfs = req->ctx->modules;
if (!ntvfs->ops->notify) {
@ -617,7 +617,7 @@ _PUBLIC_ NTSTATUS ntvfs_next_trans2(struct ntvfs_module_context *ntvfs,
*/
_PUBLIC_ NTSTATUS ntvfs_next_notify(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
struct smb_notify *info)
union smb_notify *info)
{
if (!ntvfs->next || !ntvfs->next->ops->notify) {
return NT_STATUS_NOT_IMPLEMENTED;

View File

@ -40,7 +40,7 @@ struct pvfs_notify_buffer {
struct notify_pending {
struct notify_pending *next, *prev;
struct ntvfs_request *req;
struct smb_notify *info;
union smb_notify *info;
} *pending;
};
@ -64,7 +64,7 @@ static void pvfs_notify_send(struct pvfs_notify_buffer *notify_buffer,
{
struct notify_pending *pending = notify_buffer->pending;
struct ntvfs_request *req;
struct smb_notify *info;
union smb_notify *info;
if (notify_buffer->current_buffer_size > notify_buffer->max_buffer_size &&
notify_buffer->num_changes != 0) {
@ -87,15 +87,15 @@ static void pvfs_notify_send(struct pvfs_notify_buffer *notify_buffer,
req = pending->req;
info = pending->info;
info->out.num_changes = notify_buffer->num_changes;
info->out.changes = talloc_steal(req, notify_buffer->changes);
info->nttrans.out.num_changes = notify_buffer->num_changes;
info->nttrans.out.changes = talloc_steal(req, notify_buffer->changes);
notify_buffer->num_changes = 0;
notify_buffer->changes = NULL;
notify_buffer->current_buffer_size = 0;
talloc_free(pending);
if (info->out.num_changes != 0) {
if (info->nttrans.out.num_changes != 0) {
status = NT_STATUS_OK;
}
@ -219,7 +219,7 @@ static void pvfs_notify_end(void *private, enum pvfs_wait_notice reason)
event buffer is non-empty */
NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
struct smb_notify *info)
union smb_notify *info)
{
struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
struct pvfs_state);
@ -227,7 +227,11 @@ NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs,
NTSTATUS status;
struct notify_pending *pending;
f = pvfs_find_fd(pvfs, req, info->in.file.ntvfs);
if (info->nttrans.level != RAW_NOTIFY_NTTRANS) {
return NT_STATUS_NOT_IMPLEMENTED;
}
f = pvfs_find_fd(pvfs, req, info->nttrans.in.file.ntvfs);
if (!f) {
return NT_STATUS_INVALID_HANDLE;
}
@ -246,15 +250,15 @@ NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs,
create one */
if (f->notify_buffer == NULL) {
status = pvfs_notify_setup(pvfs, f,
info->in.buffer_size,
info->in.completion_filter,
info->in.recursive);
info->nttrans.in.buffer_size,
info->nttrans.in.completion_filter,
info->nttrans.in.recursive);
NT_STATUS_NOT_OK_RETURN(status);
}
/* we update the max_buffer_size on each call, but we do not
update the recursive flag or filter */
f->notify_buffer->max_buffer_size = info->in.buffer_size;
f->notify_buffer->max_buffer_size = info->nttrans.in.buffer_size;
pending = talloc(f->notify_buffer, struct notify_pending);
NT_STATUS_HAVE_NO_MEMORY(pending);

View File

@ -520,7 +520,7 @@ static NTSTATUS unixuid_cancel(struct ntvfs_module_context *ntvfs,
change notify
*/
static NTSTATUS unixuid_notify(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, struct smb_notify *info)
struct ntvfs_request *req, union smb_notify *info)
{
NTSTATUS status;

View File

@ -345,7 +345,7 @@ static NTSTATUS nttrans_ioctl(struct smbsrv_request *req,
*/
static NTSTATUS nttrans_notify_change_send(struct nttrans_op *op)
{
struct smb_notify *info = talloc_get_type(op->op_info, struct smb_notify);
union smb_notify *info = talloc_get_type(op->op_info, union smb_notify);
size_t size = 0;
int i;
NTSTATUS status;
@ -353,8 +353,8 @@ static NTSTATUS nttrans_notify_change_send(struct nttrans_op *op)
#define MAX_BYTES_PER_CHAR 3
/* work out how big the reply buffer could be */
for (i=0;i<info->out.num_changes;i++) {
size += 12 + 3 + (1+strlen(info->out.changes[i].name.s)) * MAX_BYTES_PER_CHAR;
for (i=0;i<info->nttrans.out.num_changes;i++) {
size += 12 + 3 + (1+strlen(info->nttrans.out.changes[i].name.s)) * MAX_BYTES_PER_CHAR;
}
status = nttrans_setup_reply(op, op->trans, size, 0, 0);
@ -362,16 +362,16 @@ static NTSTATUS nttrans_notify_change_send(struct nttrans_op *op)
p = op->trans->out.params.data;
/* construct the changes buffer */
for (i=0;i<info->out.num_changes;i++) {
for (i=0;i<info->nttrans.out.num_changes;i++) {
uint32_t ofs;
ssize_t len;
SIVAL(p, 4, info->out.changes[i].action);
len = push_string(p + 12, info->out.changes[i].name.s,
SIVAL(p, 4, info->nttrans.out.changes[i].action);
len = push_string(p + 12, info->nttrans.out.changes[i].name.s,
op->trans->out.params.length -
(p+12 - op->trans->out.params.data), STR_UNICODE);
SIVAL(p, 8, len);
ofs = len + 12;
if (ofs & 3) {
@ -380,7 +380,7 @@ static NTSTATUS nttrans_notify_change_send(struct nttrans_op *op)
ofs += pad;
}
if (i == info->out.num_changes-1) {
if (i == info->nttrans.out.num_changes-1) {
SIVAL(p, 0, 0);
} else {
SIVAL(p, 0, ofs);
@ -401,25 +401,26 @@ static NTSTATUS nttrans_notify_change(struct smbsrv_request *req,
struct nttrans_op *op)
{
struct smb_nttrans *trans = op->trans;
struct smb_notify *info;
union smb_notify *info;
/* should have at least 4 setup words */
if (trans->in.setup_count != 4) {
return NT_STATUS_INVALID_PARAMETER;
}
info = talloc(op, struct smb_notify);
info = talloc(op, union smb_notify);
NT_STATUS_HAVE_NO_MEMORY(info);
info->in.completion_filter = IVAL(trans->in.setup, 0);
info->in.file.ntvfs = smbsrv_pull_fnum(req, (uint8_t *)trans->in.setup, 4);
info->in.recursive = SVAL(trans->in.setup, 6);
info->in.buffer_size = trans->in.max_param;
info->nttrans.level = RAW_NOTIFY_NTTRANS;
info->nttrans.in.completion_filter = IVAL(trans->in.setup, 0);
info->nttrans.in.file.ntvfs = smbsrv_pull_fnum(req, (uint8_t *)trans->in.setup, 4);
info->nttrans.in.recursive = SVAL(trans->in.setup, 6);
info->nttrans.in.buffer_size = trans->in.max_param;
op->op_info = info;
op->send_fn = nttrans_notify_change_send;
SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(info->in.file.ntvfs);
SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(info->nttrans.in.file.ntvfs);
return ntvfs_notify(req->ntvfs, info);
}

View File

@ -84,7 +84,7 @@ static struct {
static struct {
int notify_count;
NTSTATUS status;
struct smb_notify notify;
union smb_notify notify;
} notifies[NSERVERS][NINSTANCES];
/* info relevant to the current operation */
@ -682,7 +682,7 @@ static struct ea_struct gen_ea_struct(void)
*/
static void async_notify(struct smbcli_request *req)
{
struct smb_notify notify;
union smb_notify notify;
NTSTATUS status;
int i, j;
uint16_t tid;
@ -690,13 +690,14 @@ static void async_notify(struct smbcli_request *req)
tid = SVAL(req->in.hdr, HDR_TID);
notify.nttrans.level = RAW_NOTIFY_NTTRANS;
status = smb_raw_changenotify_recv(req, current_op.mem_ctx, &notify);
if (NT_STATUS_IS_OK(status)) {
printf("notify tid=%d num_changes=%d action=%d name=%s\n",
tid,
notify.out.num_changes,
notify.out.changes[0].action,
notify.out.changes[0].name.s);
notify.nttrans.out.num_changes,
notify.nttrans.out.changes[0].action,
notify.nttrans.out.changes[0].name.s);
}
for (i=0;i<NSERVERS;i++) {
@ -892,7 +893,7 @@ again:
for (j=0;j<NINSTANCES;j++) {
for (i=1;i<NSERVERS;i++) {
int n;
struct smb_notify not1, not2;
union smb_notify not1, not2;
if (notifies[0][j].notify_count != notifies[i][j].notify_count) {
if (tries++ < 10) goto again;
@ -919,26 +920,26 @@ again:
not1 = notifies[0][j].notify;
not2 = notifies[i][j].notify;
for (n=0;n<not1.out.num_changes;n++) {
if (not1.out.changes[n].action !=
not2.out.changes[n].action) {
for (n=0;n<not1.nttrans.out.num_changes;n++) {
if (not1.nttrans.out.changes[n].action !=
not2.nttrans.out.changes[n].action) {
printf("Notify action %d inconsistent %d %d\n", n,
not1.out.changes[n].action,
not2.out.changes[n].action);
not1.nttrans.out.changes[n].action,
not2.nttrans.out.changes[n].action);
return False;
}
if (strcmp(not1.out.changes[n].name.s,
not2.out.changes[n].name.s)) {
if (strcmp(not1.nttrans.out.changes[n].name.s,
not2.nttrans.out.changes[n].name.s)) {
printf("Notify name %d inconsistent %s %s\n", n,
not1.out.changes[n].name.s,
not2.out.changes[n].name.s);
not1.nttrans.out.changes[n].name.s,
not2.nttrans.out.changes[n].name.s);
return False;
}
if (not1.out.changes[n].name.private_length !=
not2.out.changes[n].name.private_length) {
if (not1.nttrans.out.changes[n].name.private_length !=
not2.nttrans.out.changes[n].name.private_length) {
printf("Notify name length %d inconsistent %d %d\n", n,
not1.out.changes[n].name.private_length,
not2.out.changes[n].name.private_length);
not1.nttrans.out.changes[n].name.private_length,
not2.nttrans.out.changes[n].name.private_length);
return False;
}
}
@ -1820,17 +1821,18 @@ static BOOL handler_sfileinfo(int instance)
*/
static BOOL handler_notify(int instance)
{
struct smb_notify parm[NSERVERS];
union smb_notify parm[NSERVERS];
int n;
ZERO_STRUCT(parm[0]);
parm[0].in.buffer_size = gen_io_count();
parm[0].in.completion_filter = gen_bits_mask(0xFF);
parm[0].in.file.fnum = gen_fnum(instance);
parm[0].in.recursive = gen_bool();
parm[0].nttrans.level = RAW_NOTIFY_NTTRANS;
parm[0].nttrans.in.buffer_size = gen_io_count();
parm[0].nttrans.in.completion_filter = gen_bits_mask(0xFF);
parm[0].nttrans.in.file.fnum = gen_fnum(instance);
parm[0].nttrans.in.recursive = gen_bool();
GEN_COPY_PARM;
GEN_SET_FNUM(in.file.fnum);
GEN_SET_FNUM(nttrans.in.file.fnum);
for (n=0;n<NSERVERS;n++) {
struct smbcli_request *req;

View File

@ -59,7 +59,7 @@ static BOOL test_notify_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
{
BOOL ret = True;
NTSTATUS status;
struct smb_notify notify;
union smb_notify notify;
union smb_open io;
union smb_close cl;
int i, count, fnum, fnum2;
@ -94,10 +94,11 @@ static BOOL test_notify_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
/* ask for a change notify,
on file or directory name changes */
notify.in.buffer_size = 1000;
notify.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
notify.in.file.fnum = fnum;
notify.in.recursive = True;
notify.nttrans.level = RAW_NOTIFY_NTTRANS;
notify.nttrans.in.buffer_size = 1000;
notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
notify.nttrans.in.file.fnum = fnum;
notify.nttrans.in.recursive = True;
printf("testing notify cancel\n");
@ -114,9 +115,9 @@ static BOOL test_notify_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, 1);
CHECK_VAL(notify.out.changes[0].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.out.changes[0].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.num_changes, 1);
CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
printf("testing notify rmdir\n");
@ -125,9 +126,9 @@ static BOOL test_notify_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, 1);
CHECK_VAL(notify.out.changes[0].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.out.changes[0].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.num_changes, 1);
CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
printf("testing notify mkdir - rmdir - mkdir - rmdir\n");
@ -138,15 +139,15 @@ static BOOL test_notify_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
req = smb_raw_changenotify_send(cli->tree, &notify);
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, 4);
CHECK_VAL(notify.out.changes[0].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.out.changes[0].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.out.changes[1].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.out.changes[1].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.out.changes[2].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.out.changes[2].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.out.changes[3].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.out.changes[3].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.num_changes, 4);
CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[1].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.nttrans.out.changes[1].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[2].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.nttrans.out.changes[2].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[3].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.nttrans.out.changes[3].name, "subdir-name", STR_UNICODE);
count = torture_numops;
printf("testing buffered notify on create of %d files\n", count);
@ -165,12 +166,12 @@ static BOOL test_notify_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
/* (1st notify) setup a new notify on a different directory handle.
This new notify won't see the events above. */
notify.in.file.fnum = fnum2;
notify.nttrans.in.file.fnum = fnum2;
req2 = smb_raw_changenotify_send(cli->tree, &notify);
/* (2nd notify) whereas this notify will see the above buffered events,
and it directly returns the buffered events */
notify.in.file.fnum = fnum;
notify.nttrans.in.file.fnum = fnum;
req = smb_raw_changenotify_send(cli->tree, &notify);
/* (1st unlink) as the 2nd notify directly returns,
@ -184,18 +185,18 @@ static BOOL test_notify_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, count);
for (i=1;i<notify.out.num_changes;i++) {
CHECK_VAL(notify.out.changes[i].action, NOTIFY_ACTION_ADDED);
CHECK_VAL(notify.nttrans.out.num_changes, count);
for (i=1;i<notify.nttrans.out.num_changes;i++) {
CHECK_VAL(notify.nttrans.out.changes[i].action, NOTIFY_ACTION_ADDED);
}
CHECK_WSTR(notify.out.changes[0].name, "test0.txt", STR_UNICODE);
CHECK_WSTR(notify.nttrans.out.changes[0].name, "test0.txt", STR_UNICODE);
/* and now from the 1st notify */
status = smb_raw_changenotify_recv(req2, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, 1);
CHECK_VAL(notify.out.changes[0].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.out.changes[0].name, "test0.txt", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.num_changes, 1);
CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.nttrans.out.changes[0].name, "test0.txt", STR_UNICODE);
/* (3rd notify) this notify will only see the 1st unlink */
req = smb_raw_changenotify_send(cli->tree, &notify);
@ -208,32 +209,32 @@ static BOOL test_notify_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
/* receive the 3rd notify */
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, 1);
CHECK_VAL(notify.out.changes[0].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.out.changes[0].name, "test0.txt", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.num_changes, 1);
CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.nttrans.out.changes[0].name, "test0.txt", STR_UNICODE);
/* and we now see the rest of the unlink calls on both directory handles */
notify.in.file.fnum = fnum;
notify.nttrans.in.file.fnum = fnum;
sleep(1);
req = smb_raw_changenotify_send(cli->tree, &notify);
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, count-1);
for (i=0;i<notify.out.num_changes;i++) {
CHECK_VAL(notify.out.changes[i].action, NOTIFY_ACTION_REMOVED);
CHECK_VAL(notify.nttrans.out.num_changes, count-1);
for (i=0;i<notify.nttrans.out.num_changes;i++) {
CHECK_VAL(notify.nttrans.out.changes[i].action, NOTIFY_ACTION_REMOVED);
}
notify.in.file.fnum = fnum2;
notify.nttrans.in.file.fnum = fnum2;
req = smb_raw_changenotify_send(cli->tree, &notify);
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, count-1);
for (i=0;i<notify.out.num_changes;i++) {
CHECK_VAL(notify.out.changes[i].action, NOTIFY_ACTION_REMOVED);
CHECK_VAL(notify.nttrans.out.num_changes, count-1);
for (i=0;i<notify.nttrans.out.num_changes;i++) {
CHECK_VAL(notify.nttrans.out.changes[i].action, NOTIFY_ACTION_REMOVED);
}
printf("testing if a close() on the dir handle triggers the notify reply\n");
notify.in.file.fnum = fnum;
notify.nttrans.in.file.fnum = fnum;
req = smb_raw_changenotify_send(cli->tree, &notify);
cl.close.level = RAW_CLOSE_CLOSE;
@ -244,7 +245,7 @@ static BOOL test_notify_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, 0);
CHECK_VAL(notify.nttrans.out.num_changes, 0);
done:
smb_raw_exit(cli->session);
@ -259,7 +260,7 @@ static BOOL test_notify_recursive(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
{
BOOL ret = True;
NTSTATUS status;
struct smb_notify notify;
union smb_notify notify;
union smb_open io;
int fnum;
struct smbcli_request *req1, *req2;
@ -288,14 +289,15 @@ static BOOL test_notify_recursive(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
/* ask for a change notify, on file or directory name
changes. Setup both with and without recursion */
notify.in.buffer_size = 1000;
notify.in.completion_filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_CREATION;
notify.in.file.fnum = fnum;
notify.nttrans.level = RAW_NOTIFY_NTTRANS;
notify.nttrans.in.buffer_size = 1000;
notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_CREATION;
notify.nttrans.in.file.fnum = fnum;
notify.in.recursive = True;
notify.nttrans.in.recursive = True;
req1 = smb_raw_changenotify_send(cli->tree, &notify);
notify.in.recursive = False;
notify.nttrans.in.recursive = False;
req2 = smb_raw_changenotify_send(cli->tree, &notify);
/* cancel initial requests so the buffer is setup */
@ -315,8 +317,8 @@ static BOOL test_notify_recursive(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
smbcli_rename(cli->tree, BASEDIR "\\subdir-name\\subname2", BASEDIR "\\subname2-r");
smbcli_rename(cli->tree, BASEDIR "\\subname2-r", BASEDIR "\\subname3-r");
notify.in.completion_filter = 0;
notify.in.recursive = True;
notify.nttrans.in.completion_filter = 0;
notify.nttrans.in.recursive = True;
msleep(10);
req1 = smb_raw_changenotify_send(cli->tree, &notify);
@ -324,57 +326,57 @@ static BOOL test_notify_recursive(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name");
smbcli_unlink(cli->tree, BASEDIR "\\subname3-r");
notify.in.recursive = False;
notify.nttrans.in.recursive = False;
req2 = smb_raw_changenotify_send(cli->tree, &notify);
status = smb_raw_changenotify_recv(req1, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, 11);
CHECK_VAL(notify.out.changes[0].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.out.changes[0].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.out.changes[1].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.out.changes[1].name, "subdir-name\\subname1", STR_UNICODE);
CHECK_VAL(notify.out.changes[2].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.out.changes[2].name, "subdir-name\\subname2", STR_UNICODE);
CHECK_VAL(notify.out.changes[3].action, NOTIFY_ACTION_OLD_NAME);
CHECK_WSTR(notify.out.changes[3].name, "subdir-name\\subname1", STR_UNICODE);
CHECK_VAL(notify.out.changes[4].action, NOTIFY_ACTION_NEW_NAME);
CHECK_WSTR(notify.out.changes[4].name, "subdir-name\\subname1-r", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.num_changes, 11);
CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[1].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.nttrans.out.changes[1].name, "subdir-name\\subname1", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[2].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.nttrans.out.changes[2].name, "subdir-name\\subname2", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[3].action, NOTIFY_ACTION_OLD_NAME);
CHECK_WSTR(notify.nttrans.out.changes[3].name, "subdir-name\\subname1", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[4].action, NOTIFY_ACTION_NEW_NAME);
CHECK_WSTR(notify.nttrans.out.changes[4].name, "subdir-name\\subname1-r", STR_UNICODE);
/* the remove/add between directories is acceptable in either order */
if (notify.out.changes[5].action == NOTIFY_ACTION_ADDED) {
CHECK_VAL(notify.out.changes[6].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.out.changes[6].name, "subdir-name\\subname2", STR_UNICODE);
CHECK_VAL(notify.out.changes[5].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.out.changes[5].name, "subname2-r", STR_UNICODE);
if (notify.nttrans.out.changes[5].action == NOTIFY_ACTION_ADDED) {
CHECK_VAL(notify.nttrans.out.changes[6].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.nttrans.out.changes[6].name, "subdir-name\\subname2", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[5].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.nttrans.out.changes[5].name, "subname2-r", STR_UNICODE);
} else {
CHECK_VAL(notify.out.changes[5].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.out.changes[5].name, "subdir-name\\subname2", STR_UNICODE);
CHECK_VAL(notify.out.changes[6].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.out.changes[6].name, "subname2-r", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[5].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.nttrans.out.changes[5].name, "subdir-name\\subname2", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[6].action, NOTIFY_ACTION_ADDED);
CHECK_WSTR(notify.nttrans.out.changes[6].name, "subname2-r", STR_UNICODE);
}
CHECK_VAL(notify.out.changes[7].action, NOTIFY_ACTION_MODIFIED);
CHECK_WSTR(notify.out.changes[7].name, "subname2-r", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[7].action, NOTIFY_ACTION_MODIFIED);
CHECK_WSTR(notify.nttrans.out.changes[7].name, "subname2-r", STR_UNICODE);
CHECK_VAL(notify.out.changes[8].action, NOTIFY_ACTION_OLD_NAME);
CHECK_WSTR(notify.out.changes[8].name, "subname2-r", STR_UNICODE);
CHECK_VAL(notify.out.changes[9].action, NOTIFY_ACTION_NEW_NAME);
CHECK_WSTR(notify.out.changes[9].name, "subname3-r", STR_UNICODE);
CHECK_VAL(notify.out.changes[10].action, NOTIFY_ACTION_MODIFIED);
CHECK_WSTR(notify.out.changes[10].name, "subname3-r", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[8].action, NOTIFY_ACTION_OLD_NAME);
CHECK_WSTR(notify.nttrans.out.changes[8].name, "subname2-r", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[9].action, NOTIFY_ACTION_NEW_NAME);
CHECK_WSTR(notify.nttrans.out.changes[9].name, "subname3-r", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[10].action, NOTIFY_ACTION_MODIFIED);
CHECK_WSTR(notify.nttrans.out.changes[10].name, "subname3-r", STR_UNICODE);
status = smb_raw_changenotify_recv(req2, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, 3);
CHECK_VAL(notify.out.changes[0].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.out.changes[0].name, "subdir-name\\subname1-r", STR_UNICODE);
CHECK_VAL(notify.out.changes[1].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.out.changes[1].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.out.changes[2].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.out.changes[2].name, "subname3-r", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.num_changes, 3);
CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name\\subname1-r", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[1].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.nttrans.out.changes[1].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.changes[2].action, NOTIFY_ACTION_REMOVED);
CHECK_WSTR(notify.nttrans.out.changes[2].name, "subname3-r", STR_UNICODE);
done:
smb_raw_exit(cli->session);
@ -389,7 +391,7 @@ static BOOL test_notify_mask(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
{
BOOL ret = True;
NTSTATUS status;
struct smb_notify notify;
union smb_notify notify;
union smb_open io;
int fnum, fnum2;
uint32_t mask;
@ -419,8 +421,9 @@ static BOOL test_notify_mask(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
io.ntcreatex.in.security_flags = 0;
io.ntcreatex.in.fname = BASEDIR;
notify.in.buffer_size = 1000;
notify.in.recursive = True;
notify.nttrans.level = RAW_NOTIFY_NTTRANS;
notify.nttrans.in.buffer_size = 1000;
notify.nttrans.in.recursive = True;
#define NOTIFY_MASK_TEST(setup, op, cleanup, Action, expected, nchanges) \
do { for (mask=i=0;i<32;i++) { \
@ -429,8 +432,8 @@ static BOOL test_notify_mask(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
CHECK_STATUS(status, NT_STATUS_OK); \
fnum = io.ntcreatex.out.file.fnum; \
setup \
notify.in.file.fnum = fnum; \
notify.in.completion_filter = (1<<i); \
notify.nttrans.in.file.fnum = fnum; \
notify.nttrans.in.completion_filter = (1<<i); \
req = smb_raw_changenotify_send(cli->tree, &notify); \
op \
msleep(10); smb_raw_ntcancel(req); \
@ -440,18 +443,18 @@ static BOOL test_notify_mask(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
if (NT_STATUS_EQUAL(status, NT_STATUS_CANCELLED)) continue; \
CHECK_STATUS(status, NT_STATUS_OK); \
/* special case to cope with file rename behaviour */ \
if (nchanges == 2 && notify.out.num_changes == 1 && \
notify.out.changes[0].action == NOTIFY_ACTION_MODIFIED && \
if (nchanges == 2 && notify.nttrans.out.num_changes == 1 && \
notify.nttrans.out.changes[0].action == NOTIFY_ACTION_MODIFIED && \
((expected) & FILE_NOTIFY_CHANGE_ATTRIBUTES) && \
Action == NOTIFY_ACTION_OLD_NAME) { \
printf("(rename file special handling OK)\n"); \
} else if (nchanges != notify.out.num_changes || \
notify.out.changes[0].action != Action || \
strcmp(notify.out.changes[0].name.s, "tname1") != 0) { \
} else if (nchanges != notify.nttrans.out.num_changes || \
notify.nttrans.out.changes[0].action != Action || \
strcmp(notify.nttrans.out.changes[0].name.s, "tname1") != 0) { \
printf("ERROR: nchanges=%d action=%d filter=0x%08x\n", \
notify.out.num_changes, \
notify.out.changes[0].action, \
notify.in.completion_filter); \
notify.nttrans.out.num_changes, \
notify.nttrans.out.changes[0].action, \
notify.nttrans.in.completion_filter); \
ret = False; \
} \
mask |= (1<<i); \
@ -601,7 +604,7 @@ static BOOL test_notify_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
BOOL ret = True;
union smb_open io;
union smb_close cl;
struct smb_notify notify;
union smb_notify notify;
struct smbcli_request *req;
int fnum;
const char *fname = BASEDIR "\\file.txt";
@ -626,10 +629,11 @@ static BOOL test_notify_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
/* ask for a change notify,
on file or directory name changes */
notify.in.file.fnum = fnum;
notify.in.buffer_size = 1000;
notify.in.completion_filter = FILE_NOTIFY_CHANGE_STREAM_NAME;
notify.in.recursive = False;
notify.nttrans.level = RAW_NOTIFY_NTTRANS;
notify.nttrans.in.file.fnum = fnum;
notify.nttrans.in.buffer_size = 1000;
notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_STREAM_NAME;
notify.nttrans.in.recursive = False;
printf("testing if notifies on file handles are invalid (should be)\n");
@ -658,7 +662,7 @@ static BOOL test_notify_tdis(TALLOC_CTX *mem_ctx)
{
BOOL ret = True;
NTSTATUS status;
struct smb_notify notify;
union smb_notify notify;
union smb_open io;
int fnum;
struct smbcli_request *req;
@ -692,10 +696,11 @@ static BOOL test_notify_tdis(TALLOC_CTX *mem_ctx)
/* ask for a change notify,
on file or directory name changes */
notify.in.buffer_size = 1000;
notify.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
notify.in.file.fnum = fnum;
notify.in.recursive = True;
notify.nttrans.level = RAW_NOTIFY_NTTRANS;
notify.nttrans.in.buffer_size = 1000;
notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
notify.nttrans.in.file.fnum = fnum;
notify.nttrans.in.recursive = True;
req = smb_raw_changenotify_send(cli->tree, &notify);
@ -704,7 +709,7 @@ static BOOL test_notify_tdis(TALLOC_CTX *mem_ctx)
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, 0);
CHECK_VAL(notify.nttrans.out.num_changes, 0);
done:
torture_close_connection(cli);
@ -718,7 +723,7 @@ static BOOL test_notify_exit(TALLOC_CTX *mem_ctx)
{
BOOL ret = True;
NTSTATUS status;
struct smb_notify notify;
union smb_notify notify;
union smb_open io;
int fnum;
struct smbcli_request *req;
@ -752,10 +757,11 @@ static BOOL test_notify_exit(TALLOC_CTX *mem_ctx)
/* ask for a change notify,
on file or directory name changes */
notify.in.buffer_size = 1000;
notify.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
notify.in.file.fnum = fnum;
notify.in.recursive = True;
notify.nttrans.level = RAW_NOTIFY_NTTRANS;
notify.nttrans.in.buffer_size = 1000;
notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
notify.nttrans.in.file.fnum = fnum;
notify.nttrans.in.recursive = True;
req = smb_raw_changenotify_send(cli->tree, &notify);
@ -764,7 +770,7 @@ static BOOL test_notify_exit(TALLOC_CTX *mem_ctx)
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, 0);
CHECK_VAL(notify.nttrans.out.num_changes, 0);
done:
torture_close_connection(cli);
@ -778,7 +784,7 @@ static BOOL test_notify_ulogoff(TALLOC_CTX *mem_ctx)
{
BOOL ret = True;
NTSTATUS status;
struct smb_notify notify;
union smb_notify notify;
union smb_open io;
int fnum;
struct smbcli_request *req;
@ -812,10 +818,11 @@ static BOOL test_notify_ulogoff(TALLOC_CTX *mem_ctx)
/* ask for a change notify,
on file or directory name changes */
notify.in.buffer_size = 1000;
notify.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
notify.in.file.fnum = fnum;
notify.in.recursive = True;
notify.nttrans.level = RAW_NOTIFY_NTTRANS;
notify.nttrans.in.buffer_size = 1000;
notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
notify.nttrans.in.file.fnum = fnum;
notify.nttrans.in.recursive = True;
req = smb_raw_changenotify_send(cli->tree, &notify);
@ -824,7 +831,7 @@ static BOOL test_notify_ulogoff(TALLOC_CTX *mem_ctx)
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, 0);
CHECK_VAL(notify.nttrans.out.num_changes, 0);
done:
torture_close_connection(cli);
@ -839,7 +846,7 @@ static BOOL test_notify_double(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
{
BOOL ret = True;
NTSTATUS status;
struct smb_notify notify;
union smb_notify notify;
union smb_open io;
int fnum;
struct smbcli_request *req1, *req2;
@ -868,10 +875,11 @@ static BOOL test_notify_double(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
/* ask for a change notify,
on file or directory name changes */
notify.in.buffer_size = 1000;
notify.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
notify.in.file.fnum = fnum;
notify.in.recursive = True;
notify.nttrans.level = RAW_NOTIFY_NTTRANS;
notify.nttrans.in.buffer_size = 1000;
notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
notify.nttrans.in.file.fnum = fnum;
notify.nttrans.in.recursive = True;
req1 = smb_raw_changenotify_send(cli->tree, &notify);
req2 = smb_raw_changenotify_send(cli->tree, &notify);
@ -880,15 +888,15 @@ static BOOL test_notify_double(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
status = smb_raw_changenotify_recv(req1, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, 1);
CHECK_WSTR(notify.out.changes[0].name, "subdir-name", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.num_changes, 1);
CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);
smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name2");
status = smb_raw_changenotify_recv(req2, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(notify.out.num_changes, 1);
CHECK_WSTR(notify.out.changes[0].name, "subdir-name2", STR_UNICODE);
CHECK_VAL(notify.nttrans.out.num_changes, 1);
CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name2", STR_UNICODE);
done:
smb_raw_exit(cli->session);
@ -902,7 +910,7 @@ done:
static BOOL test_notify_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
{
BOOL ret = True;
struct smb_notify notify;
union smb_notify notify;
union smb_open io;
struct smbcli_request *req;
struct {
@ -950,7 +958,8 @@ static BOOL test_notify_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
io.ntcreatex.in.security_flags = 0;
notify.in.buffer_size = 20000;
notify.nttrans.level = RAW_NOTIFY_NTTRANS;
notify.nttrans.in.buffer_size = 20000;
/*
setup the directory tree, and the notify buffer on each directory
@ -961,9 +970,9 @@ static BOOL test_notify_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
CHECK_STATUS(status, NT_STATUS_OK);
dirs[i].fnum = io.ntcreatex.out.file.fnum;
notify.in.completion_filter = dirs[i].filter;
notify.in.file.fnum = dirs[i].fnum;
notify.in.recursive = dirs[i].recursive;
notify.nttrans.in.completion_filter = dirs[i].filter;
notify.nttrans.in.file.fnum = dirs[i].fnum;
notify.nttrans.in.recursive = dirs[i].recursive;
req = smb_raw_changenotify_send(cli->tree, &notify);
smb_raw_ntcancel(req);
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
@ -983,14 +992,14 @@ static BOOL test_notify_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
/* count events that have happened in each dir */
for (i=0;i<ARRAY_SIZE(dirs);i++) {
notify.in.file.fnum = dirs[i].fnum;
notify.nttrans.in.file.fnum = dirs[i].fnum;
req = smb_raw_changenotify_send(cli->tree, &notify);
smb_raw_ntcancel(req);
notify.out.num_changes = 0;
notify.nttrans.out.num_changes = 0;
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
if (notify.out.num_changes != dirs[i].expected) {
if (notify.nttrans.out.num_changes != dirs[i].expected) {
printf("ERROR: i=%d expected %d got %d for '%s'\n",
i, dirs[i].expected, notify.out.num_changes,
i, dirs[i].expected, notify.nttrans.out.num_changes,
dirs[i].path);
ret = False;
}