~ubuntu-branches/ubuntu/trusty/gcr/trusty-proposed

« back to all changes in this revision

Viewing changes to egg/egg-buffer.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach
  • Date: 2012-05-03 10:18:39 UTC
  • Revision ID: package-import@ubuntu.com-20120503101839-wuvloldm7gmdsnij
Tags: upstream-3.4.1
ImportĀ upstreamĀ versionĀ 3.4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 
2
/* egg-buffer.c - Generic data buffer, used by openssh, gnome-keyring
 
3
 
 
4
   Copyright (C) 2007 Stefan Walter
 
5
 
 
6
   The Gnome Keyring Library is free software; you can redistribute it and/or
 
7
   modify it under the terms of the GNU Library General Public License as
 
8
   published by the Free Software Foundation; either version 2 of the
 
9
   License, or (at your option) any later version.
 
10
 
 
11
   The Gnome Keyring Library is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
   Library General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU Library General Public
 
17
   License along with the Gnome Library; see the file COPYING.LIB.  If not,
 
18
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
19
   Boston, MA 02111-1307, USA.
 
20
 
 
21
   Author: Stef Walter <stef@memberwebs.com>
 
22
*/
 
23
#include "config.h"
 
24
 
 
25
#include <string.h>
 
26
#include <stdarg.h>
 
27
 
 
28
#include "egg-buffer.h"
 
29
 
 
30
#define DEFAULT_ALLOCATOR  ((EggBufferAllocator)realloc)
 
31
 
 
32
int
 
33
egg_buffer_init (EggBuffer *buffer, size_t reserve)
 
34
{
 
35
        return egg_buffer_init_full (buffer, reserve, NULL);
 
36
}
 
37
 
 
38
int
 
39
egg_buffer_init_full (EggBuffer *buffer, size_t reserve, EggBufferAllocator allocator)
 
40
{
 
41
        memset (buffer, 0, sizeof (*buffer));
 
42
 
 
43
        if (!allocator)
 
44
                allocator = DEFAULT_ALLOCATOR;
 
45
        if (reserve == 0)
 
46
                reserve = 64;
 
47
 
 
48
        buffer->buf = (allocator) (NULL, reserve);
 
49
        if (!buffer->buf) {
 
50
                buffer->failures++;
 
51
                return 0;
 
52
        }
 
53
 
 
54
        buffer->len = 0;
 
55
        buffer->allocated_len = reserve;
 
56
        buffer->failures = 0;
 
57
        buffer->allocator = allocator;
 
58
 
 
59
        return 1;
 
60
}
 
61
 
 
62
void
 
63
egg_buffer_init_static (EggBuffer* buffer, const unsigned char *buf, size_t len)
 
64
{
 
65
        memset (buffer, 0, sizeof (*buffer));
 
66
 
 
67
        buffer->buf = (unsigned char*)buf;
 
68
        buffer->len = len;
 
69
        buffer->allocated_len = len;
 
70
        buffer->failures = 0;
 
71
 
 
72
        /* A null allocator, and the buffer can't change in size */
 
73
        buffer->allocator = NULL;
 
74
}
 
75
 
 
76
void
 
77
egg_buffer_init_allocated (EggBuffer *buffer, unsigned char *buf, size_t len,
 
78
                           EggBufferAllocator allocator)
 
79
{
 
80
        memset (buffer, 0, sizeof (*buffer));
 
81
 
 
82
        if (!allocator)
 
83
                allocator = DEFAULT_ALLOCATOR;
 
84
 
 
85
        buffer->buf = buf;
 
86
        buffer->len = len;
 
87
        buffer->allocated_len = len;
 
88
        buffer->failures = 0;
 
89
        buffer->allocator = allocator;
 
90
}
 
91
 
 
92
void
 
93
egg_buffer_reset (EggBuffer *buffer)
 
94
{
 
95
        memset (buffer->buf, 0, buffer->allocated_len);
 
96
        buffer->len = 0;
 
97
        buffer->failures = 0;
 
98
}
 
99
 
 
100
void
 
101
egg_buffer_uninit (EggBuffer *buffer)
 
102
{
 
103
        if (!buffer)
 
104
                return;
 
105
 
 
106
        /*
 
107
         * Free the memory block using allocator. If no allocator,
 
108
         * then this memory is ownerd elsewhere and not to be freed.
 
109
         */
 
110
        if (buffer->buf && buffer->allocator)
 
111
                (buffer->allocator) (buffer->buf, 0);
 
112
 
 
113
        memset (buffer, 0, sizeof (*buffer));
 
114
}
 
