Fixed a bug in read -> _read cleanup; one missed change
[wpasupplicant] / src / utils / wpabuf.c
1 /*
2  * Dynamic data buffer
3  * Copyright (c) 2007-2008, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "wpabuf.h"
19
20 static void wpabuf_overflow(const struct wpabuf *buf, size_t len)
21 {
22         wpa_printf(MSG_ERROR, "wpabuf %p (size=%lu used=%lu) overflow len=%lu",
23                    buf, (unsigned long) buf->size, (unsigned long) buf->used,
24                    (unsigned long) len);
25         abort();
26 }
27
28
29 int wpabuf_resize(struct wpabuf **_buf, size_t add_len)
30 {
31         struct wpabuf *buf = *_buf;
32         if (buf->used + add_len > buf->size) {
33                 unsigned char *nbuf;
34                 if (buf->ext_data) {
35                         nbuf = os_realloc(buf->ext_data, buf->used + add_len);
36                         if (nbuf == NULL)
37                                 return -1;
38                         os_memset(nbuf + buf->used, 0, add_len);
39                         buf->ext_data = nbuf;
40                 } else {
41                         nbuf = os_realloc(buf, sizeof(struct wpabuf) +
42                                           buf->used + add_len);
43                         if (nbuf == NULL)
44                                 return -1;
45                         buf = (struct wpabuf *) nbuf;
46                         os_memset(nbuf + sizeof(struct wpabuf) + buf->used, 0,
47                                   add_len);
48                         *_buf = buf;
49                 }
50                 buf->size = buf->used + add_len;
51         }
52
53         return 0;
54 }
55
56
57 /**
58  * wpabuf_alloc - Allocate a wpabuf of the given size
59  * @len: Length for the allocated buffer
60  * Returns: Buffer to the allocated wpabuf or %NULL on failure
61  */
62 struct wpabuf * wpabuf_alloc(size_t len)
63 {
64         struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf) + len);
65         if (buf == NULL)
66                 return NULL;
67         buf->size = len;
68         return buf;
69 }
70
71
72 struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len)
73 {
74         struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf));
75         if (buf == NULL)
76                 return NULL;
77
78         buf->size = len;
79         buf->used = len;
80         buf->ext_data = data;
81
82         return buf;
83 }
84
85
86 struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len)
87 {
88         struct wpabuf *buf = wpabuf_alloc(len);
89         if (buf)
90                 wpabuf_put_data(buf, data, len);
91         return buf;
92 }
93
94
95 struct wpabuf * wpabuf_dup(const struct wpabuf *src)
96 {
97         struct wpabuf *buf = wpabuf_alloc(wpabuf_len(src));
98         if (buf)
99                 wpabuf_put_data(buf, wpabuf_head(src), wpabuf_len(src));
100         return buf;
101 }
102
103
104 /**
105  * wpabuf_free - Free a wpabuf
106  * @buf: wpabuf buffer
107  */
108 void wpabuf_free(struct wpabuf *buf)
109 {
110         if (buf == NULL)
111                 return;
112         os_free(buf->ext_data);
113         os_free(buf);
114 }
115
116
117 void * wpabuf_put(struct wpabuf *buf, size_t len)
118 {
119         void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf);
120         buf->used += len;
121         if (buf->used > buf->size) {
122                 wpabuf_overflow(buf, len);
123         }
124         return tmp;
125 }
126
127
128 /**
129  * wpabuf_concat - Concatenate two buffers into a newly allocated one
130  * @a: First buffer
131  * @b: Second buffer
132  * Returns: wpabuf with concatenated a + b data or %NULL on failure
133  *
134  * Both buffers a and b will be freed regardless of the return value. Input
135  * buffers can be %NULL which is interpreted as an empty buffer.
136  */
137 struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b)
138 {
139         struct wpabuf *n = NULL;
140         size_t len = 0;
141
142         if (b == NULL)
143                 return a;
144
145         if (a)
146                 len += wpabuf_len(a);
147         if (b)
148                 len += wpabuf_len(b);
149
150         n = wpabuf_alloc(len);
151         if (n) {
152                 if (a)
153                         wpabuf_put_buf(n, a);
154                 if (b)
155                         wpabuf_put_buf(n, b);
156         }
157
158         wpabuf_free(a);
159         wpabuf_free(b);
160
161         return n;
162 }