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