| File: | obj-scan-build/libstore/../../libstore/kids.c |
| Location: | line 204, column 17 |
| Description: | Call to 'malloc' has an allocation size of 0 bytes |
| 1 | /* Managing sub-stores | |||
| 2 | ||||
| 3 | Copyright (C) 1995,96,97,2001,02 Free Software Foundation, Inc. | |||
| 4 | Written by Miles Bader <miles@gnu.org> | |||
| 5 | ||||
| 6 | This file is part of the GNU Hurd. | |||
| 7 | ||||
| 8 | The GNU Hurd is free software; you can redistribute it and/or | |||
| 9 | modify it under the terms of the GNU General Public License as | |||
| 10 | published by the Free Software Foundation; either version 2, or (at | |||
| 11 | your option) any later version. | |||
| 12 | ||||
| 13 | The GNU Hurd is distributed in the hope that it will be useful, but | |||
| 14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| 16 | General Public License for more details. | |||
| 17 | ||||
| 18 | You should have received a copy of the GNU General Public License | |||
| 19 | along with this program; if not, write to the Free Software | |||
| 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ | |||
| 21 | ||||
| 22 | #include <stdlib.h> | |||
| 23 | #include <string.h> | |||
| 24 | #include <stdio.h> | |||
| 25 | #include <ctype.h> | |||
| 26 | ||||
| 27 | #include "store.h" | |||
| 28 | ||||
| 29 | /* Set STORE's current children list to (a copy of) CHILDREN and NUM_CHILDREN. */ | |||
| 30 | error_t | |||
| 31 | store_set_children (struct store *store, | |||
| 32 | struct store *const *children, size_t num_children) | |||
| 33 | { | |||
| 34 | unsigned size = num_children * sizeof (struct store *); | |||
| 35 | struct store **copy = malloc (size); | |||
| 36 | ||||
| 37 | if (!copy) | |||
| 38 | return ENOMEM((0x10 << 26) | ((12) & 0x3fff)); | |||
| 39 | ||||
| 40 | if (store->children) | |||
| 41 | free (store->children); | |||
| 42 | ||||
| 43 | memcpy (copy, children, size); | |||
| 44 | store->children = copy; | |||
| 45 | store->num_children = num_children; | |||
| 46 | ||||
| 47 | return 0; | |||
| 48 | } | |||
| 49 | ||||
| 50 | /* Calls the allocate_encoding method in each child store of STORE, | |||
| 51 | propagating any errors. If any child does not hae such a method, | |||
| 52 | EOPNOTSUPP is returned. */ | |||
| 53 | error_t | |||
| 54 | store_allocate_child_encodings (const struct store *store, | |||
| 55 | struct store_enc *enc) | |||
| 56 | { | |||
| 57 | int i; | |||
| 58 | error_t err = 0; | |||
| 59 | for (i = 0; i < store->num_children && !err; i++) | |||
| 60 | { | |||
| 61 | struct store *k = store->children[i]; | |||
| 62 | if (k->class->allocate_encoding) | |||
| 63 | (*k->class->allocate_encoding) (k, enc); | |||
| 64 | else | |||
| 65 | err = EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff)); | |||
| 66 | } | |||
| 67 | return err; | |||
| 68 | } | |||
| 69 | ||||
| 70 | /* Calls the encode method in each child store of STORE, propagating any | |||
| 71 | errors. If any child does not hae such a method, EOPNOTSUPP is returned. */ | |||
| 72 | error_t | |||
| 73 | store_encode_children (const struct store *store, struct store_enc *enc) | |||
| 74 | { | |||
| 75 | int i; | |||
| 76 | error_t err = 0; | |||
| 77 | for (i = 0; i < store->num_children && !err; i++) | |||
| 78 | { | |||
| 79 | struct store *k = store->children[i]; | |||
| 80 | if (k->class->encode) | |||
| 81 | (*k->class->encode) (k, enc); | |||
| 82 | else | |||
| 83 | err = EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff)); | |||
| 84 | } | |||
| 85 | return err; | |||
| 86 | } | |||
| 87 | ||||
| 88 | /* Decodes NUM_CHILDREN from ENC, storing the results into successive | |||
| 89 | positions in CHILDREN. */ | |||
| 90 | error_t | |||
| 91 | store_decode_children (struct store_enc *enc, int num_children, | |||
| 92 | const struct store_class *const *classes, | |||
| 93 | struct store **children) | |||
| 94 | { | |||
| 95 | int i; | |||
| 96 | error_t err = 0; | |||
| 97 | for (i = 0; i < num_children && !err; i++) | |||
| 98 | err = store_decode (enc, classes, &children[i]); | |||
| 99 | if (err) | |||
| 100 | /* Deallocate anything we've already created. */ | |||
| 101 | while (--i >= 0) | |||
| 102 | store_free (children[i]); | |||
| 103 | return err; | |||
| 104 | } | |||
| 105 | ||||
| 106 | /* Set FLAGS in all children of STORE, and if successful, add FLAGS to | |||
| 107 | STORE's flags. */ | |||
| 108 | error_t | |||
| 109 | store_set_child_flags (struct store *store, int flags) | |||
| 110 | { | |||
| 111 | int i; | |||
| 112 | error_t err = 0; | |||
| 113 | int old_child_flags[store->num_children]; | |||
| 114 | ||||
| 115 | for (i = 0; i < store->num_children && !err; i++) | |||
| 116 | { | |||
| 117 | old_child_flags[i] = store->children[i]->flags; | |||
| 118 | err = store_set_flags (store->children[i], flags); | |||
| 119 | } | |||
| 120 | ||||
| 121 | if (err) | |||
| 122 | while (i-- > 0) | |||
| 123 | store_clear_flags (store->children[i], flags & ~old_child_flags[i]); | |||
| 124 | else | |||
| 125 | store->flags |= flags; | |||
| 126 | ||||
| 127 | return err; | |||
| 128 | } | |||
| 129 | ||||
| 130 | /* Clear FLAGS in all children of STORE, and if successful, remove FLAGS from | |||
| 131 | STORE's flags. */ | |||
| 132 | error_t | |||
| 133 | store_clear_child_flags (struct store *store, int flags) | |||
| 134 | { | |||
| 135 | int i; | |||
| 136 | error_t err = 0; | |||
| 137 | int old_child_flags[store->num_children]; | |||
| 138 | ||||
| 139 | for (i = 0; i < store->num_children && !err; i++) | |||
| 140 | { | |||
| 141 | old_child_flags[i] = store->children[i]->flags; | |||
| 142 | err = store_clear_flags (store->children[i], flags); | |||
| 143 | } | |||
| 144 | ||||
| 145 | if (err) | |||
| 146 | while (i-- > 0) | |||
| 147 | store_set_flags (store->children[i], flags & ~old_child_flags[i]); | |||
| 148 | else | |||
| 149 | store->flags &= ~flags; | |||
| 150 | ||||
| 151 | return err; | |||
| 152 | } | |||
| 153 | ||||
| 154 | /* Parse multiple store names in NAME, and open each individually, returning | |||
| 155 | all in the vector STORES, and the number in NUM_STORES. The syntax of | |||
| 156 | NAME is a single non-alpha-numeric separator character, followed by each | |||
| 157 | child store name separated by the same separator; each child name is | |||
| 158 | TYPE:NAME notation as parsed by store_typed_open. If every child uses the | |||
| 159 | same TYPE: prefix, then it may be factored out and put before the child | |||
| 160 | list instead (the two types of notation are differentiated by whether the | |||
| 161 | first character of name is alpha-numeric or not). */ | |||
| 162 | error_t | |||
| 163 | store_open_children (const char *name, int flags, | |||
| 164 | const struct store_class *const *classes, | |||
| 165 | struct store ***stores, size_t *num_stores) | |||
| 166 | { | |||
| 167 | char *pfx = 0; /* Prefix applied to each part name. */ | |||
| 168 | size_t pfx_len = 0; /* Space PFX + separator takes up. */ | |||
| 169 | char sep = *name; /* Character separating individual names. */ | |||
| 170 | ||||
| 171 | if (sep && isalnum (sep)((*__ctype_b_loc ())[(int) ((sep))] & (unsigned short int ) _ISalnum)) | |||
| ||||
| 172 | /* If the first character is a `name' character, it's likely to be either | |||
| 173 | a type prefix (e.g, TYPE:@NAME1@NAME2@), so we distribute the type | |||
| 174 | prefix among the elements (@TYPE:NAME1@TYPE:NAME2@). */ | |||
| 175 | { | |||
| 176 | const char *pfx_end = name; | |||
| 177 | ||||
| 178 | while (isalnum (*pfx_end)((*__ctype_b_loc ())[(int) ((*pfx_end))] & (unsigned short int) _ISalnum)) | |||
| 179 | pfx_end++; | |||
| 180 | ||||
| 181 | if (*pfx_end++ != ':') | |||
| 182 | return EINVAL((0x10 << 26) | ((22) & 0x3fff)); | |||
| 183 | ||||
| 184 | /* Make a copy of the prefix. */ | |||
| 185 | pfx = strndupa (name, pfx_end - name)(__extension__ ({ const char *__old = (name); size_t __len = strnlen (__old, (pfx_end - name)); char *__new = (char *) __builtin_alloca (__len + 1); __new[__len] = '\0'; (char *) memcpy (__new, __old , __len); })); | |||
| 186 | pfx_len = pfx_end - name; | |||
| 187 | ||||
| 188 | sep = *pfx_end; | |||
| 189 | } | |||
| 190 | ||||
| 191 | if (sep) | |||
| 192 | /* Parse a list of store specs separated by SEP. */ | |||
| 193 | { | |||
| 194 | int k; | |||
| 195 | const char *p, *end; | |||
| 196 | error_t err = 0; | |||
| 197 | size_t count = 0; | |||
| 198 | ||||
| 199 | /* First, see how many there are. */ | |||
| 200 | for (p = name; p && p[1]; p = strchr (p + 1, sep)) | |||
| 201 | count++; | |||
| 202 | ||||
| 203 | /* Make a vector to hold them. */ | |||
| 204 | *stores = malloc (count * sizeof (struct store *)); | |||
| ||||
| 205 | *num_stores = count; | |||
| 206 | if (! *stores) | |||
| 207 | return ENOMEM((0x10 << 26) | ((12) & 0x3fff)); | |||
| 208 | ||||
| 209 | bzero (*stores, count * sizeof (struct store *)); | |||
| 210 | ||||
| 211 | /* Open each child store. */ | |||
| 212 | for (p = name, k = 0; !err && p && p[1]; p = end, k++) | |||
| 213 | { | |||
| 214 | size_t kname_len; | |||
| 215 | ||||
| 216 | end = strchr (p + 1, sep); | |||
| 217 | kname_len = (end ? end - p - 1 : strlen (p + 1)); | |||
| 218 | ||||
| 219 | { | |||
| 220 | /* Allocate temporary child name on the stack. */ | |||
| 221 | char kname[pfx_len + kname_len + 1]; | |||
| 222 | ||||
| 223 | if (pfx) | |||
| 224 | /* Add type prefix to child name. */ | |||
| 225 | memcpy (kname, pfx, pfx_len); | |||
| 226 | ||||
| 227 | memcpy (kname + pfx_len, p + 1, kname_len); | |||
| 228 | kname[pfx_len + kname_len] = '\0'; | |||
| 229 | ||||
| 230 | err = store_typed_open (kname, flags, classes, &(*stores)[k]); | |||
| 231 | } | |||
| 232 | } | |||
| 233 | ||||
| 234 | if (err) | |||
| 235 | /* Failure opening some child, deallocate what we've done so far. */ | |||
| 236 | { | |||
| 237 | while (--k >= 0) | |||
| 238 | store_free ((*stores)[k]); | |||
| 239 | free (*stores); | |||
| 240 | } | |||
| 241 | ||||
| 242 | return err; | |||
| 243 | } | |||
| 244 | else | |||
| 245 | /* Empty list. */ | |||
| 246 | { | |||
| 247 | *stores = 0; | |||
| 248 | *num_stores = 0; | |||
| 249 | return 0; | |||
| 250 | } | |||
| 251 | } | |||
| 252 | ||||
| 253 | /* Try to come up with a name for the children in STORE, combining the names | |||
| 254 | of each child in a way that could be used to parse them with | |||
| 255 | store_open_children. This is done heuristically, and so may not succeed. | |||
| 256 | If a child doesn't have a name, EINVAL is returned. */ | |||
| 257 | error_t | |||
| 258 | store_children_name (const struct store *store, char **name) | |||
| 259 | { | |||
| 260 | static char try_seps[] = "@+=,._%|;^!~'&"; | |||
| 261 | struct store **kids = store->children; | |||
| 262 | size_t num_kids = store->num_children; | |||
| 263 | ||||
| 264 | if (num_kids == 0) | |||
| 265 | { | |||
| 266 | *name = strdup (""); | |||
| 267 | return *name ? 0 : ENOMEM((0x10 << 26) | ((12) & 0x3fff)); | |||
| 268 | } | |||
| 269 | else | |||
| 270 | { | |||
| 271 | int k; | |||
| 272 | char *s; /* Current separator in search for one. */ | |||
| 273 | int fail; /* If we couldn't use *S as as sep. */ | |||
| 274 | size_t total_len = 0; /* Length of name we will return. */ | |||
| 275 | ||||
| 276 | /* Detect children without names, and calculate the total length of the | |||
| 277 | name we will return (which is the sum of the lengths of the child | |||
| 278 | names plus room for the types and separator characters. */ | |||
| 279 | for (k = 0; k < num_kids; k++) | |||
| 280 | if (!kids[k] || !kids[k]->name) | |||
| 281 | return EINVAL((0x10 << 26) | ((22) & 0x3fff)); | |||
| 282 | else | |||
| 283 | total_len += | |||
| 284 | /* separator + type name + type separator + child name */ | |||
| 285 | 1 + strlen (kids[k]->class->name) + 1 + strlen (kids[k]->name); | |||
| 286 | ||||
| 287 | /* Look for a separator character from those in TRY_SEPS that doesn't | |||
| 288 | occur in any of the the child names. */ | |||
| 289 | for (s = try_seps, fail = 1; *s && fail; s++) | |||
| 290 | for (k = 0, fail = 0; k < num_kids && !fail; k++) | |||
| 291 | if (strchr (kids[k]->name, *s)) | |||
| 292 | fail = 1; | |||
| 293 | ||||
| 294 | if (*s) | |||
| 295 | /* We found a usable separator! */ | |||
| 296 | { | |||
| 297 | char *p = malloc (total_len + 1); | |||
| 298 | ||||
| 299 | if (! p) | |||
| 300 | return ENOMEM((0x10 << 26) | ((12) & 0x3fff)); | |||
| 301 | *name = p; | |||
| 302 | ||||
| 303 | for (k = 0; k < num_kids; k++) | |||
| 304 | p += | |||
| 305 | sprintf (p, "%c%s:%s", *s, kids[k]->class->name, kids[k]->name); | |||
| 306 | ||||
| 307 | return 0; | |||
| 308 | } | |||
| 309 | else | |||
| 310 | return EGRATUITOUS((0x10 << 26) | ((105) & 0x3fff)); | |||
| 311 | } | |||
| 312 | } |