115
 
 
116
unsigned char*
 
117
egg_buffer_uninit_steal (EggBuffer *buffer, size_t *n_result)
 
118
{
 
119
        unsigned char *result;
 
120
 
 
121
        if (n_result)
 
122
                *n_result = buffer->len;
 
123
        result = buffer->buf;
 
124
 
 
125
        memset (buffer, 0, sizeof (*buffer));
 
126
 
 
127
        return result;
 
128
}
 
129
 
 
130
int
 
131
egg_buffer_set_allocator (EggBuffer *buffer, EggBufferAllocator allocator)
 
132
{
 
133
        unsigned char *buf = NULL;
 
134
 
 
135
        if (!allocator)
 
136
                allocator = DEFAULT_ALLOCATOR;
 
137
        if (buffer->allocator == allocator)
 
138
                return 1;
 
139
 
 
140
        if (buffer->allocated_len) {
 
141
                /* Reallocate memory block using new allocator */
 
142
                buf = (allocator) (NULL, buffer->allocated_len);
 
143
                if (buf == NULL)
 
144
                        return 0;
 
145
 
 
146
                /* Copy stuff into new memory */
 
147
                memcpy (buf, buffer->buf, buffer->allocated_len);
 
148
        }
 
149
 
 
150
        /* If old wasn't static, then free it */
 
151
        if (buffer->allocator && buffer->buf)
 
152
                (buffer->allocator) (buffer->buf, 0);
 
153
 
 
154
        buffer->buf = buf;
 
155
        buffer->allocator = allocator;
 
156
 
 
157
        return 1;
 
158
}
 
159
 
 
160
int
 
161
egg_buffer_equal (EggBuffer *b1, EggBuffer *b2)
 
162
{
 
163
        if (b1->len != b2->len)
 
164
                return 0;
 
165
        return memcmp (b1->buf, b2->buf, b1->len) == 0;
 
166
}
 
167
 
 
168
int
 
169
egg_buffer_reserve (EggBuffer *buffer, size_t len)
 
170
{
 
171
        unsigned char *newbuf;
 
172
        size_t newlen;
 
173
 
 
174
        if (len < buffer->allocated_len)
 
175
                return 1;
 
176
 
 
177
        /* Calculate a new length, minimize number of buffer allocations */
 
178
        newlen = buffer->allocated_len * 2;
 
179
        if (len > newlen)
 
180
                newlen += len;
 
181
 
 
182
        /* Memory owned elsewhere can't be reallocated */
 
183
        if (!buffer->allocator) {
 
184
                buffer->failures++;
 
185
                return 0;
 
186
        }
 
187
 
 
188
        /* Reallocate built in buffer using allocator */
 
189
        newbuf = (buffer->allocator) (buffer->buf, newlen);
 
190
        if (!newbuf) {
 
191
                buffer->failures++;
 
192
                return 0;
 
193
        }
 
194
 
 
195
        buffer->buf = newbuf;
 
196
        buffer->allocated_len = newlen;
 
197
 
 
198
        return 1;
 
199
}
 
200
 
 
201
int
 
202
egg_buffer_resize (EggBuffer *buffer, size_t len)
 
203
{
 
204
        if (!egg_buffer_reserve (buffer, len))
 
205
                return 0;
 
206
 
 
207
        buffer->len = len;
 
208
        return 1;
 
209
}
 
210
 
 
211
unsigned char*
 
212
egg_buffer_add_empty (EggBuffer *buffer, size_t len)
 
213
{
 
214
        size_t pos = buffer->len;
 
215
        if (!egg_buffer_reserve (buffer, buffer->len + len))
 
216
                return NULL;
 
217
        buffer->len += len;
 
218
        return buffer->buf + pos;
 
219
}
 
220
 
 
221
int
 
222
egg_buffer_append (EggBuffer *buffer, const unsigned char *val,
 
223
                             size_t len)
 
224
{
 
225
        if (!egg_buffer_reserve (buffer, buffer->len + len))
 
226
                return 0; /* failures already incremented */
 
227
        memcpy (buffer->buf + buffer->len, val, len);
 
228
        buffer->len += len;
 
229
        return 1;
 
230
}
 
231
 
 
232
int
 
233
egg_buffer_add_byte (EggBuffer *buffer, unsigned char val)
 
