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