2005-01-16 Havoc Pennington <hp@redhat.com>

This is about it on what can be disabled/deleted from libdbus
	easily, back below 150K anyhow. Deeper cuts are more work than
	just turning the code off as I've done here.

	* dbus/dbus-marshal-basic.c (_dbus_pack_int32): we don't need the
	signed int convenience funcs

	* dbus/dbus-internals.c (_dbus_verbose_real): omit when not in
	verbose mode

	* dbus/dbus-string-util.c, dbus/dbus-string.c: more breaking
	things out of libdbus

	* dbus/dbus-sysdeps.c, dbus/dbus-sysdeps-util.c: same

	* dbus/dbus-hash.c: purge the TWO_STRINGS crap (well, make it
	tests-enabled-only, though it should probably be deleted)

	* dbus/dbus-message-util.c: same stuff

	* dbus/dbus-auth-util.c: same stuff
This commit is contained in:
Havoc Pennington 2005-01-17 03:53:40 +00:00
parent 4c1a2a760b
commit 7bf62e31a3
26 changed files with 6517 additions and 5626 deletions

View file

@ -1,3 +1,27 @@
2005-01-16 Havoc Pennington <hp@redhat.com>
This is about it on what can be disabled/deleted from libdbus
easily, back below 150K anyhow. Deeper cuts are more work than
just turning the code off as I've done here.
* dbus/dbus-marshal-basic.c (_dbus_pack_int32): we don't need the
signed int convenience funcs
* dbus/dbus-internals.c (_dbus_verbose_real): omit when not in
verbose mode
* dbus/dbus-string-util.c, dbus/dbus-string.c: more breaking
things out of libdbus
* dbus/dbus-sysdeps.c, dbus/dbus-sysdeps-util.c: same
* dbus/dbus-hash.c: purge the TWO_STRINGS crap (well, make it
tests-enabled-only, though it should probably be deleted)
* dbus/dbus-message-util.c: same stuff
* dbus/dbus-auth-util.c: same stuff
2005-01-16 Havoc Pennington <hp@redhat.com>
* dbus/dbus-userdb-util.c: split out part of dbus-userdb.c

View file

@ -62,15 +62,16 @@ DBUS_LIB_SOURCES= \
dbus-marshal-validate.h \
dbus-message.c \
dbus-message-internal.h \
dbus-message-private.h \
dbus-object-tree.c \
dbus-object-tree.h \
dbus-pending-call.c \
dbus-resources.c \
dbus-resources.h \
dbus-server.c \
dbus-server-protected.h \
dbus-server-debug-pipe.c \
dbus-server-debug-pipe.h \
dbus-server-protected.h \
dbus-server-unix.c \
dbus-server-unix.h \
dbus-sha.c \
@ -121,16 +122,18 @@ DBUS_SHARED_SOURCES= \
### should be underscore-prefixed but don't really need
### to be unless they move to DBUS_SHARED_SOURCES later)
DBUS_UTIL_SOURCES= \
dbus-auth-util.c \
dbus-mainloop.c \
dbus-mainloop.h \
dbus-marshal-recursive-util.c \
dbus-message-util.c \
dbus-spawn.c \
dbus-spawn.h \
dbus-string-util.c \
dbus-sysdeps-util.c \
dbus-sysdeps-util.h \
dbus-test.c \
dbus-test.h \
dbus-userdb-util.c \
dbus-userdb-util.h
dbus-userdb-util.c
libdbus_1_la_SOURCES= \
$(DBUS_LIB_SOURCES) \

169
dbus/dbus-auth-util.c Normal file
View file

