summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/smb.h1
-rw-r--r--source3/smbd/notify.c40
-rw-r--r--source3/smbd/nttrans.c12
-rw-r--r--source3/smbd/open.c5
-rw-r--r--source3/smbd/reply.c7
5 files changed, 41 insertions, 24 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 64073e902e..a7461b422c 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -440,6 +440,7 @@ struct notify_change_request {
struct notify_change_request *prev, *next;
struct files_struct *fsp; /* backpointer for cancel by mid */
char request_buf[smb_size];
+ uint32 filter;
uint32 max_param_count;
struct notify_mid_map *mid_map;
};
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 49a516b907..f94ff76e7b 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -171,7 +171,7 @@ static void change_notify_remove(struct change_notify *cnbp)
}
NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count,
- struct files_struct *fsp)
+ uint32 filter, struct files_struct *fsp)
{
struct notify_change_request *request = NULL;
struct notify_mid_map *map = NULL;
@@ -187,6 +187,7 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count,
memcpy(request->request_buf, inbuf, sizeof(request->request_buf));
request->max_param_count = max_param_count;
+ request->filter = filter;
request->fsp = fsp;
DLIST_ADD_END(fsp->notify->requests, request,
struct notify_change_request *);
@@ -406,16 +407,18 @@ int change_notify_fd(void)
Offset Data length.
0 SMB_DEV_T dev 8
8 SMB_INO_T inode 8
-16 uint32 action 4
-20.. name
+16 uint32 filter 4
+20 uint32 action 4
+24.. name
*/
-#define MSG_NOTIFY_MESSAGE_SIZE 21 /* Includes at least the '\0' terminator */
+#define MSG_NOTIFY_MESSAGE_SIZE 25 /* Includes at least the '\0' terminator */
struct notify_message {
SMB_DEV_T dev;
SMB_INO_T inode;
- uint32_t action;
+ uint32 filter;
+ uint32 action;
char *name;
};
@@ -433,8 +436,9 @@ static DATA_BLOB notify_message_to_buf(const struct notify_message *msg)
SDEV_T_VAL(result.data, 0, msg->dev);
SINO_T_VAL(result.data, 8, msg->inode);
- SIVAL(result.data, 16, msg->action);
- memcpy(result.data+20, msg->name, len+1);
+ SIVAL(result.data, 16, msg->filter);
+ SIVAL(result.data, 20, msg->action);
+ memcpy(result.data+24, msg->name, len+1);
return result;
}
@@ -450,13 +454,14 @@ static BOOL buf_to_notify_message(void *buf, size_t len,
msg->dev = DEV_T_VAL(buf, 0);
msg->inode = INO_T_VAL(buf, 8);
- msg->action = IVAL(buf, 16);
- msg->name = ((char *)buf)+20;
+ msg->filter = IVAL(buf, 16);
+ msg->action = IVAL(buf, 20);
+ msg->name = ((char *)buf)+24;
return True;
}
void notify_action(connection_struct *conn, const char *parent,
- const char *name, uint32_t action)
+ const char *name, uint32 filter, uint32_t action)
{
struct share_mode_lock *lck;
SMB_STRUCT_STAT sbuf;
@@ -484,6 +489,7 @@ void notify_action(connection_struct *conn, const char *parent,
msg.dev = sbuf.st_dev;
msg.inode = sbuf.st_ino;
+ msg.filter = filter;
msg.action = action;
msg.name = CONST_DISCARD(char *, name);
@@ -546,10 +552,13 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg)
return;
}
- if (fsp->notify->requests != NULL) {
+ if ((fsp->notify->requests != NULL)
+ && (fsp->notify->requests->filter & msg->filter)) {
/*
* Someone is waiting for the change, trigger the reply
- * immediately
+ * immediately.
+ *
+ * TODO: do we have to walk the lists of requests pending?
*/
struct notify_change_request *req = fsp->notify->requests;
@@ -560,15 +569,14 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg)
change_notify_reply(req->request_buf, req->max_param_count,
1, &onechange);
-
- DLIST_REMOVE(fsp->notify->requests, req);
- SAFE_FREE(req);
+ change_notify_remove_request(req);
return;
}
/*
* Someone has triggered a notify previously, queue the change for
- * later. TODO: Limit the number of changes queued.
+ * later. TODO: Limit the number of changes queued, test how filters
+ * apply here. Do we have to store them?
*/
if (!(changes = TALLOC_REALLOC_ARRAY(
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 0ef962ca0f..9061c75d33 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1825,7 +1825,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
{
uint16 *setup = *ppsetup;
files_struct *fsp;
- uint32 flags;
+ uint32 filter;
NTSTATUS status;
if(setup_count < 6) {
@@ -1833,7 +1833,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
}
fsp = file_fsp((char *)setup,4);
- flags = IVAL(setup, 0);
+ filter = IVAL(setup, 0);
DEBUG(3,("call_nt_transact_notify_change\n"));
@@ -1861,6 +1861,11 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
* We've got changes pending, respond immediately
*/
+ /*
+ * TODO: write a torture test to check the filtering behaviour
+ * here.
+ */
+
SMB_ASSERT(fsp->notify->requests == NULL);
change_notify_reply(inbuf, max_param_count,
@@ -1881,7 +1886,8 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
* No changes pending, queue the request
*/
- status = change_notify_add_request(inbuf, max_param_count, fsp);
+ status = change_notify_add_request(inbuf, max_param_count, filter,
+ fsp);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 895dd48221..81537e0be3 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -309,7 +309,7 @@ static NTSTATUS open_file(files_struct *fsp,
fsp);
}
- notify_action(conn, parent_dir, name,
+ notify_action(conn, parent_dir, name, -1,
NOTIFY_ACTION_ADDED);
}
@@ -1944,7 +1944,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name,
change_dir_owner_to_parent(conn, parent_dir, name, psbuf);
}
- notify_action(conn, parent_dir, dirname, NOTIFY_ACTION_ADDED);
+ notify_action(conn, parent_dir, dirname, FILE_NOTIFY_CHANGE_DIR_NAME,
+ NOTIFY_ACTION_ADDED);
return NT_STATUS_OK;
}
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index c6b3c17c01..ee930f20fb 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -2035,7 +2035,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
if (parent_dirname_talloc(tmp_talloc_ctx(), orig_name,
&dir, &fname)) {
- notify_action(conn, dir, fname,
+ notify_action(conn, dir, fname, -1,
NOTIFY_ACTION_REMOVED);
TALLOC_FREE(dir); /* not strictly necessary */
}
@@ -2097,7 +2097,8 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
}
if (SMB_VFS_UNLINK(conn,fname) == 0)
count++;
- notify_action(conn, directory, dname, NOTIFY_ACTION_REMOVED);
+ notify_action(conn, directory, dname,
+ -1, NOTIFY_ACTION_REMOVED);
DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
}
CloseDir(dir_hnd);
@@ -3964,7 +3965,7 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory)
if (parent_dirname_talloc(tmp_talloc_ctx(), directory,
&parent_dir, &dirname)) {
- notify_action(conn, parent_dir, dirname,
+ notify_action(conn, parent_dir, dirname, -1,
NOTIFY_ACTION_REMOVED);
TALLOC_FREE(parent_dir); /* Not strictly necessary */
}