234
{
 
235
        if (!egg_buffer_reserve (buffer, buffer->len + 1))
 
236
                return 0; /* failures already incremented */
 
237
        buffer->buf[buffer->len] = val;
 
238
        buffer->len++;
 
239
        return 1;
 
240
}
 
241
 
 
242
int
 
243
egg_buffer_get_byte (EggBuffer *buffer, size_t offset,
 
244
                               size_t *next_offset, unsigned char *val)
 
245
{
 
246
        unsigned char *ptr;
 
247
        if (buffer->len < 1 || offset > buffer->len - 1) {
 
248
                buffer->failures++;
 
249
                return 0;
 
250
        }
 
251
        ptr = (unsigned char*)buffer->buf + offset;
 
252
        if (val != NULL)
 
253
                *val = *ptr;
 
254
        if (next_offset != NULL)
 
255
                *next_offset = offset + 1;
 
256
        return 1;
 
257
}
 
258
 
 
259
void
 
260
egg_buffer_encode_uint16 (unsigned char* buf, uint16_t val)
 
261
{
 
262
        buf[0] = (val >> 8) & 0xff;
 
263
        buf[1] = (val >> 0) & 0xff;
 
264
}
 
265
 
 
266
uint16_t
 
267
egg_buffer_decode_uint16 (unsigned char* buf)
 
268
{
 
269
        uint16_t val = buf[0] << 8 | buf[1];
 
270
        return val;
 
271
}
 
272
 
 
273
int
 
274
egg_buffer_add_uint16 (EggBuffer *buffer, uint16_t val)
 
275
{
 
276
        if (!egg_buffer_reserve (buffer, buffer->len + 2))
 
277
                return 0; /* failures already incremented */
 
278
        buffer->len += 2;
 
279
        egg_buffer_set_uint16 (buffer, buffer->len - 2, val);
 
280
        return 1;
 
281
}
 
282
 
 
283
int
 
284
egg_buffer_set_uint16 (EggBuffer *buffer, size_t offset, uint16_t val)
 
285
{
 
286
        unsigned char *ptr;
 
287
        if (buffer->len < 2 || offset > buffer->len - 2) {
 
288
                buffer->failures++;
 
289
                return 0;
 
290
        }
 
291
        ptr = (unsigned char*)buffer->buf + offset;
 
292
        egg_buffer_encode_uint16 (ptr, val);
 
293
        return 1;
 
294
}
 
295
 
 
296
int
 
297
egg_buffer_get_uint16 (EggBuffer *buffer, size_t offset,
 
298
                       size_t *next_offset, uint16_t *val)
 
299
{
 
300
        unsigned char *ptr;
 
301
        if (buffer->len < 2 || offset > buffer->len - 2) {
 
302
                buffer->failures++;
 
303
                return 0;
 
304
        }
 
305
        ptr = (unsigned char*)buffer->buf + offset;
 
306
        if (val != NULL)
 
307
                *val = egg_buffer_decode_uint16 (ptr);
 
308
        if (next_offset != NULL)
 
309
                *next_offset = offset + 2;
 
310
        return 1;
 
311
}
 
312
 
 
313
void
 
314
egg_buffer_encode_uint32 (unsigned char* buf, uint32_t val)
 
315
{
 
316
        buf[0] = (val >> 24) & 0xff;
 
317
        buf[1] = (val >> 16) & 0xff;
 
318
        buf[2] = (val >> 8) & 0xff;
 
319
        buf[3] = (val >> 0) & 0xff;
 
320
}
 
321
 
 
322
uint32_t
 
323
egg_buffer_decode_uint32 (unsigned char* ptr)
 
324
{
 
325
        uint32_t val = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
 
326
        return val;
 
327
}
 
328
 
 
329
int
 
330
egg_buffer_add_uint32 (EggBuffer *buffer, uint32_t val)
 
331
{
 
332
        if (!egg_buffer_reserve (buffer, buffer->len + 4))
 
333
                return 0; /* failures already incremented */
 
334
        buffer->len += 4;
 
335
        egg_buffer_set_uint32 (buffer, buffer->len - 4, val);
 
336
        return 1;
 
337
}
 
338
 
 
339
int
 
340
egg_buffer_set_uint32 (EggBuffer *buffer, size_t offset, uint32_t val)
 
341
{
 
342
        unsigned char *ptr;
 
343
        if (buffer->len < 4 || offset > buffer->len - 4) {
 
344
                buffer->failures++;
 
345
                return 0;
 
346
        }
 
347
        ptr = (unsigned char*)buffer->buf + offset;
 
348
        egg_buffer_encode_uint32 (ptr, val);
 
349
        return 1;
 
350
}
 
