MSG_SMB_FILE_PATHINFO
authorStefan Metzmacher <metze@samba.org>
Thu, 16 Aug 2018 23:50:08 +0000 (01:50 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 16 Aug 2018 23:50:08 +0000 (01:50 +0200)
librpc/idl/messaging.idl
source3/locking/locking.c
source3/locking/proto.h
source3/smbd/fileio.c
source3/smbd/process.c
source3/smbd/proto.h
source3/smbd/trans2.c

index c916768ccec744685e8c32e18ed27fd25d2598c0..2a2f67187d2f0c5f437f9eadb8a512941fcf0204 100644 (file)
@@ -110,6 +110,12 @@ interface messaging
                MSG_SMB_NOTIFY_REC_CHANGES      = 0x031E,
                MSG_SMB_NOTIFY_STARTED          = 0x031F,
 
+               /*
+                * Send to all open handles, if a
+                * SMB1 QUERY PATH INFO happened.
+                */
+               MSG_SMB_FILE_PATHINFO           = 0x0320,
+
                /* winbind messages */
                MSG_WINBIND_FINISHED            = 0x0401,
                MSG_WINBIND_FORGET_STATE        = 0x0402,
index 833734cd37fa0a4c3a0ad1eec2ab12b4c0ef44bf..a5dec6c254d572028d624522139199628d3a8bc1 100644 (file)
@@ -600,12 +600,15 @@ bool rename_share_filename(struct messaging_context *msg_ctx,
        return True;
 }
 
-void get_file_infos(struct file_id id,
-                   uint32_t name_hash,
-                   bool *delete_on_close,
-                   struct timespec *write_time)
+static void get_filepath_infos(struct file_id id,
+                              struct messaging_context *pathinfo_msg_ctx,
+                              uint32_t name_hash,
+                              bool *delete_on_close,
+                              struct timespec *write_time)
 {
        struct share_mode_lock *lck;
+       uint8_t msg[24] = {0, };
+       uint32_t i;
 
        if (delete_on_close) {
                *delete_on_close = false;
@@ -627,9 +630,59 @@ void get_file_infos(struct file_id id,
                *write_time = get_share_mode_write_time(lck);
        }
 
+       if (pathinfo_msg_ctx == NULL) {
+               TALLOC_FREE(lck);
+               return;
+       }
+
+       push_file_id_24((char *)msg, &id);
+
+       for (i = 0; i < lck->data->num_share_modes; i++) {
+               struct share_mode_entry *e = &lck->data->share_modes[i];
+
+               if (!is_valid_share_mode_entry(e)) {
+                       continue;
+               }
+
+               if (!serverid_exists(&e->pid)) {
+                       continue;
+               }
+
+               messaging_send_buf(pathinfo_msg_ctx,
+                                  e->pid,
+                                  MSG_SMB_FILE_PATHINFO,
+                                  msg,
+                                  sizeof(msg));
+       }
+
        TALLOC_FREE(lck);
 }
 
+void get_file_infos(struct file_id id,
+                   uint32_t name_hash,
+                   bool *delete_on_close,
+                   struct timespec *write_time)
+{
+       get_filepath_infos(id,
+                          NULL, /* pathinfo_msg_ctx */
+                          name_hash,
+                          delete_on_close,
+                          write_time);
+}
+
+void get_path_infos(struct file_id id,
+                   struct messaging_context *msg_ctx,
+                   uint32_t name_hash,
+                   bool *delete_on_close,
+                   struct timespec *write_time)
+{
+       get_filepath_infos(id,
+                          msg_ctx,
+                          name_hash,
+                          delete_on_close,
+                          write_time);
+}
+
 bool is_valid_share_mode_entry(const struct share_mode_entry *e)
 {
        int num_props = 0;
index 1e8ae049704ea22103158c60342457abd85a1dc0..d06144f9f0bfff43ba2551c94f70f0529d4f72c9 100644 (file)
@@ -171,6 +171,11 @@ void get_file_infos(struct file_id id,
                    uint32_t name_hash,
                    bool *delete_on_close,
                    struct timespec *write_time);
+void get_path_infos(struct file_id id,
+                   struct messaging_context *msg_ctx,
+                   uint32_t name_hash,
+                   bool *delete_on_close,
+                   struct timespec *write_time);
 bool is_valid_share_mode_entry(const struct share_mode_entry *e);
 bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx);
 bool set_share_mode(struct share_mode_lock *lck, struct files_struct *fsp,
index 833b50012e2cfe7a7d8925eebc3e63062f85c681..d83efde6abb086eb9d58286dcf45a10e69c53936 100644 (file)
@@ -271,7 +271,7 @@ void trigger_write_time_update_immediate(struct files_struct *fsp)
                  fsp_str_dbg(fsp)));
 
        /* After an immediate update, reset the trigger. */
-       fsp->update_write_time_triggered = true;
+       fsp->update_write_time_triggered = true; // TODO: false???
         fsp->update_write_time_on_close = false;
 
        ZERO_STRUCT(ft);
@@ -316,6 +316,62 @@ void mark_file_modified(files_struct *fsp)
                         dosmode | FILE_ATTRIBUTE_ARCHIVE, NULL, false);
 }
 
