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
38 static char *internal_vstralloc(const char *, int, const char *, va_list);
41 * alloc - a wrapper for malloc.
51 addr = (void *)malloc(max(size, 1));
53 errordump(_("%s@%d: memory allocation failed (%zu bytes requested)"),
54 file ? file : _("(unknown)"),
64 * newalloc - free existing buffer and then alloc a new one.
75 addr = debug_alloc(file, line, size);
82 * stralloc - copies the given string into newly allocated memory.
93 addr = debug_alloc(file, line, strlen(str) + 1);
99 * internal_vstralloc - copies up to MAX_STR_ARGS strings into newly
102 * The MAX_STR_ARGS limit is purely an efficiency issue so we do not have
103 * to scan the strings more than necessary.
106 #define MAX_VSTRALLOC_ARGS 40
119 const char *arg[MAX_VSTRALLOC_ARGS+1];
120 size_t len[MAX_VSTRALLOC_ARGS+1];
124 errordump(_("internal_vstralloc: str is NULL"));
131 total_len = len[a] = l;
134 while ((next = arglist_val(argp, char *)) != NULL) {
135 if ((l = strlen(next)) == 0) {
136 continue; /* minor optimisation */
138 if (a >= MAX_VSTRALLOC_ARGS) {
139 errordump(_("%s@%d: more than %d args to vstralloc"),
140 file ? file : _("(unknown)"),
151 result = debug_alloc(file, line, total_len+1);
154 for (b = 0; b < a; b++) {
155 memcpy(next, arg[b], len[b]);
165 * vstralloc - copies multiple strings into newly allocated memory.
177 arglist_start(argp, str);
178 result = internal_vstralloc(file, line, str, argp);
185 * newstralloc - free existing string and then stralloc a new one.
196 addr = debug_stralloc(file, line, newstr);
203 * newvstralloc - free existing string and then vstralloc a new one.
216 arglist_start(argp, newstr);
217 result = internal_vstralloc(file, line, newstr, argp);
225 * vstrallocf - copies printf formatted string into newly allocated memory.
239 result = debug_alloc(file, line, MIN_ALLOC);
240 if (result != NULL) {
242 arglist_start(argp, fmt);
243 size = g_vsnprintf(result, MIN_ALLOC, fmt, argp);
246 if (size >= (size_t)MIN_ALLOC) {
248 result = debug_alloc(file, line, size + 1);
250 arglist_start(argp, fmt);
251 (void)g_vsnprintf(result, size + 1, fmt, argp);
261 * newvstrallocf - free existing string and then vstrallocf a new one.
275 result = debug_alloc(file, line, MIN_ALLOC);
276 if (result != NULL) {
278 arglist_start(argp, fmt);
279 size = g_vsnprintf(result, MIN_ALLOC, fmt, argp);
282 if (size >= MIN_ALLOC) {
284 result = debug_alloc(file, line, size + 1);
286 arglist_start(argp, fmt);
287 (void)g_vsnprintf(result, size + 1, fmt, argp);
295 /* vstrextend -- Extends the existing string by appending the other
304 char *keep = *oldstr;
307 arglist_start(ap, oldstr);
311 *oldstr = internal_vstralloc(file, line, *oldstr, ap);
319 extern char **environ;
321 * safe_env - build a "safe" environment list.
326 static char *safe_env_list[] = {
339 * If the initial environment pointer malloc fails, set up to
340 * pass back a pointer to the NULL string pointer at the end of
341 * safe_env_list so our result is always a valid, although possibly
342 * empty, environment list.
344 #define SAFE_ENV_CNT (size_t)(sizeof(safe_env_list) / sizeof(*safe_env_list))
345 char **envp = safe_env_list + SAFE_ENV_CNT - 1;
355 if (getuid() == geteuid() && getgid() == getegid()) {
357 for (env = environ; *env != NULL; env++)
359 if ((q = (char **)malloc(env_cnt*SIZEOF(char *))) != NULL) {
362 for (env = environ; *env != NULL; env++) {
363 if (strncmp("LANG=", *env, 5) != 0 &&
364 strncmp("LC_", *env, 3) != 0) {
374 if ((q = (char **)malloc(SIZEOF(safe_env_list))) != NULL) {
376 for (p = safe_env_list; *p != NULL; p++) {
377 if ((v = getenv(*p)) == NULL) {
378 continue; /* no variable to dup */
380 l1 = strlen(*p); /* variable name w/o null */
381 l2 = strlen(v) + 1; /* include null byte here */
382 if ((s = (char *)malloc(l1 + 1 + l2)) == NULL) {
383 break; /* out of memory */
385 *q++ = s; /* save the new pointer */
386 memcpy(s, *p, l1); /* left hand side */
389 memcpy(s, v, l2); /* right hand side and null */
391 *q = NULL; /* terminate the list */
397 * amtable_alloc -- (re)allocate enough space for some number of elements.
399 * input: table -- pointer to pointer to table
400 * current -- pointer to current number of elements
401 * elsize -- size of a table element
402 * count -- desired number of elements
403 * bump -- round up factor
404 * init_func -- optional element initialization function
405 * output: table -- possibly adjusted to point to new table area
406 * current -- possibly adjusted to new number of elements
418 void (*init_func)(void *))
421 size_t table_count_new;
424 if (count >= *current) {
425 table_count_new = ((count + bump) / bump) * bump;
426 table_new = debug_alloc(file, line, table_count_new * elsize);
428 memcpy(table_new, *table, *current * elsize);
432 memset(((char *)*table) + *current * elsize,
434 (table_count_new - *current) * elsize);
435 if (init_func != NULL) {
436 for (i = *current; i < table_count_new; i++) {
437 (*init_func)(((char *)*table) + i * elsize);
440 *current = table_count_new;
446 * amtable_free -- release a table.
448 * input: table -- pointer to pointer to table
449 * current -- pointer to current number of elements
450 * output: table -- possibly adjusted to point to new table area
451 * current -- possibly adjusted to new number of elements