r16989: implement SMB2 Notify in the frontend
authorStefan Metzmacher <metze@samba.org>
Wed, 12 Jul 2006 17:14:32 +0000 (17:14 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:10:07 +0000 (14:10 -0500)
metze

source/smb_server/smb2/fileio.c

index fa35afce7e4f459ee31b4cdbe7cbff37e645d901..948c53d9e66ccad685f7a85bceebfb7a3c34ba9b 100644 (file)
@@ -291,9 +291,83 @@ void smb2srv_cancel_recv(struct smb2srv_request *req)
        smb2srv_send_error(req, NT_STATUS_NOT_IMPLEMENTED);
 }
 
+static void smb2srv_notify_send(struct ntvfs_request *ntvfs)
+{
+       struct smb2srv_request *req;
+       union smb_notify *io;
+       size_t size = 0;
+       int i;
+       uint8_t *p;
+       DATA_BLOB blob = data_blob(NULL, 0);
+
+       SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_notify);
+       SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, True, 0));
+
+#define MAX_BYTES_PER_CHAR 3
+       
+       /* work out how big the reply buffer could be */
+       for (i=0;i<io->smb2.out.num_changes;i++) {
+               size += 12 + 3 + (1+strlen(io->smb2.out.changes[i].name.s)) * MAX_BYTES_PER_CHAR;
+       }
+
+       blob = data_blob_talloc(req, NULL, size);
+       if (size > 0 && !blob.data) {
+               SMB2SRV_CHECK(NT_STATUS_NO_MEMORY);
+       }
+
+       p = blob.data;
+
+       /* construct the changes buffer */
+       for (i=0;i<io->smb2.out.num_changes;i++) {
+               uint32_t ofs;
+               ssize_t len;
+
+               SIVAL(p, 4, io->smb2.out.changes[i].action);
+               len = push_string(p + 12, io->smb2.out.changes[i].name.s, 
+                                 blob.length - (p+12 - blob.data), STR_UNICODE);
+               SIVAL(p, 8, len);
+
+               ofs = len + 12;
+
+               if (ofs & 3) {
+                       int pad = 4 - (ofs & 3);
+                       memset(p+ofs, 0, pad);
+                       ofs += pad;
+               }
+
+               if (i == io->smb2.out.num_changes-1) {
+                       SIVAL(p, 0, 0);
+               } else {
+                       SIVAL(p, 0, ofs);
+               }
+
+               p += ofs;
+       }
+
+       blob.length = p - blob.data;
+
+       SMB2SRV_CHECK(smb2_push_o16s32_blob(&req->out, 0x02, blob));
+
+       smb2srv_send_reply(req);
+}
+
 void smb2srv_notify_recv(struct smb2srv_request *req)
 {
-       smb2srv_send_error(req, NT_STATUS_NOT_IMPLEMENTED);
+       union smb_notify *io;
+
+       SMB2SRV_CHECK_BODY_SIZE(req, 0x20, False);
+       SMB2SRV_TALLOC_IO_PTR(io, union smb_notify);
+       SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_notify_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
+
+       io->smb2.level                  = RAW_NOTIFY_SMB2;
+       io->smb2.in.recursive           = SVAL(req->in.body, 0x02);
+       io->smb2.in.buffer_size         = IVAL(req->in.body, 0x04);
+       io->smb2.in.file.ntvfs          = smb2srv_pull_handle(req, req->in.body, 0x08);
+       io->smb2.in.completion_filter   = IVAL(req->in.body, 0x18);
+       io->smb2.in.unknown             = BVAL(req->in.body, 0x1C);
+
+       SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs);
+       SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_notify(req->ntvfs, io));
 }
 
 void smb2srv_break_recv(struct smb2srv_request *req)