+/****************************************************************************
+ Receive notification that someone did a SMB1 QueryPathInfo on the file.
+ This changes the write time update behaviour on open handles.
+****************************************************************************/
+
+void msg_file_got_pathinfo(struct messaging_context *msg,
+                          void *private_data,
+                          uint32_t msg_type,
+                          struct server_id server_id,
+                          DATA_BLOB *data)
+{
+       struct smbd_server_connection *sconn =
+               talloc_get_type_abort(private_data,
+               struct smbd_server_connection);
+       struct files_struct *fsp = NULL;
+       struct file_id id;
+
+       if (data->data == NULL || data->length != 24) {
+               DBG_ERR("Got invalid msg len %zu\n", data->length);
+               return;
+       }
+
+       /* Unpack the message. */
+       pull_file_id_24((char *)data->data, &id);
+
+       DBG_DEBUG("Got PATHINFO notification file_id %s\n",
+                 file_id_string_tos(&id));
+
+       for(fsp = file_find_di_first(sconn, id); fsp;
+           fsp = file_find_di_next(fsp)) {
+
+               if (fsp->write_time_forced) {
+                       /*
+                        * No point - "sticky" write times
+                        * in effect.
+                        */
+                       continue;
+               }
+
+               if (!fsp->update_write_time_triggered) {
+                       /*
+                        * No write time update pending.
+                        */
+                       continue;
+               }
+
+               /*
+                * We cancel the timer, which means the write time update
+                * will happen on close.
+                */
+               DBG_INFO("Defer write time updates to close on %s\n",
+                        fsp_str_dbg(fsp));
+               TALLOC_FREE(fsp->update_write_time_event);
+       }
+}
+
 /****************************************************************************
  Write to a file.
 ****************************************************************************/
index 35b5f4df385deac116f7b565b464df73296ed554..c67d7eef7d5e2d1f694d299f331833dc956de9c2 100644 (file)
@@ -4092,6 +4092,8 @@ void smbd_process(struct tevent_context *ev_ctx,
                           MSG_SMB_CLOSE_FILE, msg_close_file);
        messaging_register(sconn->msg_ctx, sconn,
                           MSG_SMB_FILE_RENAME, msg_file_was_renamed);
+       messaging_register(sconn->msg_ctx, sconn,
+                          MSG_SMB_FILE_PATHINFO, msg_file_got_pathinfo);
 
        id_cache_register_msgs(sconn->msg_ctx);
        messaging_deregister(sconn->msg_ctx, ID_CACHE_KILL, NULL);
index 2a41d9d251ddc78e3af59357baa3f4a7f69a6438..45e39e9df37c170762cf2fbc91c24122f6a0fa8c 100644 (file)
@@ -332,6 +332,11 @@ ssize_t read_file(files_struct *fsp,char *data,off_t pos,size_t n);
 void fsp_flush_write_time_update(struct files_struct *fsp);
 void trigger_write_time_update(struct files_struct *fsp);
 void trigger_write_time_update_immediate(struct files_struct *fsp);
+void msg_file_got_pathinfo(struct messaging_context *msg,
+                          void *private_data,
+                          uint32_t msg_type,
+                          struct server_id server_id,
+                          DATA_BLOB *data);
 void mark_file_modified(files_struct *fsp);
 ssize_t write_file(struct smb_request *req,
                        files_struct *fsp,
index 0ec20fe6337f7643433ae66d42f4074c314b9fa2..a9d413bf3c3b7e4ccb8bb40401469cfce4946ceb 100644 (file)
@@ -5982,7 +5982,11 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                }
 
                fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
-               get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
+               get_path_infos(fileid,
+                              req->sconn->msg_ctx,
+                              name_hash,
+                              &delete_pending,
+                              &write_time_ts);
                if (delete_pending) {
                        reply_nterror(req, NT_STATUS_DELETE_PENDING);
                        return;