-
Notifications
You must be signed in to change notification settings - Fork 4
/
buffer.c
92 lines (82 loc) · 2.36 KB
/
buffer.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
* Authors:
* Alexander Aring <alex.aring@gmail.com>
*
* Original Authors:
* Lars Fenneberg <lf@elemental.net>
*
* This software is Copyright 1996,1997,2019 by the above mentioned author(s),
* All Rights Reserved.
*
* The license which is distributed with this software in the file COPYRIGHT
* applies to this software. If your distribution is missing this file, you
* may request it from <alex.aring@gmail.com>.
*/
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include "buffer.h"
#include "log.h"
#define SAFE_BUFFER_INIT \
(struct safe_buffer) { .should_free = 0, .allocated = 0, .used = 0, .buffer = 0 }
struct safe_buffer *safe_buffer_new(void)
{
struct safe_buffer *sb = malloc(sizeof(struct safe_buffer));
*sb = SAFE_BUFFER_INIT;
sb->should_free = 1;
return sb;
}
void safe_buffer_free(struct safe_buffer *sb)
{
if (sb->buffer) {
free(sb->buffer);
}
if (sb->should_free) {
free(sb);
}
}
/**
* Requests that the safe_buffer capacity be least n bytes in size.
*
* If n is greater than the current capacity, the function causes the container
* to reallocate its storage increasing its capacity to n (or greater).
*
* In all other cases, the function call does not cause a reallocation and the
* capacity is not affected.
*
* @param sb safe_buffer to enlarge
* @param b Minimum capacity for the safe_buffer.
*/
static void safe_buffer_resize(struct safe_buffer *sb, size_t n)
{
const int blocksize = 1 << 6; // MUST BE POWER OF 2.
if (sb->allocated < n) {
if (n % blocksize > 0) {
n |= (blocksize - 1); // Set all the low bits
n++;
}
if (n > 64 * 1024) {
flog(LOG_ERR, "Requested buffer too large for any possible IPv6 ND, even with jumbogram. Exiting.");
exit(1);
}
sb->allocated = n;
sb->buffer = realloc(sb->buffer, sb->allocated);
}
}
size_t safe_buffer_pad(struct safe_buffer *sb, size_t count)
{
safe_buffer_resize(sb, sb->used + count);
memset(&sb->buffer[sb->used], 0, count);
sb->used += count;
return count;
}
size_t safe_buffer_append(struct safe_buffer *sb, const void *v, size_t count)
{
if (sb) {
unsigned const char *m = (unsigned const char *)v;
safe_buffer_resize(sb, sb->used + count);
memcpy(&sb->buffer[sb->used], m, count);
sb->used += count;
}
return count;
}