1 //---------------------------------------------------------------------- 2 // This software is part of the OpenBeOS distribution and is covered 3 // by the OpenBeOS license. 4 //--------------------------------------------------------------------- 5 6 #include <AppMisc.h> 7 #include <Looper.h> 8 #include <Messenger.h> 9 #include <NodeMonitor.h> 10 11 // TODO: Tests! 12 13 // private libroot.so functions 14 15 /*! \brief Subscribes a target to node and/or mount watching. 16 17 Depending on \a flags, different actions are performed. If flags is \c 0, 18 mount watching is requested. \a device and \a node must be \c -1 in this 19 case. Otherwise node watching is requested. \a device and \a node must 20 refer to a valid node, and \a flags must note contain the flag 21 \c B_WATCH_MOUNT, but at least one of the other valid flags. 22 23 \param device The device the node resides on (node_ref::device). \c -1, if 24 only mount watching is requested. 25 \param node The node ID of the node (node_ref::device). \c -1, if 26 only mount watching is requested. 27 \param flags A bit mask composed of the values specified in 28 <NodeMonitor.h>. 29 \param port The port of the target (a looper port). 30 \param handlerToken The token of the target handler. \c -2, if the 31 preferred handler of the looper is the target. 32 \return \c B_OK, if everything went fine, another error code otherwise. 33 */ 34 extern "C" status_t _kstart_watching_vnode_(dev_t device, ino_t node, 35 uint32 flags, port_id port, 36 int32 handlerToken); 37 38 /*! \brief Unsubscribes a target from watching a node. 39 \param device The device the node resides on (node_ref::device). 40 \param node The node ID of the node (node_ref::device). 41 \param port The port of the target (a looper port). 42 \param handlerToken The token of the target handler. \c -2, if the 43 preferred handler of the looper is the target. 44 \return \c B_OK, if everything went fine, another error code otherwise. 45 */ 46 extern "C" status_t _kstop_watching_vnode_(dev_t device, ino_t node, 47 port_id port, int32 handlerToken); 48 49 50 /*! \brief Unsubscribes a target from node and mount monitoring. 51 \param port The port of the target (a looper port). 52 \param handlerToken The token of the target handler. \c -2, if the 53 preferred handler of the looper is the target. 54 \return \c B_OK, if everything went fine, another error code otherwise. 55 */ 56 extern "C" status_t _kstop_notifying_(port_id port, int32 handlerToken); 57 58 59 // actual implementation 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 */ 84 status_t 85 watch_node(const node_ref *node, uint32 flags, BMessenger target) 86 { 87 status_t error = (target.IsValid() ? B_OK : B_BAD_VALUE); 88 if (error == B_OK) { 89 BLooper *looper = NULL; 90 BHandler *handler = target.Target(&looper); 91 error = watch_node(node, flags, handler, looper); 92 } 93 return error; 94 } 95 96 // watch_node 97 /*! \brief Subscribes a target to node and/or mount watching, or unsubscribes 98 it from node watching. 99 100 Depending of \a flags the action performed by this function varies: 101 - \a flags is \c 0: The target is unsubscribed from watching the node. 102 \a node must not be \c NULL in this case. 103 - \a flags contains \c B_WATCH_MOUNT: The target is subscribed to mount 104 watching. 105 - \a flags contains at least one of \c B_WATCH_NAME, \c B_WATCH_STAT, 106 \c B_WATCH_ATTR, or \c B_WATCH_DIRECTORY: The target is subscribed to 107 watching the specified aspects of the node. \a node must not be \c NULL 108 in this case. 109 110 Note, that the latter two cases are not mutual exlusive, i.e. mount and 111 node watching can be requested with a single call. 112 113 \param node node_ref referring to the node to be watched. May be \c NULL, 114 if only mount watching is requested. 115 \param flags Flags indicating the actions to be performed. 116 \param handler The target handler. May be \c NULL, if \a looper is not 117 \c NULL. Then the preferred handler of the looper is targeted. 118 \param looper The target looper. May be \c NULL, if \a handler is not 119 \c NULL. Then the handler's looper is the target looper. 120 \return \c B_OK, if everything went fine, another error code otherwise. 121 */ 122 status_t 123 watch_node(const node_ref *node, uint32 flags, const BHandler *handler, 124 const BLooper *looper) 125 { 126 status_t error = B_OK; 127 // check looper and handler and get the handler token 128 int32 handlerToken = -2; 129 if (handler) { 130 handlerToken = _get_object_token_(handler); 131 if (looper) { 132 if (looper != handler->Looper()) 133 error = B_BAD_VALUE; 134 } else { 135 looper = handler->Looper(); 136 if (!looper) 137 error = B_BAD_VALUE; 138 } 139 } else if (!looper) 140 error = B_BAD_VALUE; 141 if (error == B_OK) { 142 port_id port = _get_looper_port_(looper); 143 if (flags == B_STOP_WATCHING) { 144 // unsubscribe from node node watching 145 if (node) { 146 error = _kstop_watching_vnode_(node->device, node->node, port, 147 handlerToken); 148 } else 149 error = B_BAD_VALUE; 150 } else { 151 // subscribe to... 152 // mount watching 153 if (flags & B_WATCH_MOUNT) { 154 error = _kstart_watching_vnode_((dev_t)-1, (ino_t)-1, 0, port, handlerToken); 155 flags &= ~B_WATCH_MOUNT; 156 } 157 // node watching 158 if (error == B_OK && flags) { 159 error = _kstart_watching_vnode_(node->device, node->node, 160 flags, port, handlerToken); 161 } 162 } 163 } 164 return error; 165 } 166 167 // stop_watching 168 /*! \brief Unsubscribes a target from node and mount monitoring. 169 \param target Messenger referring to the target. Must be valid. 170 \return \c B_OK, if everything went fine, another error code otherwise. 171 */ 172 status_t 173 stop_watching(BMessenger target) 174 { 175 status_t error = (target.IsValid() ? B_OK : B_BAD_VALUE); 176 if (error == B_OK) { 177 BLooper *looper = NULL; 178 BHandler *handler = target.Target(&looper); 179 error = stop_watching(handler, looper); 180 } 181 return error; 182 } 183 184 // stop_watching 185 /*! \brief Unsubscribes a target from node and mount monitoring. 186 \param handler The target handler. May be \c NULL, if \a looper is not 187 \c NULL. Then the preferred handler of the looper is targeted. 188 \param looper The target looper. May be \c NULL, if \a handler is not 189 \c NULL. Then the handler's looper is the target looper. 190 \return \c B_OK, if everything went fine, another error code otherwise. 191 */ 192 status_t 193 stop_watching(const BHandler *handler, const BLooper *looper) 194 { 195 status_t error = B_OK; 196 // check looper and handler and get the handler token 197 int32 handlerToken = -2; 198 if (handler) { 199 handlerToken = _get_object_token_(handler); 200 if (looper) { 201 if (looper != handler->Looper()) 202 error = B_BAD_VALUE; 203 } else { 204 looper = handler->Looper(); 205 if (!looper) 206 error = B_BAD_VALUE; 207 } 208 } else if (!looper) 209 error = B_BAD_VALUE; 210 // unsubscribe 211 if (error == B_OK) { 212 port_id port = _get_looper_port_(looper); 213 error = _kstop_notifying_(port, handlerToken); 214 } 215 return error; 216 } 217 218