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 tevent_context
*ev
,
52 struct smbd_server_connection
*sconn
,
53 void (*callback
)(struct smbd_server_connection
*sconn
,
54 void *, struct timespec
,
55 const struct notify_event
*))
57 struct server_id_db
*names_db
;
58 struct notify_context
*ctx
;
61 ctx
= talloc(mem_ctx
, struct notify_context
);
68 ctx
->callback
= callback
;
70 names_db
= messaging_names_db(msg
);
71 if (!server_id_db_lookup_one(names_db
, "notify-daemon",
73 DEBUG(1, ("No notify daemon around\n"));
79 struct server_id_buf tmp
;
80 DBG_DEBUG("notifyd=%s\n",
81 server_id_str_buf(ctx
->notifyd
, &tmp
));
84 if (callback
!= NULL
) {
85 status
= messaging_register(msg
, ctx
, MSG_PVFS_NOTIFY
,
87 if (!NT_STATUS_IS_OK(status
)) {
88 DEBUG(1, ("messaging_register failed: %s\n",
95 talloc_set_destructor(ctx
, notify_context_destructor
);
100 static int notify_context_destructor(struct notify_context
*ctx
)
102 if (ctx
->callback
!= NULL
) {
103 messaging_deregister(ctx
->msg_ctx
, MSG_PVFS_NOTIFY
, ctx
);
109 static void notify_handler(struct messaging_context
*msg
, void *private_data
,
110 uint32_t msg_type
, struct server_id src
,
113 struct notify_context
*ctx
= talloc_get_type_abort(
114 private_data
, struct notify_context
);
115 struct notify_event_msg
*event_msg
;
116 struct notify_event event
;
118 if (data
->length
< offsetof(struct notify_event_msg
, path
) + 1) {
119 DEBUG(1, ("message too short: %u\n", (unsigned)data
->length
));
122 if (data
->data
[data
->length
-1] != 0) {
123 DEBUG(1, ("%s: path not 0-terminated\n", __func__
));
127 event_msg
= (struct notify_event_msg
*)data
->data
;
129 event
.action
= event_msg
->action
;
130 event
.path
= event_msg
->path
;
131 event
.private_data
= event_msg
->private_data
;
133 DEBUG(10, ("%s: Got notify_event action=%u, private_data=%p, "
134 "path=%s\n", __func__
, (unsigned)event
.action
,
135 event
.private_data
, event
.path
));
137 ctx
->callback(ctx
->sconn
, event
.private_data
, event_msg
->when
, &event
);
140 NTSTATUS
notify_add(struct notify_context
*ctx
,
141 const char *path
, uint32_t filter
, uint32_t subdir_filter
,
144 struct notify_rec_change_msg msg
= {};
150 return NT_STATUS_NOT_IMPLEMENTED
;
153 DEBUG(10, ("%s: path=[%s], filter=%u, subdir_filter=%u, "
154 "private_data=%p\n", __func__
, path
, (unsigned)filter
,
155 (unsigned)subdir_filter
, private_data
));
157 pathlen
= strlen(path
)+1;
159 clock_gettime_mono(&msg
.instance
.creation_time
);
160 msg
.instance
.filter
= filter
;
161 msg
.instance
.subdir_filter
= subdir_filter
;
162 msg
.instance
.private_data
= private_data
;
164 iov
[0].iov_base
= &msg
;
165 iov
[0].iov_len
= offsetof(struct notify_rec_change_msg
, path
);
166 iov
[1].iov_base
= discard_const_p(char, path
);
167 iov
[1].iov_len
= pathlen
;
169 status
= messaging_send_iov(
170 ctx
->msg_ctx
, ctx
->notifyd
, MSG_SMB_NOTIFY_REC_CHANGE
,
171 iov
, ARRAY_SIZE(iov
), NULL
, 0);
173 if (!NT_STATUS_IS_OK(status
)) {
174 DEBUG(10, ("messaging_send_iov returned %s\n",
182 NTSTATUS
notify_remove(struct notify_context
*ctx
, void *private_data
,
185 struct notify_rec_change_msg msg
= {};
189 /* see if change notify is enabled at all */
191 return NT_STATUS_NOT_IMPLEMENTED
;
194 msg
.instance
.private_data
= private_data
;
196 iov
[0].iov_base
= &msg
;
197 iov
[0].iov_len
= offsetof(struct notify_rec_change_msg
, path
);
198 iov
[1].iov_base
= path
;
199 iov
[1].iov_len
= strlen(path
)+1;
201 status
= messaging_send_iov(
202 ctx
->msg_ctx
, ctx
->notifyd
, MSG_SMB_NOTIFY_REC_CHANGE
,
203 iov
, ARRAY_SIZE(iov
), NULL
, 0);
208 void notify_trigger(struct notify_context
*ctx
,
209 uint32_t action
, uint32_t filter
,
210 const char *dir
, const char *name
)
212 struct notify_trigger_msg msg
;
216 DEBUG(10, ("notify_trigger called action=0x%x, filter=0x%x, "
217 "dir=%s, name=%s\n", (unsigned)action
, (unsigned)filter
,
224 msg
.when
= timespec_current();
228 iov
[0].iov_base
= &msg
;
229 iov
[0].iov_len
= offsetof(struct notify_trigger_msg
, path
);
230 iov
[1].iov_base
= discard_const_p(char, dir
);
231 iov
[1].iov_len
= strlen(dir
);
232 iov
[2].iov_base
= &slash
;
234 iov
[3].iov_base
= discard_const_p(char, name
);
235 iov
[3].iov_len
= strlen(name
)+1;
238 ctx
->msg_ctx
, ctx
->notifyd
, MSG_SMB_NOTIFY_TRIGGER
,
239 iov
, ARRAY_SIZE(iov
), NULL
, 0);
242 NTSTATUS
notify_walk(struct notify_context
*notify
,
243 bool (*fn
)(const char *path
, struct server_id server
,
244 const struct notify_instance
*instance
,
248 struct tevent_context
*ev
;
249 struct tevent_req
*req
;
250 struct messaging_rec
*rec
;
256 ev
= samba_tevent_context_init(notify
);
258 return NT_STATUS_NO_MEMORY
;
261 req
= messaging_read_send(ev
, ev
, notify
->msg_ctx
, MSG_SMB_NOTIFY_DB
);
264 return NT_STATUS_NO_MEMORY
;
267 ok
= tevent_req_set_endtime(req
, ev
, timeval_current_ofs(10, 0));
270 return NT_STATUS_NO_MEMORY
;
273 status
= messaging_send_buf(notify
->msg_ctx
, notify
->notifyd
,
274 MSG_SMB_NOTIFY_GET_DB
, NULL
, 0);
275 if (!NT_STATUS_IS_OK(status
)) {
276 DEBUG(10, ("%s: messaging_send_buf failed\n",
282 ok
= tevent_req_poll(req
, ev
);
284 DEBUG(10, ("%s: tevent_req_poll failed\n", __func__
));
286 return NT_STATUS_INTERNAL_ERROR
;
289 ret
= messaging_read_recv(req
, ev
, &rec
);
291 DEBUG(10, ("%s: messaging_read_recv failed: %s\n",
292 __func__
, strerror(ret
)));
294 return map_nt_error_from_unix(ret
);
297 ret
= notifyd_parse_db(rec
->buf
.data
, rec
->buf
.length
, &log_idx
,
300 DEBUG(10, ("%s: notifyd_parse_db failed: %s\n",
301 __func__
, strerror(ret
)));
303 return map_nt_error_from_unix(ret
);