@ -0,0 +1,169 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-auth-util.c Would be in dbus-auth.c, but only used for tests/bus
*
* Copyright (C) 2002, 2003, 2004 Red Hat Inc.
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "dbus-internals.h"
#include "dbus-test.h"
#include "dbus-auth.h"
/**
* @addtogroup DBusAuth
* @{
*/
/** @} */
#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
#include "dbus-auth-script.h"
#include <stdio.h>
static dbus_bool_t
process_test_subdir (const DBusString *test_base_dir,
const char *subdir)
{
DBusString test_directory;
DBusString filename;
DBusDirIter *dir;
dbus_bool_t retval;
DBusError error;
retval = FALSE;
dir = NULL;
if (!_dbus_string_init (&test_directory))
_dbus_assert_not_reached ("didn't allocate test_directory\n");
_dbus_string_init_const (&filename, subdir);
if (!_dbus_string_copy (test_base_dir, 0,
&test_directory, 0))
_dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
if (!_dbus_concat_dir_and_file (&test_directory, &filename))
_dbus_assert_not_reached ("couldn't allocate full path");
_dbus_string_free (&filename);
if (!_dbus_string_init (&filename))
_dbus_assert_not_reached ("didn't allocate filename string\n");
dbus_error_init (&error);
dir = _dbus_directory_open (&test_directory, &error);
if (dir == NULL)
{
_dbus_warn ("Could not open %s: %s\n",
_dbus_string_get_const_data (&test_directory),
error.message);
dbus_error_free (&error);
goto failed;
}
printf ("Testing %s:\n", subdir);
next:
while (_dbus_directory_get_next_file (dir, &filename, &error))
{
DBusString full_path;
if (!_dbus_string_init (&full_path))
_dbus_assert_not_reached ("couldn't init string");
if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
_dbus_assert_not_reached ("couldn't copy dir to full_path");
if (!_dbus_concat_dir_and_file (&full_path, &filename))
_dbus_assert_not_reached ("couldn't concat file to dir");
if (!_dbus_string_ends_with_c_str (&filename, ".auth-script"))
{
_dbus_verbose ("Skipping non-.auth-script file %s\n",
_dbus_string_get_const_data (&filename));
_dbus_string_free (&full_path);
goto next;
}
printf (" %s\n", _dbus_string_get_const_data (&filename));
if (!_dbus_auth_script_run (&full_path))
{
_dbus_string_free (&full_path);
goto failed;
}
else
_dbus_string_free (&full_path);
}
if (dbus_error_is_set (&error))
{
_dbus_warn ("Could not get next file in %s: %s\n",
_dbus_string_get_const_data (&test_directory), error.message);
dbus_error_free (&error);
goto failed;
}
retval = TRUE;
failed:
if (dir)
_dbus_directory_close (dir);
_dbus_string_free (&test_directory);
_dbus_string_free (&filename);
return retval;
}
static dbus_bool_t
process_test_dirs (const char *test_data_dir)
{
DBusString test_directory;
dbus_bool_t retval;
retval = FALSE;
_dbus_string_init_const (&test_directory, test_data_dir);
if (!process_test_subdir (&test_directory, "auth"))
goto failed;
retval = TRUE;
failed:
_dbus_string_free (&test_directory);
return retval;
}
dbus_bool_t
_dbus_auth_test (const char *test_data_dir)
{
if (test_data_dir == NULL)
return TRUE;
if (!process_test_dirs (test_data_dir))
return FALSE;
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */

View file

@ -2392,139 +2392,4 @@ _dbus_auth_set_context (DBusAuth *auth,
/** @} */
#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
#include "dbus-auth-script.h"
#include <stdio.h>
static dbus_bool_t
process_test_subdir (const DBusString *test_base_dir,
const char *subdir)
{
DBusString test_directory;
DBusString filename;
DBusDirIter *dir;
dbus_bool_t retval;
DBusError error;
retval = FALSE;
dir = NULL;
if (!_dbus_string_init (&test_directory))
_dbus_assert_not_reached ("didn't allocate test_directory\n");
_dbus_string_init_const (&filename, subdir);
if (!_dbus_string_copy (test_base_dir, 0,
&test_directory, 0))
_dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
if (!_dbus_concat_dir_and_file (&test_directory, &filename))
_dbus_assert_not_reached ("couldn't allocate full path");
_dbus_string_free (&filename);
if (!_dbus_string_init (&filename))
_dbus_assert_not_reached ("didn't allocate filename string\n");
dbus_error_init (&error);
dir = _dbus_directory_open (&test_directory, &error);
if (dir == NULL)
{
_dbus_warn ("Could not open %s: %s\n",
_dbus_string_get_const_data (&test_directory),
error.message);
dbus_error_free (&error);
goto failed;
}
printf ("Testing %s:\n", subdir);
next:
while (_dbus_directory_get_next_file (dir, &filename, &error))
{
DBusString full_path;
if (!_dbus_string_init (&full_path))
_dbus_assert_not_reached ("couldn't init string");
if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
_dbus_assert_not_reached ("couldn't copy dir to full_path");
if (!_dbus_concat_dir_and_file (&full_path, &filename))
_dbus_assert_not_reached ("couldn't concat file to dir");
if (!_dbus_string_ends_with_c_str (&filename, ".auth-script"))
{
_dbus_verbose ("Skipping non-.auth-script file %s\n",
_dbus_string_get_const_data (&filename));
_dbus_string_free (&full_path);
goto next;
}
printf (" %s\n", _dbus_string_get_const_data (&filename));
if (!_dbus_auth_script_run (&full_path))
{
_dbus_string_free (&full_path);
goto failed;
}
else
_dbus_string_free (&full_path);
}
if (dbus_error_is_set (&error))
{
_dbus_warn ("Could not get next file in %s: %s\n",
_dbus_string_get_const_data (&test_directory), error.message);
dbus_error_free (&error);
goto failed;
}
retval = TRUE;
failed:
if (dir)
_dbus_directory_close (dir);
_dbus_string_free (&test_directory);
_dbus_string_free (&filename);
return retval;
}
static dbus_bool_t
process_test_dirs (const char *test_data_dir)
{
DBusString test_directory;
dbus_bool_t retval;
retval = FALSE;
_dbus_string_init_const (&test_directory, test_data_dir);
if (!process_test_subdir (&test_directory, "auth"))
goto failed;
retval = TRUE;
failed:
_dbus_string_free (&test_directory);
return retval;
}
dbus_bool_t
_dbus_auth_test (const char *test_data_dir)
{
if (test_data_dir == NULL)
return TRUE;
if (!process_test_dirs (test_data_dir))
return FALSE;
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */
/* tests in dbus-auth-util.c */

View file

@ -231,13 +231,17 @@ static DBusHashEntry* find_string_function (DBusHashTable *table,
dbus_bool_t create_if_not_found,
DBusHashEntry ***bucket,
DBusPreallocatedHash *preallocated);
#ifdef DBUS_BUILD_TESTS
static DBusHashEntry* find_two_strings_function (DBusHashTable *table,
void *key,
dbus_bool_t create_if_not_found,
DBusHashEntry ***bucket,
DBusPreallocatedHash *preallocated);
#endif
static unsigned int string_hash (const char *str);
#ifdef DBUS_BUILD_TESTS
static unsigned int two_strings_hash (const char *str);
#endif
static void rebuild_table (DBusHashTable *table);
static DBusHashEntry* alloc_entry (DBusHashTable *table);
static void remove_entry (DBusHashTable *table,
@ -330,7 +334,9 @@ _dbus_hash_table_new (DBusHashType type,
table->find_function = find_string_function;
break;
case DBUS_HASH_TWO_STRINGS:
#ifdef DBUS_BUILD_TESTS
table->find_function = find_two_strings_function;
#endif
break;
default:
_dbus_assert_not_reached ("Unknown hash table type");
@ -696,6 +702,7 @@ _dbus_hash_iter_get_string_key (DBusHashIter *iter)
return real->entry->key;
}
#ifdef DBUS_BUILD_TESTS
/**
* Gets the key for the current entry.
* Only works for hash tables of type #DBUS_HASH_TWO_STRINGS
@ -713,6 +720,7 @@ _dbus_hash_iter_get_two_strings_key (DBusHashIter *iter)
return real->entry->key;
}
#endif /* DBUS_BUILD_TESTS */
/**
* A low-level but efficient interface for manipulating the hash
@ -849,6 +857,7 @@ string_hash (const char *str)
return h;
}
#ifdef DBUS_BUILD_TESTS
/* This hashes a memory block with two nul-terminated strings
* in it, used in dbus-object-registry.c at the moment.
*/
@ -867,6 +876,7 @@ two_strings_hash (const char *str)
return h;
}
#endif /* DBUS_BUILD_TESTS */
/** Key comparison function */
typedef int (* KeyCompareFunc) (const void *key_a, const void *key_b);
@ -928,6 +938,7 @@ find_string_function (DBusHashTable *table,
preallocated);
}
#ifdef DBUS_BUILD_TESTS
static int
two_strings_cmp (const char *a,
const char *b)
@ -945,7 +956,9 @@ two_strings_cmp (const char *a,
return strcmp (a + len_a + 1, b + len_b + 1);
}
#endif
#ifdef DBUS_BUILD_TESTS
static DBusHashEntry*
find_two_strings_function (DBusHashTable *table,
void *key,
@ -961,6 +974,7 @@ find_two_strings_function (DBusHashTable *table,
(KeyCompareFunc) two_strings_cmp, create_if_not_found, bucket,
preallocated);
}
#endif /* DBUS_BUILD_TESTS */
static DBusHashEntry*
find_direct_function (DBusHashTable *table,
@ -1077,7 +1091,12 @@ rebuild_table (DBusHashTable *table)
idx = string_hash (entry->key) & table->mask;
break;
case DBUS_HASH_TWO_STRINGS:
#ifdef DBUS_BUILD_TESTS
idx = two_strings_hash (entry->key) & table->mask;
#else
idx = 0;
_dbus_assert_not_reached ("two-strings is not enabled");
#endif
break;
case DBUS_HASH_INT:
case DBUS_HASH_ULONG:
@ -1127,6 +1146,7 @@ _dbus_hash_table_lookup_string (DBusHashTable *table,
return NULL;
}
#ifdef DBUS_BUILD_TESTS
/**
* Looks up the value for a given string in a hash table
* of type #DBUS_HASH_TWO_STRINGS. Returns %NULL if the value
@ -1151,6 +1171,7 @@ _dbus_hash_table_lookup_two_strings (DBusHashTable *table,
else
return NULL;
}
#endif /* DBUS_BUILD_TESTS */
/**
* Looks up the value for a given integer in a hash table
@ -1258,6 +1279,7 @@ _dbus_hash_table_remove_string (DBusHashTable *table,
return FALSE;
}
#ifdef DBUS_BUILD_TESTS
/**
* Removes the hash entry for the given key. If no hash entry
* for the key exists, does nothing.
@ -1285,6 +1307,7 @@ _dbus_hash_table_remove_two_strings (DBusHashTable *table,
else
return FALSE;
}
#endif /* DBUS_BUILD_TESTS */
/**
* Removes the hash entry for the given key. If no hash entry
@ -1407,6 +1430,7 @@ _dbus_hash_table_insert_string (DBusHashTable *table,
return TRUE;
}
#ifdef DBUS_BUILD_TESTS
/**
* Creates a hash entry with the given key and value.
* The key and value are not copied; they are stored
@ -1447,6 +1471,7 @@ _dbus_hash_table_insert_two_strings (DBusHashTable *table,
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */
/**
* Creates a hash entry with the given key and value.

View file

@ -174,6 +174,8 @@ _dbus_warn (const char *format,
va_end (args);
}
#ifdef DBUS_ENABLE_VERBOSE_MODE
static dbus_bool_t verbose_initted = FALSE;
/**
@ -238,6 +240,8 @@ _dbus_verbose_reset_real (void)
verbose_initted = FALSE;
}
#endif /* DBUS_ENABLE_VERBOSE_MODE */
/**
* Duplicates a string. Result must be freed with
* dbus_free(). Returns #NULL if memory allocation fails.
@ -354,6 +358,7 @@ _dbus_string_array_contains (const char **array,
return FALSE;
}
#ifdef DBUS_BUILD_TESTS
/**
* Returns a string describing the given name.
*
@ -387,6 +392,7 @@ _dbus_header_field_to_string (int header_field)
return "unknown";
}
}
#endif /* DBUS_BUILD_TESTS */
#ifndef DBUS_DISABLE_CHECKS
/** String used in _dbus_return_if_fail macro */

View file

@ -39,9 +39,6 @@ DBUS_BEGIN_DECLS
void _dbus_warn (const char *format,
...) _DBUS_GNUC_PRINTF (1, 2);
void _dbus_verbose_real (const char *format,
...) _DBUS_GNUC_PRINTF (1, 2);
void _dbus_verbose_reset_real (void);
#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#define _DBUS_FUNCTION_NAME __func__
@ -79,6 +76,11 @@ void _dbus_verbose_reset_real (void);
#endif
#ifdef DBUS_ENABLE_VERBOSE_MODE
void _dbus_verbose_real (const char *format,
...) _DBUS_GNUC_PRINTF (1, 2);
void _dbus_verbose_reset_real (void);
# define _dbus_verbose _dbus_verbose_real
# define _dbus_verbose_reset _dbus_verbose_reset_real
#else

View file

@ -126,6 +126,7 @@ link_before (DBusList **list,
}
}
#ifdef DBUS_BUILD_TESTS
static void
link_after (DBusList **list,
DBusList *after_this_link,
@ -145,6 +146,7 @@ link_after (DBusList **list,
link->next->prev = link;
}
}
#endif /* DBUS_BUILD_TESTS */
/** @} */
@ -313,6 +315,7 @@ _dbus_list_prepend_link (DBusList **list,
link_before (list, *list, link);
}
#ifdef DBUS_BUILD_TESTS
/**
* Inserts data into the list before the given existing link.
*
@ -341,7 +344,9 @@ _dbus_list_insert_before (DBusList **list,
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */
#ifdef DBUS_BUILD_TESTS
/**
* Inserts data into the list after the given existing link.
*
@ -370,6 +375,7 @@ _dbus_list_insert_after (DBusList **list,
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */
/**
* Inserts a link into the list before the given existing link.
@ -389,6 +395,7 @@ _dbus_list_insert_before_link (DBusList **list,
link_before (list, before_this_link, link);
}
#ifdef DBUS_BUILD_TESTS
/**
* Inserts a link into the list after the given existing link.
*
@ -406,6 +413,7 @@ _dbus_list_insert_after_link (DBusList **list,
else
link_after (list, after_this_link, link);
}
#endif /* DBUS_BUILD_TESTS */
/**
* Removes a value from the list. Only removes the
@ -690,6 +698,7 @@ _dbus_list_pop_last (DBusList **list)
return data;
}
#ifdef DBUS_BUILD_TESTS
/**
* Removes the last link in the list and returns it. This is a
* constant-time operation.
@ -710,6 +719,7 @@ _dbus_list_pop_last_link (DBusList **list)
return link;
}
#endif /* DBUS_BUILD_TESTS */
/**
* Copies a list. This is a linear-time operation. If there isn't

View file

@ -88,21 +88,6 @@ _dbus_pack_uint32 (dbus_uint32_t value,
pack_4_octets (value, byte_order, data);
}
/**
* Packs a 32 bit signed integer into a data pointer.
*
* @param value the value
* @param byte_order the byte order to use
* @param data the data pointer
*/
void
_dbus_pack_int32 (dbus_int32_t value,
int byte_order,
unsigned char *data)
{
pack_4_octets ((dbus_uint32_t) value, byte_order, data);
}
#ifndef DBUS_HAVE_INT64
/* from ORBit */
static void
@ -183,20 +168,6 @@ _dbus_unpack_uint32 (int byte_order,
}
#endif /* _dbus_unpack_uint32 */
/**
* Unpacks a 32 bit signed integer from a data pointer
*
* @param byte_order The byte order to use
* @param data the data pointer
* @returns the integer
*/
dbus_int32_t
_dbus_unpack_int32 (int byte_order,
const unsigned char *data)
{
return (dbus_int32_t) _dbus_unpack_uint32 (byte_order, data);
}
static void
set_4_octets (DBusString *str,
int offset,

View file

@ -152,11 +152,6 @@ typedef union
DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)(data)))
#endif
void _dbus_pack_int32 (dbus_int32_t value,
int byte_order,
unsigned char *data);
dbus_int32_t _dbus_unpack_int32 (int byte_order,
const unsigned char *data);
void _dbus_pack_uint32 (dbus_uint32_t value,
int byte_order,
unsigned char *data);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -335,6 +335,115 @@ append_string_field (DBusString *dest,
return TRUE;
}
#ifdef DBUS_BUILD_TESTS
/**
* Parses a basic type defined by type contained in a DBusString. The
* end_return parameter may be #NULL if you aren't interested in it. The
* type is parsed and stored in value_return. Return parameters are not
* initialized if the function returns #FALSE.
*
* @param str the string
* @param type the type of the basic type
* @param start the byte index of the start of the type
* @param value_return return location of the value or #NULL
* @param end_return return location of the end of the type, or #NULL
* @returns #TRUE on success
*/
static dbus_bool_t
_dbus_string_parse_basic_type (const DBusString *str,
char type,
int start,
void *value,
int *end_return)
{
int end = start;
switch (type)
{
case DBUS_TYPE_BOOLEAN:
{
int len = _dbus_string_get_length (str) - start;
if (len >= 5 && _dbus_string_find_to (str, start, start + 5, "false", NULL))
{
end += 5;
*(unsigned char *) value = TRUE;
}
else if (len >= 4 && _dbus_string_find_to (str, start, start + 4, "true", NULL))
{
end += 4;
*(unsigned char *) value = FALSE;
}
else
_dbus_warn ("could not parse BOOLEAN\n");
break;
}
case DBUS_TYPE_BYTE:
{
long val = 0;
if (_dbus_string_get_byte (str, start) == '\'' &&
_dbus_string_get_length (str) >= start + 4 &&
_dbus_string_get_byte (str, start + 1) == '\\' &&
_dbus_string_get_byte (str, start + 2) == '\'' &&
_dbus_string_get_byte (str, start + 3) == '\'')
{
val = '\'';
end += 4;
}
else if (_dbus_string_get_byte (str, start) == '\'' &&
_dbus_string_get_length (str) >= start + 3 &&
_dbus_string_get_byte (str, start + 2) == '\'')
{
val = _dbus_string_get_byte (str, start + 1);
end += 3;
}
else
{
if (!_dbus_string_parse_int (str, start, &val, &end))
_dbus_warn ("Failed to parse integer for BYTE\n");
}
if (val > 255)
_dbus_warn ("A byte must be in range 0-255 not %ld\n", val);
*(unsigned char *) value = val;
break;
}
case DBUS_TYPE_INT32:
{
long val;
if (_dbus_string_parse_int (str, start, &val, &end))
*(dbus_int32_t *)value = val;
break;
}
case DBUS_TYPE_UINT32:
{
unsigned long val;
if (_dbus_string_parse_uint (str, start, &val, &end))
*(dbus_uint32_t *)value = val;
break;
}
#ifdef DBUS_HAVE_INT64
case DBUS_TYPE_INT64:
case DBUS_TYPE_UINT64:
/* use stroll oull */
_dbus_assert_not_reached ("string -> [u]int64 not supported yet");
break;
#endif /* DBUS_HAVE_INT64 */
case DBUS_TYPE_DOUBLE:
_dbus_string_parse_double (str, start, value, &end);
break;
default:
_dbus_assert_not_reached ("not a basic type");
break;
}
if (end_return)
*end_return = end;
return end != start;
}
#endif /* DBUS_BUILD_TESTS */
static dbus_bool_t
parse_basic_type (DBusString *src, char type,
DBusString *dest, dbus_bool_t *unalign,

View file

@ -71,4 +71,4 @@ long _dbus_message_loader_get_max_message_size (DBusMessageLoader
DBUS_END_DECLS
#endif /* DBUS_MESSAGE_H */
#endif /* DBUS_MESSAGE_INTERNAL_H */

119
dbus/dbus-message-private.h Normal file
View file

@ -0,0 +1,119 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-message-private.h header shared between dbus-message.c and dbus-message-util.c
*
* Copyright (C) 2005 Red Hat Inc.
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef DBUS_MESSAGE_PRIVATE_H
#define DBUS_MESSAGE_PRIVATE_H
#include <dbus/dbus-message.h>
#include <dbus/dbus-message-internal.h>
#include <dbus/dbus-string.h>
#include <dbus/dbus-dataslot.h>
#include <dbus/dbus-marshal-header.h>
DBUS_BEGIN_DECLS
/**
* @addtogroup DBusMessageInternals
* @{
*/
/**
* @typedef DBusMessageLoader
*
* The DBusMessageLoader object encapsulates the process of converting
* a byte stream into a series of DBusMessage. It buffers the incoming
* bytes as efficiently as possible, and generates a queue of
* messages. DBusMessageLoader is typically used as part of a
* DBusTransport implementation. The DBusTransport then hands off
* the loaded messages to a DBusConnection, making the messages
* visible to the application.
*
* @todo write tests for break-loader that a) randomly delete header
* fields and b) set string fields to zero-length and other funky
* values.
*
*/
/**
* Implementation details of DBusMessageLoader.
* All members are private.
*/
struct DBusMessageLoader
{
int refcount; /**< Reference count. */
DBusString data; /**< Buffered data */
DBusList *messages; /**< Complete messages. */
long max_message_size; /**< Maximum size of a message */
unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
};
/** How many bits are in the changed_stamp used to validate iterators */
#define CHANGED_STAMP_BITS 21
/**
* @brief Internals of DBusMessage
*
* Object representing a message received from or to be sent to
* another application. This is an opaque object, all members
* are private.
*/
struct DBusMessage
{
DBusAtomic refcount; /**< Reference count */
DBusHeader header; /**< Header network data and associated cache */
DBusString body; /**< Body network data. */
char byte_order; /**< Message byte order. */
unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
DBusList *size_counters; /**< 0-N DBusCounter used to track message size. */
long size_counter_delta; /**< Size we incremented the size counters by. */
dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; /**< Incremented when iterators are invalidated. */
DBusDataSlotList slot_list; /**< Data stored by allocated integer ID */
#ifndef DBUS_DISABLE_CHECKS
int generation; /**< _dbus_current_generation when message was created */
#endif
};
dbus_bool_t _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
DBusError *error,
int first_arg_type,
va_list var_args);
/** @} */
DBUS_END_DECLS
#endif /* DBUS_MESSAGE_H */

1309
dbus/dbus-message-util.c Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -53,6 +53,62 @@ typedef struct
unsigned int align_offset : 3; /**< str - align_offset is the actual malloc block */
} DBusRealString;
/**
* @defgroup DBusStringInternals DBusString implementation details
* @ingroup DBusInternals
* @brief DBusString implementation details
*
* The guts of DBusString.
*
* @{
*/
/**
* This is the maximum max length (and thus also the maximum length)
* of a DBusString
*/
#define _DBUS_STRING_MAX_MAX_LENGTH (_DBUS_INT_MAX - _DBUS_STRING_ALLOCATION_PADDING)
/**
* Checks a bunch of assertions about a string object
*
* @param real the DBusRealString
*/
#define DBUS_GENERIC_STRING_PREAMBLE(real) _dbus_assert ((real) != NULL); _dbus_assert (!(real)->invalid); _dbus_assert ((real)->len >= 0); _dbus_assert ((real)->allocated >= 0); _dbus_assert ((real)->max_length >= 0); _dbus_assert ((real)->len <= ((real)->allocated - _DBUS_STRING_ALLOCATION_PADDING)); _dbus_assert ((real)->len <= (real)->max_length)
/**
* Checks assertions about a string object that needs to be
* modifiable - may not be locked or const. Also declares
* the "real" variable pointing to DBusRealString.
* @param str the string
*/
#define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
DBUS_GENERIC_STRING_PREAMBLE (real); \
_dbus_assert (!(real)->constant); \
_dbus_assert (!(real)->locked)
/**
* Checks assertions about a string object that may be locked but
* can't be const. i.e. a string object that we can free. Also
* declares the "real" variable pointing to DBusRealString.
*
* @param str the string
*/
#define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
DBUS_GENERIC_STRING_PREAMBLE (real); \
_dbus_assert (!(real)->constant)
/**
* Checks assertions about a string that may be const or locked. Also
* declares the "real" variable pointing to DBusRealString.
* @param str the string.
*/
#define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \
DBUS_GENERIC_STRING_PREAMBLE (real)
/** @} */
DBUS_END_DECLS
#endif /* DBUS_STRING_PRIVATE_H */

