1 /*
2  * lib/data.c		Abstract Data
3  *
4  *	This library is free software; you can redistribute it and/or
5  *	modify it under the terms of the GNU Lesser General Public
6  *	License as published by the Free Software Foundation version 2.1
7  *	of the License.
8  *
9  * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 /**
13  * @ingroup core
14  * @defgroup data Abstract Data
15  * @{
16  */
17 
18 #include <netlink-local.h>
19 #include <netlink/netlink.h>
20 #include <netlink/utils.h>
21 #include <linux/socket.h>
22 
23 /**
24  * @name General
25  * @{
26  */
27 
28 /**
29  * Allocate a new abstract data object.
30  * @arg buf		Data buffer containing the actual data.
31  * @arg size		Size of data buffer.
32  *
33  * Allocates a new abstract data and copies the specified data
34  * buffer into the new handle.
35  *
36  * @return Newly allocated data handle or NULL
37  */
nl_data_alloc(void * buf,size_t size)38 struct nl_data *nl_data_alloc(void *buf, size_t size)
39 {
40 	struct nl_data *data;
41 
42 	data = calloc(1, sizeof(*data));
43 	if (!data)
44 		goto errout;
45 
46 	data->d_data = calloc(1, size);
47 	if (!data->d_data) {
48 		free(data);
49 		goto errout;
50 	}
51 
52 	data->d_size = size;
53 
54 	if (buf)
55 		memcpy(data->d_data, buf, size);
56 
57 	return data;
58 errout:
59 	return NULL;
60 }
61 
62 /**
63  * Allocate abstract data object based on netlink attribute.
64  * @arg nla		Netlink attribute of unspecific type.
65  *
66  * Allocates a new abstract data and copies the payload of the
67  * attribute to the abstract data object.
68  *
69  * @see nla_data_alloc
70  * @return Newly allocated data handle or NULL
71  */
nl_data_alloc_attr(struct nlattr * nla)72 struct nl_data *nl_data_alloc_attr(struct nlattr *nla)
73 {
74 	return nl_data_alloc(nla_data(nla), nla_len(nla));
75 }
76 
77 /**
78  * Clone an abstract data object.
79  * @arg src		Abstract data object
80  *
81  * @return Cloned object or NULL
82  */
nl_data_clone(struct nl_data * src)83 struct nl_data *nl_data_clone(struct nl_data *src)
84 {
85 	return nl_data_alloc(src->d_data, src->d_size);
86 }
87 
88 /**
89  * Append data to an abstract data object.
90  * @arg data		Abstract data object.
91  * @arg buf		Data buffer containing the data to be appended.
92  * @arg size		Size of data to be apppended.
93  *
94  * Reallocates an abstract data and copies the specified data
95  * buffer into the new handle.
96  *
97  * @return 0 on success or a negative error code
98  */
nl_data_append(struct nl_data * data,void * buf,size_t size)99 int nl_data_append(struct nl_data *data, void *buf, size_t size)
100 {
101 	if (size < 0)
102 		BUG();
103 
104 	if (size > 0) {
105 		data->d_data = realloc(data->d_data, data->d_size + size);
106 		if (!data->d_data)
107 			return -NLE_NOMEM;
108 
109 		if (buf)
110 			memcpy(data->d_data + data->d_size, buf, size);
111 		else
112 			memset(data->d_data + data->d_size, 0, size);
113 
114 		data->d_size += size;
115 	}
116 
117 	return 0;
118 }
119 
120 /**
121  * Free an abstract data object.
122  * @arg data		Abstract data object.
123  */
nl_data_free(struct nl_data * data)124 void nl_data_free(struct nl_data *data)
125 {
126 	if (data)
127 		free(data->d_data);
128 
129 	free(data);
130 }
131 
132 /** @} */
133 
134 /**
135  * @name Attribute Access
136  * @{
137  */
138 
139 /**
140  * Get data buffer of abstract data object.
141  * @arg data		Abstract data object.
142  * @return Data buffer or NULL if empty.
143  */
nl_data_get(struct nl_data * data)144 void *nl_data_get(struct nl_data *data)
145 {
146 	return data->d_size > 0 ? data->d_data : NULL;
147 }
148 
149 /**
150  * Get size of data buffer of abstract data object.
151  * @arg data		Abstract data object.
152  * @return Size of data buffer.
153  */
nl_data_get_size(struct nl_data * data)154 size_t nl_data_get_size(struct nl_data *data)
155 {
156 	return data->d_size;
157 }
158 
159 /** @} */
160 
161 /**
162  * @name Misc
163  * @{
164  */
165 
166 /**
167  * Compare two abstract data objects.
168  * @arg a		Abstract data object.
169  * @arg b		Another abstract data object.
170  * @return An integer less than, equal to, or greater than zero if
171  *         a is found, respectively, to be less than, to match, or
172  *         be greater than b.
173  */
nl_data_cmp(struct nl_data * a,struct nl_data * b)174 int nl_data_cmp(struct nl_data *a, struct nl_data *b)
175 {
176 	void *a_ = nl_data_get(a);
177 	void *b_ = nl_data_get(b);
178 
179 	if (a_ && b_)
180 		return memcmp(a_, b_, nl_data_get_size(a));
181 	else
182 		return -1;
183 }
184 
185 /** @} */
186 /** @} */
187