summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2007-01-31 14:42:56 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:17:36 -0500
commit2852ecc67ebded7758a07d8fb72eef53bfa1c63a (patch)
tree4c69630521ef333be31379e0433fb53fad37919a
parentaccbfaa4c3ffe669cc29aac8a85c4144ad234e43 (diff)
downloadsamba-2852ecc67ebded7758a07d8fb72eef53bfa1c63a.tar.gz
samba-2852ecc67ebded7758a07d8fb72eef53bfa1c63a.tar.bz2
samba-2852ecc67ebded7758a07d8fb72eef53bfa1c63a.zip
r21092: Ok, that's the one that activates the Samba4 notify backend.
Now to clean up / fix lots of stuff. Volker (This used to be commit 9e7443fa1417c01be903b15073825dc4def78d99)
-rw-r--r--source3/include/smb.h1
-rw-r--r--source3/smbd/files.c5
-rw-r--r--source3/smbd/notify.c97
-rw-r--r--source3/smbd/nttrans.c54
-rw-r--r--source3/smbd/service.c7
5 files changed, 118 insertions, 46 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 5ad05cd2f9..4b4cebf5c1 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -669,6 +669,7 @@ typedef struct connection_struct {
name_compare_entry *aio_write_behind_list; /* Per-share list of files to use aio write behind on. */
struct dfree_cached_info *dfree_info;
struct trans_state *pending_trans;
+ struct notify_context *notify_ctx;
} connection_struct;
struct current_user {
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 982de4c55f..fc1700de11 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -483,7 +483,10 @@ void file_free(files_struct *fsp)
fsp->fh->ref_count--;
}
- TALLOC_FREE(fsp->notify);
+ if (fsp->notify) {
+ notify_remove(fsp->conn->notify_ctx, fsp);
+ TALLOC_FREE(fsp->notify);
+ }
bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
files_used--;
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 49219bcca5..93a6357d0c 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -159,7 +159,8 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count,
}
NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count,
- uint32 filter, struct files_struct *fsp)
+ uint32 filter, BOOL recursive,
+ struct files_struct *fsp)
{
struct notify_change_request *request = NULL;
struct notify_mid_map *map = NULL;
@@ -177,9 +178,7 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count,
request->max_param_count = max_param_count;
request->filter = filter;
request->fsp = fsp;
-
- request->backend_data = cnotify->notify_add(NULL, smbd_event_context(),
- fsp, &request->filter);
+ request->backend_data = NULL;
DLIST_ADD_END(fsp->notify->requests, request,
struct notify_change_request *);
@@ -343,6 +342,18 @@ void notify_action(connection_struct *conn, const char *parent,
return;
}
+ {
+ char *fullpath;
+
+ if (asprintf(&fullpath, "%s/%s/%s", conn->connectpath,
+ parent, name) != -1) {
+ notify_trigger(conn->notify_ctx, action, filter,
+ fullpath);
+ SAFE_FREE(fullpath);
+ }
+ return;
+ }
+
if (!(lck = get_share_mode_lock(NULL, sbuf.st_dev, sbuf.st_ino,
NULL, NULL))) {
return;
@@ -405,20 +416,21 @@ void notify_action(connection_struct *conn, const char *parent,
void notify_fname(connection_struct *conn, uint32 action, uint32 filter,
const char *path)
{
- char *parent;
- const char *name;
+ char *fullpath;
- if (!parent_dirname_talloc(tmp_talloc_ctx(), path, &parent, &name)) {
+ if (asprintf(&fullpath, "%s/%s", conn->connectpath, path) == -1) {
+ DEBUG(0, ("asprintf failed\n"));
return;
}
- notify_action(conn, parent, name, filter, action);
- TALLOC_FREE(parent);
+ notify_trigger(conn->notify_ctx, action, filter, fullpath);
+ SAFE_FREE(fullpath);
}
-void notify_fsp(files_struct *fsp, uint32 action, char *name)
+void notify_fsp(files_struct *fsp, uint32 action, const char *name)
{
struct notify_change *change, *changes;
+ char *name2;
if (fsp->notify == NULL) {
/*
@@ -427,35 +439,12 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name)
return;
}
- if (fsp->notify->requests != NULL) {
- /*
- * Someone is waiting for the change, trigger the reply
- * immediately.
- *
- * TODO: do we have to walk the lists of requests pending?
- */
-
- struct notify_change_request *req = fsp->notify->requests;
- struct notify_change onechange;
-
- if (name == NULL) {
- /*
- * Catch-all change, possibly from notify_hash.c
- */
- change_notify_reply(req->request_buf,
- req->max_param_count,
- -1, NULL);
+ if (!(name2 = talloc_strdup(fsp->notify, name))) {
+ DEBUG(0, ("talloc_strdup failed\n"));
return;
}
- onechange.action = action;
- onechange.name = name;
-
- change_notify_reply(req->request_buf, req->max_param_count,
- 1, &onechange);
- change_notify_remove_request(req);
- return;
- }
+ string_replace(name2, '/', '\\');
/*
* Someone has triggered a notify previously, queue the change for
@@ -468,6 +457,7 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name)
* W2k3 seems to store at most 30 changes.
*/
TALLOC_FREE(fsp->notify->changes);
+ TALLOC_FREE(name2);
fsp->notify->num_changes = -1;
return;
}
@@ -480,6 +470,7 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name)
fsp->notify, fsp->notify->changes,
struct notify_change, fsp->notify->num_changes+1))) {
DEBUG(0, ("talloc_realloc failed\n"));
+ TALLOC_FREE(name2);
return;
}
@@ -487,14 +478,40 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name)
change = &(fsp->notify->changes[fsp->notify->num_changes]);
- if (!(change->name = talloc_strdup(changes, name))) {
- DEBUG(0, ("talloc_strdup failed\n"));
- return;
- }
+ change->name = talloc_move(changes, &name2);
change->action = action;
fsp->notify->num_changes += 1;
+ if (fsp->notify->requests == NULL) {
+ /*
+ * Nobody is waiting, so don't send anything. The ot
+ */
+ return;
+ }
+
+ if (action == NOTIFY_ACTION_OLD_NAME) {
+ /*
+ * We have to send the two rename events in one reply. So hold
+ * the first part back.
+ */
return;
+ }
+
+ /*
+ * Someone is waiting for the change, trigger the reply immediately.
+ *
+ * TODO: do we have to walk the lists of requests pending?
+ */
+
+ change_notify_reply(fsp->notify->requests->request_buf,
+ fsp->notify->requests->max_param_count,
+ fsp->notify->num_changes,
+ fsp->notify->changes);
+
+ change_notify_remove_request(fsp->notify->requests);
+
+ TALLOC_FREE(fsp->notify->changes);
+ fsp->notify->num_changes = 0;
}
static void notify_message_callback(int msgtype, struct process_id pid,
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 07d345aacd..6db6311a29 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1787,6 +1787,13 @@ int reply_ntrename(connection_struct *conn,
don't allow a directory to be opened.
****************************************************************************/
+static void notify_callback(void *private_data, const struct notify_event *e)
+{
+ files_struct *fsp = (files_struct *)private_data;
+ DEBUG(10, ("notify_callback called for %s\n", fsp->fsp_name));
+ notify_fsp(fsp, e->action, e->path);
+}
+
static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
char *outbuf, int length,
int bufsize,
@@ -1801,6 +1808,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
files_struct *fsp;
uint32 filter;
NTSTATUS status;
+ BOOL recursive;
if(setup_count < 6) {
return ERROR_DOS(ERRDOS,ERRbadfunc);
@@ -1808,6 +1816,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
fsp = file_fsp((char *)setup,4);
filter = IVAL(setup, 0);
+ recursive = (SVAL(setup, 6) != 0) ? True : False;
DEBUG(3,("call_nt_transact_notify_change\n"));
@@ -1815,18 +1824,55 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
return ERROR_DOS(ERRDOS,ERRbadfid);
}
- DEBUG(3,("call_nt_transact_notify_change: notify change called on "
- "directory name = %s\n", fsp->fsp_name ));
+ {
+ char *filter_string;
+
+ if (!(filter_string = notify_filter_string(NULL, filter))) {
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ DEBUG(3,("call_nt_transact_notify_change: notify change "
+ "called on %s, filter = %s, recursive = %d\n",
+ fsp->fsp_name, filter_string, recursive));
+
+ TALLOC_FREE(filter_string);
+ }
if((!fsp->is_directory) || (conn != fsp->conn)) {
return ERROR_DOS(ERRDOS,ERRbadfid);
}
if (fsp->notify == NULL) {
+ char *fullpath;
+ struct notify_entry e;
+
if (!(fsp->notify = TALLOC_ZERO_P(
NULL, struct notify_change_buf))) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
+
+ if (asprintf(&fullpath, "%s/%s", fsp->conn->connectpath,
+ fsp->fsp_name) == -1) {
+ DEBUG(0, ("asprintf failed\n"));
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ e.path = fullpath;
+ e.filter = filter;
+ e.subdir_filter = 0;
+ if (recursive) {
+ e.subdir_filter = filter;
+ }
+
+ status = notify_add(fsp->conn->notify_ctx, &e, notify_callback,
+ fsp);
+ SAFE_FREE(fullpath);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("notify_add returned %s\n",
+ nt_errstr(status)));
+ return ERROR_NT(status);
+ }
}
if (fsp->notify->num_changes != 0) {
@@ -1840,8 +1886,6 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
* here.
*/
- SMB_ASSERT(fsp->notify->requests == NULL);
-
change_notify_reply(inbuf, max_param_count,
fsp->notify->num_changes,
fsp->notify->changes);
@@ -1861,7 +1905,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
*/
status = change_notify_add_request(inbuf, max_param_count, filter,
- fsp);
+ recursive, fsp);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index b5569c680d..8dbcc2b5ab 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -946,6 +946,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
set_conn_connectpath(conn,s);
}
+ if ((!conn->printer) && (!conn->ipc)) {
+ conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
+ smbd_messaging_context(),
+ smbd_event_context(),
+ conn->params);
+ }
+
/* ROOT Activities: */
/* check number of connections */
if (!claim_connection(conn,