xref: /aosp_15_r20/external/libpcap/missing/asprintf.c (revision 8b26181f966a6af5cf6981a6f474313de533bb28)
1*8b26181fSAndroid Build Coastguard Worker #include <stdio.h>
2*8b26181fSAndroid Build Coastguard Worker #include <stdlib.h>
3*8b26181fSAndroid Build Coastguard Worker #include <stdarg.h>
4*8b26181fSAndroid Build Coastguard Worker 
5*8b26181fSAndroid Build Coastguard Worker #include "portability.h"
6*8b26181fSAndroid Build Coastguard Worker 
7*8b26181fSAndroid Build Coastguard Worker /*
8*8b26181fSAndroid Build Coastguard Worker  * vasprintf() and asprintf() for platforms with a C99-compliant
9*8b26181fSAndroid Build Coastguard Worker  * snprintf() - so that, if you format into a 1-byte buffer, it
10*8b26181fSAndroid Build Coastguard Worker  * will return how many characters it would have produced had
11*8b26181fSAndroid Build Coastguard Worker  * it been given an infinite-sized buffer.
12*8b26181fSAndroid Build Coastguard Worker  */
13*8b26181fSAndroid Build Coastguard Worker int
pcap_vasprintf(char ** strp,const char * format,va_list args)14*8b26181fSAndroid Build Coastguard Worker pcap_vasprintf(char **strp, const char *format, va_list args)
15*8b26181fSAndroid Build Coastguard Worker {
16*8b26181fSAndroid Build Coastguard Worker 	char buf;
17*8b26181fSAndroid Build Coastguard Worker 	int len;
18*8b26181fSAndroid Build Coastguard Worker 	size_t str_size;
19*8b26181fSAndroid Build Coastguard Worker 	char *str;
20*8b26181fSAndroid Build Coastguard Worker 	int ret;
21*8b26181fSAndroid Build Coastguard Worker 
22*8b26181fSAndroid Build Coastguard Worker 	/*
23*8b26181fSAndroid Build Coastguard Worker 	 * XXX - the C99 standard says, in section 7.19.6.5 "The
24*8b26181fSAndroid Build Coastguard Worker 	 * nprintf function":
25*8b26181fSAndroid Build Coastguard Worker 	 *
26*8b26181fSAndroid Build Coastguard Worker 	 *    The snprintf function is equivalent to fprintf, except that
27*8b26181fSAndroid Build Coastguard Worker 	 *    the output is written into an array (specified by argument s)
28*8b26181fSAndroid Build Coastguard Worker 	 *    rather than to a stream.  If n is zero, nothing is written,
29*8b26181fSAndroid Build Coastguard Worker 	 *    and s may be a null pointer.  Otherwise, output characters
30*8b26181fSAndroid Build Coastguard Worker 	 *    beyond the n-1st are discarded rather than being written
31*8b26181fSAndroid Build Coastguard Worker 	 *    to the array, and a null character is written at the end
32*8b26181fSAndroid Build Coastguard Worker 	 *    of the characters actually written into the array.
33*8b26181fSAndroid Build Coastguard Worker 	 *
34*8b26181fSAndroid Build Coastguard Worker 	 *        ...
35*8b26181fSAndroid Build Coastguard Worker 	 *
36*8b26181fSAndroid Build Coastguard Worker 	 *    The snprintf function returns the number of characters that
37*8b26181fSAndroid Build Coastguard Worker 	 *    would have been written had n been sufficiently large, not
38*8b26181fSAndroid Build Coastguard Worker 	 *    counting the terminating null character, or a negative value
39*8b26181fSAndroid Build Coastguard Worker 	 *    if an encoding error occurred. Thus, the null-terminated
40*8b26181fSAndroid Build Coastguard Worker 	 *    output has been completely written if and only if the returned
41*8b26181fSAndroid Build Coastguard Worker 	 *    value is nonnegative and less than n.
42*8b26181fSAndroid Build Coastguard Worker 	 *
43*8b26181fSAndroid Build Coastguard Worker 	 * That doesn't make it entirely clear whether, if a null buffer
44*8b26181fSAndroid Build Coastguard Worker 	 * pointer and a zero count are passed, it will return the number
45*8b26181fSAndroid Build Coastguard Worker 	 * of characters that would have been written had a buffer been
46*8b26181fSAndroid Build Coastguard Worker 	 * passed.
47*8b26181fSAndroid Build Coastguard Worker 	 *
48*8b26181fSAndroid Build Coastguard Worker 	 * And, even if C99 *does*, in fact, say it has to work, it
49*8b26181fSAndroid Build Coastguard Worker 	 * doesn't work in Solaris 8, for example - it returns -1 for
50*8b26181fSAndroid Build Coastguard Worker 	 * NULL/0, but returns the correct character count for a 1-byte
51*8b26181fSAndroid Build Coastguard Worker 	 * buffer.
52*8b26181fSAndroid Build Coastguard Worker 	 *
53*8b26181fSAndroid Build Coastguard Worker 	 * So we pass a one-character pointer in order to find out how
54*8b26181fSAndroid Build Coastguard Worker 	 * many characters this format and those arguments will need
55*8b26181fSAndroid Build Coastguard Worker 	 * without actually generating any more of those characters
56*8b26181fSAndroid Build Coastguard Worker 	 * than we need.
57*8b26181fSAndroid Build Coastguard Worker 	 *
58*8b26181fSAndroid Build Coastguard Worker 	 * (The fact that it might happen to work with GNU libc or with
59*8b26181fSAndroid Build Coastguard Worker 	 * various BSD libcs is completely uninteresting, as those tend
60*8b26181fSAndroid Build Coastguard Worker 	 * to have asprintf() already and thus don't even *need* this
61*8b26181fSAndroid Build Coastguard Worker 	 * code; this is for use in those UN*Xes that *don't* have
62*8b26181fSAndroid Build Coastguard Worker 	 * asprintf().)
63*8b26181fSAndroid Build Coastguard Worker 	 */
64*8b26181fSAndroid Build Coastguard Worker 	len = vsnprintf(&buf, sizeof buf, format, args);
65*8b26181fSAndroid Build Coastguard Worker 	if (len == -1) {
66*8b26181fSAndroid Build Coastguard Worker 		*strp = NULL;
67*8b26181fSAndroid Build Coastguard Worker 		return (-1);
68*8b26181fSAndroid Build Coastguard Worker 	}
69*8b26181fSAndroid Build Coastguard Worker 	str_size = len + 1;
70*8b26181fSAndroid Build Coastguard Worker 	str = malloc(str_size);
71*8b26181fSAndroid Build Coastguard Worker 	if (str == NULL) {
72*8b26181fSAndroid Build Coastguard Worker 		*strp = NULL;
73*8b26181fSAndroid Build Coastguard Worker 		return (-1);
74*8b26181fSAndroid Build Coastguard Worker 	}
75*8b26181fSAndroid Build Coastguard Worker 	ret = vsnprintf(str, str_size, format, args);
76*8b26181fSAndroid Build Coastguard Worker 	if (ret == -1) {
77*8b26181fSAndroid Build Coastguard Worker 		free(str);
78*8b26181fSAndroid Build Coastguard Worker 		*strp = NULL;
79*8b26181fSAndroid Build Coastguard Worker 		return (-1);
80*8b26181fSAndroid Build Coastguard Worker 	}
81*8b26181fSAndroid Build Coastguard Worker 	*strp = str;
82*8b26181fSAndroid Build Coastguard Worker 	/*
83*8b26181fSAndroid Build Coastguard Worker 	 * vsnprintf() shouldn't truncate the string, as we have
84*8b26181fSAndroid Build Coastguard Worker 	 * allocated a buffer large enough to hold the string, so its
85*8b26181fSAndroid Build Coastguard Worker 	 * return value should be the number of characters written.
86*8b26181fSAndroid Build Coastguard Worker 	 */
87*8b26181fSAndroid Build Coastguard Worker 	return (ret);
88*8b26181fSAndroid Build Coastguard Worker }
89*8b26181fSAndroid Build Coastguard Worker 
90*8b26181fSAndroid Build Coastguard Worker int
pcap_asprintf(char ** strp,const char * format,...)91*8b26181fSAndroid Build Coastguard Worker pcap_asprintf(char **strp, const char *format, ...)
92*8b26181fSAndroid Build Coastguard Worker {
93*8b26181fSAndroid Build Coastguard Worker 	va_list args;
94*8b26181fSAndroid Build Coastguard Worker 	int ret;
95*8b26181fSAndroid Build Coastguard Worker 
96*8b26181fSAndroid Build Coastguard Worker 	va_start(args, format);
97*8b26181fSAndroid Build Coastguard Worker 	ret = pcap_vasprintf(strp, format, args);
98*8b26181fSAndroid Build Coastguard Worker 	va_end(args);
99*8b26181fSAndroid Build Coastguard Worker 	return (ret);
100*8b26181fSAndroid Build Coastguard Worker }
101*8b26181fSAndroid Build Coastguard Worker 
102