727
dbus/dbus-string-util.c Normal file
View file

@ -0,0 +1,727 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-string-util.c Would be in dbus-string.c, but not used in libdbus
*
* Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "dbus-internals.h"
#include "dbus-string.h"
#define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
#include "dbus-string-private.h"
/**
* @addtogroup DBusString
* @{
*/
/**
* Copies the contents of a DBusString into a different
* buffer. The resulting buffer will be nul-terminated.
*
* @param str a string
* @param buffer a C buffer to copy data to
* @param avail_len maximum length of C buffer
*/
void
_dbus_string_copy_to_buffer (const DBusString *str,
char *buffer,
int avail_len)
{
int copy_len;
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (avail_len >= 0);
copy_len = MIN (avail_len, real->len+1);
memcpy (buffer, real->str, copy_len);
if (avail_len > 0 && avail_len == copy_len)
buffer[avail_len-1] = '\0';
}
/**
* Returns whether a string ends with the given suffix
*
* @todo memcmp might make this faster.
*
* @param a the string
* @param c_str the C-style string
* @returns #TRUE if the string ends with the suffix
*/
dbus_bool_t
_dbus_string_ends_with_c_str (const DBusString *a,
const char *c_str)
{
const unsigned char *ap;
const unsigned char *bp;
const unsigned char *a_end;
unsigned long c_str_len;
const DBusRealString *real_a = (const DBusRealString*) a;
DBUS_GENERIC_STRING_PREAMBLE (real_a);
_dbus_assert (c_str != NULL);
c_str_len = strlen (c_str);
if (((unsigned long)real_a->len) < c_str_len)
return FALSE;
ap = real_a->str + (real_a->len - c_str_len);
bp = (const unsigned char*) c_str;
a_end = real_a->str + real_a->len;
while (ap != a_end)
{
if (*ap != *bp)
return FALSE;
++ap;
++bp;
}
_dbus_assert (*ap == '\0');
_dbus_assert (*bp == '\0');
return TRUE;
}
/**
* Find the given byte scanning backward from the given start.
* Sets *found to -1 if the byte is not found.
*
* @param str the string
* @param start the place to start scanning (will not find the byte at this point)
* @param byte the byte to find
* @param found return location for where it was found
* @returns #TRUE if found
*/
dbus_bool_t
_dbus_string_find_byte_backward (const DBusString *str,
int start,
unsigned char byte,
int *found)
{
int i;
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (start <= real->len);
_dbus_assert (start >= 0);
_dbus_assert (found != NULL);
i = start - 1;
while (i >= 0)
{
if (real->str[i] == byte)
break;
--i;
}
if (found)
*found = i;
return i >= 0;
}
/**
* Skips whitespace from start, storing the first non-whitespace in *end.
* (whitespace is space, tab, newline, CR).
*
* @param str the string
* @param start where to start
* @param end where to store the first non-whitespace byte index
*/
void
_dbus_string_skip_white (const DBusString *str,
int start,
int *end)
{
int i;
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (start <= real->len);
_dbus_assert (start >= 0);
i = start;
while (i < real->len)
{
if (!(real->str[i] == ' ' ||
real->str[i] == '\n' ||
real->str[i] == '\r' ||
real->str[i] == '\t'))
break;
++i;
}
_dbus_assert (i == real->len || !(real->str[i] == ' ' ||
real->str[i] == '\t'));
if (end)
*end = i;
}
/** @} */
#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
#include <stdio.h>
static void
test_max_len (DBusString *str,
int max_len)
{
if (max_len > 0)
{
if (!_dbus_string_set_length (str, max_len - 1))
_dbus_assert_not_reached ("setting len to one less than max should have worked");
}
if (!_dbus_string_set_length (str, max_len))
_dbus_assert_not_reached ("setting len to max len should have worked");
if (_dbus_string_set_length (str, max_len + 1))
_dbus_assert_not_reached ("setting len to one more than max len should not have worked");
if (!_dbus_string_set_length (str, 0))
_dbus_assert_not_reached ("setting len to zero should have worked");
}
static void
test_hex_roundtrip (const unsigned char *data,
int len)
{
DBusString orig;
DBusString encoded;
DBusString decoded;
int end;
if (len < 0)
len = strlen (data);
if (!_dbus_string_init (&orig))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_init (&encoded))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_init (&decoded))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_append_len (&orig, data, len))
_dbus_assert_not_reached ("couldn't append orig data");
if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0))
_dbus_assert_not_reached ("could not encode");
if (!_dbus_string_hex_decode (&encoded, 0, &end, &decoded, 0))
_dbus_assert_not_reached ("could not decode");
_dbus_assert (_dbus_string_get_length (&encoded) == end);
if (!_dbus_string_equal (&orig, &decoded))
{
const char *s;
printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
_dbus_string_get_length (&orig),
_dbus_string_get_length (&encoded),
_dbus_string_get_length (&decoded));
printf ("Original: %s\n", data);
s = _dbus_string_get_const_data (&decoded);
printf ("Decoded: %s\n", s);
_dbus_assert_not_reached ("original string not the same as string decoded from hex");
}
_dbus_string_free (&orig);
_dbus_string_free (&encoded);
_dbus_string_free (&decoded);
}
typedef void (* TestRoundtripFunc) (const unsigned char *data,
int len);
static void
test_roundtrips (TestRoundtripFunc func)
{
(* func) ("Hello this is a string\n", -1);
(* func) ("Hello this is a string\n1", -1);
(* func) ("Hello this is a string\n12", -1);
(* func) ("Hello this is a string\n123", -1);
(* func) ("Hello this is a string\n1234", -1);
(* func) ("Hello this is a string\n12345", -1);
(* func) ("", 0);
(* func) ("1", 1);
(* func) ("12", 2);
(* func) ("123", 3);
(* func) ("1234", 4);
(* func) ("12345", 5);
(* func) ("", 1);
(* func) ("1", 2);
(* func) ("12", 3);
(* func) ("123", 4);
(* func) ("1234", 5);
(* func) ("12345", 6);
{
unsigned char buf[512];
int i;
i = 0;
while (i < _DBUS_N_ELEMENTS (buf))
{
buf[i] = i;
++i;
}
i = 0;
while (i < _DBUS_N_ELEMENTS (buf))
{
(* func) (buf, i);
++i;
}
}
}
#ifdef DBUS_BUILD_TESTS
/* The max length thing is sort of a historical artifact
* from a feature that turned out to be dumb; perhaps
* we should purge it entirely. The problem with
* the feature is that it looks like memory allocation
* failure, but is not a transient or resolvable failure.
*/
static void
set_max_length (DBusString *str,
int max_length)
{
DBusRealString *real;
real = (DBusRealString*) str;
real->max_length = max_length;
}
#endif /* DBUS_BUILD_TESTS */
/**
* @ingroup DBusStringInternals
* Unit test for DBusString.
*
* @todo Need to write tests for _dbus_string_copy() and
* _dbus_string_move() moving to/from each of start/middle/end of a
* string. Also need tests for _dbus_string_move_len ()
*
* @returns #TRUE on success.
*/
dbus_bool_t
_dbus_string_test (void)
{
DBusString str;
DBusString other;
int i, end;
long v;
double d;
int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 };
char *s;
dbus_unichar_t ch;
i = 0;
while (i < _DBUS_N_ELEMENTS (lens))
{
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
set_max_length (&str, lens[i]);
test_max_len (&str, lens[i]);
_dbus_string_free (&str);
++i;
}
/* Test shortening and setting length */
i = 0;
while (i < _DBUS_N_ELEMENTS (lens))
{
int j;
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
set_max_length (&str, lens[i]);
if (!_dbus_string_set_length (&str, lens[i]))
_dbus_assert_not_reached ("failed to set string length");
j = lens[i];
while (j > 0)
{
_dbus_assert (_dbus_string_get_length (&str) == j);
if (j > 0)
{
_dbus_string_shorten (&str, 1);
_dbus_assert (_dbus_string_get_length (&str) == (j - 1));
}
--j;
}
_dbus_string_free (&str);
++i;
}
/* Test appending data */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
i = 0;
while (i < 10)
{
if (!_dbus_string_append (&str, "a"))
_dbus_assert_not_reached ("failed to append string to string\n");
_dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
if (!_dbus_string_append_byte (&str, 'b'))
_dbus_assert_not_reached ("failed to append byte to string\n");
_dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
++i;
}
_dbus_string_free (&str);
/* Check steal_data */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
if (!_dbus_string_append (&str, "Hello World"))
_dbus_assert_not_reached ("could not append to string");
i = _dbus_string_get_length (&str);
if (!_dbus_string_steal_data (&str, &s))
_dbus_assert_not_reached ("failed to steal data");
_dbus_assert (_dbus_string_get_length (&str) == 0);
_dbus_assert (((int)strlen (s)) == i);
dbus_free (s);
/* Check move */
if (!_dbus_string_append (&str, "Hello World"))
_dbus_assert_not_reached ("could not append to string");
i = _dbus_string_get_length (&str);
if (!_dbus_string_init (&other))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_move (&str, 0, &other, 0))
_dbus_assert_not_reached ("could not move");
_dbus_assert (_dbus_string_get_length (&str) == 0);
_dbus_assert (_dbus_string_get_length (&other) == i);
if (!_dbus_string_append (&str, "Hello World"))
_dbus_assert_not_reached ("could not append to string");
if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
_dbus_assert_not_reached ("could not move");
_dbus_assert (_dbus_string_get_length (&str) == 0);
_dbus_assert (_dbus_string_get_length (&other) == i * 2);
if (!_dbus_string_append (&str, "Hello World"))
_dbus_assert_not_reached ("could not append to string");
if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
_dbus_assert_not_reached ("could not move");
_dbus_assert (_dbus_string_get_length (&str) == 0);
_dbus_assert (_dbus_string_get_length (&other) == i * 3);
_dbus_string_free (&other);
/* Check copy */
if (!_dbus_string_append (&str, "Hello World"))
_dbus_assert_not_reached ("could not append to string");
i = _dbus_string_get_length (&str);
if (!_dbus_string_init (&other))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_copy (&str, 0, &other, 0))
_dbus_assert_not_reached ("could not copy");
_dbus_assert (_dbus_string_get_length (&str) == i);
_dbus_assert (_dbus_string_get_length (&other) == i);
if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
_dbus_assert_not_reached ("could not copy");
_dbus_assert (_dbus_string_get_length (&str) == i);
_dbus_assert (_dbus_string_get_length (&other) == i * 2);
_dbus_assert (_dbus_string_equal_c_str (&other,
"Hello WorldHello World"));
if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
_dbus_assert_not_reached ("could not copy");
_dbus_assert (_dbus_string_get_length (&str) == i);
_dbus_assert (_dbus_string_get_length (&other) == i * 3);
_dbus_assert (_dbus_string_equal_c_str (&other,
"Hello WorldHello WorldHello World"));
_dbus_string_free (&str);
_dbus_string_free (&other);
/* Check replace */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
if (!_dbus_string_append (&str, "Hello World"))
_dbus_assert_not_reached ("could not append to string");
i = _dbus_string_get_length (&str);
if (!_dbus_string_init (&other))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
&other, 0, _dbus_string_get_length (&other)))
_dbus_assert_not_reached ("could not replace");
_dbus_assert (_dbus_string_get_length (&str) == i);
_dbus_assert (_dbus_string_get_length (&other) == i);
_dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
&other, 5, 1))
_dbus_assert_not_reached ("could not replace center space");
_dbus_assert (_dbus_string_get_length (&str) == i);
_dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
_dbus_assert (_dbus_string_equal_c_str (&other,
"HelloHello WorldWorld"));
if (!_dbus_string_replace_len (&str, 1, 1,
&other,
_dbus_string_get_length (&other) - 1,
1))
_dbus_assert_not_reached ("could not replace end character");
_dbus_assert (_dbus_string_get_length (&str) == i);
_dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
_dbus_assert (_dbus_string_equal_c_str (&other,
"HelloHello WorldWorle"));
_dbus_string_free (&str);
_dbus_string_free (&other);
/* Check append/get unichar */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
ch = 0;
if (!_dbus_string_append_unichar (&str, 0xfffc))
_dbus_assert_not_reached ("failed to append unichar");
_dbus_string_get_unichar (&str, 0, &ch, &i);
_dbus_assert (ch == 0xfffc);
_dbus_assert (i == _dbus_string_get_length (&str));
_dbus_string_free (&str);
/* Check insert/set/get byte */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
if (!_dbus_string_append (&str, "Hello"))
_dbus_assert_not_reached ("failed to append Hello");
_dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
_dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
_dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
_dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
_dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
_dbus_string_set_byte (&str, 1, 'q');
_dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
if (!_dbus_string_insert_bytes (&str, 0, 1, 255))
_dbus_assert_not_reached ("can't insert byte");
if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z'))
_dbus_assert_not_reached ("can't insert byte");
if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W'))
_dbus_assert_not_reached ("can't insert byte");
_dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
_dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
_dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
_dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z');
_dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z');
_dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z');
_dbus_assert (_dbus_string_get_byte (&str, 6) == 'q');
_dbus_assert (_dbus_string_get_byte (&str, 7) == 'l');
_dbus_assert (_dbus_string_get_byte (&str, 8) == 'l');
_dbus_assert (_dbus_string_get_byte (&str, 9) == 'o');
_dbus_assert (_dbus_string_get_byte (&str, 10) == 'W');
_dbus_string_free (&str);
/* Check append/parse int/double */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
if (!_dbus_string_append_int (&str, 27))
_dbus_assert_not_reached ("failed to append int");
i = _dbus_string_get_length (&str);
if (!_dbus_string_parse_int (&str, 0, &v, &end))
_dbus_assert_not_reached ("failed to parse int");
_dbus_assert (v == 27);
_dbus_assert (end == i);
_dbus_string_free (&str);
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
if (!_dbus_string_append_double (&str, 50.3))
_dbus_assert_not_reached ("failed to append float");
i = _dbus_string_get_length (&str);
if (!_dbus_string_parse_double (&str, 0, &d, &end))
_dbus_assert_not_reached ("failed to parse float");
_dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
_dbus_assert (end == i);
_dbus_string_free (&str);
/* Test find */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
if (!_dbus_string_append (&str, "Hello"))
_dbus_assert_not_reached ("couldn't append to string");
if (!_dbus_string_find (&str, 0, "He", &i))
_dbus_assert_not_reached ("didn't find 'He'");
_dbus_assert (i == 0);
if (!_dbus_string_find (&str, 0, "Hello", &i))
_dbus_assert_not_reached ("didn't find 'Hello'");
_dbus_assert (i == 0);
if (!_dbus_string_find (&str, 0, "ello", &i))
_dbus_assert_not_reached ("didn't find 'ello'");
_dbus_assert (i == 1);
if (!_dbus_string_find (&str, 0, "lo", &i))
_dbus_assert_not_reached ("didn't find 'lo'");
_dbus_assert (i == 3);
if (!_dbus_string_find (&str, 2, "lo", &i))
_dbus_assert_not_reached ("didn't find 'lo'");
_dbus_assert (i == 3);
if (_dbus_string_find (&str, 4, "lo", &i))
_dbus_assert_not_reached ("did find 'lo'");
if (!_dbus_string_find (&str, 0, "l", &i))
_dbus_assert_not_reached ("didn't find 'l'");
_dbus_assert (i == 2);
if (!_dbus_string_find (&str, 0, "H", &i))
_dbus_assert_not_reached ("didn't find 'H'");
_dbus_assert (i == 0);
if (!_dbus_string_find (&str, 0, "", &i))
_dbus_assert_not_reached ("didn't find ''");
_dbus_assert (i == 0);
if (_dbus_string_find (&str, 0, "Hello!", NULL))
_dbus_assert_not_reached ("Did find 'Hello!'");
if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
_dbus_assert_not_reached ("Did find 'Oh, Hello'");
if (_dbus_string_find (&str, 0, "ill", NULL))
_dbus_assert_not_reached ("Did find 'ill'");
if (_dbus_string_find (&str, 0, "q", NULL))
_dbus_assert_not_reached ("Did find 'q'");
if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
_dbus_assert_not_reached ("Didn't find 'He'");
if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
_dbus_assert_not_reached ("Did find 'Hello'");
if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i))
_dbus_assert_not_reached ("Did not find 'H'");
_dbus_assert (i == 0);
if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i))
_dbus_assert_not_reached ("Did not find 'o'");
_dbus_assert (i == _dbus_string_get_length (&str) - 1);
if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i))
_dbus_assert_not_reached ("Did find 'o'");
_dbus_assert (i == -1);
if (_dbus_string_find_byte_backward (&str, 1, 'e', &i))
_dbus_assert_not_reached ("Did find 'e'");
_dbus_assert (i == -1);
if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i))
_dbus_assert_not_reached ("Didn't find 'e'");
_dbus_assert (i == 1);
_dbus_string_free (&str);
/* Hex encoding */
_dbus_string_init_const (&str, "cafebabe, this is a bogus hex string");
if (!_dbus_string_init (&other))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_hex_decode (&str, 0, &end, &other, 0))
_dbus_assert_not_reached ("deccoded bogus hex string with no error");
_dbus_assert (end == 8);
_dbus_string_free (&other);
test_roundtrips (test_hex_roundtrip);
_dbus_string_free (&str);
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */

File diff suppressed because it is too large Load diff

View file

@ -54,6 +54,7 @@ struct DBusString
* to inline non-exported symbols across files in the library.
* Note that these break type safety (due to the casts)
*/
#define _dbus_string_get_data(s) ((char*)(((DBusString*)(s))->dummy1))
#define _dbus_string_get_length(s) (((DBusString*)(s))->dummy2)
#define _dbus_string_set_byte(s, i, b) ((((unsigned char*)(((DBusString*)(s))->dummy1))[(i)]) = (unsigned char) (b))
#define _dbus_string_get_byte(s, i) (((const unsigned char*)(((DBusString*)(s))->dummy1))[(i)])
@ -71,7 +72,9 @@ dbus_bool_t _dbus_string_init_preallocated (DBusString *str,
int allocate_size);
void _dbus_string_free (DBusString *str);
void _dbus_string_lock (DBusString *str);
#ifndef _dbus_string_get_data
char* _dbus_string_get_data (DBusString *str);
#endif /* _dbus_string_get_data */
#ifndef _dbus_string_get_const_data
const char* _dbus_string_get_const_data (const DBusString *str);
#endif /* _dbus_string_get_const_data */
@ -205,11 +208,6 @@ dbus_bool_t _dbus_string_parse_double (const DBusString *str,
int start,
double *value,
int *end_return);
dbus_bool_t _dbus_string_parse_basic_type (const DBusString *str,
char type,
int start,
void *value,
int *end_return);
dbus_bool_t _dbus_string_find (const DBusString *str,
int start,
const char *substr,

871
dbus/dbus-sysdeps-util.c Normal file
View file

@ -0,0 +1,871 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-sysdeps-util.c Would be in dbus-sysdeps.c, but not used in libdbus
*
* Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
* Copyright (C) 2003 CodeFactory AB
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "dbus-sysdeps.h"
#include "dbus-internals.h"
#include "dbus-protocol.h"
#include "dbus-string.h"
#define DBUS_USERDB_INCLUDES_PRIVATE 1
#include "dbus-userdb.h"
#include "dbus-test.h"
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <grp.h>
#include <sys/socket.h>
#include <dirent.h>
#include <sys/un.h>
#ifndef O_BINARY
#define O_BINARY 0
#endif
/**
* @addtogroup DBusInternalsUtils
* @{
*/
/**
* Does the chdir, fork, setsid, etc. to become a daemon process.
*
* @param pidfile #NULL, or pidfile to create
* @param print_pid_fd file descriptor to print pid to, or -1 for none
* @param error return location for errors
* @returns #FALSE on failure
*/
dbus_bool_t
_dbus_become_daemon (const DBusString *pidfile,
int print_pid_fd,
DBusError *error)
{
const char *s;
pid_t child_pid;
int dev_null_fd;
_dbus_verbose ("Becoming a daemon...\n");
_dbus_verbose ("chdir to /\n");
if (chdir ("/") < 0)
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"Could not chdir() to root directory");
return FALSE;
}
_dbus_verbose ("forking...\n");
switch ((child_pid = fork ()))
{
case -1:
_dbus_verbose ("fork failed\n");
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to fork daemon: %s", _dbus_strerror (errno));
return FALSE;
break;
case 0:
_dbus_verbose ("in child, closing std file descriptors\n");
/* silently ignore failures here, if someone
* doesn't have /dev/null we may as well try
* to continue anyhow
*/
dev_null_fd = open ("/dev/null", O_RDWR);
if (dev_null_fd >= 0)
{
dup2 (dev_null_fd, 0);
dup2 (dev_null_fd, 1);
s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
if (s == NULL || *s == '\0')
dup2 (dev_null_fd, 2);
else
_dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
}
/* Get a predictable umask */
_dbus_verbose ("setting umask\n");
umask (022);
break;
default:
if (pidfile)
{
_dbus_verbose ("parent writing pid file\n");
if (!_dbus_write_pid_file (pidfile,
child_pid,
error))
{
_dbus_verbose ("pid file write failed, killing child\n");
kill (child_pid, SIGTERM);
return FALSE;
}
}
/* Write PID if requested */
if (print_pid_fd >= 0)
{
DBusString pid;
int bytes;
if (!_dbus_string_init (&pid))
{
_DBUS_SET_OOM (error);
kill (child_pid, SIGTERM);
return FALSE;
}
if (!_dbus_string_append_int (&pid, _dbus_getpid ()) ||
!_dbus_string_append (&pid, "\n"))
{
_dbus_string_free (&pid);
_DBUS_SET_OOM (error);
kill (child_pid, SIGTERM);
return FALSE;
}
bytes = _dbus_string_get_length (&pid);
if (_dbus_write (print_pid_fd, &pid, 0, bytes) != bytes)
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"Printing message bus PID: %s\n",
_dbus_strerror (errno));
_dbus_string_free (&pid);
kill (child_pid, SIGTERM);
return FALSE;
}
_dbus_string_free (&pid);
}
_dbus_verbose ("parent exiting\n");
_exit (0);
break;
}
_dbus_verbose ("calling setsid()\n");
if (setsid () == -1)
_dbus_assert_not_reached ("setsid() failed");
return TRUE;
}
/**
* Creates a file containing the process ID.
*
* @param filename the filename to write to
* @param pid our process ID
* @param error return location for errors
* @returns #FALSE on failure
*/
dbus_bool_t
_dbus_write_pid_file (const DBusString *filename,
unsigned long pid,
DBusError *error)
{
const char *cfilename;
int fd;
FILE *f;
cfilename = _dbus_string_get_const_data (filename);
fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
if (fd < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to open \"%s\": %s", cfilename,
_dbus_strerror (errno));
return FALSE;
}
if ((f = fdopen (fd, "w")) == NULL)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
close (fd);
return FALSE;
}
if (fprintf (f, "%lu\n", pid) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to write to \"%s\": %s", cfilename,
_dbus_strerror (errno));
return FALSE;
}
if (fclose (f) == EOF)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to close \"%s\": %s", cfilename,
_dbus_strerror (errno));
return FALSE;
}
return TRUE;
}
/**
* Changes the user and group the bus is running as.
*
* @param uid the new user ID
* @param gid the new group ID
* @param error return location for errors
* @returns #FALSE on failure
*/
dbus_bool_t
_dbus_change_identity (dbus_uid_t uid,
dbus_gid_t gid,
DBusError *error)
{
/* setgroups() only works if we are a privileged process,
* so we don't return error on failure; the only possible
* failure is that we don't have perms to do it.
* FIXME not sure this is right, maybe if setuid()
* is going to work then setgroups() should also work.
*/
if (setgroups (0, NULL) < 0)
_dbus_warn ("Failed to drop supplementary groups: %s\n",
_dbus_strerror (errno));
/* Set GID first, or the setuid may remove our permission
* to change the GID
*/
if (setgid (gid) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to set GID to %lu: %s", gid,
_dbus_strerror (errno));
return FALSE;
}
if (setuid (uid) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to set UID to %lu: %s", uid,
_dbus_strerror (errno));
return FALSE;
}
return TRUE;
}
/** Installs a UNIX signal handler
*
* @param sig the signal to handle
* @param handler the handler
*/
void
_dbus_set_signal_handler (int sig,
DBusSignalHandler handler)
{
struct sigaction act;
sigset_t empty_mask;
sigemptyset (&empty_mask);
act.sa_handler = handler;
act.sa_mask = empty_mask;
act.sa_flags = 0;
sigaction (sig, &act, 0);
}
/**
* Removes a directory; Directory must be empty
*
* @param filename directory filename
* @param error initialized error object
* @returns #TRUE on success
*/
dbus_bool_t
_dbus_delete_directory (const DBusString *filename,
DBusError *error)
{
const char *filename_c;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
filename_c = _dbus_string_get_const_data (filename);
if (rmdir (filename_c) != 0)
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"Failed to remove directory %s: %s\n",
filename_c, _dbus_strerror (errno));
return FALSE;
}
return TRUE;
}
/** Checks if a file exists
*
* @param file full path to the file
* @returns #TRUE if file exists
*/
dbus_bool_t
_dbus_file_exists (const char *file)
{
return (access (file, F_OK) == 0);
}
/** Checks if user is at the console
*
* @param username user to check
* @param error return location for errors
* @returns #TRUE is the user is at the consolei and there are no errors
*/
dbus_bool_t
_dbus_user_at_console (const char *username,
DBusError *error)
{
DBusString f;
dbus_bool_t result;
result = FALSE;
if (!_dbus_string_init (&f))
{
_DBUS_SET_OOM (error);
return FALSE;
}
if (!_dbus_string_append (&f, DBUS_CONSOLE_DIR))
{
_DBUS_SET_OOM (error);
goto out;
}
if (!_dbus_string_append (&f, username))
{
_DBUS_SET_OOM (error);
goto out;
}
result = _dbus_file_exists (_dbus_string_get_const_data (&f));
out:
_dbus_string_free (&f);
return result;
}
/**
* Checks whether the filename is an absolute path
*
* @param filename the filename
* @returns #TRUE if an absolute path
*/
dbus_bool_t
_dbus_path_is_absolute (const DBusString *filename)
{
if (_dbus_string_get_length (filename) > 0)
return _dbus_string_get_byte (filename, 0) == '/';
else
return FALSE;
}
/**
* stat() wrapper.
*
* @param filename the filename to stat
* @param statbuf the stat info to fill in
* @param error return location for error
* @returns #FALSE if error was set
*/
dbus_bool_t
_dbus_stat (const DBusString *filename,
DBusStat *statbuf,
DBusError *error)
{
const char *filename_c;
struct stat sb;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
filename_c = _dbus_string_get_const_data (filename);
if (stat (filename_c, &sb) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"%s", _dbus_strerror (errno));
return FALSE;
}
statbuf->mode = sb.st_mode;
statbuf->nlink = sb.st_nlink;
statbuf->uid = sb.st_uid;
statbuf->gid = sb.st_gid;
statbuf->size = sb.st_size;
statbuf->atime = sb.st_atime;
statbuf->mtime = sb.st_mtime;
statbuf->ctime = sb.st_ctime;
return TRUE;
}
/**
* Internals of directory iterator
*/
struct DBusDirIter
{
DIR *d; /**< The DIR* from opendir() */
};
/**
* Open a directory to iterate over.
*
* @param filename the directory name
* @param error exception return object or #NULL
* @returns new iterator, or #NULL on error
*/
DBusDirIter*
_dbus_directory_open (const DBusString *filename,
DBusError *error)
{
DIR *d;
DBusDirIter *iter;
const char *filename_c;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
filename_c = _dbus_string_get_const_data (filename);
d = opendir (filename_c);
if (d == NULL)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to read directory \"%s\": %s",
filename_c,
_dbus_strerror (errno));
return NULL;
}
iter = dbus_new0 (DBusDirIter, 1);
if (iter == NULL)
{
closedir (d);
dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
"Could not allocate memory for directory iterator");
return NULL;
}
iter->d = d;
return iter;
}
/**
* Get next file in the directory. Will not return "." or ".." on
* UNIX. If an error occurs, the contents of "filename" are
* undefined. The error is never set if the function succeeds.
*
* @todo for thread safety, I think we have to use
* readdir_r(). (GLib has the same issue, should file a bug.)
*
* @param iter the iterator
* @param filename string to be set to the next file in the dir
* @param error return location for error
* @returns #TRUE if filename was filled in with a new filename
*/
dbus_bool_t
_dbus_directory_get_next_file (DBusDirIter *iter,
DBusString *filename,
DBusError *error)
{
struct dirent *ent;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
again:
errno = 0;
ent = readdir (iter->d);
if (ent == NULL)
{
if (errno != 0)
dbus_set_error (error,
_dbus_error_from_errno (errno),
"%s", _dbus_strerror (errno));
return FALSE;
}
else if (ent->d_name[0] == '.' &&
(ent->d_name[1] == '\0' ||
(ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
goto again;
else
{
_dbus_string_set_length (filename, 0);
if (!_dbus_string_append (filename, ent->d_name))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
"No memory to read directory entry");
return FALSE;
}
else
return TRUE;
}
}
/**
* Closes a directory iteration.
*/
void
_dbus_directory_close (DBusDirIter *iter)
{
closedir (iter->d);
dbus_free (iter);
}
static dbus_bool_t
fill_user_info_from_group (struct group *g,
DBusGroupInfo *info,
DBusError *error)
{
_dbus_assert (g->gr_name != NULL);
info->gid = g->gr_gid;
info->groupname = _dbus_strdup (g->gr_name);
/* info->members = dbus_strdupv (g->gr_mem) */
if (info->groupname == NULL)
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
return FALSE;
}
return TRUE;
}
static dbus_bool_t
fill_group_info (DBusGroupInfo *info,
dbus_gid_t gid,
const DBusString *groupname,
DBusError *error)
{
const char *group_c_str;
_dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
_dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
if (groupname)
group_c_str = _dbus_string_get_const_data (groupname);
else
group_c_str = NULL;
/* For now assuming that the getgrnam() and getgrgid() flavors
* always correspond to the pwnam flavors, if not we have
* to add more configure checks.
*/
#if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
{
struct group *g;
int result;
char buf[1024];
struct group g_str;
g = NULL;
#ifdef HAVE_POSIX_GETPWNAME_R
if (group_c_str)
result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
&g);
else
result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
&g);
#else
p = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
result = 0;
#endif /* !HAVE_POSIX_GETPWNAME_R */
if (result == 0 && g == &g_str)
{
return fill_user_info_from_group (g, info, error);
}
else
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Group %s unknown or failed to look it up\n",
group_c_str ? group_c_str : "???");
return FALSE;
}
}
#else /* ! HAVE_GETPWNAM_R */
{
/* I guess we're screwed on thread safety here */
struct group *g;
g = getgrnam (group_c_str);
if (g != NULL)
{
return fill_user_info_from_group (g, info, error);
}
else
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Group %s unknown or failed to look it up\n",
group_c_str ? group_c_str : "???");
return FALSE;
}
}
#endif /* ! HAVE_GETPWNAM_R */
}
/**
* Initializes the given DBusGroupInfo struct
* with information about the given group name.
*
* @param info the group info struct
* @param groupname name of group
* @param error the error return
* @returns #FALSE if error is set
*/
dbus_bool_t
_dbus_group_info_fill (DBusGroupInfo *info,
const DBusString *groupname,
DBusError *error)
{
return fill_group_info (info, DBUS_GID_UNSET,
groupname, error);
}
/**
* Initializes the given DBusGroupInfo struct
* with information about the given group ID.
*
* @param info the group info struct
* @param gid group ID
* @param error the error return
* @returns #FALSE if error is set
*/
dbus_bool_t
_dbus_group_info_fill_gid (DBusGroupInfo *info,
dbus_gid_t gid,
DBusError *error)
{
return fill_group_info (info, gid, NULL, error);
}
/**
* Frees the members of info (but not info itself).
*
* @param info the group info
*/
void
_dbus_group_info_free (DBusGroupInfo *info)
{
dbus_free (info->groupname);
}
/** @} */ /* End of DBusInternalsUtils functions */
/**
* @addtogroup DBusString
*
* @{
*/
/**
* Get the directory name from a complete filename
* @param filename the filename
* @param dirname string to append directory name to
* @returns #FALSE if no memory
*/
dbus_bool_t
_dbus_string_get_dirname (const DBusString *filename,
DBusString *dirname)
{
int sep;
_dbus_assert (filename != dirname);
_dbus_assert (filename != NULL);
_dbus_assert (dirname != NULL);
/* Ignore any separators on the end */
sep = _dbus_string_get_length (filename);
if (sep == 0)
return _dbus_string_append (dirname, "."); /* empty string passed in */
while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
--sep;
_dbus_assert (sep >= 0);
if (sep == 0)
return _dbus_string_append (dirname, "/");
/* Now find the previous separator */
_dbus_string_find_byte_backward (filename, sep, '/', &sep);
if (sep < 0)
return _dbus_string_append (dirname, ".");
/* skip multiple separators */
while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
--sep;
_dbus_assert (sep >= 0);
if (sep == 0 &&
_dbus_string_get_byte (filename, 0) == '/')
return _dbus_string_append (dirname, "/");
else
return _dbus_string_copy_len (filename, 0, sep - 0,
dirname, _dbus_string_get_length (dirname));
}
/** @} */ /* DBusString stuff */
#ifdef DBUS_BUILD_TESTS
#include <stdlib.h>
static void
check_dirname (const char *filename,
const char *dirname)
{
DBusString f, d;
_dbus_string_init_const (&f, filename);
if (!_dbus_string_init (&d))
_dbus_assert_not_reached ("no memory");
if (!_dbus_string_get_dirname (&f, &d))
_dbus_assert_not_reached ("no memory");
if (!_dbus_string_equal_c_str (&d, dirname))
{
_dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
filename,
_dbus_string_get_const_data (&d),
dirname);
exit (1);
}
_dbus_string_free (&d);
}
static void
check_path_absolute (const char *path,
dbus_bool_t expected)
{
DBusString p;
_dbus_string_init_const (&p, path);
if (_dbus_path_is_absolute (&p) != expected)
{
_dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
path, expected, _dbus_path_is_absolute (&p));
exit (1);
}
}
/**
* Unit test for dbus-sysdeps.c.
*
* @returns #TRUE on success.
*/
dbus_bool_t
_dbus_sysdeps_test (void)
{
DBusString str;
double val;
int pos;
check_dirname ("foo", ".");
check_dirname ("foo/bar", "foo");
check_dirname ("foo//bar", "foo");
check_dirname ("foo///bar", "foo");
check_dirname ("foo/bar/", "foo");
check_dirname ("foo//bar/", "foo");
check_dirname ("foo///bar/", "foo");
check_dirname ("foo/bar//", "foo");
check_dirname ("foo//bar////", "foo");
check_dirname ("foo///bar///////", "foo");
check_dirname ("/foo", "/");
check_dirname ("////foo", "/");
check_dirname ("/foo/bar", "/foo");
check_dirname ("/foo//bar", "/foo");
check_dirname ("/foo///bar", "/foo");
check_dirname ("/", "/");
check_dirname ("///", "/");
check_dirname ("", ".");
_dbus_string_init_const (&str, "3.5");
if (!_dbus_string_parse_double (&str,
0, &val, &pos))
{
_dbus_warn ("Failed to parse double");
exit (1);
}
if (ABS(3.5 - val) > 1e-6)
{
_dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
exit (1);
}
if (pos != 3)
{
_dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
exit (1);
}
_dbus_string_init_const (&str, "0xff");
if (!_dbus_string_parse_double (&str,
0, &val, &pos))
{
_dbus_warn ("Failed to parse double");
exit (1);
}
if (ABS (0xff - val) > 1e-6)
{
_dbus_warn ("Failed to parse 0xff correctly, got: %f\n", val);
exit (1);
}
if (pos != 4)
{
_dbus_warn ("_dbus_string_parse_double of \"0xff\" returned wrong position %d", pos);
exit (1);
}
check_path_absolute ("/", TRUE);
check_path_absolute ("/foo", TRUE);
check_path_absolute ("", FALSE);
check_path_absolute ("foo", FALSE);
check_path_absolute ("foo/bar", FALSE);
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */

View file

@ -1628,149 +1628,6 @@ _dbus_user_info_free (DBusUserInfo *info)
dbus_free (info->homedir);
}
static dbus_bool_t
fill_user_info_from_group (struct group *g,
DBusGroupInfo *info,
DBusError *error)
{
_dbus_assert (g->gr_name != NULL);
info->gid = g->gr_gid;
info->groupname = _dbus_strdup (g->gr_name);
/* info->members = dbus_strdupv (g->gr_mem) */
if (info->groupname == NULL)
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
return FALSE;
}
return TRUE;
}
static dbus_bool_t
fill_group_info (DBusGroupInfo *info,
dbus_gid_t gid,
const DBusString *groupname,
DBusError *error)
{
const char *group_c_str;
_dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
_dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
if (groupname)
group_c_str = _dbus_string_get_const_data (groupname);
else
group_c_str = NULL;
/* For now assuming that the getgrnam() and getgrgid() flavors
* always correspond to the pwnam flavors, if not we have
* to add more configure checks.
*/
#if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
{
struct group *g;
int result;
char buf[1024];
struct group g_str;
g = NULL;
#ifdef HAVE_POSIX_GETPWNAME_R
if (group_c_str)
result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
&g);
else
result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
&g);
#else
p = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
result = 0;
#endif /* !HAVE_POSIX_GETPWNAME_R */
if (result == 0 && g == &g_str)
{
return fill_user_info_from_group (g, info, error);
}
else
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Group %s unknown or failed to look it up\n",
group_c_str ? group_c_str : "???");
return FALSE;
}
}
#else /* ! HAVE_GETPWNAM_R */
{
/* I guess we're screwed on thread safety here */
struct group *g;
g = getgrnam (group_c_str);
if (g != NULL)
{
return fill_user_info_from_group (g, info, error);
}
else
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Group %s unknown or failed to look it up\n",
group_c_str ? group_c_str : "???");
return FALSE;
}
}
#endif /* ! HAVE_GETPWNAM_R */
}
/**
* Initializes the given DBusGroupInfo struct
* with information about the given group name.
*
* @param info the group info struct
* @param groupname name of group
* @param error the error return
* @returns #FALSE if error is set
*/
dbus_bool_t
_dbus_group_info_fill (DBusGroupInfo *info,
const DBusString *groupname,
DBusError *error)
{
return fill_group_info (info, DBUS_GID_UNSET,
groupname, error);
}
/**
* Initializes the given DBusGroupInfo struct
* with information about the given group ID.
*
* @param info the group info struct
* @param gid group ID
* @param error the error return
* @returns #FALSE if error is set
*/
dbus_bool_t
_dbus_group_info_fill_gid (DBusGroupInfo *info,
dbus_gid_t gid,
DBusError *error)
{
return fill_group_info (info, gid, NULL, error);
}
/**
* Frees the members of info (but not info itself).
*
* @param info the group info
*/
void
_dbus_group_info_free (DBusGroupInfo *info)
{
dbus_free (info->groupname);
}
/**
* Sets fields in DBusCredentials to DBUS_PID_UNSET,
* DBUS_UID_UNSET, DBUS_GID_UNSET.
@ -1849,6 +1706,7 @@ _dbus_getuid (void)
return getuid ();
}
#ifdef DBUS_BUILD_TESTS
/** Gets our GID
* @returns process GID
*/
@ -1857,6 +1715,7 @@ _dbus_getgid (void)
{
return getgid ();
}
#endif
_DBUS_DEFINE_GLOBAL_LOCK (atomic);
@ -2467,118 +2326,6 @@ _dbus_concat_dir_and_file (DBusString *dir,
_dbus_string_get_length (dir));
}
/**
* Internals of directory iterator
*/
struct DBusDirIter
{
DIR *d; /**< The DIR* from opendir() */
};
/**
* Open a directory to iterate over.
*
* @param filename the directory name
* @param error exception return object or #NULL
* @returns new iterator, or #NULL on error
*/
DBusDirIter*
_dbus_directory_open (const DBusString *filename,
DBusError *error)
{
DIR *d;
DBusDirIter *iter;
const char *filename_c;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
filename_c = _dbus_string_get_const_data (filename);
d = opendir (filename_c);
if (d == NULL)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to read directory \"%s\": %s",
filename_c,
_dbus_strerror (errno));
return NULL;
}
iter = dbus_new0 (DBusDirIter, 1);
if (iter == NULL)
{
closedir (d);
dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
"Could not allocate memory for directory iterator");
return NULL;
}
iter->d = d;
return iter;
}
/**
* Get next file in the directory. Will not return "." or ".." on
* UNIX. If an error occurs, the contents of "filename" are
* undefined. The error is never set if the function succeeds.
*
* @todo for thread safety, I think we have to use
* readdir_r(). (GLib has the same issue, should file a bug.)
*
* @param iter the iterator
* @param filename string to be set to the next file in the dir
* @param error return location for error
* @returns #TRUE if filename was filled in with a new filename
*/
dbus_bool_t
_dbus_directory_get_next_file (DBusDirIter *iter,
DBusString *filename,
DBusError *error)
{
struct dirent *ent;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
again:
errno = 0;
ent = readdir (iter->d);
if (ent == NULL)
{
if (errno != 0)
dbus_set_error (error,
_dbus_error_from_errno (errno),
"%s", _dbus_strerror (errno));
return FALSE;
}
else if (ent->d_name[0] == '.' &&
(ent->d_name[1] == '\0' ||
(ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
goto again;
else
{
_dbus_string_set_length (filename, 0);
if (!_dbus_string_append (filename, ent->d_name))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
"No memory to read directory entry");
return FALSE;
}
else
return TRUE;
}
}
/**
* Closes a directory iteration.
*/
void
_dbus_directory_close (DBusDirIter *iter)
{
closedir (iter->d);
dbus_free (iter);
}
static dbus_bool_t
pseudorandom_generate_random_bytes (DBusString *str,
int n_bytes)
@ -2858,62 +2605,6 @@ _dbus_exit (int code)
_exit (code);
}
/**
* Creates a full-duplex pipe (as in socketpair()).
* Sets both ends of the pipe nonblocking.
*
* @param fd1 return location for one end
* @param fd2 return location for the other end
* @param blocking #TRUE if pipe should be blocking
* @param error error return
* @returns #FALSE on failure (if error is set)
*/
dbus_bool_t
_dbus_full_duplex_pipe (int *fd1,
int *fd2,
dbus_bool_t blocking,
DBusError *error)
{
#ifdef HAVE_SOCKETPAIR
int fds[2];
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Could not create full-duplex pipe");
return FALSE;
}
if (!blocking &&
(!_dbus_set_fd_nonblocking (fds[0], NULL) ||
!_dbus_set_fd_nonblocking (fds[1], NULL)))
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Could not set full-duplex pipe nonblocking");
close (fds[0]);
close (fds[1]);
return FALSE;
}
*fd1 = fds[0];
*fd2 = fds[1];
_dbus_verbose ("full-duplex pipe %d <-> %d\n",
*fd1, *fd2);
return TRUE;
#else
_dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
dbus_set_error (error, DBUS_ERROR_FAILED,
"_dbus_full_duplex_pipe() not implemented on this OS");
return FALSE;
#endif
}
/**
* Closes a file descriptor.
*
@ -3055,6 +2746,67 @@ _dbus_parse_uid (const DBusString *uid_str,
return TRUE;
}
/**
* Creates a full-duplex pipe (as in socketpair()).
* Sets both ends of the pipe nonblocking.
*
* @todo libdbus only uses this for the debug-pipe server, so in
* principle it could be in dbus-sysdeps-util.c, except that
* dbus-sysdeps-util.c isn't in libdbus when tests are enabled and the
* debug-pipe server is used.
*
* @param fd1 return location for one end
* @param fd2 return location for the other end
* @param blocking #TRUE if pipe should be blocking
* @param error error return
* @returns #FALSE on failure (if error is set)
*/
dbus_bool_t
_dbus_full_duplex_pipe (int *fd1,
int *fd2,
dbus_bool_t blocking,
DBusError *error)
{
#ifdef HAVE_SOCKETPAIR
int fds[2];
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Could not create full-duplex pipe");
return FALSE;
}
if (!blocking &&
(!_dbus_set_fd_nonblocking (fds[0], NULL) ||
!_dbus_set_fd_nonblocking (fds[1], NULL)))
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Could not set full-duplex pipe nonblocking");
close (fds[0]);
close (fds[1]);
return FALSE;
}
*fd1 = fds[0];
*fd2 = fds[1];
_dbus_verbose ("full-duplex pipe %d <-> %d\n",
*fd1, *fd2);
return TRUE;
#else
_dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
dbus_set_error (error, DBUS_ERROR_FAILED,
"_dbus_full_duplex_pipe() not implemented on this OS");
return FALSE;
#endif
}
/** @} end of sysdeps */
/* tests in dbus-sysdeps-util.c */

View file

@ -32,7 +32,6 @@
* @{
*/
/**
* Checks to see if the UID sent in is the console user
*

View file

@ -442,6 +442,7 @@ _dbus_user_database_new (void)
return NULL;
}
#ifdef DBUS_BUILD_TESTS
/**
* Increments refcount of user database.
* @param db the database
@ -456,6 +457,7 @@ _dbus_user_database_ref (DBusUserDatabase *db)
return db;
}
#endif /* DBUS_BUILD_TESTS */
/**
* Decrements refcount of user database.

View file

@ -230,6 +230,8 @@ trace 'reachable' through hardcoded function calls, if a function is
called only through a vtable, it won't be marked reachable (and
neither will its children in the call graph).
Also, the sizes mentioned are more or less completely bogus.
"""
print "The following are hardcoded in as vtable roots: %s" % vtable_roots