351
 
 
352
int
 
353
egg_buffer_get_uint32 (EggBuffer *buffer, size_t offset, size_t *next_offset,
 
354
                                 uint32_t *val)
 
355
{
 
356
        unsigned char *ptr;
 
357
        if (buffer->len < 4 || offset > buffer->len - 4) {
 
358
                buffer->failures++;
 
359
                return 0;
 
360
        }
 
361
        ptr = (unsigned char*)buffer->buf + offset;
 
362
        if (val != NULL)
 
363
                *val = egg_buffer_decode_uint32 (ptr);
 
364
        if (next_offset != NULL)
 
365
                *next_offset = offset + 4;
 
366
        return 1;
 
367
}
 
368
 
 
369
int
 
370
egg_buffer_add_uint64 (EggBuffer *buffer, uint64_t val)
 
371
{
 
372
        if (!egg_buffer_add_uint32 (buffer, ((val >> 32) & 0xffffffff)))
 
373
                return 0;
 
374
        return egg_buffer_add_uint32 (buffer, (val & 0xffffffff));
 
375
}
 
376
 
 
377
int
 
378
egg_buffer_get_uint64 (EggBuffer *buffer, size_t offset,
 
379
                                           size_t *next_offset, uint64_t *val)
 
380
{
 
381
        uint32_t a, b;
 
382
        if (!egg_buffer_get_uint32 (buffer, offset, &offset, &a))
 
383
                return 0;
 
384
        if (!egg_buffer_get_uint32 (buffer, offset, &offset, &b))
 
385
                return 0;
 
386
        if (val != NULL)
 
387
                *val = ((uint64_t)a) << 32 | b;
 
388
        if (next_offset != NULL)
 
389
                *next_offset = offset;
 
390
        return 1;
 
391
}
 
392
 
 
393
int
 
394
egg_buffer_add_byte_array (EggBuffer *buffer, const unsigned char *val,
 
395
                                     size_t len)
 
396
{
 
397
        if (val == NULL)
 
398
                return egg_buffer_add_uint32 (buffer, 0xffffffff);
 
399
        if (len >= 0x7fffffff) {
 
400
                buffer->failures++;
 
401
                return 0;
 
402
        }
 
403
        if (!egg_buffer_add_uint32 (buffer, len))
 
404
                return 0;
 
405
        return egg_buffer_append (buffer, val, len);
 
406
}
 
407
 
 
408
unsigned char*
 
409
egg_buffer_add_byte_array_empty (EggBuffer *buffer, size_t vlen)
 
410
{
 
411
        if (vlen >= 0x7fffffff) {
 
412
                buffer->failures++;
 
413
                return NULL;
 
414
        }
 
415
        if (!egg_buffer_add_uint32 (buffer, vlen))
 
416
                return NULL;
 
417
        return egg_buffer_add_empty (buffer, vlen);
 
418
}
 
419
 
 
420
int
 
421
egg_buffer_get_byte_array (EggBuffer *buffer, size_t offset,
 
422
                           size_t *next_offset, const unsigned char **val,
 
423
                           size_t *vlen)
 
424
{
 
425
        uint32_t len;
 
426
        if (!egg_buffer_get_uint32 (buffer, offset, &offset, &len))
 
427
                return 0;
 
428
        if (len == 0xffffffff) {
 
429
                if (next_offset)
 
430
                        *next_offset = offset;
 
431
                if (val)
 
432
                        *val = NULL;
 
433
                if (vlen)
 
434
                        *vlen = 0;
 
435
                return 1;
 
436
        } else if (len >= 0x7fffffff) {
 
437
                buffer->failures++;
 
438
                return 0;
 
439
        }
 
440
 
 
441
        if (buffer->len < len || offset > buffer->len - len) {
 
442
                buffer->failures++;
 
443
                return 0;
 
444
        }
 
445
 
 
446
        if (val)
 
447
                *val = buffer->buf + offset;
 
448
        if (vlen)
 
449
                *vlen = len;
 
450
        if (next_offset)
 
451
                *next_offset = offset + len;
 
452
 
 
453
        return 1;
 
454
}
 
455
 
 
456
int
 
457
egg_buffer_add_string (EggBuffer *buffer, const char *str)
 
