//---------------------------------------------------------------------- // This software is part of the OpenBeOS distribution and is covered // by the OpenBeOS license. //--------------------------------------------------------------------- #include #include #include #include // TODO: Tests! // private libroot.so functions /*! \brief Subscribes a target to node and/or mount watching. Depending on \a flags, different actions are performed. If flags is \c 0, mount watching is requested. \a device and \a node must be \c -1 in this case. Otherwise node watching is requested. \a device and \a node must refer to a valid node, and \a flags must note contain the flag \c B_WATCH_MOUNT, but at least one of the other valid flags. \param device The device the node resides on (node_ref::device). \c -1, if only mount watching is requested. \param node The node ID of the node (node_ref::device). \c -1, if only mount watching is requested. \param flags A bit mask composed of the values specified in . \param port The port of the target (a looper port). \param handlerToken The token of the target handler. \c -2, if the preferred handler of the looper is the target. \return \c B_OK, if everything went fine, another error code otherwise. */ extern "C" status_t _kstart_watching_vnode_(dev_t device, ino_t node, uint32 flags, port_id port, int32 handlerToken); /*! \brief Unsubscribes a target from watching a node. \param device The device the node resides on (node_ref::device). \param node The node ID of the node (node_ref::device). \param port The port of the target (a looper port). \param handlerToken The token of the target handler. \c -2, if the preferred handler of the looper is the target. \return \c B_OK, if everything went fine, another error code otherwise. */ extern "C" status_t _kstop_watching_vnode_(dev_t device, ino_t node, port_id port, int32 handlerToken); /*! \brief Unsubscribes a target from node and mount monitoring. \param port The port of the target (a looper port). \param handlerToken The token of the target handler. \c -2, if the preferred handler of the looper is the target. \return \c B_OK, if everything went fine, another error code otherwise. */ extern "C" status_t _kstop_notifying_(port_id port, int32 handlerToken); // actual implementation // watch_node /*! \brief Subscribes a target to node and/or mount watching, or unsubscribes it from node watching. Depending of \a flags the action performed by this function varies: - \a flags is \c 0: The target is unsubscribed from watching the node. \a node must not be \c NULL in this case. - \a flags contains \c B_WATCH_MOUNT: The target is subscribed to mount watching. - \a flags contains at least one of \c B_WATCH_NAME, \c B_WATCH_STAT, \c B_WATCH_ATTR, or \c B_WATCH_DIRECTORY: The target is subscribed to watching the specified aspects of the node. \a node must not be \c NULL in this case. Note, that the latter two cases are not mutual exlusive, i.e. mount and node watching can be requested with a single call. \param node node_ref referring to the node to be watched. May be \c NULL, if only mount watching is requested. \param flags Flags indicating the actions to be performed. \param target Messenger referring to the target. Must be valid. \return \c B_OK, if everything went fine, another error code otherwise. */ status_t watch_node(const node_ref *node, uint32 flags, BMessenger target) { status_t error = (target.IsValid() ? B_OK : B_BAD_VALUE); if (error == B_OK) { BLooper *looper = NULL; BHandler *handler = target.Target(&looper); error = watch_node(node, flags, handler, looper); } return error; } // watch_node /*! \brief Subscribes a target to node and/or mount watching, or unsubscribes it from node watching. Depending of \a flags the action performed by this function varies: - \a flags is \c 0: The target is unsubscribed from watching the node. \a node must not be \c NULL in this case. - \a flags contains \c B_WATCH_MOUNT: The target is subscribed to mount watching. - \a flags contains at least one of \c B_WATCH_NAME, \c B_WATCH_STAT, \c B_WATCH_ATTR, or \c B_WATCH_DIRECTORY: The target is subscribed to watching the specified aspects of the node. \a node must not be \c NULL in this case. Note, that the latter two cases are not mutual exlusive, i.e. mount and node watching can be requested with a single call. \param node node_ref referring to the node to be watched. May be \c NULL, if only mount watching is requested. \param flags Flags indicating the actions to be performed. \param handler The target handler. May be \c NULL, if \a looper is not \c NULL. Then the preferred handler of the looper is targeted. \param looper The target looper. May be \c NULL, if \a handler is not \c NULL. Then the handler's looper is the target looper. \return \c B_OK, if everything went fine, another error code otherwise. */ status_t watch_node(const node_ref *node, uint32 flags, const BHandler *handler, const BLooper *looper) { status_t error = B_OK; // check looper and handler and get the handler token int32 handlerToken = -2; if (handler) { handlerToken = _get_object_token_(handler); if (looper) { if (looper != handler->Looper()) error = B_BAD_VALUE; } else { looper = handler->Looper(); if (!looper) error = B_BAD_VALUE; } } else if (!looper) error = B_BAD_VALUE; if (error == B_OK) { port_id port = _get_looper_port_(looper); if (flags == B_STOP_WATCHING) { // unsubscribe from node node watching if (node) { error = _kstop_watching_vnode_(node->device, node->node, port, handlerToken); } else error = B_BAD_VALUE; } else { // subscribe to... // mount watching if (flags & B_WATCH_MOUNT) { error = _kstart_watching_vnode_((dev_t)-1, (ino_t)-1, 0, port, handlerToken); flags &= ~B_WATCH_MOUNT; } // node watching if (error == B_OK && flags) { error = _kstart_watching_vnode_(node->device, node->node, flags, port, handlerToken); } } } return error; } // stop_watching /*! \brief Unsubscribes a target from node and mount monitoring. \param target Messenger referring to the target. Must be valid. \return \c B_OK, if everything went fine, another error code otherwise. */ status_t stop_watching(BMessenger target) { status_t error = (target.IsValid() ? B_OK : B_BAD_VALUE); if (error == B_OK) { BLooper *looper = NULL; BHandler *handler = target.Target(&looper); error = stop_watching(handler, looper); } return error; } // stop_watching /*! \brief Unsubscribes a target from node and mount monitoring. \param handler The target handler. May be \c NULL, if \a looper is not \c NULL. Then the preferred handler of the looper is targeted. \param looper The target looper. May be \c NULL, if \a handler is not \c NULL. Then the handler's looper is the target looper. \return \c B_OK, if everything went fine, another error code otherwise. */ status_t stop_watching(const BHandler *handler, const BLooper *looper) { status_t error = B_OK; // check looper and handler and get the handler token int32 handlerToken = -2; if (handler) { handlerToken = _get_object_token_(handler); if (looper) { if (looper != handler->Looper()) error = B_BAD_VALUE; } else { looper = handler->Looper(); if (!looper) error = B_BAD_VALUE; } } else if (!looper) error = B_BAD_VALUE; // unsubscribe if (error == B_OK) { port_id port = _get_looper_port_(looper); error = _kstop_notifying_(port, handlerToken); } return error; }