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