458
{
 
459
        if (str == NULL) {
 
460
                return egg_buffer_add_uint32 (buffer, 0xffffffff);
 
461
        } else {
 
462
                size_t len = strlen (str);
 
463
                if (len >= 0x7fffffff)
 
464
                        return 0;
 
465
                if (!egg_buffer_add_uint32 (buffer, len))
 
466
                        return 0;
 
467
                return egg_buffer_append (buffer, (unsigned char*)str, len);
 
468
        }
 
469
}
 
470
 
 
471
int
 
472
egg_buffer_get_string (EggBuffer *buffer, size_t offset, size_t *next_offset,
 
473
                       char **str_ret, EggBufferAllocator allocator)
 
474
{
 
475
        uint32_t len;
 
476
 
 
477
        if (!allocator)
 
478
                allocator = buffer->allocator;
 
479
        if (!allocator)
 
480
                allocator = DEFAULT_ALLOCATOR;
 
481
 
 
482
        if (!egg_buffer_get_uint32 (buffer, offset, &offset, &len)) {
 
483
                return 0;
 
484
        }
 
485
        if (len == 0xffffffff) {
 
486
                *next_offset = offset;
 
487
                *str_ret = NULL;
 
488
                return 1;
 
489
        } else if (len >= 0x7fffffff) {
 
490
                return 0;
 
491
        }
 
492
 
 
493
        if (buffer->len < len ||
 
494
            offset > buffer->len - len) {
 
495
                return 0;
 
496
        }
 
497
 
 
498
        /* Make sure no null characters in string */
 
499
        if (memchr (buffer->buf + offset, 0, len) != NULL)
 
500
                return 0;
 
501
 
 
502
        /* The passed allocator may be for non-pageable memory */
 
503
        *str_ret = (allocator) (NULL, len + 1);
 
504
        if (!*str_ret)
 
505
                return 0;
 
506
        memcpy (*str_ret, buffer->buf + offset, len);
 
507
 
 
508
        /* Always zero terminate */
 
509
        (*str_ret)[len] = 0;
 
510
        *next_offset = offset + len;
 
511
 
 
512
        return 1;
 
513
}
 
514
 
 
515
int
 
516
egg_buffer_add_stringv (EggBuffer *buffer, const char** strv)
 
517
{
 
518
        const char **v;
 
519
        uint32_t n = 0;
 
520
 
 
521
        if (!strv)
 
522
                return 0;
 
523
 
 
524
        /* Add the number of strings coming */
 
525
        for (v = strv; *v; ++v)
 
526
                ++n;
 
527
        if (!egg_buffer_add_uint32 (buffer, n))
 
528
                return 0;
 
529
 
 
530
        /* Add the individual strings */
 
531
        for (v = strv; *v; ++v) {
 
532
                if (!egg_buffer_add_string (buffer, *v))
 
533
                        return 0;
 
534
        }
 
535
 
 
536
        return 1;
 
537
}
 
538
 
 
539
int
 
540
egg_buffer_get_stringv (EggBuffer *buffer, size_t offset, size_t *next_offset,
 
541
                                char ***strv_ret, EggBufferAllocator allocator)
 
542
{
 
543
        uint32_t n, i, j;
 
544
        size_t len;
 
545
 
 
546
        if (!allocator)
 
547
                allocator = buffer->allocator;
 
548
        if (!allocator)
 
549
                allocator = DEFAULT_ALLOCATOR;
 
550
 
 
551
        /* First the number of environment variable lines */
 
552
        if (!egg_buffer_get_uint32 (buffer, offset, &offset, &n))
 
553
                return 0;
 
554
 
 
555
        /* Then that number of strings */
 
556
        len = (n + 1) * sizeof (char*);
 
557
        *strv_ret = (char**)(allocator) (NULL, len);
 
558
        if (!*strv_ret)
 
559
                return 0;
 
560
 
 
561
        /* All null strings */
 
562
        memset (*strv_ret, 0, len);
 
563
 
 
564
        for (i = 0; i < n; ++i) {
 
565
                if (!egg_buffer_get_string (buffer, offset, &offset,
 
566
                                            &((*strv_ret)[i]), allocator)) {
 
567
 
 
568
                        /* Free all the strings on failure */
 
569
                        for (j = 0; j < i; ++j) {
 
570
                                if ((*strv_ret)[j])
 
571
                                        (allocator) ((*strv_ret)[j], 0);
 
572
                        }
 
573
 
 
574
                        return 0;
 
575
                }
 
576
        }
 
577
 
 
578
        if (next_offset != NULL)
 
579
                *next_offset = offset;
 
580
 
 
581
        return 1;
 
582
}