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;
}
Пример #4
0
/**
 * 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;
}
Пример #6
0
/**
 * 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);
    }
}
Пример #7
0
/**
 * 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;
}
Пример #8
0
/**
 * 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;
}