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 (at) 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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