2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Volker Lendecke 2014
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "librpc/gen_ndr/notify.h"
22 #include "librpc/gen_ndr/messaging.h"
23 #include "lib/dbwrap/dbwrap.h"
24 #include "lib/dbwrap/dbwrap_rbt.h"
25 #include "lib/util/server_id.h"
31 #include "lib/util/server_id_db.h"
32 #include "smbd/notifyd/notifyd.h"
34 struct notify_context
{
35 struct server_id notifyd
;
36 struct messaging_context
*msg_ctx
;
38 struct smbd_server_connection
*sconn
;
39 void (*callback
)(struct smbd_server_connection
*sconn
,
40 void *private_data
, struct timespec when
,
41 const struct notify_event
*ctx
);
44 static void notify_handler(struct messaging_context
*msg
, void *private_data
,
45 uint32_t msg_type
, struct server_id src
,
47 static int notify_context_destructor(struct notify_context
*ctx
);
49 struct notify_context
*notify_init(
50 TALLOC_CTX
*mem_ctx
, struct messaging_context
*msg
,
51 struct smbd_server_connection
*sconn
,
52 void (*callback
)(struct smbd_server_connection
*sconn
,
53 void *, struct timespec
,
54 const struct notify_event
*))
56 struct server_id_db
*names_db
;
57 struct notify_context
*ctx
;
60 ctx
= talloc(mem_ctx
, struct notify_context
);
67 ctx
->callback
= callback
;
69 names_db
= messaging_names_db(msg
);
70 if (!server_id_db_lookup_one(names_db
, "notify-daemon",
72 DBG_WARNING("No notify daemon around\n");
78 struct server_id_buf tmp
;
79 DBG_DEBUG("notifyd=%s\n",
80 server_id_str_buf(ctx
->notifyd
, &tmp
));
83 if (callback
!= NULL
) {
84 status
= messaging_register(msg
, ctx
, MSG_PVFS_NOTIFY
,
86 if (!NT_STATUS_IS_OK(status
)) {
87 DBG_WARNING("messaging_register failed: %s\n",
94 talloc_set_destructor(ctx
, notify_context_destructor
);
99 static int notify_context_destructor(struct notify_context
*ctx
)
101 if (ctx
->callback
!= NULL
) {
102 messaging_deregister(ctx
->msg_ctx
, MSG_PVFS_NOTIFY
, ctx
);
108 static void notify_handler(struct messaging_context
*msg
, void *private_data
,
109 uint32_t msg_type
, struct server_id src
,
112 struct notify_context
*ctx
= talloc_get_type_abort(
113 private_data
, struct notify_context
);
114 struct notify_event_msg
*event_msg
;
115 struct notify_event event
;
117 if (data
->length
< offsetof(struct notify_event_msg
, path
) + 1) {
118 DBG_WARNING("message too short: %zu\n", data
->length
);
121 if (data
->data
[data
->length
-1] != 0) {
122 DBG_WARNING("path not 0-terminated\n");
126 event_msg
= (struct notify_event_msg
*)data
->data
;
128 event
.action
= event_msg
->action
;
129 event
.path
= event_msg
->path
;
130 event
.private_data
= event_msg
->private_data
;
132 DBG_DEBUG("Got notify_event action=%"PRIu32
", private_data=%p, "
138 ctx
->callback(ctx
->sconn
, event
.private_data
, event_msg
->when
, &event
);
141 NTSTATUS
notify_add(struct notify_context
*ctx
,
142 const char *path
, uint32_t filter
, uint32_t subdir_filter
,
145 struct notify_rec_change_msg msg
= {};
151 return NT_STATUS_NOT_IMPLEMENTED
;
154 DBG_DEBUG("path=[%s], filter=%"PRIu32
", subdir_filter=%"PRIu32
", "
161 pathlen
= strlen(path
)+1;
163 clock_gettime_mono(&msg
.instance
.creation_time
);
164 msg
.instance
.filter
= filter
;
165 msg
.instance
.subdir_filter
= subdir_filter
;
166 msg
.instance
.private_data
= private_data
;
168 iov
[0].iov_base
= &msg
;
169 iov
[0].iov_len
= offsetof(struct notify_rec_change_msg
, path
);
170 iov
[1].iov_base
= discard_const_p(char, path
);
171 iov
[1].iov_len
= pathlen
;
173 status
= messaging_send_iov(
174 ctx
->msg_ctx
, ctx
->notifyd
, MSG_SMB_NOTIFY_REC_CHANGE
,
175 iov
, ARRAY_SIZE(iov
), NULL
, 0);
177 if (!NT_STATUS_IS_OK(status
)) {
178 DBG_DEBUG("messaging_send_iov returned %s\n",
186 NTSTATUS
notify_remove(struct notify_context
*ctx
, void *private_data
,
189 struct notify_rec_change_msg msg
= {};
193 /* see if change notify is enabled at all */
195 return NT_STATUS_NOT_IMPLEMENTED
;
198 msg
.instance
.private_data
= private_data
;
200 iov
[0].iov_base
= &msg
;
201 iov
[0].iov_len
= offsetof(struct notify_rec_change_msg
, path
);
202 iov
[1].iov_base
= path
;
203 iov
[1].iov_len
= strlen(path
)+1;
205 status
= messaging_send_iov(
206 ctx
->msg_ctx
, ctx
->notifyd
, MSG_SMB_NOTIFY_REC_CHANGE
,
207 iov
, ARRAY_SIZE(iov
), NULL
, 0);
212 void notify_trigger(struct notify_context
*ctx
,
213 uint32_t action
, uint32_t filter
,
214 const char *dir
, const char *name
)
216 struct notify_trigger_msg msg
;
220 DBG_DEBUG("notify_trigger called action=0x%"PRIx32
", "
221 "filter=0x%"PRIx32
", dir=%s, name=%s\n",
231 msg
.when
= timespec_current();
235 iov
[0].iov_base
= &msg
;
236 iov
[0].iov_len
= offsetof(struct notify_trigger_msg
, path
);
237 iov
[1].iov_base
= discard_const_p(char, dir
);
238 iov
[1].iov_len
= strlen(dir
);
239 iov
[2].iov_base
= &slash
;
241 iov
[3].iov_base
= discard_const_p(char, name
);
242 iov
[3].iov_len
= strlen(name
)+1;
245 ctx
->msg_ctx
, ctx
->notifyd
, MSG_SMB_NOTIFY_TRIGGER
,
246 iov
, ARRAY_SIZE(iov
), NULL
, 0);