helpers.h: add xasprintf function
This is our own version of asprintf(). This original code was written by Mike Frysinger, and I was able to modify it to use our memory helper functions. We need a version of this code because it is not available on glibc at least without defining _GNU_SOURCE, and I would rather not do that. This is the first step in improving string handling in OpenRC for #207.
This commit is contained in:
		@@ -53,6 +53,7 @@
 | 
			
		||||
	} while (/* CONSTCOND */ 0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
 | 
			
		||||
@@ -123,4 +124,52 @@ _unused static bool existss(const char *pathname)
 | 
			
		||||
	return (stat(pathname, &buf) == 0 && buf.st_size != 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This is an OpenRC specific version of the asprintf() function.
 | 
			
		||||
 * We do this to avoid defining the _GNU_SOURCE feature test macro on
 | 
			
		||||
 * glibc systems and to insure that we have a consistent function across
 | 
			
		||||
 * platforms. This also allows us to call our xmalloc and xrealloc
 | 
			
		||||
 * functions to handle memory allocation.
 | 
			
		||||
 * this function was originally written by Mike Frysinger.
 | 
			
		||||
 */
 | 
			
		||||
_unused static int xasprintf(char **strp, const char *fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
	va_list ap;
 | 
			
		||||
	int len;
 | 
			
		||||
	int memlen;
 | 
			
		||||
	char *ret;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Start with a buffer size that should cover the vast majority of uses
 | 
			
		||||
	 * (path construction).
 | 
			
		||||
	 */
 | 
			
		||||
	memlen = 4096;
 | 
			
		||||
	ret = xmalloc(memlen);
 | 
			
		||||
 | 
			
		||||
	va_start(ap, fmt);
 | 
			
		||||
	len = vsnprintf(ret, memlen, fmt, ap);
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
	if (len >= memlen) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * Output was truncated, so increase buffer to exactly what we need.
 | 
			
		||||
		 */
 | 
			
		||||
		memlen = len + 1;
 | 
			
		||||
		ret = xrealloc(ret, memlen);
 | 
			
		||||
		va_start(ap, fmt);
 | 
			
		||||
		len = vsnprintf(ret, len + 1, fmt, ap);
 | 
			
		||||
		va_end(ap);
 | 
			
		||||
		if (len >= memlen) {
 | 
			
		||||
			/* Give up! */
 | 
			
		||||
			free(ret);
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (len < 0) {
 | 
			
		||||
		free(ret);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	*strp = ret;
 | 
			
		||||
	return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user