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