2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1999 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: alloc.c 5280 2007-02-13 15:58:56Z martineau $
29 * Memory allocators with error handling. If the allocation fails,
30 * errordump() is called, relieving the caller from checking the return
39 static char *internal_vstralloc(const char *, int, const char *, va_list);
42 * alloc - a wrapper for malloc.
52 addr = (void *)malloc(max(size, 1));
54 errordump(_("%s@%d: memory allocation failed (%zu bytes requested)"),
55 file ? file : _("(unknown)"),
65 * newalloc - free existing buffer and then alloc a new one.
76 addr = debug_alloc(file, line, size);
83 * stralloc - copies the given string into newly allocated memory.
94 addr = debug_alloc(file, line, strlen(str) + 1);
100 * internal_vstralloc - copies up to MAX_STR_ARGS strings into newly
103 * The MAX_STR_ARGS limit is purely an efficiency issue so we do not have
104 * to scan the strings more than necessary.
107 #define MAX_VSTRALLOC_ARGS 32
120 const char *arg[MAX_VSTRALLOC_ARGS+1];
121 size_t len[MAX_VSTRALLOC_ARGS+1];
125 errordump(_("internal_vstralloc: str is NULL"));
132 total_len = len[a] = l;
135 while ((next = arglist_val(argp, char *)) != NULL) {
136 if ((l = strlen(next)) == 0) {
137 continue; /* minor optimisation */
139 if (a >= MAX_VSTRALLOC_ARGS) {
140 errordump(_("%s@%d: more than %d args to vstralloc"),
141 file ? file : _("(unknown)"),
152 result = debug_alloc(file, line, total_len+1);
155 for (b = 0; b < a; b++) {
156 memcpy(next, arg[b], len[b]);
166 * vstralloc - copies multiple strings into newly allocated memory.
178 arglist_start(argp, str);
179 result = internal_vstralloc(file, line, str, argp);
186 * newstralloc - free existing string and then stralloc a new one.
197 addr = debug_stralloc(file, line, newstr);
204 * newvstralloc - free existing string and then vstralloc a new one.
217 arglist_start(argp, newstr);
218 result = internal_vstralloc(file, line, newstr, argp);
226 * vstrallocf - copies printf formatted string into newly allocated memory.
240 result = debug_alloc(file, line, MIN_ALLOC);
241 if (result != NULL) {
243 arglist_start(argp, fmt);
244 size = g_vsnprintf(result, MIN_ALLOC, fmt, argp);
247 if (size >= (size_t)MIN_ALLOC) {
249 result = debug_alloc(file, line, size + 1);
251 arglist_start(argp, fmt);
252 (void)g_vsnprintf(result, size + 1, fmt, argp);
262 * newvstrallocf - free existing string and then vstrallocf a new one.
276 result = debug_alloc(file, line, MIN_ALLOC);
277 if (result != NULL) {
279 arglist_start(argp, fmt);
280 size = g_vsnprintf(result, MIN_ALLOC, fmt, argp);
283 if (size >= MIN_ALLOC) {
285 result = debug_alloc(file, line, size + 1);
287 arglist_start(argp, fmt);
288 (void)g_vsnprintf(result, size + 1, fmt, argp);
296 /* vstrextend -- Extends the existing string by appending the other
305 char *keep = *oldstr;
308 arglist_start(ap, oldstr);
312 *oldstr = internal_vstralloc(file, line, *oldstr, ap);
320 extern char **environ;
322 * safe_env - build a "safe" environment list.
327 static char *safe_env_list[] = {
340 * If the initial environment pointer malloc fails, set up to
341 * pass back a pointer to the NULL string pointer at the end of
342 * safe_env_list so our result is always a valid, although possibly
343 * empty, environment list.
345 #define SAFE_ENV_CNT (size_t)(sizeof(safe_env_list) / sizeof(*safe_env_list))
346 char **envp = safe_env_list + SAFE_ENV_CNT - 1;
356 if (getuid() == geteuid() && getgid() == getegid()) {
358 for (env = environ; *env != NULL; env++)
360 if ((q = (char **)malloc(env_cnt*SIZEOF(char *))) != NULL) {
363 for (env = environ; *env != NULL; env++) {
364 if (strncmp("LANG=", *env, 5) != 0 &&
365 strncmp("LC_", *env, 3) != 0) {
375 if ((q = (char **)malloc(SIZEOF(safe_env_list))) != NULL) {
377 for (p = safe_env_list; *p != NULL; p++) {
378 if ((v = getenv(*p)) == NULL) {
379 continue; /* no variable to dup */
381 l1 = strlen(*p); /* variable name w/o null */
382 l2 = strlen(v) + 1; /* include null byte here */
383 if ((s = (char *)malloc(l1 + 1 + l2)) == NULL) {
384 break; /* out of memory */
386 *q++ = s; /* save the new pointer */
387 memcpy(s, *p, l1); /* left hand side */
390 memcpy(s, v, l2); /* right hand side and null */
392 *q = NULL; /* terminate the list */
398 * amtable_alloc -- (re)allocate enough space for some number of elements.
400 * input: table -- pointer to pointer to table
401 * current -- pointer to current number of elements
402 * elsize -- size of a table element
403 * count -- desired number of elements
404 * bump -- round up factor
405 * init_func -- optional element initialization function
406 * output: table -- possibly adjusted to point to new table area
407 * current -- possibly adjusted to new number of elements
419 void (*init_func)(void *))
422 size_t table_count_new;
425 if (count >= *current) {
426 table_count_new = ((count + bump) / bump) * bump;
427 table_new = debug_alloc(file, line, table_count_new * elsize);
429 memcpy(table_new, *table, *current * elsize);
433 memset(((char *)*table) + *current * elsize,
435 (table_count_new - *current) * elsize);
436 if (init_func != NULL) {
437 for (i = *current; i < table_count_new; i++) {
438 (*init_func)(((char *)*table) + i * elsize);
441 *current = table_count_new;
447 * amtable_free -- release a table.
449 * input: table -- pointer to pointer to table
450 * current -- pointer to current number of elements
451 * output: table -- possibly adjusted to point to new table area
452 * current -- possibly adjusted to new number of elements