Commit bc86794f authored by Havoc Pennington's avatar Havoc Pennington

2003-03-30 Havoc Pennington <hp@pobox.com>

	* bus/config-parser.c: hacking

	* dbus/dbus-memory.c: don't use DBusList for the list of stuff
	to shut down, since it could cause weirdness with the DBusList
	lock

	* dbus/dbus-list.c (_dbus_list_test): add tests for the
	link-oriented stack routines
	(alloc_link): free the mempool if the first alloc from it fails

	* dbus/dbus-mempool.c (struct DBusMemBlock): fix alignment issue

	* dbus/dbus-string.c (UNICODE_VALID): sync new version of this
	from GLib
	(_dbus_string_skip_white): new

	* doc/config-file.txt (Elements): add <includedir>
parent d361874e
2003-03-30 Havoc Pennington <hp@pobox.com>
* bus/config-parser.c: hacking
* dbus/dbus-memory.c: don't use DBusList for the list of stuff
to shut down, since it could cause weirdness with the DBusList
lock
* dbus/dbus-list.c (_dbus_list_test): add tests for the
link-oriented stack routines
(alloc_link): free the mempool if the first alloc from it fails
* dbus/dbus-mempool.c (struct DBusMemBlock): fix alignment issue
* dbus/dbus-string.c (UNICODE_VALID): sync new version of this
from GLib
(_dbus_string_skip_white): new
* doc/config-file.txt (Elements): add <includedir>
2003-03-28 Havoc Pennington <hp@pobox.com>
* dbus/dbus-string.c (_dbus_string_copy_data_len)
(_dbus_string_copy_data): new functions
2003-03-28 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-bus.c: (bus_data_free), (dbus_bus_get):
......
......@@ -4,7 +4,7 @@
* Copyright (C) 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
*
* 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
......@@ -14,7 +14,7 @@
* 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
......@@ -41,6 +41,27 @@ typedef struct
dbus_bool_t failed;
} ExpatParseContext;
static dbus_bool_t
process_content (ExpatParseContext *context)
{
if (context->failed)
return FALSE;
if (_dbus_string_get_length (&context->content) > 0)
{
if (!bus_config_parser_content (context->parser,
&context->content,
context->error))
{
context->failed = TRUE;
return FALSE;
}
_dbus_string_set_length (&context->content, 0);
}
return TRUE;
}
static void
expat_StartElementHandler (void *userData,
const XML_Char *name,
......@@ -50,13 +71,16 @@ expat_StartElementHandler (void *userData,
int i;
char **names;
char **values;
/* Expat seems to suck and can't abort the parse if we
* throw an error. Expat 2.0 is supposed to fix this.
*/
if (context->failed)
return;
if (!process_content (context))
return;
/* "atts" is key, value, key, value, NULL */
for (i = 0; atts[i] != NULL; ++i)
; /* nothing */
......@@ -73,17 +97,17 @@ expat_StartElementHandler (void *userData,
dbus_free (values);
return;
}
i = 0;
while (atts[i] != NULL)
{
_dbus_assert (i % 2 == 0);
names [i / 2] = (char*) atts[i];
values[i / 2 + 1] = (char*) atts[i+1];
names [i / 2] = (char*) atts[i];
values[i / 2] = (char*) atts[i+1];
i += 2;
}
if (!bus_config_parser_start_element (context->parser,
name,
(const char **) names,
......@@ -105,20 +129,9 @@ expat_EndElementHandler (void *userData,
const XML_Char *name)
{
ExpatParseContext *context = userData;
if (context->failed)
return;
if (_dbus_string_get_length (&context->content) > 0)
{
if (!bus_config_parser_content (context->parser,
&context->content,
context->error))
{
context->failed = TRUE;
return;
}
_dbus_string_set_length (&context->content, 0);
}
if (!process_content (context))
return;
if (!bus_config_parser_end_element (context->parser,
name,
......@@ -157,22 +170,22 @@ bus_config_load (const DBusString *file,
const char *filename;
BusConfigParser *parser;
ExpatParseContext context;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
parser = NULL;
expat = NULL;
context.error = error;
context.failed = FALSE;
_dbus_string_get_const_data (file, &filename);
if (!_dbus_string_init (&context.content, _DBUS_INT_MAX))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
return NULL;
}
expat = XML_ParserCreate_MM ("UTF-8", &memsuite, NULL);
if (expat == NULL)
{
......@@ -186,6 +199,7 @@ bus_config_load (const DBusString *file,
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto failed;
}
context.parser = parser;
XML_SetUserData (expat, &context);
XML_SetElementHandler (expat,
......@@ -197,28 +211,28 @@ bus_config_load (const DBusString *file,
{
DBusString data;
const char *data_str;
if (!_dbus_string_init (&data, _DBUS_INT_MAX))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto failed;
}
if (!_dbus_file_get_contents (&data, file, error))
{
_dbus_string_free (&data);
goto failed;
}
_dbus_string_get_const_data (&data, &data_str);
if (!XML_Parse (expat, data_str, _dbus_string_get_length (&data), TRUE))
{
if (context.error != NULL &&
!dbus_error_is_set (context.error))
{
enum XML_Error e;
e = XML_GetErrorCode (expat);
if (e == XML_ERROR_NO_MEMORY)
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
......@@ -230,7 +244,7 @@ bus_config_load (const DBusString *file,
XML_GetCurrentColumnNumber (expat),
XML_ErrorString (e));
}
_dbus_string_free (&data);
goto failed;
}
......@@ -240,7 +254,7 @@ bus_config_load (const DBusString *file,
if (context.failed)
goto failed;
}
if (!bus_config_parser_finished (parser, error))
goto failed;
......@@ -249,10 +263,10 @@ bus_config_load (const DBusString *file,
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
return parser;
failed:
_DBUS_ASSERT_ERROR_IS_SET (error);
_dbus_string_free (&context.content);
if (expat)
XML_ParserFree (expat);
......
This diff is collapsed.
......@@ -69,8 +69,8 @@ main (int argc, char **argv)
printf ("%s: Running config file parser test\n", argv[0]);
if (!bus_config_parser_test (&test_data_dir))
die ("parser");
check_memleaks (argv[0]);
check_memleaks (argv[0]);
printf ("%s: Running policy test\n", argv[0]);
if (!bus_policy_test (&test_data_dir))
......
......@@ -345,7 +345,7 @@ _dbus_test_oom_handling (const char *description,
if (!(* func) (data))
return FALSE;
approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
_dbus_verbose ("=================\n%s: about %d mallocs total\n=================\n",
......
......@@ -212,7 +212,8 @@ _DBUS_DECLARE_GLOBAL_LOCK (atomic);
_DBUS_DECLARE_GLOBAL_LOCK (message_handler);
_DBUS_DECLARE_GLOBAL_LOCK (user_info);
_DBUS_DECLARE_GLOBAL_LOCK (bus);
#define _DBUS_N_GLOBAL_LOCKS (7)
_DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs);
#define _DBUS_N_GLOBAL_LOCKS (8)
DBUS_END_DECLS;
......
......@@ -57,8 +57,8 @@ alloc_link (void *data)
if (!_DBUS_LOCK (list))
return NULL;
if (!list_pool)
if (list_pool == NULL)
{
list_pool = _dbus_mem_pool_new (sizeof (DBusList), TRUE);
......@@ -67,9 +67,21 @@ alloc_link (void *data)
_DBUS_UNLOCK (list);
return NULL;
}
link = _dbus_mem_pool_alloc (list_pool);
if (link == NULL)
{
_dbus_mem_pool_free (list_pool);
list_pool = NULL;
_DBUS_UNLOCK (list);
return NULL;
}
}
link = _dbus_mem_pool_alloc (list_pool);
else
{
link = _dbus_mem_pool_alloc (list_pool);
}
if (link)
link->data = data;
......@@ -80,13 +92,14 @@ alloc_link (void *data)
static void
free_link (DBusList *link)
{
{
_DBUS_LOCK (list);
if (_dbus_mem_pool_dealloc (list_pool, link))
{
_dbus_mem_pool_free (list_pool);
list_pool = NULL;
}
_DBUS_UNLOCK (list);
}
......@@ -607,6 +620,27 @@ _dbus_list_pop_last (DBusList **list)
return data;
}
/**
* Removes the last link in the list and returns it. This is a
* constant-time operation.
*
* @param list address of the list head.
* @returns the last link in the list, or #NULL for an empty list.
*/
DBusList*
_dbus_list_pop_last_link (DBusList **list)
{
DBusList *link;
link = _dbus_list_get_last_link (list);
if (link == NULL)
return NULL;
_dbus_list_unlink (list, link);
return link;
}
/**
* Copies a list. This is a linear-time operation. If there isn't
* enough memory to copy the entire list, the destination list will be
......@@ -952,6 +986,58 @@ _dbus_list_test (void)
_dbus_assert (list1 == NULL);
_dbus_assert (list2 == NULL);
/* Test get_first_link, get_last_link, pop_first_link, pop_last_link */
i = 0;
while (i < 10)
{
_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
++i;
}
--i;
while (i >= 0)
{
DBusList *got_link1;
DBusList *got_link2;
DBusList *link1;
DBusList *link2;
void *data1;
void *data2;
got_link1 = _dbus_list_get_last_link (&list1);
got_link2 = _dbus_list_get_first_link (&list2);
link1 = _dbus_list_pop_last_link (&list1);
link2 = _dbus_list_pop_first_link (&list2);
_dbus_assert (got_link1 == link1);
_dbus_assert (got_link2 == link2);
data1 = link1->data;
data2 = link2->data;
_dbus_list_free_link (link1);
_dbus_list_free_link (link2);
_dbus_assert (_DBUS_POINTER_TO_INT (data1) == i);
_dbus_assert (_DBUS_POINTER_TO_INT (data2) == i);
verify_list (&list1);
verify_list (&list2);
_dbus_assert (is_ascending_sequence (&list1));
_dbus_assert (is_descending_sequence (&list2));
--i;
}
_dbus_assert (list1 == NULL);
_dbus_assert (list2 == NULL);
/* Test iteration */
i = 0;
......
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-list.h Generic linked list utility (internal to D-BUS implementation)
*
* Copyright (C) 2002 Red Hat, Inc.
* Copyright (C) 2002, 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
......@@ -63,6 +63,7 @@ void* _dbus_list_get_first (DBusList **list);
void* _dbus_list_pop_first (DBusList **list);
void* _dbus_list_pop_last (DBusList **list);
DBusList* _dbus_list_pop_first_link (DBusList **list);
DBusList* _dbus_list_pop_last_link (DBusList **list);
dbus_bool_t _dbus_list_copy (DBusList **list,
DBusList **dest);
int _dbus_list_get_length (DBusList **list);
......
......@@ -633,13 +633,17 @@ dbus_free_string_array (char **str_array)
*/
int _dbus_current_generation = 1;
static DBusList *registered_globals = NULL;
typedef struct ShutdownClosure ShutdownClosure;
typedef struct
struct ShutdownClosure
{
ShutdownClosure *next;
DBusShutdownFunction func;
void *data;
} ShutdownClosure;
};
_DBUS_DEFINE_GLOBAL_LOCK (shutdown_funcs);
static ShutdownClosure *registered_globals = NULL;
/**
* The D-BUS library keeps some internal global variables, for example
......@@ -656,22 +660,18 @@ typedef struct
void
dbus_shutdown (void)
{
DBusList *link;
link = _dbus_list_get_first_link (&registered_globals);
while (link != NULL)
while (registered_globals != NULL)
{
ShutdownClosure *c = link->data;
ShutdownClosure *c;
c = registered_globals;
registered_globals = c->next;
(* c->func) (c->data);
dbus_free (c);
link = _dbus_list_get_next_link (&registered_globals, link);
dbus_free (c);
}
_dbus_list_clear (&registered_globals);
_dbus_current_generation += 1;
}
......@@ -693,20 +693,17 @@ _dbus_register_shutdown_func (DBusShutdownFunction func,
if (c == NULL)
return FALSE;
c->func = func;
c->data = data;
/* We prepend, then shutdown the list in order, so
* we shutdown last-registered stuff first which
* is right.
*/
if (!_dbus_list_prepend (&registered_globals, c))
{
dbus_free (c);
return FALSE;
}
_DBUS_LOCK (shutdown_funcs);
c->next = registered_globals;
registered_globals = c;
_DBUS_UNLOCK (shutdown_funcs);
return TRUE;
}
......
......@@ -84,7 +84,8 @@ struct DBusMemBlock
* when we free the mem pool.
*/
int used_so_far; /**< bytes of this block already allocated as elements. */
/* this is a long so that "elements" is aligned */
long used_so_far; /**< bytes of this block already allocated as elements. */
unsigned char elements[ELEMENT_PADDING]; /**< the block data, actually allocated to required size */
};
......@@ -254,7 +255,7 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
memset (element, '\0', pool->element_size);
pool->allocated_elements += 1;
return element;
}
else
......@@ -311,11 +312,11 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
}
element = &pool->blocks->elements[pool->blocks->used_so_far];
pool->blocks->used_so_far += pool->element_size;
pool->allocated_elements += 1;
return element;
}
}
......
......@@ -633,7 +633,74 @@ _dbus_string_steal_data_len (DBusString *str,
return FALSE;
}
_dbus_warn ("Broken code in _dbus_string_steal_data_len(), FIXME\n");
_dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
if (!_dbus_string_steal_data (&dest, data_return))
{
_dbus_string_free (&dest);
return FALSE;
}
_dbus_string_free (&dest);
return TRUE;
}
/**
* Copies the data from the string into a char*
*
* @param str the string
* @param data_return place to return the data
* @returns #TRUE on success, #FALSE on no memory
*/
dbus_bool_t
_dbus_string_copy_data (const DBusString *str,
char **data_return)
{
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (data_return != NULL);
*data_return = dbus_malloc (real->len + 1);
if (*data_return == NULL)
return FALSE;
memcpy (*data_return, real->str, real->len + 1);
return TRUE;
}
/**
* Copies a segment of the string into a char*
*
* @param str the string
* @param data_return place to return the data
* @param start start index
* @param len length to copy
* @returns #FALSE if no memory
*/
dbus_bool_t
_dbus_string_copy_data_len (const DBusString *str,
char **data_return,
int start,
int len)
{
DBusString dest;
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (data_return != NULL);
_dbus_assert (start >= 0);
_dbus_assert (len >= 0);
_dbus_assert (start <= real->len);
_dbus_assert (len <= real->len - start);
if (!_dbus_string_init (&dest, real->max_length))
return FALSE;
if (!_dbus_string_copy_len (str, start, len, &dest, 0))
{
_dbus_string_free (&dest);
return FALSE;
}
if (!_dbus_string_steal_data (&dest, data_return))
{
_dbus_string_free (&dest);
......@@ -1235,8 +1302,9 @@ _dbus_string_replace_len (const DBusString *source,
*/
#define UNICODE_VALID(Char) \
((Char) < 0x110000 && \
((Char) < 0xD800 || (Char) >= 0xE000) && \
(Char) != 0xFFFE && (Char) != 0xFFFF)
(((Char) & 0xFFFFF800) != 0xD800) && \
((Char) < 0xFDD0 || (Char) > 0xFDEF) && \
((Char) & 0xFFFF) != 0xFFFF)
/**
* Gets a unicode character from a UTF-8 string. Does no validation;
......@@ -1426,6 +1494,7 @@ _dbus_string_find_blank (const DBusString *str,
/**
* Skips blanks from start, storing the first non-blank in *end
* (blank is space or tab).
*
* @param str the string
* @param start where to start
......@@ -1458,6 +1527,43 @@ _dbus_string_skip_blank (const DBusString *str,
*end = i;
}
/**
* 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;
}
/**
* Assigns a newline-terminated or \r\n-terminated line from the front
* of the string to the given dest string. The dest string's previous
......
......@@ -81,6 +81,12 @@ dbus_bool_t _dbus_string_steal_data_len (DBusString *str,
char **data_return,
int start,
int len);
dbus_bool_t _dbus_string_copy_data (const DBusString *str,
char **data_return);
dbus_bool_t _dbus_string_copy_data_len (const DBusString *str,
char **data_return,
int start,
int len);
int _dbus_string_get_length (const DBusString *str);
......@@ -175,6 +181,10 @@ void _dbus_string_skip_blank (const DBusString *str,
int start,
int *end);
void _dbus_string_skip_white (const DBusString *str,
int start,
int *end);
dbus_bool_t _dbus_string_equal (const DBusString *a,
const DBusString *b);
......
......@@ -245,7 +245,8 @@ init_global_locks (void)
LOCK_ADDR (atomic),
LOCK_ADDR (message_handler),
LOCK_ADDR (user_info),
LOCK_ADDR (bus)
LOCK_ADDR (bus),
LOCK_ADDR (shutdown_funcs)
#undef LOCK_ADDR
};
......
......@@ -32,6 +32,18 @@ Elements:
Include a file <include>filename.conf</include> at this point.
<includedir>
Include all files in <includedir>foo.d</includedir> at this
point. Files in the directory are included in undefined order.
Only files ending in ".conf" are included.
This is intended to allow extension of the system bus by
particular packages. For example, if CUPS wants to be able to send
out notification of printer queue changes, it could install a file
to /etc/dbus/system.d that allowed all apps to receive this
message and allowed the printer daemon user to send it.
<user>
The user account the daemon should run as, as either a username or
......@@ -42,13 +54,12 @@ Elements:
The last <user> entry in the file "wins", the others are ignored.
<listen>
address="name" mandatory attribute
Add an address that the bus should listen on. The
address is in the standard D-BUS format that contains
a transport name plus possible parameters/options.
Example: <listen address="unix:path=/tmp/foo"/>
Example: <listen>unix:path=/tmp/foo</listen>
If there are multiple <listen> elements, then the bus listens
on multiple addresses.
......
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<user>mybususer</user>
<listen>unix:path=/foo/bar</listen>
<listen>tcp:port=1234</listen>
<include ignore_missing="yes">nonexistent.conf</include>
<policy context="default">
<allow user="*"/>
</policy>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment