1/*
2 * Copyright 2001-2010, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Ingo Weinhold, bonefish@@users.sf.net
7 *		Axel Dörfler, axeld@pinc-software.de
8 *		Clemens Zeidler <haiku@clemens-zeidler.de>
9 */
10
11
12#include <Messenger.h>
13#include <NodeMonitor.h>
14
15#include <MessengerPrivate.h>
16
17#include <syscalls.h>
18
19#include "node_monitor_private.h"
20
21
22// TODO: Tests!
23
24
25// watch_volume
26/*!	\brief Subscribes a target to watch node changes on a volume.
27
28	Depending of \a flags the action performed by this function varies:
29	- \a flags contains at least one of \c B_WATCH_NAME, \c B_WATCH_STAT,
30	  or \c B_WATCH_ATTR: The target is subscribed to
31	  watching the specified aspects of any node on the volume.
32
33	\param volume dev_t referring to the volume to be watched.
34	\param flags Flags indicating the actions to be performed.
35	\param target Messenger referring to the target. Must be valid.
36	\return \c B_OK, if everything went fine, another error code otherwise.
37*/
38status_t
39watch_volume(dev_t volume, uint32 flags, BMessenger target)
40{
41	if ((flags & (B_WATCH_NAME | B_WATCH_STAT | B_WATCH_ATTR)) == 0)
42		return B_BAD_VALUE;
43
44	flags |= B_WATCH_VOLUME;
45
46	BMessenger::Private messengerPrivate(target);
47	port_id port = messengerPrivate.Port();
48	int32 token = messengerPrivate.Token();
49	return _kern_start_watching(volume, (ino_t)-1, flags, port, token);
50}
51
52
53status_t
54watch_volume(dev_t volume, uint32 flags, const BHandler *handler,
55	const BLooper *looper)
56{
57	return watch_volume(volume, flags, BMessenger(handler, looper));
58}
59
60
61// watch_node
62/*!	\brief Subscribes a target to node and/or mount watching, or unsubscribes
63		   it from node watching.
64
65	Depending of \a flags the action performed by this function varies:
66	- \a flags is \c 0: The target is unsubscribed from watching the node.
67	  \a node must not be \c NULL in this case.
68	- \a flags contains \c B_WATCH_MOUNT: The target is subscribed to mount
69	  watching.
70	- \a flags contains at least one of \c B_WATCH_NAME, \c B_WATCH_STAT,
71	  \c B_WATCH_ATTR, or \c B_WATCH_DIRECTORY: The target is subscribed to
72	  watching the specified aspects of the node. \a node must not be \c NULL
73	  in this case.
74
75	Note, that the latter two cases are not mutual exlusive, i.e. mount and
76	node watching can be requested with a single call.
77
78	\param node node_ref referring to the node to be watched. May be \c NULL,
79		   if only mount watching is requested.
80	\param flags Flags indicating the actions to be performed.
81	\param target Messenger referring to the target. Must be valid.
82	\return \c B_OK, if everything went fine, another error code otherwise.
83*/
84status_t
85watch_node(const node_ref *node, uint32 flags, BMessenger target)
86{
87	if (!target.IsValid())
88		return B_BAD_VALUE;
89
90	BMessenger::Private messengerPrivate(target);
91	port_id port = messengerPrivate.Port();
92	int32 token = messengerPrivate.Token();
93
94	if (flags == B_STOP_WATCHING) {
95		// unsubscribe from node node watching
96		if (node == NULL)
97			return B_BAD_VALUE;
98
99		return _kern_stop_watching(node->device, node->node, port, token);
100	}
101
102	// subscribe to...
103	// mount watching
104	if (flags & B_WATCH_MOUNT) {
105		status_t status = _kern_start_watching((dev_t)-1, (ino_t)-1,
106			B_WATCH_MOUNT, port, token);
107		if (status < B_OK)
108			return status;
109
110		flags &= ~B_WATCH_MOUNT;
111	}
112
113	// node watching
114	if (flags != 0) {
115		if (node == NULL)
116			return B_BAD_VALUE;
117
118		return _kern_start_watching(node->device, node->node, flags, port,
119			token);
120	}
121
122	return B_OK;
123}
124
125// watch_node
126/*!	\brief Subscribes a target to node and/or mount watching, or unsubscribes
127		   it from node watching.
128
129	Depending of \a flags the action performed by this function varies:
130	- \a flags is \c 0: The target is unsubscribed from watching the node.
131	  \a node must not be \c NULL in this case.
132	- \a flags contains \c B_WATCH_MOUNT: The target is subscribed to mount
133	  watching.
134	- \a flags contains at least one of \c B_WATCH_NAME, \c B_WATCH_STAT,
135	  \c B_WATCH_ATTR, or \c B_WATCH_DIRECTORY: The target is subscribed to
136	  watching the specified aspects of the node. \a node must not be \c NULL
137	  in this case.
138
139	Note, that the latter two cases are not mutual exlusive, i.e. mount and
140	node watching can be requested with a single call.
141
142	\param node node_ref referring to the node to be watched. May be \c NULL,
143		   if only mount watching is requested.
144	\param flags Flags indicating the actions to be performed.
145	\param handler The target handler. May be \c NULL, if \a looper is not
146		   \c NULL. Then the preferred handler of the looper is targeted.
147	\param looper The target looper. May be \c NULL, if \a handler is not
148		   \c NULL. Then the handler's looper is the target looper.
149	\return \c B_OK, if everything went fine, another error code otherwise.
150*/
151status_t
152watch_node(const node_ref *node, uint32 flags, const BHandler *handler,
153	const BLooper *looper)
154{
155	return watch_node(node, flags, BMessenger(handler, looper));
156}
157
158
159/*!	\brief Unsubscribes a target from node and mount monitoring.
160	\param target Messenger referring to the target. Must be valid.
161	\return \c B_OK, if everything went fine, another error code otherwise.
162*/
163status_t
164stop_watching(BMessenger target)
165{
166	if (!target.IsValid())
167		return B_BAD_VALUE;
168
169	BMessenger::Private messengerPrivate(target);
170	port_id port = messengerPrivate.Port();
171	int32 token = messengerPrivate.Token();
172
173	return _kern_stop_notifying(port, token);
174}
175
176
177/*!	\brief Unsubscribes a target from node and mount monitoring.
178	\param handler The target handler. May be \c NULL, if \a looper is not
179		   \c NULL. Then the preferred handler of the looper is targeted.
180	\param looper The target looper. May be \c NULL, if \a handler is not
181		   \c NULL. Then the handler's looper is the target looper.
182	\return \c B_OK, if everything went fine, another error code otherwise.
183*/
184status_t
185stop_watching(const BHandler *handler, const BLooper *looper)
186{
187	return stop_watching(BMessenger(handler, looper));
188}
189
190