X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Falloc.c;h=c470b9d974c33a248edca731b19bce016f8396fe;hb=b116e9366c7b2ea2c2eb53b0a13df4090e176235;hp=07bab02fc09b86ecadf390c4cc27479ecc0136f5;hpb=3ab887b9bc819a846c75dd7f2ee5d41fac22b19f;p=debian%2Famanda diff --git a/common-src/alloc.c b/common-src/alloc.c index 07bab02..c470b9d 100644 --- a/common-src/alloc.c +++ b/common-src/alloc.c @@ -1,6 +1,6 @@ /* * Amanda, The Advanced Maryland Automatic Network Disk Archiver - * Copyright (c) 1991-1998 University of Maryland at College Park + * Copyright (c) 1991-1999 University of Maryland at College Park * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -24,7 +24,7 @@ * file named AUTHORS, in the root directory of this distribution. */ /* - * $Id: alloc.c,v 1.17.2.1.4.3.2.3 2002/10/27 14:31:18 martinea Exp $ + * $Id: alloc.c 5280 2007-02-13 15:58:56Z martineau $ * * Memory allocators with error handling. If the allocation fails, * errordump() is called, relieving the caller from checking the return @@ -33,196 +33,29 @@ #include "amanda.h" #include "arglist.h" -/* - *===================================================================== - * debug_caller_loc -- keep track of all allocation callers - * - * char *debug_caller_loc(char *file, int line) - * - * entry: file = source file - * line = source line - * exit: a string like "genversion.c@999" - * - * The debug malloc library has a concept of a call stack that can be used - * to fine tune what was running when a particular allocation was done. - * We use it to tell who called our various allocation wrappers since - * it wouldn't do much good to tell us a problem happened because of - * the malloc call in alloc (they are all from there at some point). - * - * But the library expects the string passed to malloc_enter/malloc_leave - * to be static, so we build a linked list of each one we get (there are - * not really that many during a given execution). When we get a repeat - * we return the previously allocated string. For a bit of performance, - * we keep the list in least recently used order, which helps because - * the calls to us come in pairs (one for malloc_enter and one right - * after for malloc_leave). - *===================================================================== - */ - -char * -debug_caller_loc(file, line) - char *file; - int line; -{ - struct loc_str { - char *str; - struct loc_str *next; - }; - static struct loc_str *root = NULL; - struct loc_str *ls, *ls_last; - int len; - int size; - char *p; - static char *loc = NULL; - static int loc_size = 0; - - if ((p = strrchr(file, '/')) == NULL) { - p = file; /* keep the whole name */ - } else { - p++; /* just the last path element */ - } - - len = strlen (p); - size = len + 1 + NUM_STR_SIZE + 1; - if (size > loc_size) { - size = ((size + 64 - 1) / 64) * 64; /* might as well get a bunch */ - /* - * We should free the previous loc area, but we have marked it - * as a non-leak and the library considers it an error to free - * such an area, so we just ignore it. We probably grabbed - * enough the first time that this will not even happen. - */ - loc = malloc (size); - if (loc == NULL) { - return "??"; /* not much better than abort */ - } - malloc_mark (loc); - loc_size = size; - } - - strcpy (loc, p); - ap_snprintf(loc + len, 1 + NUM_STR_SIZE, "@%d", line); - - for (ls_last = NULL, ls = root; ls != NULL; ls_last = ls, ls = ls->next) { - if (strcmp (loc, ls->str) == 0) { - break; - } - } - - if (ls == NULL) { - /* - * This is a new entry. Put it at the head of the list. - */ - ls = malloc (sizeof (*ls)); - if (ls == NULL) { - return "??"; /* not much better than abort */ - } - malloc_mark (ls); - size = strlen (loc) + 1; - ls->str = malloc (size); - if (ls->str == NULL) { - free (ls); - return "??"; /* not much better than abort */ - } - malloc_mark (ls->str); - strcpy (ls->str, loc); - ls->next = root; - root = ls; - } else if (ls_last != NULL) { - /* - * This is a repeat and was not at the head of the list. - * Unlink it and move it to the front. - */ - ls_last->next = ls->next; - ls->next = root; - root = ls; - } else { - /* - * This is a repeat but was already at the head of the list, - * so nothing else needs to be done. - */ - } - return ls->str; -} - -/* - *===================================================================== - * Save the current source line for vstralloc/newvstralloc. - * - * int debug_alloc_push (char *s, int l) - * - * entry: s = source file - * l = source line - * exit: always zero - * - * See the comments in amanda.h about what this is used for. - *===================================================================== - */ - -#define DEBUG_ALLOC_SAVE_MAX 10 - -static struct { - char *file; - int line; -} debug_alloc_loc_info[DEBUG_ALLOC_SAVE_MAX]; -static int debug_alloc_ptr = 0; - -static char *saved_file; -static int saved_line; - -int -debug_alloc_push (s, l) - char *s; - int l; -{ - debug_alloc_loc_info[debug_alloc_ptr].file = s; - debug_alloc_loc_info[debug_alloc_ptr].line = l; - debug_alloc_ptr = (debug_alloc_ptr + 1) % DEBUG_ALLOC_SAVE_MAX; - return 0; -} - -/* - *===================================================================== - * Pop the current source line information for vstralloc/newvstralloc. - * - * int debug_alloc_pop (void) - * - * entry: none - * exit: none - * - * See the comments in amanda.h about what this is used for. - *===================================================================== - */ +#define MIN_ALLOC 64 -void -debug_alloc_pop () -{ - debug_alloc_ptr = - (debug_alloc_ptr + DEBUG_ALLOC_SAVE_MAX - 1) % DEBUG_ALLOC_SAVE_MAX; - saved_file = debug_alloc_loc_info[debug_alloc_ptr].file; - saved_line = debug_alloc_loc_info[debug_alloc_ptr].line; -} +static char *internal_vstralloc(const char *, int, const char *, va_list); /* * alloc - a wrapper for malloc. */ void * -debug_alloc(s, l, size) - char *s; - int l; - size_t size; +debug_alloc( + const char *file, + int line, + size_t size) { void *addr; - malloc_enter(debug_caller_loc(s, l)); addr = (void *)malloc(max(size, 1)); - if(addr == NULL) { - errordump("%s@%d: memory allocation failed (%u bytes requested)", - s ? s : "(unknown)", - s ? l : -1, + if (addr == NULL) { + errordump(_("%s@%d: memory allocation failed (%zu bytes requested)"), + file ? file : _("(unknown)"), + file ? line : -1, size); + /*NOTREACHED*/ } - malloc_leave(debug_caller_loc(s, l)); return addr; } @@ -231,18 +64,16 @@ debug_alloc(s, l, size) * newalloc - free existing buffer and then alloc a new one. */ void * -debug_newalloc(s, l, old, size) - char *s; - int l; - void *old; - size_t size; +debug_newalloc( + const char *file, + int line, + void * old, + size_t size) { char *addr; - malloc_enter(debug_caller_loc(s, l)); - addr = debug_alloc(s, l, size); + addr = debug_alloc(file, line, size); amfree(old); - malloc_leave(debug_caller_loc(s, l)); return addr; } @@ -252,21 +83,18 @@ debug_newalloc(s, l, old, size) * Just like strdup()! */ char * -debug_stralloc(s, l, str) - char *s; - int l; - const char *str; +debug_stralloc( + const char *file, + int line, + const char *str) { char *addr; - malloc_enter(debug_caller_loc(s, l)); - addr = debug_alloc(s, l, strlen(str) + 1); + addr = debug_alloc(file, line, strlen(str) + 1); strcpy(addr, str); - malloc_leave(debug_caller_loc(s, l)); - return addr; + return (addr); } - /* * internal_vstralloc - copies up to MAX_STR_ARGS strings into newly * allocated memory. @@ -275,24 +103,26 @@ debug_stralloc(s, l, str) * to scan the strings more than necessary. */ -#define MAX_VSTRALLOC_ARGS 32 +#define MAX_VSTRALLOC_ARGS 40 static char * -internal_vstralloc(str, argp) - const char *str; - va_list argp; +internal_vstralloc( + const char *file, + int line, + const char *str, + va_list argp) { char *next; char *result; - int a; + int a, b; size_t total_len; const char *arg[MAX_VSTRALLOC_ARGS+1]; size_t len[MAX_VSTRALLOC_ARGS+1]; size_t l; - const char *s; if (str == NULL) { - return NULL; /* probably will not happen */ + errordump(_("internal_vstralloc: str is NULL")); + /*NOTREACHED*/ } a = 0; @@ -306,24 +136,24 @@ internal_vstralloc(str, argp) continue; /* minor optimisation */ } if (a >= MAX_VSTRALLOC_ARGS) { - errordump("%s@%d: more than %d arg%s to vstralloc", - saved_file ? saved_file : "(unknown)", - saved_file ? saved_line : -1, - MAX_VSTRALLOC_ARGS, - (MAX_VSTRALLOC_ARGS == 1) ? "" : "s"); + errordump(_("%s@%d: more than %d args to vstralloc"), + file ? file : _("(unknown)"), + file ? line : -1, + MAX_VSTRALLOC_ARGS); + /*NOTREACHED*/ } arg[a] = next; len[a] = l; total_len += l; a++; } - arg[a] = NULL; - len[a] = 0; - next = result = debug_alloc(saved_file, saved_line, total_len+1); - for (a = 0; (s = arg[a]) != NULL; a++) { - memcpy(next, s, len[a]); - next += len[a]; + result = debug_alloc(file, line, total_len+1); + + next = result; + for (b = 0; b < a; b++) { + memcpy(next, arg[b], len[b]); + next += len[b]; } *next = '\0'; @@ -334,17 +164,19 @@ internal_vstralloc(str, argp) /* * vstralloc - copies multiple strings into newly allocated memory. */ -arglist_function(char *debug_vstralloc, const char *, str) +char * +debug_vstralloc( + const char *file, + int line, + const char *str, + ...) { va_list argp; char *result; - debug_alloc_pop(); - malloc_enter(debug_caller_loc(saved_file, saved_line)); arglist_start(argp, str); - result = internal_vstralloc(str, argp); + result = internal_vstralloc(file, line, str, argp); arglist_end(argp); - malloc_leave(debug_caller_loc(saved_file, saved_line)); return result; } @@ -353,95 +185,151 @@ arglist_function(char *debug_vstralloc, const char *, str) * newstralloc - free existing string and then stralloc a new one. */ char * -debug_newstralloc(s, l, oldstr, newstr) - char *s; - int l; - char *oldstr; - const char *newstr; +debug_newstralloc( + const char *file, + int line, + char * oldstr, + const char *newstr) { char *addr; - malloc_enter(debug_caller_loc(s, l)); - addr = debug_stralloc(s, l, newstr); + addr = debug_stralloc(file, line, newstr); amfree(oldstr); - malloc_leave(debug_caller_loc(s, l)); - return addr; + return (addr); } /* * newvstralloc - free existing string and then vstralloc a new one. */ -arglist_function1(char *debug_newvstralloc, - char *, - oldstr, - const char *, - newstr) +char * +debug_newvstralloc( + const char *file, + int line, + char * oldstr, + const char *newstr, + ...) { va_list argp; char *result; - debug_alloc_pop(); - malloc_enter(debug_caller_loc(saved_file, saved_line)); arglist_start(argp, newstr); - result = internal_vstralloc(newstr, argp); + result = internal_vstralloc(file, line, newstr, argp); arglist_end(argp); amfree(oldstr); - malloc_leave(debug_caller_loc(saved_file, saved_line)); return result; } /* - * sbuf_man - static buffer manager. - * - * Manage a bunch of static buffer pointers. + * vstrallocf - copies printf formatted string into newly allocated memory. */ -void *sbuf_man(e_bufs, ptr) - void *e_bufs; /* XXX - I dont think this is right */ - void *ptr; +char * +debug_vstrallocf( + const char *file, + int line, + const char *fmt, + ...) { - SBUF2_DEF(1) *bufs; - int slot; + char * result; + size_t size; + va_list argp; + - bufs = e_bufs; + result = debug_alloc(file, line, MIN_ALLOC); + if (result != NULL) { - /* try and trap bugs */ - assert(bufs->magic == SBUF_MAGIC); - assert(bufs->max > 0); + arglist_start(argp, fmt); + size = g_vsnprintf(result, MIN_ALLOC, fmt, argp); + arglist_end(argp); - /* initialise first time through */ - if(bufs->cur == -1) - for(slot=0; slot < bufs->max; slot++) { - bufs->bufp[slot] = (void *)0; - } + if (size >= (size_t)MIN_ALLOC) { + amfree(result); + result = debug_alloc(file, line, size + 1); + + arglist_start(argp, fmt); + (void)g_vsnprintf(result, size + 1, fmt, argp); + arglist_end(argp); + } + } + + return result; +} + + +/* + * newvstrallocf - free existing string and then vstrallocf a new one. + */ +char * +debug_newvstrallocf( + const char *file, + int line, + char * oldstr, + const char *fmt, + ...) +{ + size_t size; + char * result; + va_list argp; - /* calculate the next slot */ - slot = bufs->cur + 1; - if (slot >= bufs->max) slot = 0; + result = debug_alloc(file, line, MIN_ALLOC); + if (result != NULL) { - /* free the previous inhabitant */ - if(bufs->bufp[slot] != (void *)0) free(bufs->bufp[slot]); + arglist_start(argp, fmt); + size = g_vsnprintf(result, MIN_ALLOC, fmt, argp); + arglist_end(argp); - /* store the new one */ - bufs->bufp[slot] = ptr; - bufs->cur = slot; + if (size >= MIN_ALLOC) { + amfree(result); + result = debug_alloc(file, line, size + 1); - return ptr; + arglist_start(argp, fmt); + (void)g_vsnprintf(result, size + 1, fmt, argp); + arglist_end(argp); + } + } + amfree(oldstr); + return result; } +/* vstrextend -- Extends the existing string by appending the other + * arguments. */ +char * +debug_vstrextend( + const char *file, + int line, + char ** oldstr, + ...) +{ + char *keep = *oldstr; + va_list ap; + + arglist_start(ap, oldstr); + + if (*oldstr == NULL) + *oldstr = ""; + *oldstr = internal_vstralloc(file, line, *oldstr, ap); + amfree(keep); + + arglist_end(ap); + return *oldstr; +} /* - * safe_env - build a "safe" environment list. + * safe_env_full - build a "safe" environment list. */ char ** -safe_env() +safe_env_full(char **add) { static char *safe_env_list[] = { "TZ", +#ifdef __CYGWIN__ + "SYSTEMROOT", +#endif #ifdef NEED_PATH_ENV "PATH", #endif + "DISPLAY", NULL }; @@ -451,7 +339,7 @@ safe_env() * safe_env_list so our result is always a valid, although possibly * empty, environment list. */ -#define SAFE_ENV_CNT (sizeof(safe_env_list) / sizeof(*safe_env_list)) +#define SAFE_ENV_CNT (size_t)(sizeof(safe_env_list) / sizeof(*safe_env_list)) char **envp = safe_env_list + SAFE_ENV_CNT - 1; char **p; @@ -459,9 +347,47 @@ safe_env() char *s; char *v; size_t l1, l2; + char **env; + int env_cnt; + int nadd = 0; + + /* count ADD */ + for (p = add; p && *p; p++) + nadd++; + + if (getuid() == geteuid() && getgid() == getegid()) { + env_cnt = 1; + for (env = environ; *env != NULL; env++) + env_cnt++; + if ((q = (char **)malloc((nadd+env_cnt)*SIZEOF(char *))) != NULL) { + envp = q; + p = envp; + /* copy in ADD */ + for (env = add; env && *env; env++) { + *p = *env; + p++; + } + for (env = environ; *env != NULL; env++) { + if (strncmp("LANG=", *env, 5) != 0 && + strncmp("LC_", *env, 3) != 0) { + *p = stralloc(*env); + p++; + } + } + *p = NULL; + } + return envp; + } - if ((q = (char **)malloc(sizeof(safe_env_list))) != NULL) { + if ((q = (char **)malloc(nadd*sizeof(char *) + SIZEOF(safe_env_list))) != NULL) { envp = q; + /* copy in ADD */ + for (p = add; p && *p; p++) { + *q = *p; + q++; + } + + /* and copy any SAFE_ENV that are already set */ for (p = safe_env_list; *p != NULL; p++) { if ((v = getenv(*p)) == NULL) { continue; /* no variable to dup */ @@ -481,70 +407,3 @@ safe_env() } return envp; } - -/* - * amtable_alloc -- (re)allocate enough space for some number of elements. - * - * input: table -- pointer to pointer to table - * current -- pointer to current number of elements - * elsize -- size of a table element - * count -- desired number of elements - * bump -- round up factor - * init_func -- optional element initialization function - * output: table -- possibly adjusted to point to new table area - * current -- possibly adjusted to new number of elements - */ - -int -debug_amtable_alloc(s, l, table, current, elsize, count, bump, init_func) - char *s; - int l; - void **table; - int *current; - size_t elsize; - int count; - int bump; - void (*init_func)(void *); -{ - void *table_new; - int table_count_new; - int i; - - if (count >= *current) { - table_count_new = ((count + bump) / bump) * bump; - table_new = debug_alloc(s, l, table_count_new * elsize); - if (0 != *table) { - memcpy(table_new, *table, *current * elsize); - free(*table); - } - *table = table_new; - memset(((char *)*table) + *current * elsize, - 0, - (table_count_new - *current) * elsize); - if (init_func != NULL) { - for (i = *current; i < table_count_new; i++) { - (*init_func)(((char *)*table) + i * elsize); - } - } - *current = table_count_new; - } - return 0; -} - -/* - * amtable_free -- release a table. - * - * input: table -- pointer to pointer to table - * current -- pointer to current number of elements - * output: table -- possibly adjusted to point to new table area - * current -- possibly adjusted to new number of elements - */ - -void -amtable_free(table, current) - void **table; - int *current; -{ - amfree(*table); - *current = 0; -}