Update Red Hat Copyright Notices
[nbdkit.git] / common / allocators / allocator.c
blob6c2d8099f48ee85ca06ce2ad80318580e9a4bbd0
1 /* nbdkit
2 * Copyright Red Hat
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 #include <config.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdbool.h>
38 #include <string.h>
40 #include <nbdkit-plugin.h>
42 #include "allocator.h"
43 #include "allocator-internal.h"
44 #include "strndup.h"
45 #include "vector.h"
47 /* The list of registered allocators. */
48 DEFINE_VECTOR_TYPE (allocator_list, const struct allocator_functions *);
49 static allocator_list allocators = empty_vector;
51 void
52 register_allocator (const struct allocator_functions *f)
54 if (allocator_list_append (&allocators, f) == -1) {
55 perror ("realloc");
56 exit (EXIT_FAILURE);
60 static void
61 free_key_value (struct key_value kv)
63 free (kv.key);
64 free (kv.value);
67 static void
68 free_allocator_parameters (allocator_parameters *params)
70 allocator_parameters_iter (params, free_key_value);
71 free (params->ptr);
74 /* The type may be followed by parameters "type,key=value[,...]" */
75 static int
76 parse_parameters (const char *type, size_t *type_len,
77 allocator_parameters *params)
79 size_t i, j, len;
81 *type_len = strcspn (type, ",");
83 nbdkit_debug ("allocator: %*s", (int) *type_len, type);
85 /* Split the parameters. */
86 for (i = *type_len; type[i] == ',';) {
87 struct key_value kv;
89 i++;
90 len = strcspn (&type[i], ",");
91 if (len == 0) {
92 i++;
93 continue;
96 j = strcspn (&type[i], "=");
97 if (j == 0) {
98 nbdkit_error ("invalid allocator parameter");
99 free_allocator_parameters (params);
100 return -1;
102 if (j < len) {
103 kv.key = strndup (&type[i], j);
104 kv.value = strndup (&type[i+j+1], len-j-1);
106 else {
107 kv.key = strndup (&type[i], len);
108 kv.value = strdup ("1");
110 if (kv.key == NULL || kv.value == NULL) {
111 nbdkit_error ("strdup: %m");
112 free (kv.key);
113 free (kv.value);
114 free_allocator_parameters (params);
115 return -1;
118 nbdkit_debug ("allocator parameter: %s=%s", kv.key, kv.value);
119 if (allocator_parameters_append (params, kv) == -1) {
120 nbdkit_error ("realloc: %m");
121 free_allocator_parameters (params);
122 return -1;
124 i += len;
127 return 0;
130 struct allocator *
131 create_allocator (const char *type, bool debug)
133 struct allocator *ret = NULL;
134 allocator_parameters params = empty_vector;
135 size_t i, type_len;
137 if (parse_parameters (type, &type_len, &params) == -1)
138 return NULL;
140 /* See if we can find the allocator. */
141 for (i = 0; i < allocators.len; ++i) {
142 if (strncmp (type, allocators.ptr[i]->type, type_len) == 0) {
143 ret = allocators.ptr[i]->create (&params);
144 break;
148 if (ret == NULL)
149 nbdkit_error ("unknown allocator \"%s\"", type);
151 /* Free the parameters allocated above. */
152 free_allocator_parameters (&params);
154 if (ret) {
155 ret->debug = debug;
156 ret->f = allocators.ptr[i];
158 return ret;
161 void
162 cleanup_free_allocator (struct allocator **ap)
164 struct allocator *a = *ap;
166 if (a && a->f)
167 a->f->free (a);