1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*0Sstevel@tonic-gate * Use is subject to license terms.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate #include "volume_string.h"
30*0Sstevel@tonic-gate
31*0Sstevel@tonic-gate #include <ctype.h>
32*0Sstevel@tonic-gate #include <errno.h>
33*0Sstevel@tonic-gate #include <libintl.h>
34*0Sstevel@tonic-gate #include <math.h>
35*0Sstevel@tonic-gate #include <stdarg.h>
36*0Sstevel@tonic-gate #include <stdio.h>
37*0Sstevel@tonic-gate #include <stdlib.h>
38*0Sstevel@tonic-gate #include <string.h>
39*0Sstevel@tonic-gate #include "volume_error.h"
40*0Sstevel@tonic-gate #include "volume_output.h"
41*0Sstevel@tonic-gate
42*0Sstevel@tonic-gate /*
43*0Sstevel@tonic-gate * ******************************************************************
44*0Sstevel@tonic-gate *
45*0Sstevel@tonic-gate * Function prototypes
46*0Sstevel@tonic-gate *
47*0Sstevel@tonic-gate * ******************************************************************
48*0Sstevel@tonic-gate */
49*0Sstevel@tonic-gate
50*0Sstevel@tonic-gate static void *append_to_pointer_array(void **array, void *pointer);
51*0Sstevel@tonic-gate
52*0Sstevel@tonic-gate /*
53*0Sstevel@tonic-gate * ******************************************************************
54*0Sstevel@tonic-gate *
55*0Sstevel@tonic-gate * Data
56*0Sstevel@tonic-gate *
57*0Sstevel@tonic-gate * ******************************************************************
58*0Sstevel@tonic-gate */
59*0Sstevel@tonic-gate
60*0Sstevel@tonic-gate /* All-inclusive valid size units */
61*0Sstevel@tonic-gate units_t universal_units[] = {
62*0Sstevel@tonic-gate {"BLOCKS", BYTES_PER_BLOCK},
63*0Sstevel@tonic-gate {"KB", BYTES_PER_KILOBYTE},
64*0Sstevel@tonic-gate {"MB", BYTES_PER_MEGABYTE},
65*0Sstevel@tonic-gate {"GB", BYTES_PER_GIGABYTE},
66*0Sstevel@tonic-gate {"TB", BYTES_PER_TERABYTE},
67*0Sstevel@tonic-gate {NULL, 0}
68*0Sstevel@tonic-gate };
69*0Sstevel@tonic-gate
70*0Sstevel@tonic-gate /*
71*0Sstevel@tonic-gate * ******************************************************************
72*0Sstevel@tonic-gate *
73*0Sstevel@tonic-gate * External functions
74*0Sstevel@tonic-gate *
75*0Sstevel@tonic-gate * ******************************************************************
76*0Sstevel@tonic-gate */
77*0Sstevel@tonic-gate
78*0Sstevel@tonic-gate /*
79*0Sstevel@tonic-gate * Concatenates a list of strings. The result must be free()d.
80*0Sstevel@tonic-gate *
81*0Sstevel@tonic-gate * @param numargs
82*0Sstevel@tonic-gate * The number of strings to concatenate.
83*0Sstevel@tonic-gate *
84*0Sstevel@tonic-gate * @param ...
85*0Sstevel@tonic-gate * The strings (type char *) to concatenate.
86*0Sstevel@tonic-gate *
87*0Sstevel@tonic-gate * @return the concatenated string
88*0Sstevel@tonic-gate * if succesful
89*0Sstevel@tonic-gate *
90*0Sstevel@tonic-gate * @return NULL
91*0Sstevel@tonic-gate * if memory could not be allocated
92*0Sstevel@tonic-gate */
93*0Sstevel@tonic-gate char *
stralloccat(int numargs,...)94*0Sstevel@tonic-gate stralloccat(
95*0Sstevel@tonic-gate int numargs,
96*0Sstevel@tonic-gate ...)
97*0Sstevel@tonic-gate {
98*0Sstevel@tonic-gate va_list vl;
99*0Sstevel@tonic-gate int i;
100*0Sstevel@tonic-gate int len = 1;
101*0Sstevel@tonic-gate char *cat;
102*0Sstevel@tonic-gate
103*0Sstevel@tonic-gate /* Determine length of concatenated string */
104*0Sstevel@tonic-gate va_start(vl, numargs);
105*0Sstevel@tonic-gate for (i = 0; i < numargs; i++) {
106*0Sstevel@tonic-gate char *str = va_arg(vl, char *);
107*0Sstevel@tonic-gate if (str != NULL) {
108*0Sstevel@tonic-gate len += strlen(str);
109*0Sstevel@tonic-gate }
110*0Sstevel@tonic-gate }
111*0Sstevel@tonic-gate va_end(vl);
112*0Sstevel@tonic-gate
113*0Sstevel@tonic-gate /* Allocate memory for concatenation plus a trailing NULL */
114*0Sstevel@tonic-gate cat = (char *)calloc(1, len * sizeof (char));
115*0Sstevel@tonic-gate
116*0Sstevel@tonic-gate if (cat == NULL) {
117*0Sstevel@tonic-gate return (NULL);
118*0Sstevel@tonic-gate }
119*0Sstevel@tonic-gate
120*0Sstevel@tonic-gate /* Concatenate strings */
121*0Sstevel@tonic-gate va_start(vl, numargs);
122*0Sstevel@tonic-gate for (i = 0; i < numargs; i++) {
123*0Sstevel@tonic-gate char *str = va_arg(vl, char *);
124*0Sstevel@tonic-gate if (str != NULL) {
125*0Sstevel@tonic-gate strcat(cat, str);
126*0Sstevel@tonic-gate }
127*0Sstevel@tonic-gate }
128*0Sstevel@tonic-gate va_end(vl);
129*0Sstevel@tonic-gate
130*0Sstevel@tonic-gate return (cat);
131*0Sstevel@tonic-gate }
132*0Sstevel@tonic-gate
133*0Sstevel@tonic-gate /*
134*0Sstevel@tonic-gate * Convert the given string to a uint16_t, verifying that the value
135*0Sstevel@tonic-gate * does not exceed the lower or upper bounds of a uint16_t.
136*0Sstevel@tonic-gate *
137*0Sstevel@tonic-gate * @param str
138*0Sstevel@tonic-gate * the string to convert
139*0Sstevel@tonic-gate *
140*0Sstevel@tonic-gate * @param num
141*0Sstevel@tonic-gate * the addr of the uint16_t
142*0Sstevel@tonic-gate *
143*0Sstevel@tonic-gate * @return 0
144*0Sstevel@tonic-gate * if the given string was converted to a uint16_t
145*0Sstevel@tonic-gate *
146*0Sstevel@tonic-gate * @return -1
147*0Sstevel@tonic-gate * if the string could could not be converted to a number
148*0Sstevel@tonic-gate *
149*0Sstevel@tonic-gate * @return -2
150*0Sstevel@tonic-gate * if the converted number exceeds the lower or upper
151*0Sstevel@tonic-gate * bounds of a uint16_t
152*0Sstevel@tonic-gate */
153*0Sstevel@tonic-gate int
str_to_uint16(char * str,uint16_t * num)154*0Sstevel@tonic-gate str_to_uint16(
155*0Sstevel@tonic-gate char *str,
156*0Sstevel@tonic-gate uint16_t *num)
157*0Sstevel@tonic-gate {
158*0Sstevel@tonic-gate long long lnum;
159*0Sstevel@tonic-gate int error = 0;
160*0Sstevel@tonic-gate
161*0Sstevel@tonic-gate /* Convert string to long long */
162*0Sstevel@tonic-gate if (sscanf(str, "%lld", &lnum) != 1) {
163*0Sstevel@tonic-gate error = -1;
164*0Sstevel@tonic-gate } else {
165*0Sstevel@tonic-gate
166*0Sstevel@tonic-gate /*
167*0Sstevel@tonic-gate * Verify that the long long value does not exceed the
168*0Sstevel@tonic-gate * lower or upper bounds of a uint16_t
169*0Sstevel@tonic-gate */
170*0Sstevel@tonic-gate
171*0Sstevel@tonic-gate /* Maximum value of uint16_t */
172*0Sstevel@tonic-gate uint16_t max = (uint16_t)~0ULL;
173*0Sstevel@tonic-gate
174*0Sstevel@tonic-gate if (lnum < 0 || lnum > max) {
175*0Sstevel@tonic-gate error = -2;
176*0Sstevel@tonic-gate } else {
177*0Sstevel@tonic-gate *num = lnum;
178*0Sstevel@tonic-gate }
179*0Sstevel@tonic-gate }
180*0Sstevel@tonic-gate
181*0Sstevel@tonic-gate return (error);
182*0Sstevel@tonic-gate }
183*0Sstevel@tonic-gate
184*0Sstevel@tonic-gate /*
185*0Sstevel@tonic-gate * Converts the given long long into a string. This string must be
186*0Sstevel@tonic-gate * freed.
187*0Sstevel@tonic-gate *
188*0Sstevel@tonic-gate * @param num
189*0Sstevel@tonic-gate * the long long to convert
190*0Sstevel@tonic-gate *
191*0Sstevel@tonic-gate * @param str
192*0Sstevel@tonic-gate * the addr of the string
193*0Sstevel@tonic-gate *
194*0Sstevel@tonic-gate * @return 0
195*0Sstevel@tonic-gate * if successful
196*0Sstevel@tonic-gate *
197*0Sstevel@tonic-gate * @return ENOMEM
198*0Sstevel@tonic-gate * if the physical limits of the system are exceeded by
199*0Sstevel@tonic-gate * size bytes of memory which cannot be allocated
200*0Sstevel@tonic-gate *
201*0Sstevel@tonic-gate * @return EAGAIN
202*0Sstevel@tonic-gate * if there is not enough memory available to allocate
203*0Sstevel@tonic-gate * size bytes of memory
204*0Sstevel@tonic-gate */
205*0Sstevel@tonic-gate int
ll_to_str(long long num,char ** str)206*0Sstevel@tonic-gate ll_to_str(
207*0Sstevel@tonic-gate long long num,
208*0Sstevel@tonic-gate char **str)
209*0Sstevel@tonic-gate {
210*0Sstevel@tonic-gate int error = 0;
211*0Sstevel@tonic-gate
212*0Sstevel@tonic-gate /* Allocate memory for the string */
213*0Sstevel@tonic-gate if ((*str = calloc(1, LONG_LONG_STR_SIZE * sizeof (char))) == NULL) {
214*0Sstevel@tonic-gate error = errno;
215*0Sstevel@tonic-gate } else {
216*0Sstevel@tonic-gate /* Convert the integer to a string */
217*0Sstevel@tonic-gate snprintf(*str, LONG_LONG_STR_SIZE, "%lld", num);
218*0Sstevel@tonic-gate }
219*0Sstevel@tonic-gate
220*0Sstevel@tonic-gate return (error);
221*0Sstevel@tonic-gate }
222*0Sstevel@tonic-gate
223*0Sstevel@tonic-gate /*
224*0Sstevel@tonic-gate * Convert a size specification to bytes.
225*0Sstevel@tonic-gate *
226*0Sstevel@tonic-gate * @param str
227*0Sstevel@tonic-gate * a size specification strings of the form
228*0Sstevel@tonic-gate * <value><units>, where valid <units> are specified by
229*0Sstevel@tonic-gate * the units argument and <value> is the (floating-point)
230*0Sstevel@tonic-gate * multiplier of the units
231*0Sstevel@tonic-gate *
232*0Sstevel@tonic-gate * @param bytes
233*0Sstevel@tonic-gate * RETURN: the result of converting the given size string
234*0Sstevel@tonic-gate * to bytes
235*0Sstevel@tonic-gate *
236*0Sstevel@tonic-gate * @return 0
237*0Sstevel@tonic-gate * if successful
238*0Sstevel@tonic-gate *
239*0Sstevel@tonic-gate * @return non-zero
240*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to
241*0Sstevel@tonic-gate * retrieve the associated error message.
242*0Sstevel@tonic-gate */
243*0Sstevel@tonic-gate int
sizestr_to_bytes(char * str,uint64_t * bytes,units_t units[])244*0Sstevel@tonic-gate sizestr_to_bytes(
245*0Sstevel@tonic-gate char *str,
246*0Sstevel@tonic-gate uint64_t *bytes,
247*0Sstevel@tonic-gate units_t units[])
248*0Sstevel@tonic-gate {
249*0Sstevel@tonic-gate char *unit_str;
250*0Sstevel@tonic-gate long double d;
251*0Sstevel@tonic-gate int error = 0;
252*0Sstevel@tonic-gate int i;
253*0Sstevel@tonic-gate
254*0Sstevel@tonic-gate /* Convert <value> string to double */
255*0Sstevel@tonic-gate if ((d = strtod(str, &unit_str)) == 0) {
256*0Sstevel@tonic-gate volume_set_error(gettext("invalid size string: %s"), str);
257*0Sstevel@tonic-gate error = -1;
258*0Sstevel@tonic-gate } else {
259*0Sstevel@tonic-gate
260*0Sstevel@tonic-gate /* Trim leading white space */
261*0Sstevel@tonic-gate while (isspace(*unit_str) != 0) {
262*0Sstevel@tonic-gate ++unit_str;
263*0Sstevel@tonic-gate }
264*0Sstevel@tonic-gate
265*0Sstevel@tonic-gate /* Convert to bytes based on <units> */
266*0Sstevel@tonic-gate for (i = 0; units[i].unit_str != NULL; i++) {
267*0Sstevel@tonic-gate if (strcasecmp(unit_str, units[i].unit_str) == 0) {
268*0Sstevel@tonic-gate d *= units[i].bytes_per_unit;
269*0Sstevel@tonic-gate break;
270*0Sstevel@tonic-gate }
271*0Sstevel@tonic-gate }
272*0Sstevel@tonic-gate
273*0Sstevel@tonic-gate /* Was a valid unit string found? */
274*0Sstevel@tonic-gate if (units[i].unit_str == NULL) {
275*0Sstevel@tonic-gate volume_set_error(
276*0Sstevel@tonic-gate gettext("missing or invalid units indicator in size: %s"),
277*0Sstevel@tonic-gate str);
278*0Sstevel@tonic-gate error = -1;
279*0Sstevel@tonic-gate }
280*0Sstevel@tonic-gate }
281*0Sstevel@tonic-gate
282*0Sstevel@tonic-gate if (error) {
283*0Sstevel@tonic-gate *bytes = 0;
284*0Sstevel@tonic-gate } else {
285*0Sstevel@tonic-gate *bytes = (uint64_t)d;
286*0Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
287*0Sstevel@tonic-gate gettext("converted \"%s\" to %llu bytes\n"), str, *bytes);
288*0Sstevel@tonic-gate }
289*0Sstevel@tonic-gate
290*0Sstevel@tonic-gate return (error);
291*0Sstevel@tonic-gate }
292*0Sstevel@tonic-gate
293*0Sstevel@tonic-gate /*
294*0Sstevel@tonic-gate * Convert bytes to a size specification string.
295*0Sstevel@tonic-gate *
296*0Sstevel@tonic-gate * @param bytes
297*0Sstevel@tonic-gate * the number of bytes
298*0Sstevel@tonic-gate *
299*0Sstevel@tonic-gate * @param str
300*0Sstevel@tonic-gate * RETURN: a size specification strings of the form
301*0Sstevel@tonic-gate * <value><units>, where valid <units> are specified by
302*0Sstevel@tonic-gate * the units argument and <value> is the (floating-point)
303*0Sstevel@tonic-gate * multiplier of the units. This string must be freed.
304*0Sstevel@tonic-gate *
305*0Sstevel@tonic-gate * @return 0
306*0Sstevel@tonic-gate * if successful
307*0Sstevel@tonic-gate *
308*0Sstevel@tonic-gate * @return non-zero
309*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to
310*0Sstevel@tonic-gate * retrieve the associated error message.
311*0Sstevel@tonic-gate */
312*0Sstevel@tonic-gate int
bytes_to_sizestr(uint64_t bytes,char ** str,units_t units[],boolean_t round)313*0Sstevel@tonic-gate bytes_to_sizestr(
314*0Sstevel@tonic-gate uint64_t bytes,
315*0Sstevel@tonic-gate char **str,
316*0Sstevel@tonic-gate units_t units[],
317*0Sstevel@tonic-gate boolean_t round)
318*0Sstevel@tonic-gate {
319*0Sstevel@tonic-gate int i, len, error = 0;
320*0Sstevel@tonic-gate double value;
321*0Sstevel@tonic-gate const char *format;
322*0Sstevel@tonic-gate units_t use_units = units[0];
323*0Sstevel@tonic-gate
324*0Sstevel@tonic-gate /* Determine the units to use */
325*0Sstevel@tonic-gate for (i = 0; units[i].unit_str != NULL; i++) {
326*0Sstevel@tonic-gate if (bytes >= units[i].bytes_per_unit) {
327*0Sstevel@tonic-gate use_units = units[i];
328*0Sstevel@tonic-gate }
329*0Sstevel@tonic-gate }
330*0Sstevel@tonic-gate
331*0Sstevel@tonic-gate value = ((long double)bytes / use_units.bytes_per_unit);
332*0Sstevel@tonic-gate
333*0Sstevel@tonic-gate /* Length of string plus trailing NULL */
334*0Sstevel@tonic-gate len = LONG_LONG_STR_SIZE + strlen(use_units.unit_str) + 1;
335*0Sstevel@tonic-gate
336*0Sstevel@tonic-gate if (round) {
337*0Sstevel@tonic-gate value = floor(value + 0.5F);
338*0Sstevel@tonic-gate format = "%.0f%s";
339*0Sstevel@tonic-gate } else {
340*0Sstevel@tonic-gate format = "%.2f%s";
341*0Sstevel@tonic-gate }
342*0Sstevel@tonic-gate
343*0Sstevel@tonic-gate /* Append units to string */
344*0Sstevel@tonic-gate *str = calloc(1, len * sizeof (char));
345*0Sstevel@tonic-gate if (*str == NULL) {
346*0Sstevel@tonic-gate error = errno;
347*0Sstevel@tonic-gate } else {
348*0Sstevel@tonic-gate snprintf(*str, len, format, value, use_units.unit_str);
349*0Sstevel@tonic-gate }
350*0Sstevel@tonic-gate
351*0Sstevel@tonic-gate return (error);
352*0Sstevel@tonic-gate }
353*0Sstevel@tonic-gate
354*0Sstevel@tonic-gate /*
355*0Sstevel@tonic-gate * Appends a copy of the given string to the given string array,
356*0Sstevel@tonic-gate * ensuring that the last element in the array is NULL. This array
357*0Sstevel@tonic-gate * must be freed via free_string_array.
358*0Sstevel@tonic-gate *
359*0Sstevel@tonic-gate * Note when an error occurs and NULL is returned, array is not freed.
360*0Sstevel@tonic-gate * Subsequently callers should save a pointer to the original array
361*0Sstevel@tonic-gate * until success is verified.
362*0Sstevel@tonic-gate *
363*0Sstevel@tonic-gate * @param array
364*0Sstevel@tonic-gate * the array to append to, or NULL to create a new array
365*0Sstevel@tonic-gate *
366*0Sstevel@tonic-gate * @param str
367*0Sstevel@tonic-gate * the string to copy and add to the array
368*0Sstevel@tonic-gate *
369*0Sstevel@tonic-gate * @return a pointer to the realloc'd (and possibly moved) array
370*0Sstevel@tonic-gate * if succesful
371*0Sstevel@tonic-gate *
372*0Sstevel@tonic-gate * @return NULL
373*0Sstevel@tonic-gate * if unsuccesful
374*0Sstevel@tonic-gate */
375*0Sstevel@tonic-gate char **
append_to_string_array(char ** array,char * str)376*0Sstevel@tonic-gate append_to_string_array(
377*0Sstevel@tonic-gate char **array,
378*0Sstevel@tonic-gate char *str)
379*0Sstevel@tonic-gate {
380*0Sstevel@tonic-gate char *copy = strdup(str);
381*0Sstevel@tonic-gate
382*0Sstevel@tonic-gate if (copy == NULL) {
383*0Sstevel@tonic-gate return (NULL);
384*0Sstevel@tonic-gate }
385*0Sstevel@tonic-gate
386*0Sstevel@tonic-gate return ((char **)append_to_pointer_array((void **)array, copy));
387*0Sstevel@tonic-gate }
388*0Sstevel@tonic-gate
389*0Sstevel@tonic-gate /*
390*0Sstevel@tonic-gate * Frees each element of the given string array, then frees the array
391*0Sstevel@tonic-gate * itself.
392*0Sstevel@tonic-gate *
393*0Sstevel@tonic-gate * @param array
394*0Sstevel@tonic-gate * a NULL-terminated string array
395*0Sstevel@tonic-gate */
396*0Sstevel@tonic-gate void
free_string_array(char ** array)397*0Sstevel@tonic-gate free_string_array(
398*0Sstevel@tonic-gate char **array)
399*0Sstevel@tonic-gate {
400*0Sstevel@tonic-gate int i;
401*0Sstevel@tonic-gate
402*0Sstevel@tonic-gate /* Free each available element */
403*0Sstevel@tonic-gate for (i = 0; array[i] != NULL; i++) {
404*0Sstevel@tonic-gate free(array[i]);
405*0Sstevel@tonic-gate }
406*0Sstevel@tonic-gate
407*0Sstevel@tonic-gate /* Free the array itself */
408*0Sstevel@tonic-gate free((void *)array);
409*0Sstevel@tonic-gate }
410*0Sstevel@tonic-gate
411*0Sstevel@tonic-gate /*
412*0Sstevel@tonic-gate * ******************************************************************
413*0Sstevel@tonic-gate *
414*0Sstevel@tonic-gate * Static functions
415*0Sstevel@tonic-gate *
416*0Sstevel@tonic-gate * ******************************************************************
417*0Sstevel@tonic-gate */
418*0Sstevel@tonic-gate
419*0Sstevel@tonic-gate /*
420*0Sstevel@tonic-gate * Appends the given pointer to the given pointer array, ensuring that
421*0Sstevel@tonic-gate * the last element in the array is NULL.
422*0Sstevel@tonic-gate *
423*0Sstevel@tonic-gate * Note when an error occurs and NULL is returned, array is not freed.
424*0Sstevel@tonic-gate * Subsequently callers should save a pointer to the original array
425*0Sstevel@tonic-gate * until success is verified.
426*0Sstevel@tonic-gate *
427*0Sstevel@tonic-gate * @param array
428*0Sstevel@tonic-gate * the array to append to, or NULL to create a new array
429*0Sstevel@tonic-gate *
430*0Sstevel@tonic-gate * @param pointer
431*0Sstevel@tonic-gate * the pointer to add to the array
432*0Sstevel@tonic-gate *
433*0Sstevel@tonic-gate * @return a pointer to the realloc'd (and possibly moved) array
434*0Sstevel@tonic-gate * if succesful
435*0Sstevel@tonic-gate *
436*0Sstevel@tonic-gate * @return NULL
437*0Sstevel@tonic-gate * if unsuccesful
438*0Sstevel@tonic-gate */
439*0Sstevel@tonic-gate static void *
append_to_pointer_array(void ** array,void * pointer)440*0Sstevel@tonic-gate append_to_pointer_array(
441*0Sstevel@tonic-gate void **array,
442*0Sstevel@tonic-gate void *pointer)
443*0Sstevel@tonic-gate {
444*0Sstevel@tonic-gate void **newarray = NULL;
445*0Sstevel@tonic-gate int i = 0;
446*0Sstevel@tonic-gate
447*0Sstevel@tonic-gate if (array != NULL) {
448*0Sstevel@tonic-gate /* Count the elements currently in the array */
449*0Sstevel@tonic-gate for (i = 0; array[i] != NULL; ++i);
450*0Sstevel@tonic-gate }
451*0Sstevel@tonic-gate
452*0Sstevel@tonic-gate /* realloc, adding a slot for the new pointer */
453*0Sstevel@tonic-gate newarray = (void **)realloc(array, (i + 2) * sizeof (*array));
454*0Sstevel@tonic-gate
455*0Sstevel@tonic-gate if (newarray != NULL) {
456*0Sstevel@tonic-gate /* Append pointer and terminal NULL */
457*0Sstevel@tonic-gate newarray[i] = pointer;
458*0Sstevel@tonic-gate newarray[i+1] = NULL;
459*0Sstevel@tonic-gate }
460*0Sstevel@tonic-gate
461*0Sstevel@tonic-gate return (newarray);
462*0Sstevel@tonic-gate }
463