Subject: [PATCH] [FEAT LS1201] zdsfs: util_list backport
From: Stefan Weinhuber <wein@de.ibm.com>

Summary:     zdsfs: backport of common code prerequisite util_list
Description: The zdsfs implementation uses the s390-tools common code list
             implementation util_list. This is the backport of the required
             code.
Upstream-ID: -
Problem-ID:  LS1201

Signed-off-by: Stefan Weinhuber <wein@de.ibm.com>
---
 Makefile            |    2 
 include/util.h      |   14 ++
 include/util_list.h |   65 +++++++++++++
 libutil/Makefile    |   12 ++
 libutil/util_list.c |  246 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 338 insertions(+), 1 deletion(-)

--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ ARCH := $(shell uname -m | sed -e s/i.86
 # Include commond definitions
 include common.mak
 
-LIB_DIRS = libvtoc libu2s
+LIB_DIRS = libvtoc libu2s libutil
 SUB_DIRS = $(LIB_DIRS) zipl zdump fdasd dasdfmt dasdview tunedasd \
 	   tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \
 	   vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
--- /dev/null
+++ b/include/util.h
@@ -0,0 +1,14 @@
+/*
+ * util - Utility function library
+ *
+ * Library helper functions
+ *
+ * Copyright IBM Corp. 2013
+ */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include "util_list.h"
+
+#endif /* UTIL_H */
--- /dev/null
+++ b/include/util_list.h
@@ -0,0 +1,65 @@
+/*
+ * util - Utility function library
+ *
+ * Linked lists
+ *
+ * Copyright IBM Corp. 2013
+ */
+
+#ifndef UTIL_LIST_H
+#define UTIL_LIST_H
+
+#ifndef UTIL_H
+#warning "Please include util.h and not util_list.h directly!"
+#endif
+
+#include <stddef.h>
+
+struct util_list {
+	unsigned long offset;		/* Offset of struct util_list_node */
+	struct util_list_node *start;	/* First element */
+	struct util_list_node *end;	/* Last element */
+};
+
+struct util_list_node {
+	struct util_list_node *next;
+	struct util_list_node *prev;
+};
+
+#define util_list_new(type, member) util_list_new_offset(offsetof(type, member))
+#define util_list_init(list, type, member) \
+	util_list_init_offset(list, offsetof(type, member))
+void util_list_free(struct util_list *list);
+struct util_list *util_list_new_offset(unsigned long offset);
+void util_list_init_offset(struct util_list *list, unsigned long offset);
+void util_list_add_tail(struct util_list *list, void *entry);
+void util_list_add_head(struct util_list *list, void *entry);
+void util_list_add_next(struct util_list *list, void *entry, void *list_entry);
+void util_list_add_prev(struct util_list *list, void *entry, void *list_entry);
+void util_list_remove(struct util_list *list, void *entry);
+void *util_list_next(struct util_list *list, void *entry);
+void *util_list_prev(struct util_list *list, void *entry);
+void *util_list_start(struct util_list *list);
+int util_list_is_empty(struct util_list *list);
+unsigned long util_list_len(struct util_list *list);
+
+/*
+ * The compare function should return the following:
+ *  a < b --> < 0
+ *  a > b --> > 0
+ *  a = b --> = 0
+ */
+typedef int (*util_list_cmp_fn)(void *a, void *b, void *data);
+void util_list_sort(struct util_list *list, util_list_cmp_fn fn, void *data);
+
+#define util_list_iterate(list, i)		\
+	for (i = util_list_start(list);		\
+	     i != NULL;				\
+	     i = util_list_next(list, i))	\
+
+#define util_list_iterate_safe(list, i, n)				\
+	for (i = util_list_start(list), n = util_list_next(list, i);	\
+	     i != NULL;							\
+	     i = n, n = util_list_next(list, i))			\
+
+#endif /* UTIL_LIST_H */
--- /dev/null
+++ b/libutil/Makefile
@@ -0,0 +1,12 @@
+include ../common.mak
+
+CPPFLAGS += -I../include
+
+all: util_list.o
+
+util_list.o: util_list.c ../include/util.h
+
+install: all
+
+clean:
+	rm -f *.o *~ core
--- /dev/null
+++ b/libutil/util_list.c
@@ -0,0 +1,246 @@
+/*
+ * util - Utility function library
+ *
+ * Linked list functions
+ *
+ * Copyright IBM Corp. 2013
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "util.h"
+
+/*
+ * Node to entry
+ */
+static inline void *n2e(struct util_list *list, struct util_list_node *node)
+{
+	return ((void *) node) - list->offset;
+}
+
+/*
+ * Entry to node
+ */
+static inline struct util_list_node *e2n(struct util_list *list, void *entry)
+{
+	return entry + list->offset;
+}
+
+/*
+ * Initialize linked list
+ */
+void util_list_init_offset(struct util_list *list, unsigned long offset)
+{
+	memset(list, 0, sizeof(*list));
+	list->offset = offset;
+}
+
+/*
+ * Create new linked list
+ */
+struct util_list *util_list_new_offset(unsigned long offset)
+{
+	struct util_list *list = malloc(sizeof(*list));
+
+	if (!list)
+		return NULL;
+	util_list_init_offset(list, offset);
+	return list;
+}
+
+/*
+ * Free linked list
+ */
+void util_list_free(struct util_list *list)
+{
+	free(list);
+}
+
+/*
+ * Add new element to end of list
+ */
+void util_list_add_tail(struct util_list *list, void *entry)
+{
+	struct util_list_node *node = e2n(list, entry);
+
+	node->next = NULL;
+	if (!list->start) {
+		list->start = node;
+		node->prev = NULL;
+	} else {
+		list->end->next = node;
+		node->prev = list->end;
+	}
+	list->end = node;
+}
+
+/*
+ * Add new element to front of list
+ */
+void util_list_add_head(struct util_list *list, void *entry)
+{
+	struct util_list_node *node = e2n(list, entry);
+
+	node->prev = NULL;
+	node->next = NULL;
+	if (!list->start) {
+		list->end = node;
+	} else {
+		list->start->prev = node;
+		node->next = list->start;
+	}
+	list->start = node;
+}
+
+/*
+ * Add new element (entry) after an existing element (list_entry)
+ */
+void util_list_add_next(struct util_list *list, void *entry, void *list_entry)
+{
+	struct util_list_node *node = e2n(list, entry);
+	struct util_list_node *list_node = e2n(list, list_entry);
+
+	node->next = list_node->next;
+	node->prev = list_node;
+	if (list_node->next)
+		list_node->next->prev = node;
+	else
+		list->end = node;
+	list_node->next = node;
+}
+
+/*
+ * Add new element (entry) before an existing element (list_entry)
+ */
+void util_list_add_prev(struct util_list *list, void *entry, void *list_entry)
+{
+	struct util_list_node *node = e2n(list, entry);
+	struct util_list_node *list_node = e2n(list, list_entry);
+
+	node->prev = list_node->prev;
+	node->next = list_node;
+	if (list_node->prev)
+		list_node->prev->next = node;
+	else
+		list->start = node;
+	list_node->prev = node;
+}
+
+/*
+ * Remove element from list
+ */
+void util_list_remove(struct util_list *list, void *entry)
+{
+	struct util_list_node *node = e2n(list, entry);
+
+	if (list->start == node)
+		list->start = node->next;
+	if (list->end == node)
+		list->end = node->prev;
+	if (node->prev)
+		node->prev->next = node->next;
+	if (node->next)
+		node->next->prev = node->prev;
+}
+
+/*
+ * Get first element of list
+ */
+void *util_list_start(struct util_list *list)
+{
+	if (!list->start)
+		return NULL;
+	return ((void *) list->start) - list->offset;
+}
+
+/*
+ * Get next element after entry
+ */
+void *util_list_next(struct util_list *list, void *entry)
+{
+	struct util_list_node *node;
+
+	if (!entry)
+		return NULL;
+	node = e2n(list, entry);
+	node = node->next;
+	if (!node)
+		return NULL;
+	return n2e(list, node);
+}
+
+/*
+ * Get previous element before entry
+ */
+void *util_list_prev(struct util_list *list, void *entry)
+{
+	struct util_list_node *node;
+
+	if (!entry)
+		return NULL;
+	node = e2n(list, entry);
+	node = node->prev;
+	if (!node)
+		return NULL;
+	return n2e(list, node);
+}
+
+/*
+ * Get number of list entries
+ */
+unsigned long util_list_len(struct util_list *list)
+{
+	unsigned long cnt = 0;
+	void *entry;
+
+	util_list_iterate(list, entry)
+		cnt++;
+	return cnt;
+}
+
+/*
+ * Sort table (bubble sort)
+ */
+void util_list_sort(struct util_list *list, util_list_cmp_fn cmp_fn,
+		    void *data)
+{
+	struct util_list_node *node1, *node2;
+	unsigned long list_cnt, i, j;
+	void *entry1, *entry2;
+
+	list_cnt = util_list_len(list);
+
+	for (i = 1; i < list_cnt; i++) {
+		node1 = list->start;
+		for (j = 0; j < list_cnt - i; j++) {
+			node2 = node1->next;
+			entry1 = n2e(list, node1);
+			entry2 = n2e(list, node2);
+			if (cmp_fn(entry1, entry2, data) > 0) {
+				node1->next = node2->next;
+				if (node1->next)
+					node1->next->prev = node1;
+				else
+					list->end = node1;
+				node2->next = node1;
+				node2->prev = node1->prev;
+				if (node2->prev)
+					node2->prev->next = node2;
+				else
+					list->start = node2;
+				node1->prev = node2;
+			} else {
+				node1 = node2;
+			}
+		}
+	}
+}
+
+/*
+ * Check if list is empty
+ */
+int util_list_is_empty(struct util_list *list)
+{
+	return list->start == NULL;
+}
