diff options
-rw-r--r-- | source3/include/smb.h | 1 | ||||
-rw-r--r-- | source3/smbd/notify.c | 40 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 12 | ||||
-rw-r--r-- | source3/smbd/open.c | 5 | ||||
-rw-r--r-- | source3/smbd/reply.c | 7 |
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 */ } |