aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'libsbutil/include/rcscripts/util')
-rw-r--r--libsbutil/include/rcscripts/util/Makefile.am10
-rw-r--r--libsbutil/include/rcscripts/util/config.h40
-rw-r--r--libsbutil/include/rcscripts/util/debug.h162
-rw-r--r--libsbutil/include/rcscripts/util/dynbuf.h67
-rw-r--r--libsbutil/include/rcscripts/util/file.h69
-rw-r--r--libsbutil/include/rcscripts/util/list.h446
-rw-r--r--libsbutil/include/rcscripts/util/simple-regex.h87
-rw-r--r--libsbutil/include/rcscripts/util/str_list.h244
-rw-r--r--libsbutil/include/rcscripts/util/string.h64
9 files changed, 1189 insertions, 0 deletions
diff --git a/libsbutil/include/rcscripts/util/Makefile.am b/libsbutil/include/rcscripts/util/Makefile.am
new file mode 100644
index 0000000..01a3358
--- /dev/null
+++ b/libsbutil/include/rcscripts/util/Makefile.am
@@ -0,0 +1,10 @@
+rcdir = $(pkgincludedir)/util
+rc_HEADERS = \
+ debug.h \
+ dynbuf.h \
+ list.h \
+ string.h \
+ file.h \
+ config.h \
+ simple-regex.h \
+ str_list.h
diff --git a/libsbutil/include/rcscripts/util/config.h b/libsbutil/include/rcscripts/util/config.h
new file mode 100644
index 0000000..b45ac47
--- /dev/null
+++ b/libsbutil/include/rcscripts/util/config.h
@@ -0,0 +1,40 @@
+/*
+ * config.h
+ *
+ * Miscellaneous config related macro's and functions.
+ *
+ * Copyright 2004-2007 Martin Schlemmer <azarah@nosferatu.za.org>
+ *
+ *
+ * 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 version 2 of the License.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Header$
+ */
+
+#ifndef __RC_CONFIG_H__
+#define __RC_CONFIG_H__
+
+#include <stdio.h>
+
+/* The following return a pointer on success, or NULL with errno set on error.
+ * If it returned NULL, but errno is not set, then there was no error, but
+ * there is nothing to return. */
+/* rc_get_cnf_entry() will get the last config entry (ala bash variable
+ * assignment rules) if 'sep' equals NULL, else it will concat all values
+ * together seperated by 'sep'. */
+char *rc_get_cnf_entry (const char *pathname, const char *entry,
+ const char *sep);
+char ** rc_get_list_file (char **list, char *filename);
+
+#endif /* __RC_CONFIG_H__ */
diff --git a/libsbutil/include/rcscripts/util/debug.h b/libsbutil/include/rcscripts/util/debug.h
new file mode 100644
index 0000000..ae614ad
--- /dev/null
+++ b/libsbutil/include/rcscripts/util/debug.h
@@ -0,0 +1,162 @@
+/*
+ * debug.h
+ *
+ * Simle debugging/logging macro's and functions.
+ *
+ * Copyright 2004-2007 Martin Schlemmer <azarah@nosferatu.za.org>
+ *
+ *
+ * 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 version 2 of the License.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Header$
+ */
+
+#ifndef __RC_DEBUG_H__
+#define __RC_DEBUG_H__
+
+#include <errno.h>
+#include <stdio.h>
+
+#define save_errno() int old_errno = errno;
+#define restore_errno() errno = old_errno;
+#define saved_errno old_errno
+
+void
+rc_log_domain (const char *new_domain);
+void
+rc_debug_enabled (bool enabled);
+
+/* Using errno to try and create a debug system that will 'trace' from the
+ * point the initial error occured, is highly messy and needs strict errno
+ * accounting. So we rather implement our own private errno system.
+ * Currently it still is a form of errno (I'd rather move to something less
+ * messy, but it can be changed after I have a better idea of what exactly is
+ * needed), as its easier to map to the normal errno system, but without the
+ * issue of needing to keep in mind what others might do with errno's value,
+ * and slightly less of an accounting nightmare. */
+void
+rc_errno_set (int rc_errno);
+void
+rc_errno_clear (void);
+int
+rc_errno_get (void);
+bool
+rc_errno_is_set (void);
+
+#define rc_errno_save() int _rc_old_errno = rc_errno_get ();
+#define rc_errno_restore() rc_errno_set (_rc_old_errno);
+#define rc_errno_saved _rc_old_errno
+
+void
+debug_message (const char *file, const char *func, int line,
+ const char *format, ...);
+
+#define DBG_MSG(_format, _arg...) \
+ do { \
+ debug_message (__FILE__, __FUNCTION__, __LINE__, _format, ## _arg); \
+ } while (0)
+
+#define FATAL_ERROR() \
+ do { \
+ save_errno (); \
+ fprintf(stderr, "ERROR: file '%s', function '%s', line %i.\n", \
+ __FILE__, __FUNCTION__, __LINE__); \
+ restore_errno (); \
+ if (0 != errno) \
+ { \
+ perror("ERROR"); \
+ } \
+ exit(EXIT_FAILURE); \
+ } while (0)
+
+#define NEG_FATAL_ERROR(_x) \
+ do { \
+ if (-1 == _x) \
+ { \
+ FATAL_ERROR(); \
+ } \
+ } while (0)
+
+#define NULL_FATAL_ERROR(_x) \
+ do { \
+ if (NULL == _x) \
+ { \
+ FATAL_ERROR(); \
+ } \
+ } while (0)
+
+/*
+ * Functions to check validity of some types.
+ * They do not set errno.
+ */
+
+inline bool check_ptr (const void *ptr);
+inline bool check_str (const char *str);
+inline bool check_strv (char **str);
+inline bool check_fd (int fd);
+inline bool check_fp (FILE * fp);
+
+/*
+ * Functions and macro's to check validity of some types.
+ * They DO set errno to EINVAL.
+ */
+
+inline bool __check_arg_ptr (const void *ptr, const char *file, const char *func,
+ size_t line);
+inline bool __check_arg_str (const char *str, const char *file, const char *func,
+ size_t line);
+inline bool __check_arg_strv (char **str, const char *file, const char *func,
+ size_t line);
+inline bool __check_arg_fd (int fd, const char *file, const char *func,
+ size_t line);
+inline bool __check_arg_fp (FILE * fp, const char *file, const char *func,
+ size_t line);
+
+#define check_arg_ptr(_ptr) \
+ __check_arg_ptr (_ptr, __FILE__, __FUNCTION__, __LINE__)
+#define check_arg_str(_str) \
+ __check_arg_str (_str, __FILE__, __FUNCTION__, __LINE__)
+#define check_arg_strv(_str) \
+ __check_arg_strv (_str, __FILE__, __FUNCTION__, __LINE__)
+#define check_arg_fd(_fd) \
+ __check_arg_fd (_fd, __FILE__, __FUNCTION__, __LINE__)
+#define check_arg_fp(_fp) \
+ __check_arg_fp (_fp, __FILE__, __FUNCTION__, __LINE__)
+
+/*
+ * Various memory allocation functions and macro's.
+ * They set errno to ENOMEM and print debug info.
+ */
+
+inline void *__xcalloc (size_t nmemb, size_t size, const char *file,
+ const char *func, size_t line);
+inline void *__xmalloc (size_t size, const char *file, const char *func,
+ size_t line);
+inline void *__xrealloc (void *ptr, size_t size, const char *file,
+ const char *func, size_t line);
+
+#define xcalloc(_nmemb, _size) \
+ __xcalloc (_nmemb, _size, __FILE__, __FUNCTION__, __LINE__)
+#define xmalloc(_size) \
+ __xmalloc (_size, __FILE__, __FUNCTION__, __LINE__)
+#define xrealloc(_ptr, _size) \
+ __xrealloc (_ptr, _size, __FILE__, __FUNCTION__, __LINE__)
+
+inline char *__xstrndup (const char *str, size_t size, const char *file,
+ const char *func, size_t line);
+
+#define xstrndup(_str, _size) \
+ __xstrndup (_str, _size, __FILE__, __FUNCTION__, __LINE__)
+
+#endif /* __RC_DEBUG_H__ */
diff --git a/libsbutil/include/rcscripts/util/dynbuf.h b/libsbutil/include/rcscripts/util/dynbuf.h
new file mode 100644
index 0000000..3ed488a
--- /dev/null
+++ b/libsbutil/include/rcscripts/util/dynbuf.h
@@ -0,0 +1,67 @@
+/*
+ * dynbuf.h
+ *
+ * Dynamic allocated buffers.
+ *
+ * Copyright 2004-2007 Martin Schlemmer <azarah@nosferatu.za.org>
+ *
+ *
+ * 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 version 2 of the License.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Header$
+ */
+
+#ifndef __RC_DYNBUF_H__
+#define __RC_DYNBUF_H__
+
+typedef struct
+{
+ char *data; /* Actual data */
+ size_t length; /* Length of data block */
+ size_t rd_index; /* Current read index */
+ size_t wr_index; /* Current write index */
+ bool file_map; /* File mapped as dynbuf */
+} rc_dynbuf_t;
+
+rc_dynbuf_t *rc_dynbuf_new (void);
+
+rc_dynbuf_t *rc_dynbuf_new_mmap_file (const char *name);
+
+void rc_dynbuf_free (rc_dynbuf_t *dynbuf);
+
+int rc_dynbuf_write (rc_dynbuf_t *dynbuf, const char *buf, size_t length);
+
+int rc_dynbuf_write_fd (rc_dynbuf_t *dynbuf, int fd, size_t length);
+
+int rc_dynbuf_sprintf (rc_dynbuf_t *dynbuf, const char *format, ...);
+
+int rc_dynbuf_read (rc_dynbuf_t *dynbuf, char *buf, size_t length);
+
+int rc_dynbuf_read_fd (rc_dynbuf_t *dynbuf, int fd, size_t length);
+
+char *rc_dynbuf_read_line (rc_dynbuf_t *dynbuf);
+
+int rc_dynbuf_replace_char (rc_dynbuf_t *dynbuf, const char old, const char new);
+
+bool rc_dynbuf_read_eof (rc_dynbuf_t *dynbuf);
+
+inline bool rc_check_dynbuf (rc_dynbuf_t *dynbuf);
+inline bool __rc_check_arg_dynbuf (rc_dynbuf_t *dynbuf, const char *file,
+ const char *func, size_t line);
+
+#define rc_check_arg_dynbuf(_dynbuf) \
+ __rc_check_arg_dynbuf (_dynbuf, __FILE__, __FUNCTION__, __LINE__)
+
+#endif /* __RC_DYNBUF_H__ */
+
diff --git a/libsbutil/include/rcscripts/util/file.h b/libsbutil/include/rcscripts/util/file.h
new file mode 100644
index 0000000..7ace060
--- /dev/null
+++ b/libsbutil/include/rcscripts/util/file.h
@@ -0,0 +1,69 @@
+/*
+ * file.h
+ *
+ * Miscellaneous file related macro's and functions.
+ *
+ * Copyright 2004-2007 Martin Schlemmer <azarah@nosferatu.za.org>
+ *
+ *
+ * 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 version 2 of the License.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Header$
+ */
+
+#ifndef __RC_FILE_H__
+#define __RC_FILE_H__
+
+#include <stdio.h>
+
+/* Return true if filename '_name' ends in '_ext' */
+#define CHECK_FILE_EXTENSION(_name, _ext) \
+ ((check_str (_name)) && (check_str (_ext)) \
+ && (strlen (_name) > strlen (_ext)) \
+ && (0 == strncmp (&(_name[strlen(_name) - strlen(_ext)]), \
+ _ext, strlen(_ext))))
+
+/* The following functions do not care about errors - they only return
+ * TRUE if 'pathname' exist, and is the type requested, or else FALSE.
+ * This is only if pathname is valid ... */
+bool rc_file_exists (const char *pathname);
+bool rc_is_file (const char *pathname, bool follow_link);
+bool rc_is_link (const char *pathname);
+bool rc_is_dir (const char *pathname, bool follow_link);
+
+/* The following functions do not care about errors - it only returns
+ * the size/mtime of 'pathname' if it exists, and is the type requested,
+ * or else 0. */
+off_t rc_get_size (const char *pathname, bool follow_link);
+time_t rc_get_mtime (const char *pathname, bool follow_link);
+
+/* The following functions return 0 on success, or -1 with errno set on error. */
+#if !defined(HAVE_REMOVE)
+int remove (const char *pathname);
+#endif
+int rc_mktree (const char *pathname, mode_t mode);
+int rc_rmtree (const char *pathname);
+
+/* The following return a pointer on success, or NULL with errno set on error.
+ * If it returned NULL, but errno is not set, then there was no error, but
+ * there is nothing to return. */
+char **rc_ls_dir (const char *pathname, bool hidden, bool sort);
+
+/* Below two functions (rc_file_map and rc_file_unmap) are from
+ * udev-050 (udev_utils.c). Please see misc.c for copyright info.
+ * (Some are slightly modified, please check udev for originals.) */
+int rc_file_map (const char *filename, char **buf, size_t * bufsize);
+void rc_file_unmap (char *buf, size_t bufsize);
+
+#endif /* __RC_FILE_H__ */
diff --git a/libsbutil/include/rcscripts/util/list.h b/libsbutil/include/rcscripts/util/list.h
new file mode 100644
index 0000000..e4c7a74
--- /dev/null
+++ b/libsbutil/include/rcscripts/util/list.h
@@ -0,0 +1,446 @@
+/*
+ * Copied from the Linux kernel source tree, version 2.6.0-test1.
+ *
+ * Licensed under the GPL v2 as per the whole kernel source tree.
+ *
+ * Ripped out the rcu stuff, as it's not needed.
+ *
+ * $Header$
+ */
+
+#ifndef __LINUX_LIST_H__
+#define __LINUX_LIST_H__
+
+//#include <linux/stddef.h>
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ *
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+//#include <linux/prefetch.h>
+static inline void prefetch(const void *x) {;}
+
+//#include <asm/system.h>
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+#define LIST_POISON1 ((void *) 0x00100100)
+#define LIST_POISON2 ((void *) 0x00200200)
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = LIST_POISON1;
+ entry->prev = LIST_POISON2;
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+static inline void __list_splice(struct list_head *list,
+ struct list_head *head)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+ pos = pos->next, prefetch(pos->next))
+
+/**
+ * __list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
+ pos = pos->prev, prefetch(pos->prev))
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop counter.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member), \
+ prefetch(pos->member.prev); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member), \
+ prefetch(pos->member.prev))
+
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop counter.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/*
+ * Double linked lists with a single pointer list head.
+ * Mostly useful for hash tables where the two pointer list head is
+ * too wasteful.
+ * You lose the ability to access the tail in O(1).
+ */
+
+struct hlist_head {
+ struct hlist_node *first;
+};
+
+struct hlist_node {
+ struct hlist_node *next, **pprev;
+};
+
+#define HLIST_HEAD_INIT { .first = NULL }
+#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
+#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
+#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)
+
+static __inline__ int hlist_unhashed(struct hlist_node *h)
+{
+ return !h->pprev;
+}
+
+static __inline__ int hlist_empty(struct hlist_head *h)
+{
+ return !h->first;
+}
+
+static __inline__ void __hlist_del(struct hlist_node *n)
+{
+ struct hlist_node *next = n->next;
+ struct hlist_node **pprev = n->pprev;
+ *pprev = next;
+ if (next)
+ next->pprev = pprev;
+}
+
+static __inline__ void hlist_del(struct hlist_node *n)
+{
+ __hlist_del(n);
+ n->next = LIST_POISON1;
+ n->pprev = LIST_POISON2;
+}
+
+static __inline__ void hlist_del_init(struct hlist_node *n)
+{
+ if (n->pprev) {
+ __hlist_del(n);
+ INIT_HLIST_NODE(n);
+ }
+}
+
+static __inline__ void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+ struct hlist_node *first = h->first;
+ n->next = first;
+ if (first)
+ first->pprev = &n->next;
+ h->first = n;
+ n->pprev = &h->first;
+}
+
+/* next must be != NULL */
+static __inline__ void hlist_add_before(struct hlist_node *n, struct hlist_node *next)
+{
+ n->pprev = next->pprev;
+ n->next = next;
+ next->pprev = &n->next;
+ *(n->pprev) = n;
+}
+
+static __inline__ void hlist_add_after(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ next->next = n->next;
+ *(next->pprev) = n;
+ n->next = next;
+}
+
+#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
+
+/* Cannot easily do prefetch unfortunately */
+#define hlist_for_each(pos, head) \
+ for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
+ pos = pos->next)
+
+#define hlist_for_each_safe(pos, n, head) \
+ for (pos = (head)->first; n = pos ? pos->next : 0, pos; \
+ pos = n)
+
+/**
+ * hlist_for_each_entry - iterate over list of given type
+ * @tpos: the type * to use as a loop counter.
+ * @pos: the &struct hlist_node to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry(tpos, pos, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point
+ * @tpos: the type * to use as a loop counter.
+ * @pos: the &struct hlist_node to use as a loop counter.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_continue(tpos, pos, member) \
+ for (pos = (pos)->next; \
+ pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_from - iterate over a hlist continuing from existing point
+ * @tpos: the type * to use as a loop counter.
+ * @pos: the &struct hlist_node to use as a loop counter.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_from(tpos, pos, member) \
+ for (; pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @tpos: the type * to use as a loop counter.
+ * @pos: the &struct hlist_node to use as a loop counter.
+ * @n: another &struct hlist_node to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ n = pos->next; 1; }) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = n)
+
+#endif
diff --git a/libsbutil/include/rcscripts/util/simple-regex.h b/libsbutil/include/rcscripts/util/simple-regex.h
new file mode 100644
index 0000000..56da8b0
--- /dev/null
+++ b/libsbutil/include/rcscripts/util/simple-regex.h
@@ -0,0 +1,87 @@
+/*
+ * simple_regex.h
+ *
+ * Simle regex library.
+ *
+ * Copyright 2004-2007 Martin Schlemmer <azarah@nosferatu.za.org>
+ *
+ *
+ * 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 version 2 of the License.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Header$
+ */
+
+#ifndef __RC_SIMPLE_REGEX_H__
+#define __RC_SIMPLE_REGEX_H__
+
+#define REGEX_NO_MATCH 0 /* We have no match */
+#define REGEX_PARTIAL_MATCH 1 /* Some of the string matches the regex */
+#define REGEX_FULL_MATCH 2 /* The whole string matches the regex */
+
+/* Macro to fill in .data and .regex */
+#define FILL_REGEX_DATA(_regex_data, _string, _regex) \
+ do { \
+ _regex_data.data = _string; \
+ _regex_data.regex = _regex; \
+ } while (0)
+
+/* Fill in _regex_data with _data and _regex, on failure goto _error */
+#define DO_REGEX(_regex_data, _data, _regex, _error) \
+ do { \
+ FILL_REGEX_DATA(_regex_data, _data, _regex); \
+ if (-1 == match(&_regex_data)) \
+ { \
+ DBG_MSG("Could not do regex match!\n"); \
+ goto _error; \
+ } \
+ } while (0)
+
+/* Evaluate to true if we have some kind of match */
+#define REGEX_MATCH(_regex_data) \
+ ((REGEX_FULL_MATCH == _regex_data.match) \
+ || (REGEX_PARTIAL_MATCH == _regex_data.match))
+
+/* Same as above, but for use when _regex_data is a pointer */
+#define REGEX_MATCH_P(_regex_data) \
+ ((REGEX_FULL_MATCH == _regex_data->match) \
+ || (REGEX_PARTIAL_MATCH == _regex_data->match))
+
+typedef struct
+{
+ char *data; /* String to perform regex operation on */
+ char *regex; /* String containing regex to use */
+ int match; /* Will be set if there was a match. Check
+ * REGEX_*_MATCH above for possible values */
+ char *where; /* Pointer to where match starts in data */
+ size_t count; /* Count characters from data matched by regex */
+ size_t r_count; /* Count characters of regex used for match. This
+ * should normally be the lenght of regex, but might
+ * not be for some internal functions ... */
+} regex_data_t;
+
+/*
+ * Return:
+ *
+ * 0 - There was no error. If there was a match, regex_data->match
+ * - will be > 0 (this is the definitive check - if not true, the
+ * - other values of the struct may be bogus), regex_data->count
+ * - will be the amount of data that was matched (might be 0 for
+ * - some wildcards), and regex_data->r_count will be > 0.
+ *
+ * -1 - An error occured. Check errno for more info.
+ *
+ */
+int match (regex_data_t * regex_data);
+
+#endif /* __RC_SIMPLE_REGEX_H__ */
diff --git a/libsbutil/include/rcscripts/util/str_list.h b/libsbutil/include/rcscripts/util/str_list.h
new file mode 100644
index 0000000..f0c9355
--- /dev/null
+++ b/libsbutil/include/rcscripts/util/str_list.h
@@ -0,0 +1,244 @@
+/*
+ * str_list.h
+ *
+ * String list macros.
+ *
+ * Copyright 2004-2007 Martin Schlemmer <azarah@nosferatu.za.org>
+ *
+ *
+ * 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 version 2 of the License.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Header$
+ */
+
+#ifndef __RC_STR_LIST_H__
+#define __RC_STR_LIST_H__
+
+/* Add a new item to a string list. If the pointer to the list is NULL,
+ * allocate enough memory for the amount of entries needed. Ditto for
+ * when it already exists, but we add one more entry than it can
+ * contain. The list is NULL terminated.
+ * NOTE: _only_ memory for the list are allocated, and not for the items - that
+ * should be done by relevant code (unlike str_list_del_item() that will
+ * free the memory) */
+#define str_list_add_item(_string_list, _item, _error) \
+ do { \
+ char **_tmp_p; \
+ int _i = 0; \
+ if (!check_str (_item)) \
+ { \
+ goto _error; \
+ } \
+ while ((NULL != _string_list) && (NULL != _string_list[_i])) \
+ { \
+ _i++; \
+ } \
+ /* Amount of entries + new + terminator */ \
+ _tmp_p = xrealloc (_string_list, sizeof (char *) * (_i + 2)); \
+ if (NULL == _tmp_p) \
+ { \
+ goto _error; \
+ } \
+ _string_list = _tmp_p; \
+ _string_list[_i] = _item; \
+ /* Terminator */ \
+ _string_list[_i+1] = NULL; \
+ } while (0)
+
+/* Same as above, just makes a copy of the item, so calling code do not need
+ * to do this. */
+#define str_list_add_item_copy(_string_list, _item, _error) \
+ do { \
+ char *_tmp_str; \
+ char **_tmp_p; \
+ int _i = 0; \
+ if (!check_str (_item)) \
+ { \
+ goto _error; \
+ } \
+ while ((NULL != _string_list) && (NULL != _string_list[_i])) \
+ { \
+ _i++; \
+ } \
+ /* Amount of entries + new + terminator */ \
+ _tmp_p = xrealloc (_string_list, sizeof (char *) * (_i + 2)); \
+ if (NULL == _tmp_p) \
+ { \
+ goto _error; \
+ } \
+ _string_list = _tmp_p; \
+ _tmp_str = xstrndup (_item, strlen (_item)); \
+ if (NULL == _tmp_str) \
+ { \
+ goto _error; \
+ } \
+ _string_list[_i] = _tmp_str; \
+ /* Terminator */ \
+ _string_list[_i+1] = NULL; \
+ } while (0)
+
+/* Add a new item to a string list (foundamental the same as above), but make
+ * sure we have all the items alphabetically sorted. */
+#define str_list_add_item_sorted(_string_list, _item, _error) \
+ do { \
+ char **_tmp_p; \
+ char *_str_p1; \
+ char *_str_p2; \
+ int _i = 0; \
+ if (!check_str (_item)) \
+ { \
+ goto _error; \
+ } \
+ while ((NULL != _string_list) && (NULL != _string_list[_i])) \
+ { \
+ _i++; \
+ } \
+ /* Amount of entries + new + terminator */ \
+ _tmp_p = xrealloc (_string_list, sizeof (char *) * (_i + 2)); \
+ if (NULL == _tmp_p) \
+ { \
+ goto _error; \
+ } \
+ _string_list = _tmp_p; \
+ if (0 == _i) \
+ { \
+ /* Needed so that the end NULL will propagate
+ * (iow, make sure our 'NULL != _str_p1' test below
+ * do not fail) */ \
+ _string_list[_i] = NULL; \
+ } \
+ /* Actual terminator that needs adding */ \
+ _string_list[_i+1] = NULL; \
+ _i = 0; \
+ /* See where we should insert the new item to have it all \
+ * alphabetically sorted */ \
+ while (NULL != _string_list[_i]) \
+ { \
+ if (strcmp (_string_list[_i], _item) > 0) \
+ { \
+ break; \
+ } \
+ _i++; \
+ } \
+ /* Now just insert the new item, and shift the rest one over.
+ * '_str_p2' is temporary storage to swap the indexes in a loop,
+ * and 'str_p1' is used to store the old value across the loop */ \
+ _str_p1 = _string_list[_i]; \
+ _string_list[_i] = _item; \
+ do { \
+ _i++;\
+ _str_p2 = _string_list[_i]; \
+ _string_list[_i] = _str_p1; \
+ _str_p1 = _str_p2; \
+ } while (NULL != _str_p1); \
+ } while (0)
+
+/* Delete one entry from the string list, and shift the rest down if the entry
+ * was not at the end. For now we do not resize the amount of entries the
+ * string list can contain, and free the memory for the matching item */
+#define str_list_del_item(_string_list, _item, _error) \
+ do { \
+ int _i = 0; \
+ if (!check_str (_item)) \
+ { \
+ goto _error; \
+ } \
+ if (NULL == _string_list) \
+ { \
+ rc_errno_set (EINVAL); \
+ DBG_MSG ("Invalid string list passed!\n"); \
+ goto _error; \
+ } \
+ while (NULL != _string_list[_i]) \
+ { \
+ if (0 == strcmp (_item, _string_list[_i])) \
+ { \
+ break; \
+ } \
+ else \
+ { \
+ _i++; \
+ } \
+ } \
+ if (NULL == _string_list[_i]) \
+ { \
+ rc_errno_set (EINVAL); \
+ DBG_MSG ("Invalid string list item passed!\n"); \
+ goto _error; \
+ } \
+ free (_string_list[_i]); \
+ /* Shift all the following items one forward */ \
+ do { \
+ _string_list[_i] = _string_list[_i+1]; \
+ /* This stupidity is to shutup gcc */ \
+ _i++; \
+ } while (NULL != _string_list[_i]); \
+ } while (0)
+
+/* Step through each entry in the string list, setting '_pos' to the
+ * beginning of the entry. '_counter' is used by the macro as index,
+ * but should not be used by code as index (or if really needed, then
+ * it should usually by +1 from what you expect, and should only be
+ * used in the scope of the macro) */
+#define str_list_for_each_item(_string_list, _pos, _counter) \
+ if ((NULL != _string_list) && (0 == (_counter = 0))) \
+ while (NULL != (_pos = _string_list[_counter++]))
+
+/* Same as above (with the same warning about '_counter'). Now we just
+ * have '_next' that are also used for indexing. Once again rather refrain
+ * from using it if not absolutely needed. The major difference to above,
+ * is that it should be safe from having the item removed from under you. */
+#define str_list_for_each_item_safe(_string_list, _pos, _next, _counter) \
+ if ((NULL != _string_list) && (0 == (_counter = 0))) \
+ /* First part of the while checks if this is the
+ * first loop, and if so setup _pos and _next
+ * and increment _counter */ \
+ while ((((0 == _counter) \
+ && (NULL != (_pos = _string_list[_counter])) \
+ && (_pos != (_next = _string_list[++_counter]))) \
+ /* Second part is when it is not the first loop
+ * and _pos was not removed from under us. We
+ * just increment _counter, and setup _pos and
+ * _next */ \
+ || ((0 != _counter) \
+ && (_pos == _string_list[_counter-1]) \
+ && (_next == _string_list[_counter]) \
+ && (NULL != (_pos = _string_list[_counter])) \
+ && (_pos != (_next = _string_list[++_counter]))) \
+ /* Last part is when _pos was removed from under
+ * us. We basically just setup _pos and _next,
+ * but leave _counter alone */ \
+ || ((0 != _counter) \
+ && (_pos != _string_list[_counter-1]) \
+ && (_next == _string_list[_counter-1]) \
+ && (NULL != (_pos = _string_list[_counter-1])) \
+ && (_pos != (_next = _string_list[_counter])))))
+
+/* Just free the whole string list */
+#define str_list_free(_string_list) \
+ do { \
+ if (NULL != _string_list) \
+ { \
+ int _i = 0; \
+ while (NULL != _string_list[_i]) \
+ { \
+ free (_string_list[_i]); \
+ _string_list[_i++] = NULL; \
+ } \
+ free (_string_list); \
+ _string_list = NULL; \
+ } \
+ } while (0)
+
+#endif /* __RC_STR_LIST_H__ */
diff --git a/libsbutil/include/rcscripts/util/string.h b/libsbutil/include/rcscripts/util/string.h
new file mode 100644
index 0000000..9753d7a
--- /dev/null
+++ b/libsbutil/include/rcscripts/util/string.h
@@ -0,0 +1,64 @@
+/*
+ * string.h
+ *
+ * Miscellaneous string related macro's and functions.
+ *
+ * Copyright 2004-2007 Martin Schlemmer <azarah@nosferatu.za.org>
+ *
+ *
+ * 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 version 2 of the License.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Header$
+ */
+
+#ifndef __RC_STRING_H__
+#define __RC_STRING_H__
+
+#include <stdio.h>
+
+/* Gentoo style e* printing macro's */
+#define EINFO(_args...) \
+ do { \
+ save_errno (); \
+ printf (" \033[32;01m*\033[0m " _args); \
+ restore_errno (); \
+ } while (0)
+
+#define EWARN(_args...) \
+ do { \
+ save_errno (); \
+ printf (" \033[33;01m*\033[0m " _args); \
+ restore_errno (); \
+ } while (0)
+
+#define EERROR(_args...) \
+ do { \
+ save_errno (); \
+ fprintf (stderr, " \033[31;01m*\033[0m " _args); \
+ restore_errno (); \
+ } while (0)
+
+/* String functions. Return a string on success, or NULL on error
+ * or no action taken. On error errno will be set.*/
+char *rc_memrepchr (char **str, char old, char _new, size_t size);
+/* Concat two paths adding '/' if needed. Memory will be allocated
+ * with the malloc() call. */
+char *rc_strcatpaths (const char *pathname1, const char *pathname2);
+
+/* Compat functions for GNU extensions */
+char *rc_strndup (const char *str, size_t size);
+/* Same as basename(3), but do not modify path */
+char *rc_basename (const char *path);
+
+#endif /* __RC_STRING_H__ */