[pacman-dev] [PATCH 2/5] util: Add _alpm_realloc()

Dave Reisner d at falconindy.com
Mon Jan 27 18:30:58 EST 2014


On Tue, Jan 28, 2014 at 12:02:34AM +0100, Florian Pritz wrote:
> Signed-off-by: Florian Pritz <bluewind at xinu.at>
> ---
>  lib/libalpm/util.c | 38 ++++++++++++++++++++++++++++++++++++++
>  lib/libalpm/util.h |  1 +
>  2 files changed, 39 insertions(+)
> 
> diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
> index 1bbc768..5f99f35 100644
> --- a/lib/libalpm/util.c
> +++ b/lib/libalpm/util.c
> @@ -1287,6 +1287,44 @@ int _alpm_fnmatch(const void *pattern, const void *string)
>  	return fnmatch(pattern, string, 0);
>  }
>  
> +/**
> + * Think of this as realloc with error handling and
> + * automatic growing bases on current/required

Hrmmm, I'm not really a fan of this as is. One might argue that it
doesn't really do error handling -- it returns NULL on error (the same
as realloc), and merely wraps some semi-arbitrary logic for deciding how
much to grow the buffer. The caller still needs to save the value if
they want to avoid a crappy situation on OOM.

I think we can do better, and I'd suggesting looking greedy_realloc
(function and macro) in systemd's codebase (src/shared/util.[ch]). What
you have here is close, but a minor switch in the return value and the
first parameter makes this a whole lot more useful.

> + *
> + * @param data source memory space
> + * @param current size of the space pointed to be data
> + * @param required size you want
> + * @return new memory
> + */
> +void *_alpm_realloc(void *data, size_t *current, const size_t required)
> +{
> +	if(required >= *current) {
> +		size_t old_size = *current;
> +		char *newdata;
> +		size_t newsize = *current;
> +
> +		if(*current == 0) {
> +			newsize = ALPM_BUFFER_SIZE;
> +		} else if (required > (*current) * 2) {
> +			newsize = required * 2;
> +		} else {
> +			newsize *= 2;
> +		}
> +
> +		newdata = realloc(data, newsize);
> +		if(!newdata) {
> +			_alpm_alloc_fail(newsize);
> +			return NULL;
> +		}
> +		/* ensure all new memory is zeroed out, in both the initial
> +		 * allocation and later reallocs */
> +		memset(newdata + old_size, 0, *current - old_size);
> +		*current = newsize;
> +		return newdata;
> +	}
> +	return data;
> +}
> +
>  void _alpm_alloc_fail(size_t size)
>  {
>  	fprintf(stderr, "alloc failure: could not allocate %zd bytes\n", size);
> diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h
> index b566868..b7e6e90 100644
> --- a/lib/libalpm/util.h
> +++ b/lib/libalpm/util.h
> @@ -141,6 +141,7 @@ int _alpm_raw_ncmp(const char *first, const char *second, size_t max);
>  int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int amode);
>  int _alpm_fnmatch_patterns(alpm_list_t *patterns, const char *string);
>  int _alpm_fnmatch(const void *pattern, const void *string);
> +void *_alpm_realloc(void *data, size_t *current, const size_t required);
>  
>  #ifndef HAVE_STRSEP
>  char *strsep(char **, const char *);
> -- 
> 1.8.5.3
> 


More information about the pacman-dev mailing list