static void socket_set_poll_remove (DBusSocketSet *set, int fd) { DBusSocketSetPoll *self = socket_set_poll_cast (set); socket_set_poll_disable (set, fd); self->n_reserved--; _dbus_verbose ("after removing fd %d from %p, %d en/%d res/%d alloc\n", fd, self, self->n_fds, self->n_reserved, self->n_allocated); _dbus_assert (self->n_fds <= self->n_reserved); _dbus_assert (self->n_reserved <= self->n_allocated); if (self->n_reserved + MINIMUM_SIZE < self->n_allocated / 2) { /* Our array is twice as big as it needs to be - deflate it until it's * only slightly larger than the number reserved. */ DBusPollFD *new_fds = dbus_realloc (self->fds, sizeof (DBusPollFD) * (self->n_reserved + MINIMUM_SIZE)); _dbus_verbose ("before deflating %p, %d en/%d res/%d alloc\n", self, self->n_fds, self->n_reserved, self->n_allocated); if (_DBUS_UNLIKELY (new_fds == NULL)) { /* Weird. Oh well, never mind, the too-big array is untouched */ return; } self->fds = new_fds; self->n_allocated = self->n_reserved; } }
/** * Checks that the given range of the string is a valid member name * in the D-Bus protocol. This includes a length restriction, etc., * see the specification. * * @todo this is inconsistent with most of DBusString in that * it allows a start,len range that extends past the string end. * * @param str the string * @param start first byte index to check * @param len number of bytes to check * @returns #TRUE if the byte range exists and is a valid name */ dbus_bool_t _dbus_validate_member (const DBusString *str, int start, int len) { const unsigned char *s; const unsigned char *end; const unsigned char *member; _dbus_assert (start >= 0); _dbus_assert (len >= 0); _dbus_assert (start <= _dbus_string_get_length (str)); if (len > _dbus_string_get_length (str) - start) return FALSE; if (len > DBUS_MAXIMUM_NAME_LENGTH) return FALSE; if (len == 0) return FALSE; member = _dbus_string_get_const_data (str) + start; end = member + len; s = member; /* check special cases of first char so it doesn't have to be done * in the loop. Note we know len > 0 */ if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) return FALSE; else ++s; while (s != end) { if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) { return FALSE; } ++s; } return TRUE; }
/** * Checks that the given range of the string is a valid object path * name in the D-Bus protocol. Part of the validation ensures that * the object path contains only ASCII. * * @todo this is inconsistent with most of DBusString in that * it allows a start,len range that extends past the string end. * * @todo change spec to disallow more things, such as spaces in the * path name * * @param str the string * @param start first byte index to check * @param len number of bytes to check * @returns #TRUE if the byte range exists and is a valid name */ dbus_bool_t _dbus_validate_path (const DBusString *str, int start, int len) { const unsigned char *s; const unsigned char *end; const unsigned char *last_slash; _dbus_assert (start >= 0); _dbus_assert (len >= 0); _dbus_assert (start <= _dbus_string_get_length (str)); if (len > _dbus_string_get_length (str) - start) return FALSE; if (len == 0) return FALSE; s = _dbus_string_get_const_data (str) + start; end = s + len; if (*s != '/') return FALSE; last_slash = s; ++s; while (s != end) { if (*s == '/') { if ((s - last_slash) < 2) return FALSE; /* no empty path components allowed */ last_slash = s; } else { if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) return FALSE; } ++s; } if ((end - last_slash) < 2 && len > 1) return FALSE; /* trailing slash not allowed unless the string is "/" */ return TRUE; }
/** * Internals of _dbus_assert(); it's a function * rather than a macro with the inline code so * that the assertion failure blocks don't show up * in test suite coverage, and to shrink code size. * * @param condition TRUE if assertion succeeded * @param condition_text condition as a string * @param file file the assertion is in * @param line line the assertion is in * @param func function the assertion is in */ void _dbus_real_assert (dbus_bool_t condition, const char *condition_text, const char *file, int line, const char *func) { if (_DBUS_UNLIKELY (!condition)) { _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n", _dbus_pid_for_log (), condition_text, file, line, func); _dbus_abort (); } }
static unsigned int watch_flags_from_poll_revents (short revents) { unsigned int condition = 0; if (revents & _DBUS_POLLIN) condition |= DBUS_WATCH_READABLE; if (revents & _DBUS_POLLOUT) condition |= DBUS_WATCH_WRITABLE; if (revents & _DBUS_POLLHUP) condition |= DBUS_WATCH_HANGUP; if (revents & _DBUS_POLLERR) condition |= DBUS_WATCH_ERROR; if (_DBUS_UNLIKELY (revents & _DBUS_POLLNVAL)) condition |= _DBUS_WATCH_NVAL; return condition; }
/** * Decrements the reference count of a DBusServer. Finalizes the * server if the reference count reaches zero. * * The server must be disconnected before the refcount reaches zero. * * @param server the server. */ void dbus_server_unref (DBusServer *server) { dbus_int32_t old_refcount; /* keep this in sync with unref_unlocked */ _dbus_return_if_fail (server != NULL); old_refcount = _dbus_atomic_dec (&server->refcount); #ifndef DBUS_DISABLE_CHECKS if (_DBUS_UNLIKELY (old_refcount <= 0)) { /* undo side-effect first * please do not try to simplify the code here by using * _dbus_atomic_get(), why we don't use it is * because it issues another atomic operation even though * DBUS_DISABLE_CHECKS defined. * Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68303 */ _dbus_atomic_inc (&server->refcount); _dbus_warn_check_failed (_dbus_return_if_fail_warning_format, _DBUS_FUNCTION_NAME, "old_refcount > 0", __FILE__, __LINE__); return; } #endif _dbus_server_trace_ref (server, old_refcount, old_refcount - 1, "unref"); if (old_refcount == 1) { /* lock not held! */ _dbus_assert (server->disconnected); _dbus_assert (server->vtable->finalize != NULL); (* server->vtable->finalize) (server); } }
/** * Increments the reference count of a DBusServer. * * @param server the server. * @returns the server */ DBusServer * dbus_server_ref (DBusServer *server) { dbus_int32_t old_refcount; _dbus_return_val_if_fail (server != NULL, NULL); old_refcount = _dbus_atomic_inc (&server->refcount); #ifndef DBUS_DISABLE_CHECKS if (_DBUS_UNLIKELY (old_refcount <= 0)) { _dbus_atomic_dec (&server->refcount); _dbus_warn_return_if_fail (_DBUS_FUNCTION_NAME, "old_refcount > 0", __FILE__, __LINE__); return NULL; } #endif _dbus_server_trace_ref (server, old_refcount, old_refcount + 1, "ref"); return server; }
/** * Decrement the reference count on the babysitter object. * When the reference count of the babysitter object reaches * zero, the babysitter is killed and the child that was being * babysat gets emancipated. * * @param sitter the babysitter */ void _dbus_babysitter_unref (DBusBabysitter *sitter) { _dbus_assert (sitter != NULL); _dbus_assert (sitter->refcount > 0); sitter->refcount -= 1; if (sitter->refcount == 0) { /* If we haven't forked other babysitters * since this babysitter and socket were * created then this close will cause the * babysitter to wake up from poll with * a hangup and then the babysitter will * quit itself. */ close_socket_to_babysitter (sitter); close_error_pipe_from_child (sitter); if (sitter->sitter_pid > 0) { int status; int ret; /* It's possible the babysitter died on its own above * from the close, or was killed randomly * by some other process, so first try to reap it */ ret = waitpid (sitter->sitter_pid, &status, WNOHANG); /* If we couldn't reap the child then kill it, and * try again */ if (ret == 0) kill (sitter->sitter_pid, SIGKILL); if (ret == 0) { do { ret = waitpid (sitter->sitter_pid, &status, 0); } while (_DBUS_UNLIKELY (ret < 0 && errno == EINTR)); } if (ret < 0) { if (errno == ECHILD) _dbus_warn ("Babysitter process not available to be reaped; should not happen"); else _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s", errno, _dbus_strerror (errno)); } else { _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n", (long) ret, (long) sitter->sitter_pid); if (WIFEXITED (sitter->status)) _dbus_verbose ("Babysitter exited with status %d\n", WEXITSTATUS (sitter->status)); else if (WIFSIGNALED (sitter->status)) _dbus_verbose ("Babysitter received signal %d\n", WTERMSIG (sitter->status)); else _dbus_verbose ("Babysitter exited abnormally\n"); } sitter->sitter_pid = -1; } if (sitter->watches) _dbus_watch_list_free (sitter->watches); dbus_free (sitter->log_name); dbus_free (sitter); } }
/** * Checks that the given range of the string is a valid bus name in * the D-Bus protocol. This includes a length restriction, etc., see * the specification. * * @todo this is inconsistent with most of DBusString in that * it allows a start,len range that extends past the string end. * * @param str the string * @param start first byte index to check * @param len number of bytes to check * @returns #TRUE if the byte range exists and is a valid name */ dbus_bool_t _dbus_validate_bus_name (const DBusString *str, int start, int len) { const unsigned char *s; const unsigned char *end; const unsigned char *iface; const unsigned char *last_dot; _dbus_assert (start >= 0); _dbus_assert (len >= 0); _dbus_assert (start <= _dbus_string_get_length (str)); if (len > _dbus_string_get_length (str) - start) return FALSE; if (len > DBUS_MAXIMUM_NAME_LENGTH) return FALSE; if (len == 0) return FALSE; last_dot = NULL; iface = _dbus_string_get_const_data (str) + start; end = iface + len; s = iface; /* check special cases of first char so it doesn't have to be done * in the loop. Note we know len > 0 */ if (*s == ':') { /* unique name */ ++s; while (s != end) { if (*s == '.') { if (_DBUS_UNLIKELY ((s + 1) == end)) return FALSE; if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1)))) return FALSE; ++s; /* we just validated the next char, so skip two */ } else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) { return FALSE; } ++s; } return TRUE; } else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ return FALSE; else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s))) return FALSE; else ++s; while (s != end) { if (*s == '.') { if (_DBUS_UNLIKELY ((s + 1) == end)) return FALSE; else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1)))) return FALSE; last_dot = s; ++s; /* we just validated the next char, so skip two */ } else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) { return FALSE; } ++s; } if (_DBUS_UNLIKELY (last_dot == NULL)) return FALSE; return TRUE; }