r21092: Ok, that's the one that activates the Samba4 notify backend.
authorVolker Lendecke <vlendec@samba.org>
Wed, 31 Jan 2007 14:42:56 +0000 (14:42 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:17:36 +0000 (12:17 -0500)
Now to clean up / fix lots of stuff.

Volker
(This used to be commit 9e7443fa1417c01be903b15073825dc4def78d99)

source3/include/smb.h
source3/smbd/files.c
source3/smbd/notify.c
source3/smbd/nttrans.c
source3/smbd/service.c

index 5ad05cd2f98c8b22ed11f3952b31c3b7b8dbc528..4b4cebf5c18fa7171174d0781c5f8add8b864b07 100644 (file)
@@ -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 {
index 982de4c55fd0658298c24ddfb1ac6f600de60134..fc1700de118898e4dfe3194fe15131406da465b0 100644 (file)
@@ -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--;
index 49219bcca5277b390dd6d9a3cddefc260fe6f8b5..93a6357d0c847cd8a51af75a484624fdcbbc34b4 100644 (file)
@@ -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,
index 07d345aacd4877f5f16fccb844270056cea9b274..6db6311a29bcc532dd6f3693d6256540156069db 100644 (file)
@@ -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);
        }
index b5569c680decb41c8d349c0d21c2c4b040022bef..8dbcc2b5abe622c44ea60ca3ae9e78b21024aab5 100644 (file)
@@ -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,