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,
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;
*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;
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,
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);
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.
****************************************************************************/
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);
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,
}
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;