1 /*
2 * Copyright (c) 2002-2010 Balabit
3 * Copyright (c) 1998-2010 Balázs Scheidler
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * As an additional exemption you are allowed to compile & link against the
20 * OpenSSL libraries as published by the OpenSSL project. See the file
21 * COPYING for details.
22 *
23 */
24
25 #ifndef SERIALIZE_H_INCLUDED
26 #define SERIALIZE_H_INCLUDED
27
28 #include "syslog-ng.h"
29
30 #include <stdio.h>
31 #include <string.h>
32
33 typedef struct _SerializeArchive SerializeArchive;
34
35 struct _SerializeArchive
36 {
37 GError *error;
38 guint16 len;
39 guint16 silent:1;
40
41 gboolean (*read_bytes)(SerializeArchive *archive, gchar *buf, gsize count, GError **error);
42 gboolean (*write_bytes)(SerializeArchive *archive, const gchar *buf, gsize count, GError **error);
43 };
44
45 /* this is private and is only published so that the inline functions below can invoke it */
46 void _serialize_handle_errors(SerializeArchive *self, const gchar *error_desc, GError *error);
47
48 static inline gboolean
serialize_archive_read_bytes(SerializeArchive * self,gchar * buf,gsize buflen)49 serialize_archive_read_bytes(SerializeArchive *self, gchar *buf, gsize buflen)
50 {
51 GError *error = NULL;
52
53 if ((self->error == NULL) && !self->read_bytes(self, buf, buflen, &error))
54 _serialize_handle_errors(self, "Error reading serialized data", error);
55 return self->error == NULL;
56 }
57
58 static inline gboolean
serialize_archive_write_bytes(SerializeArchive * self,const gchar * buf,gsize buflen)59 serialize_archive_write_bytes(SerializeArchive *self, const gchar *buf, gsize buflen)
60 {
61 GError *error = NULL;
62
63 if ((self->error == NULL) && !self->write_bytes(self, buf, buflen, &error))
64 _serialize_handle_errors(self, "Error writing serialized data", error);
65 return self->error == NULL;
66 }
67
68 static inline gboolean
serialize_write_uint32(SerializeArchive * archive,guint32 value)69 serialize_write_uint32(SerializeArchive *archive, guint32 value)
70 {
71 guint32 n;
72
73 n = GUINT32_TO_BE(value);
74 return serialize_archive_write_bytes(archive, (gchar *) &n, sizeof(n));
75 }
76
77 static inline gboolean
serialize_read_uint32(SerializeArchive * archive,guint32 * value)78 serialize_read_uint32(SerializeArchive *archive, guint32 *value)
79 {
80 guint32 n;
81
82 if (serialize_archive_read_bytes(archive, (gchar *) &n, sizeof(n)))
83 {
84 *value = GUINT32_FROM_BE(n);
85 return TRUE;
86 }
87 return FALSE;
88 }
89
90 /* NOTE: this function writes to the array to convert it to big endian. It
91 * is converted back to native byte order before returning */
92 static inline gboolean
serialize_write_uint32_array(SerializeArchive * archive,guint32 * values,gsize elements)93 serialize_write_uint32_array(SerializeArchive *archive, guint32 *values, gsize elements)
94 {
95 const int buffer_size = 128;
96 guint32 converted_values[buffer_size];
97 gint converted_ndx;
98
99 while (elements > 0)
100 {
101 for (converted_ndx = 0;
102 converted_ndx < buffer_size && converted_ndx < elements;
103 converted_ndx++)
104 converted_values[converted_ndx] = GUINT32_TO_BE(values[converted_ndx]);
105
106 if (!serialize_archive_write_bytes(archive, (void *) converted_values, converted_ndx * sizeof(guint32)))
107 return FALSE;
108
109 values += converted_ndx;
110 elements -= converted_ndx;
111 }
112 return TRUE;
113 }
114
115 static inline gboolean
serialize_read_uint32_array(SerializeArchive * archive,guint32 * values,gsize elements)116 serialize_read_uint32_array(SerializeArchive *archive, guint32 *values, gsize elements)
117 {
118 if (serialize_archive_read_bytes(archive, (void *) values, elements * sizeof(guint32)))
119 {
120 for (int i = 0; i < elements; i++)
121 values[i] = GUINT32_FROM_BE(values[i]);
122 return TRUE;
123 }
124 return FALSE;
125 }
126
127 static inline gboolean
serialize_read_uint16_array(SerializeArchive * archive,guint32 * values,gsize elements)128 serialize_read_uint16_array(SerializeArchive *archive, guint32 *values, gsize elements)
129 {
130 guint16 buffer[elements];
131
132 if (serialize_archive_read_bytes(archive, (void *) &buffer, elements * sizeof(guint16)))
133 {
134 for (int i = 0; i < elements; i++)
135 values[i] = GUINT16_FROM_BE(buffer[i]);
136 return TRUE;
137 }
138 return FALSE;
139 }
140
141 static inline gboolean
serialize_write_uint64(SerializeArchive * archive,guint64 value)142 serialize_write_uint64(SerializeArchive *archive, guint64 value)
143 {
144 guint64 n;
145
146 n = GUINT64_TO_BE(value);
147 return serialize_archive_write_bytes(archive, (gchar *) &n, sizeof(n));
148 }
149
150 static inline gboolean
serialize_read_uint64(SerializeArchive * archive,guint64 * value)151 serialize_read_uint64(SerializeArchive *archive, guint64 *value)
152 {
153 guint64 n;
154
155 if (serialize_archive_read_bytes(archive, (gchar *) &n, sizeof(n)))
156 {
157 *value = GUINT64_FROM_BE(n);
158 return TRUE;
159 }
160 return FALSE;
161 }
162
163 static inline gboolean
serialize_write_uint16(SerializeArchive * archive,guint16 value)164 serialize_write_uint16(SerializeArchive *archive, guint16 value)
165 {
166 guint16 n;
167
168 n = GUINT16_TO_BE(value);
169 return serialize_archive_write_bytes(archive, (gchar *) &n, sizeof(n));
170 }
171
172 static inline gboolean
serialize_read_uint16(SerializeArchive * archive,guint16 * value)173 serialize_read_uint16(SerializeArchive *archive, guint16 *value)
174 {
175 guint16 n;
176
177 if (serialize_archive_read_bytes(archive, (gchar *) &n, sizeof(n)))
178 {
179 *value = GUINT16_FROM_BE(n);
180 return TRUE;
181 }
182 return FALSE;
183 }
184
185 static inline gboolean
serialize_write_uint8(SerializeArchive * archive,guint8 value)186 serialize_write_uint8(SerializeArchive *archive, guint8 value)
187 {
188 guint8 n;
189
190 n = value;
191 return serialize_archive_write_bytes(archive, (gchar *) &n, sizeof(n));
192 }
193
194 static inline gboolean
serialize_read_uint8(SerializeArchive * archive,guint8 * value)195 serialize_read_uint8(SerializeArchive *archive, guint8 *value)
196 {
197 guint8 n;
198
199 if (serialize_archive_read_bytes(archive, (gchar *) &n, sizeof(n)))
200 {
201 *value = n;
202 return TRUE;
203 }
204 return FALSE;
205 }
206
207
208 static inline gboolean
serialize_write_blob(SerializeArchive * archive,const void * blob,gsize len)209 serialize_write_blob(SerializeArchive *archive, const void *blob, gsize len)
210 {
211 return serialize_archive_write_bytes(archive, blob, len);
212 }
213
214 static inline gboolean
serialize_read_blob(SerializeArchive * archive,void * blob,gsize len)215 serialize_read_blob(SerializeArchive *archive, void *blob, gsize len)
216 {
217 return serialize_archive_read_bytes(archive, blob, len);
218 }
219
220 static inline gboolean
serialize_write_string(SerializeArchive * archive,GString * str)221 serialize_write_string(SerializeArchive *archive, GString *str)
222 {
223 return serialize_write_uint32(archive, str->len) &&
224 serialize_archive_write_bytes(archive, str->str, str->len);
225 }
226
227 static inline gboolean
serialize_read_string(SerializeArchive * archive,GString * str)228 serialize_read_string(SerializeArchive *archive, GString *str)
229 {
230 guint32 len;
231
232 if (serialize_read_uint32(archive, &len))
233 {
234 if (len > str->allocated_len)
235 {
236 gchar *p;
237
238 p = g_try_realloc(str->str, len + 1);
239 if (!p)
240 return FALSE;
241 str->str = p;
242 str->str[len] = 0;
243 str->len = len;
244 }
245 else
246 g_string_set_size(str, len);
247
248 return serialize_archive_read_bytes(archive, str->str, len);
249 }
250 return FALSE;
251 }
252
253 static inline gboolean
serialize_write_cstring(SerializeArchive * archive,const gchar * str,gssize len)254 serialize_write_cstring(SerializeArchive *archive, const gchar *str, gssize len)
255 {
256 if (len < 0)
257 len = strlen(str);
258
259 return serialize_write_uint32(archive, len) &&
260 (len == 0 || serialize_archive_write_bytes(archive, str, len));
261 }
262
263 static inline gboolean
serialize_read_cstring(SerializeArchive * archive,gchar ** str,gsize * str_len)264 serialize_read_cstring(SerializeArchive *archive, gchar **str, gsize *str_len)
265 {
266 guint32 len;
267
268 if (serialize_read_uint32(archive, &len))
269 {
270 *str = g_try_malloc(len + 1);
271
272 if (!(*str))
273 return FALSE;
274 (*str)[len] = 0;
275 if (str_len)
276 *str_len = len;
277 return serialize_archive_read_bytes(archive, *str, len);
278 }
279 return FALSE;
280 }
281
282
283 SerializeArchive *serialize_file_archive_new(FILE *f);
284 SerializeArchive *serialize_string_archive_new(GString *str);
285 void serialize_string_archive_reset(SerializeArchive *sa);
286 SerializeArchive *serialize_buffer_archive_new(gchar *buff, gsize len);
287 gsize serialize_buffer_archive_get_pos(SerializeArchive *self);
288 void serialize_archive_free(SerializeArchive *self);
289
290 #endif
291