xref: /titanic_51/usr/src/lib/libpkg/common/pkgstr.c (revision 5c51f1241dbbdf2656d0e10011981411ed0c9673)
1*5c51f124SMoriah Waterland /*
2*5c51f124SMoriah Waterland  * CDDL HEADER START
3*5c51f124SMoriah Waterland  *
4*5c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
5*5c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
6*5c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
7*5c51f124SMoriah Waterland  *
8*5c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
10*5c51f124SMoriah Waterland  * See the License for the specific language governing permissions
11*5c51f124SMoriah Waterland  * and limitations under the License.
12*5c51f124SMoriah Waterland  *
13*5c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
14*5c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
16*5c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
17*5c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5c51f124SMoriah Waterland  *
19*5c51f124SMoriah Waterland  * CDDL HEADER END
20*5c51f124SMoriah Waterland  */
21*5c51f124SMoriah Waterland 
22*5c51f124SMoriah Waterland /*
23*5c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24*5c51f124SMoriah Waterland  * Use is subject to license terms.
25*5c51f124SMoriah Waterland  */
26*5c51f124SMoriah Waterland 
27*5c51f124SMoriah Waterland 
28*5c51f124SMoriah Waterland /*
29*5c51f124SMoriah Waterland  * Module:	pkgstr.c
30*5c51f124SMoriah Waterland  * Synopsis:	general string services
31*5c51f124SMoriah Waterland  * Taxonomy:	project private
32*5c51f124SMoriah Waterland  * Debug Flag:	str
33*5c51f124SMoriah Waterland  * Description:
34*5c51f124SMoriah Waterland  *
35*5c51f124SMoriah Waterland  *   This module implements general string utility services
36*5c51f124SMoriah Waterland  *
37*5c51f124SMoriah Waterland  * Public Methods:
38*5c51f124SMoriah Waterland  *
39*5c51f124SMoriah Waterland  *   pkgstrAddToken - Add a token to a string
40*5c51f124SMoriah Waterland  *   pkgstrContainsToken - Determine if a string contains a specified token
41*5c51f124SMoriah Waterland  *   pkgstrConvertPathToBasename - Return copy of base name in path string
42*5c51f124SMoriah Waterland  *   pkgstrConvertPathToDirname - Return copy of directory name in path string
43*5c51f124SMoriah Waterland  *   pkgstrConvertUllToTimeString_r - convert unsigned long long to time string
44*5c51f124SMoriah Waterland  *   pkgstrExpandTokens - Expand tokens from string appending tokens to another
45*5c51f124SMoriah Waterland  *   pkgstrGetToken - Get a token from a string
46*5c51f124SMoriah Waterland  *   pkgstrGetToken_r - Get a token from a string into a fixed buffer
47*5c51f124SMoriah Waterland  *   pkgstrLocatePathBasename - Locate position of base name in path string
48*5c51f124SMoriah Waterland  *   pkgstrNumTokens - Determine number of tokens in string
49*5c51f124SMoriah Waterland  *   pkgstrPrintf - Create a string from a printf style format and arguments
50*5c51f124SMoriah Waterland  *   pkgstrPrintf_r - Create a string from a printf style format and arguments
51*5c51f124SMoriah Waterland  *			into a fixed buffer
52*5c51f124SMoriah Waterland  *   pkgstrRemoveToken - Remove a token from a string
53*5c51f124SMoriah Waterland  *   pkgstrRemoveLeadingWhitespace - remove leading whitespace from string
54*5c51f124SMoriah Waterland  *   pkgstrScaleNumericString - Convert unsigned long long to human
55*5c51f124SMoriah Waterland  *	readable form
56*5c51f124SMoriah Waterland  */
57*5c51f124SMoriah Waterland 
58*5c51f124SMoriah Waterland /*
59*5c51f124SMoriah Waterland  * Unix Includes
60*5c51f124SMoriah Waterland  */
61*5c51f124SMoriah Waterland 
62*5c51f124SMoriah Waterland #define	__EXTENSIONS__
63*5c51f124SMoriah Waterland 
64*5c51f124SMoriah Waterland #include <stdio.h>
65*5c51f124SMoriah Waterland #include <stdlib.h>
66*5c51f124SMoriah Waterland #include <string.h>
67*5c51f124SMoriah Waterland #include <libintl.h>
68*5c51f124SMoriah Waterland #include <limits.h>
69*5c51f124SMoriah Waterland #include <sys/types.h>
70*5c51f124SMoriah Waterland #include <assert.h>
71*5c51f124SMoriah Waterland #include <errno.h>
72*5c51f124SMoriah Waterland #include <libintl.h>
73*5c51f124SMoriah Waterland #include <ctype.h>
74*5c51f124SMoriah Waterland #include <unistd.h>
75*5c51f124SMoriah Waterland #include <strings.h>
76*5c51f124SMoriah Waterland #include <stdarg.h>
77*5c51f124SMoriah Waterland 
78*5c51f124SMoriah Waterland /*
79*5c51f124SMoriah Waterland  * pkglib Includes
80*5c51f124SMoriah Waterland  */
81*5c51f124SMoriah Waterland 
82*5c51f124SMoriah Waterland #include "pkglib.h"
83*5c51f124SMoriah Waterland #include "pkgstrct.h"
84*5c51f124SMoriah Waterland #include "libintl.h"
85*5c51f124SMoriah Waterland #include "pkglocale.h"
86*5c51f124SMoriah Waterland 
87*5c51f124SMoriah Waterland /*
88*5c51f124SMoriah Waterland  * External definitions
89*5c51f124SMoriah Waterland  */
90*5c51f124SMoriah Waterland 
91*5c51f124SMoriah Waterland /*
92*5c51f124SMoriah Waterland  * Public methods
93*5c51f124SMoriah Waterland  */
94*5c51f124SMoriah Waterland 
95*5c51f124SMoriah Waterland /*
96*5c51f124SMoriah Waterland  * Name:	pkgstrRemoveLeadingWhitespace
97*5c51f124SMoriah Waterland  * Synopsis:	Remove leading whitespace from string
98*5c51f124SMoriah Waterland  * Description:	Remove all leading whitespace characters from a string
99*5c51f124SMoriah Waterland  * Arguments:	a_str - [RO, *RW] - (char **)
100*5c51f124SMoriah Waterland  *			Pointer to handle to string (in allocated storage) to
101*5c51f124SMoriah Waterland  *			remove all leading whitespace from
102*5c51f124SMoriah Waterland  * Returns:	void
103*5c51f124SMoriah Waterland  *			The input string is modified as follows:
104*5c51f124SMoriah Waterland  *			== (char *)NULL:
105*5c51f124SMoriah Waterland  *				- input string was (char *)NULL
106*5c51f124SMoriah Waterland  *				- input string is all whitespace
107*5c51f124SMoriah Waterland  *			!= (char *)NULL:
108*5c51f124SMoriah Waterland  *				- copy of input string with leading
109*5c51f124SMoriah Waterland  *				  whitespace removed
110*5c51f124SMoriah Waterland  * CAUTION:	The input string must be allocated space (via mem* or
111*5c51f124SMoriah Waterland  *		pkgstr* methods) - it must not be a static or inline
112*5c51f124SMoriah Waterland  *		character string
113*5c51f124SMoriah Waterland  * NOTE:	The input string a_str will be freed with 'free'
114*5c51f124SMoriah Waterland  *		if it is all whitespace, or if it contains any leading
115*5c51f124SMoriah Waterland  *		whitespace characters
116*5c51f124SMoriah Waterland  * NOTE:    	Any string returned is placed in new storage for the
117*5c51f124SMoriah Waterland  *		calling method. The caller must use 'free' to dispose
118*5c51f124SMoriah Waterland  *		of the storage once the string is no longer needed.
119*5c51f124SMoriah Waterland  * Errors:	If the string cannot be created, the process exits
120*5c51f124SMoriah Waterland  */
121*5c51f124SMoriah Waterland 
122*5c51f124SMoriah Waterland void
123*5c51f124SMoriah Waterland pkgstrRemoveLeadingWhitespace(char **a_str)
124*5c51f124SMoriah Waterland {
125*5c51f124SMoriah Waterland 	char	*o_str;
126*5c51f124SMoriah Waterland 
127*5c51f124SMoriah Waterland 	/* entry assertions */
128*5c51f124SMoriah Waterland 
129*5c51f124SMoriah Waterland 	assert(a_str != (char **)NULL);
130*5c51f124SMoriah Waterland 
131*5c51f124SMoriah Waterland 	/* if string is null, just return */
132*5c51f124SMoriah Waterland 
133*5c51f124SMoriah Waterland 	if (*a_str == (char *)NULL) {
134*5c51f124SMoriah Waterland 		return;
135*5c51f124SMoriah Waterland 	}
136*5c51f124SMoriah Waterland 	o_str = *a_str;
137*5c51f124SMoriah Waterland 
138*5c51f124SMoriah Waterland 	/* if string is empty, deallocate and return NULL */
139*5c51f124SMoriah Waterland 
140*5c51f124SMoriah Waterland 	if (*o_str == '\0') {
141*5c51f124SMoriah Waterland 		/* free string - handle is reset to NULL by free */
142*5c51f124SMoriah Waterland 		free(*a_str);
143*5c51f124SMoriah Waterland 		*a_str = (char *)NULL;
144*5c51f124SMoriah Waterland 		return;
145*5c51f124SMoriah Waterland 	}
146*5c51f124SMoriah Waterland 
147*5c51f124SMoriah Waterland 	/* if first character is not a space, just return */
148*5c51f124SMoriah Waterland 
149*5c51f124SMoriah Waterland 	if (!isspace(*o_str)) {
150*5c51f124SMoriah Waterland 		return;
151*5c51f124SMoriah Waterland 	}
152*5c51f124SMoriah Waterland 
153*5c51f124SMoriah Waterland 	/* advance past all space characters */
154*5c51f124SMoriah Waterland 
155*5c51f124SMoriah Waterland 	while ((*o_str != '\0') && (isspace(*o_str))) {
156*5c51f124SMoriah Waterland 		o_str++;
157*5c51f124SMoriah Waterland 	}
158*5c51f124SMoriah Waterland 
159*5c51f124SMoriah Waterland 	/* if string was all space characters, deallocate and return NULL */
160*5c51f124SMoriah Waterland 
161*5c51f124SMoriah Waterland 	if (*o_str == '\0') {
162*5c51f124SMoriah Waterland 		/* free string - *a_str is reset to NULL by free */
163*5c51f124SMoriah Waterland 		free(*a_str);
164*5c51f124SMoriah Waterland 		*a_str = (char *)NULL;
165*5c51f124SMoriah Waterland 		return;
166*5c51f124SMoriah Waterland 	}
167*5c51f124SMoriah Waterland 
168*5c51f124SMoriah Waterland 	/* have non-space/null byte, return dup, deallocate original */
169*5c51f124SMoriah Waterland 
170*5c51f124SMoriah Waterland 	o_str = strdup(o_str);
171*5c51f124SMoriah Waterland 	assert(o_str != (char *)NULL);
172*5c51f124SMoriah Waterland 	if (o_str != (char *)NULL) {
173*5c51f124SMoriah Waterland 		free(*a_str);
174*5c51f124SMoriah Waterland 		*a_str = o_str;
175*5c51f124SMoriah Waterland 	}
176*5c51f124SMoriah Waterland }
177*5c51f124SMoriah Waterland 
178*5c51f124SMoriah Waterland unsigned long
179*5c51f124SMoriah Waterland pkgstrNumTokens(char *a_string, char *a_separators)
180*5c51f124SMoriah Waterland {
181*5c51f124SMoriah Waterland 	int	index;
182*5c51f124SMoriah Waterland 
183*5c51f124SMoriah Waterland 	if (a_string == (char *)NULL) {
184*5c51f124SMoriah Waterland 		return (0);
185*5c51f124SMoriah Waterland 	}
186*5c51f124SMoriah Waterland 
187*5c51f124SMoriah Waterland 	if (*a_string == '\0') {
188*5c51f124SMoriah Waterland 		return (0);
189*5c51f124SMoriah Waterland 	}
190*5c51f124SMoriah Waterland 
191*5c51f124SMoriah Waterland 	for (index = 0 ; ; index ++) {
192*5c51f124SMoriah Waterland 		char *p;
193*5c51f124SMoriah Waterland 
194*5c51f124SMoriah Waterland 		p = pkgstrGetToken((char *)NULL, a_string, index, a_separators);
195*5c51f124SMoriah Waterland 		if (p == (char *)NULL) {
196*5c51f124SMoriah Waterland 			return (index);
197*5c51f124SMoriah Waterland 		}
198*5c51f124SMoriah Waterland 		free(p);
199*5c51f124SMoriah Waterland 	}
200*5c51f124SMoriah Waterland }
201*5c51f124SMoriah Waterland 
202*5c51f124SMoriah Waterland /*
203*5c51f124SMoriah Waterland  * Name:	pkgstrPrintf_r
204*5c51f124SMoriah Waterland  * Synopsis:	Create string from printf style format and arguments
205*5c51f124SMoriah Waterland  * Description:	Call to convert a printf style format and arguments into a
206*5c51f124SMoriah Waterland  *		string of characters placed in allocated storage
207*5c51f124SMoriah Waterland  * Arguments:	a_buf - [RO, *RW] - (char *)
208*5c51f124SMoriah Waterland  *			- Pointer to buffer used as storage space for the
209*5c51f124SMoriah Waterland  *			  returned string created
210*5c51f124SMoriah Waterland  *		a_bufLen - [RO, *RO] - (int)
211*5c51f124SMoriah Waterland  *			- Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1'
212*5c51f124SMoriah Waterland  *			  bytes will be placed in 'a_buf' - the returned
213*5c51f124SMoriah Waterland  *			  string is always null terminated
214*5c51f124SMoriah Waterland  *		a_format - [RO, RO*] (char *)
215*5c51f124SMoriah Waterland  *			printf-style format for string to be formatted
216*5c51f124SMoriah Waterland  *		VARG_LIST - [RO] (?)
217*5c51f124SMoriah Waterland  *			arguments as appropriate to 'format' specified
218*5c51f124SMoriah Waterland  * Returns:	void
219*5c51f124SMoriah Waterland  */
220*5c51f124SMoriah Waterland 
221*5c51f124SMoriah Waterland /*PRINTFLIKE3*/
222*5c51f124SMoriah Waterland void
223*5c51f124SMoriah Waterland pkgstrPrintf_r(char *a_buf, int a_bufLen, char *a_format, ...)
224*5c51f124SMoriah Waterland {
225*5c51f124SMoriah Waterland 	va_list		ap;
226*5c51f124SMoriah Waterland 	size_t		vres = 0;
227*5c51f124SMoriah Waterland 
228*5c51f124SMoriah Waterland 	/* entry assertions */
229*5c51f124SMoriah Waterland 
230*5c51f124SMoriah Waterland 	assert(a_format != (char *)NULL);
231*5c51f124SMoriah Waterland 	assert(*a_format != '\0');
232*5c51f124SMoriah Waterland 	assert(a_buf != (char *)NULL);
233*5c51f124SMoriah Waterland 	assert(a_bufLen > 1);
234*5c51f124SMoriah Waterland 
235*5c51f124SMoriah Waterland 	/* generate the results of the printf conversion */
236*5c51f124SMoriah Waterland 
237*5c51f124SMoriah Waterland 	va_start(ap, a_format);
238*5c51f124SMoriah Waterland 	vres = vsnprintf(a_buf, a_bufLen-1, a_format, ap);
239*5c51f124SMoriah Waterland 	va_end(ap);
240*5c51f124SMoriah Waterland 
241*5c51f124SMoriah Waterland 	assert(vres > 0);
242*5c51f124SMoriah Waterland 	assert(vres < a_bufLen);
243*5c51f124SMoriah Waterland 
244*5c51f124SMoriah Waterland 	a_buf[a_bufLen-1] = '\0';
245*5c51f124SMoriah Waterland }
246*5c51f124SMoriah Waterland 
247*5c51f124SMoriah Waterland /*
248*5c51f124SMoriah Waterland  * Name:	pkgstrPrintf
249*5c51f124SMoriah Waterland  * Synopsis:	Create string from printf style format and arguments
250*5c51f124SMoriah Waterland  * Description:	Call to convert a printf style format and arguments into a
251*5c51f124SMoriah Waterland  *		string of characters placed in allocated storage
252*5c51f124SMoriah Waterland  * Arguments:	format - [RO, RO*] (char *)
253*5c51f124SMoriah Waterland  *			printf-style format for string to be formatted
254*5c51f124SMoriah Waterland  *		VARG_LIST - [RO] (?)
255*5c51f124SMoriah Waterland  *			arguments as appropriate to 'format' specified
256*5c51f124SMoriah Waterland  * Returns:	char *
257*5c51f124SMoriah Waterland  *			A string representing the printf conversion results
258*5c51f124SMoriah Waterland  * NOTE:    	Any string returned is placed in new storage for the
259*5c51f124SMoriah Waterland  *		calling method. The caller must use 'free' to dispose
260*5c51f124SMoriah Waterland  *		of the storage once the string is no longer needed.
261*5c51f124SMoriah Waterland  * Errors:	If the string cannot be created, the process exits
262*5c51f124SMoriah Waterland  */
263*5c51f124SMoriah Waterland 
264*5c51f124SMoriah Waterland /*PRINTFLIKE1*/
265*5c51f124SMoriah Waterland char *
266*5c51f124SMoriah Waterland pkgstrPrintf(char *a_format, ...)
267*5c51f124SMoriah Waterland {
268*5c51f124SMoriah Waterland 	va_list		ap;
269*5c51f124SMoriah Waterland 	size_t		vres = 0;
270*5c51f124SMoriah Waterland 	char		bfr[1];
271*5c51f124SMoriah Waterland 	char		*rstr = (char *)NULL;
272*5c51f124SMoriah Waterland 
273*5c51f124SMoriah Waterland 	/* entry assertions */
274*5c51f124SMoriah Waterland 
275*5c51f124SMoriah Waterland 	assert(a_format != (char *)NULL);
276*5c51f124SMoriah Waterland 	assert(*a_format != '\0');
277*5c51f124SMoriah Waterland 
278*5c51f124SMoriah Waterland 	/* determine size of the message in bytes */
279*5c51f124SMoriah Waterland 
280*5c51f124SMoriah Waterland 	va_start(ap, a_format);
281*5c51f124SMoriah Waterland 	vres = vsnprintf(bfr, 1, a_format, ap);
282*5c51f124SMoriah Waterland 	va_end(ap);
283*5c51f124SMoriah Waterland 
284*5c51f124SMoriah Waterland 	assert(vres > 0);
285*5c51f124SMoriah Waterland 	assert(vres < LINE_MAX);
286*5c51f124SMoriah Waterland 
287*5c51f124SMoriah Waterland 	/* allocate storage to hold the message */
288*5c51f124SMoriah Waterland 
289*5c51f124SMoriah Waterland 	rstr = (char *)calloc(1, vres+2);
290*5c51f124SMoriah Waterland 	assert(rstr != (char *)NULL);
291*5c51f124SMoriah Waterland 	if (rstr == (char *)NULL) {
292*5c51f124SMoriah Waterland 		return ((char *)NULL);
293*5c51f124SMoriah Waterland 	}
294*5c51f124SMoriah Waterland 
295*5c51f124SMoriah Waterland 	/* generate the results of the printf conversion */
296*5c51f124SMoriah Waterland 
297*5c51f124SMoriah Waterland 	va_start(ap, a_format);
298*5c51f124SMoriah Waterland 	vres = vsnprintf(rstr, vres+1, a_format, ap);
299*5c51f124SMoriah Waterland 	va_end(ap);
300*5c51f124SMoriah Waterland 
301*5c51f124SMoriah Waterland 	assert(vres > 0);
302*5c51f124SMoriah Waterland 	assert(vres < LINE_MAX);
303*5c51f124SMoriah Waterland 	assert(*rstr != '\0');
304*5c51f124SMoriah Waterland 
305*5c51f124SMoriah Waterland 	/* return the results */
306*5c51f124SMoriah Waterland 
307*5c51f124SMoriah Waterland 	return (rstr);
308*5c51f124SMoriah Waterland }
309*5c51f124SMoriah Waterland 
310*5c51f124SMoriah Waterland /*
311*5c51f124SMoriah Waterland  * Name:	pkgstrExpandTokens
312*5c51f124SMoriah Waterland  * Synopsis:	Expand tokens from string appending tokens to another
313*5c51f124SMoriah Waterland  * Description:	Given a string and a list of one or more separators,
314*5c51f124SMoriah Waterland  *		expand each token from the string and append those tokens
315*5c51f124SMoriah Waterland  *		to a string that is in allocated space - create new string
316*5c51f124SMoriah Waterland  *		if no string to append to exists.
317*5c51f124SMoriah Waterland  * Arguments:	a_old - [RO, *RW] - (char **)
318*5c51f124SMoriah Waterland  *			- Pointer to handle to string to append token to
319*5c51f124SMoriah Waterland  *			  == (char *)NULL - new string is created
320*5c51f124SMoriah Waterland  *		a_separator - [RO, *RO] - (char *)
321*5c51f124SMoriah Waterland  *			- separator to end tokens returned
322*5c51f124SMoriah Waterland  *		a_separators - [RO, *RO] - (char *)
323*5c51f124SMoriah Waterland  *			- String containing one or more characters that
324*5c51f124SMoriah Waterland  *			  can separate one "token" from a_string from another
325*5c51f124SMoriah Waterland  * Returns:	void
326*5c51f124SMoriah Waterland  * NOTE:    	Any token string returned is placed in new storage for the
327*5c51f124SMoriah Waterland  *		calling method. The caller must use 'free' to dispose
328*5c51f124SMoriah Waterland  *		of the storage once the token string is no longer needed.
329*5c51f124SMoriah Waterland  */
330*5c51f124SMoriah Waterland 
331*5c51f124SMoriah Waterland void
332*5c51f124SMoriah Waterland pkgstrExpandTokens(char **a_old, char *a_string, char a_separator,
333*5c51f124SMoriah Waterland 	char *a_separators)
334*5c51f124SMoriah Waterland {
335*5c51f124SMoriah Waterland 	int		i;
336*5c51f124SMoriah Waterland 	char		sep[2] = {'\0', '\0'};
337*5c51f124SMoriah Waterland 
338*5c51f124SMoriah Waterland 	/* convert single separator character into character string */
339*5c51f124SMoriah Waterland 
340*5c51f124SMoriah Waterland 	sep[0] = a_separator;
341*5c51f124SMoriah Waterland 
342*5c51f124SMoriah Waterland 	/*
343*5c51f124SMoriah Waterland 	 * iterate extracting tokens from the source string and adding
344*5c51f124SMoriah Waterland 	 * those tokens to the target string when the tokens are not
345*5c51f124SMoriah Waterland 	 * already present in the target string
346*5c51f124SMoriah Waterland 	 */
347*5c51f124SMoriah Waterland 
348*5c51f124SMoriah Waterland 	for (i = 0; ; i++) {
349*5c51f124SMoriah Waterland 		char	*p;
350*5c51f124SMoriah Waterland 
351*5c51f124SMoriah Waterland 		/* extract the next matching token from the source string */
352*5c51f124SMoriah Waterland 
353*5c51f124SMoriah Waterland 		p = pkgstrGetToken((char *)NULL, a_string, i, a_separators);
354*5c51f124SMoriah Waterland 
355*5c51f124SMoriah Waterland 		/* return if no token is available */
356*5c51f124SMoriah Waterland 
357*5c51f124SMoriah Waterland 		if (p == (char *)NULL) {
358*5c51f124SMoriah Waterland 			return;
359*5c51f124SMoriah Waterland 		}
360*5c51f124SMoriah Waterland 
361*5c51f124SMoriah Waterland 		/*
362*5c51f124SMoriah Waterland 		 * obtained token from source string: if the token is not
363*5c51f124SMoriah Waterland 		 * in the target string, add the token to the target string
364*5c51f124SMoriah Waterland 		 */
365*5c51f124SMoriah Waterland 
366*5c51f124SMoriah Waterland 		if (pkgstrContainsToken(*a_old, p, sep) == B_FALSE) {
367*5c51f124SMoriah Waterland 			pkgstrAddToken(a_old, p, *sep);
368*5c51f124SMoriah Waterland 		}
369*5c51f124SMoriah Waterland 
370*5c51f124SMoriah Waterland 		/* free up temporary storage used by token from source string */
371*5c51f124SMoriah Waterland 
372*5c51f124SMoriah Waterland 		free(p);
373*5c51f124SMoriah Waterland 	}
374*5c51f124SMoriah Waterland 	/*NOTREACHED*/
375*5c51f124SMoriah Waterland }
376*5c51f124SMoriah Waterland 
377*5c51f124SMoriah Waterland 
378*5c51f124SMoriah Waterland /*
379*5c51f124SMoriah Waterland  * Name:	pkgstrGetToken
380*5c51f124SMoriah Waterland  * Synopsis:	Get a separator delimited token from a string
381*5c51f124SMoriah Waterland  * Description:	Given a string and a list of one or more separators,
382*5c51f124SMoriah Waterland  *		return the position specified token (sequence of one or
383*5c51f124SMoriah Waterland  *		more characters that do not include any of the separators)
384*5c51f124SMoriah Waterland  * Arguments:	r_sep - [*RW] - (char *)
385*5c51f124SMoriah Waterland  *			- separator that ended the token returned
386*5c51f124SMoriah Waterland  *			- NOTE: this is a pointer to a "char", e.g.:
387*5c51f124SMoriah Waterland  *				- char a;
388*5c51f124SMoriah Waterland  *				- pkgstrGetToken(&a, ...)
389*5c51f124SMoriah Waterland  *		a_string - [RO, *RO] - (char *)
390*5c51f124SMoriah Waterland  *			- pointer to string to extract token from
391*5c51f124SMoriah Waterland  *		a_index - [RO, *RO] - (int)
392*5c51f124SMoriah Waterland  *			- Index of token to return; '0' is first matching
393*5c51f124SMoriah Waterland  *			  token, '1' is second matching token, etc.
394*5c51f124SMoriah Waterland  *		a_separators - [RO, *RO] - (char *)
395*5c51f124SMoriah Waterland  *			- String containing one or more characters that
396*5c51f124SMoriah Waterland  *			  can separate one "token" from another
397*5c51f124SMoriah Waterland  * Returns:	char *
398*5c51f124SMoriah Waterland  *			== (char *)NULL - no token matching criteria found
399*5c51f124SMoriah Waterland  *			!= (char *)NULL - token matching criteria
400*5c51f124SMoriah Waterland  * NOTE:    	Any token string returned is placed in new storage for the
401*5c51f124SMoriah Waterland  *		calling method. The caller must use 'free' to dispose
402*5c51f124SMoriah Waterland  *		of the storage once the token string is no longer needed.
403*5c51f124SMoriah Waterland  */
404*5c51f124SMoriah Waterland 
405*5c51f124SMoriah Waterland char *
406*5c51f124SMoriah Waterland pkgstrGetToken(char *r_sep, char *a_string, int a_index, char *a_separators)
407*5c51f124SMoriah Waterland {
408*5c51f124SMoriah Waterland 	char	*p;
409*5c51f124SMoriah Waterland 	char	*q;
410*5c51f124SMoriah Waterland 	char	*lasts;
411*5c51f124SMoriah Waterland 
412*5c51f124SMoriah Waterland 	/* entry assertions */
413*5c51f124SMoriah Waterland 
414*5c51f124SMoriah Waterland 	assert(a_string != (char *)NULL);
415*5c51f124SMoriah Waterland 	assert(a_index >= 0);
416*5c51f124SMoriah Waterland 	assert(a_separators != (char *)NULL);
417*5c51f124SMoriah Waterland 	assert(*a_separators != '\0');
418*5c51f124SMoriah Waterland 
419*5c51f124SMoriah Waterland 	/* if returned separator requested, reset to null until token found */
420*5c51f124SMoriah Waterland 
421*5c51f124SMoriah Waterland 	if (r_sep != (char *)NULL) {
422*5c51f124SMoriah Waterland 		*r_sep = '\0';
423*5c51f124SMoriah Waterland 	}
424*5c51f124SMoriah Waterland 
425*5c51f124SMoriah Waterland 	/* duplicate original string before breaking down into tokens */
426*5c51f124SMoriah Waterland 
427*5c51f124SMoriah Waterland 	p = strdup(a_string);
428*5c51f124SMoriah Waterland 	assert(p != (char *)NULL);
429*5c51f124SMoriah Waterland 	if (p == (char *)NULL) {
430*5c51f124SMoriah Waterland 		return ((char *)NULL);
431*5c51f124SMoriah Waterland 	}
432*5c51f124SMoriah Waterland 	lasts = p;
433*5c51f124SMoriah Waterland 
434*5c51f124SMoriah Waterland 	/* scan for separators and return 'index'th token found */
435*5c51f124SMoriah Waterland 
436*5c51f124SMoriah Waterland 	while (q = strtok_r((char *)NULL, a_separators, &lasts)) {
437*5c51f124SMoriah Waterland 		/* retrieve separator if requested */
438*5c51f124SMoriah Waterland 
439*5c51f124SMoriah Waterland 		if (r_sep != (char *)NULL) {
440*5c51f124SMoriah Waterland 			char	*x;
441*5c51f124SMoriah Waterland 
442*5c51f124SMoriah Waterland 			x = strpbrk(a_string, a_separators);
443*5c51f124SMoriah Waterland 			if (x) {
444*5c51f124SMoriah Waterland 				*r_sep = *x;
445*5c51f124SMoriah Waterland 			}
446*5c51f124SMoriah Waterland 		}
447*5c51f124SMoriah Waterland 
448*5c51f124SMoriah Waterland 		/* if this is the 'index'th token requested return it */
449*5c51f124SMoriah Waterland 
450*5c51f124SMoriah Waterland 		if (a_index-- == 0) {
451*5c51f124SMoriah Waterland 			char	*tmp;
452*5c51f124SMoriah Waterland 
453*5c51f124SMoriah Waterland 			/* duplicate token into its own storage */
454*5c51f124SMoriah Waterland 
455*5c51f124SMoriah Waterland 			tmp = strdup(q);
456*5c51f124SMoriah Waterland 			assert(tmp != (char *)NULL);
457*5c51f124SMoriah Waterland 			if (tmp == (char *)NULL) {
458*5c51f124SMoriah Waterland 				return ((char *)NULL);
459*5c51f124SMoriah Waterland 			}
460*5c51f124SMoriah Waterland 
461*5c51f124SMoriah Waterland 			/* free up copy of original input string */
462*5c51f124SMoriah Waterland 
463*5c51f124SMoriah Waterland 			free(p);
464*5c51f124SMoriah Waterland 
465*5c51f124SMoriah Waterland 			/* return token found */
466*5c51f124SMoriah Waterland 
467*5c51f124SMoriah Waterland 			return (tmp);
468*5c51f124SMoriah Waterland 		}
469*5c51f124SMoriah Waterland 	}
470*5c51f124SMoriah Waterland 
471*5c51f124SMoriah Waterland 	/*
472*5c51f124SMoriah Waterland 	 * token not found
473*5c51f124SMoriah Waterland 	 */
474*5c51f124SMoriah Waterland 
475*5c51f124SMoriah Waterland 	/* free up copy of original input string */
476*5c51f124SMoriah Waterland 
477*5c51f124SMoriah Waterland 	free(p);
478*5c51f124SMoriah Waterland 
479*5c51f124SMoriah Waterland 	/* return NULL pointer (token not found) */
480*5c51f124SMoriah Waterland 
481*5c51f124SMoriah Waterland 	return ((char *)NULL);
482*5c51f124SMoriah Waterland }
483*5c51f124SMoriah Waterland 
484*5c51f124SMoriah Waterland /*
485*5c51f124SMoriah Waterland  * Name:	pkgstrGetToken
486*5c51f124SMoriah Waterland  * Synopsis:	Get separator delimited token from a string into a fixed buffer
487*5c51f124SMoriah Waterland  * Description:	Given a string and a list of one or more separators,
488*5c51f124SMoriah Waterland  *		return the position specified token (sequence of one or
489*5c51f124SMoriah Waterland  *		more characters that do not include any of the separators)
490*5c51f124SMoriah Waterland  *		into a specified buffer of a fixed maximum size
491*5c51f124SMoriah Waterland  * Arguments:	r_sep - [*RW] - (char *)
492*5c51f124SMoriah Waterland  *			- separator that ended the token returned
493*5c51f124SMoriah Waterland  *			- NOTE: this is a pointer to a "char", e.g.:
494*5c51f124SMoriah Waterland  *				- char a;
495*5c51f124SMoriah Waterland  *				- pkgstrGetToken(&a, ...)
496*5c51f124SMoriah Waterland  *		a_string - [RO, *RO] - (char *)
497*5c51f124SMoriah Waterland  *			- pointer to string to extract token from
498*5c51f124SMoriah Waterland  *		a_index - [RO, *RO] - (int)
499*5c51f124SMoriah Waterland  *			- Index of token to return; '0' is first matching
500*5c51f124SMoriah Waterland  *			  token, '1' is second matching token, etc.
501*5c51f124SMoriah Waterland  *		a_separators - [RO, *RO] - (char *)
502*5c51f124SMoriah Waterland  *			- String containing one or more characters that
503*5c51f124SMoriah Waterland  *			  can separate one "token" from another
504*5c51f124SMoriah Waterland  *		a_buf - [RO, *RW] - (char *)
505*5c51f124SMoriah Waterland  *			- Pointer to buffer used as storage space for the
506*5c51f124SMoriah Waterland  *			  returned token - the returned token is always
507*5c51f124SMoriah Waterland  *			  null terminated
508*5c51f124SMoriah Waterland  *			  a_buf[0] == '\0' - no token meeting criteria found
509*5c51f124SMoriah Waterland  *			  a_buf[0] != '\0' - token meeting criteria returned
510*5c51f124SMoriah Waterland  *		a_bufLen - [RO, *RO] - (int)
511*5c51f124SMoriah Waterland  *			- Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1'
512*5c51f124SMoriah Waterland  *			  bytes will be placed in 'a_buf' - the returned
513*5c51f124SMoriah Waterland  *			  token is always null terminated
514*5c51f124SMoriah Waterland  * Returns:	void
515*5c51f124SMoriah Waterland  */
516*5c51f124SMoriah Waterland 
517*5c51f124SMoriah Waterland void
518*5c51f124SMoriah Waterland pkgstrGetToken_r(char *r_sep, char *a_string, int a_index,
519*5c51f124SMoriah Waterland 	char *a_separators, char *a_buf, int a_bufLen)
520*5c51f124SMoriah Waterland {
521*5c51f124SMoriah Waterland 	char	*p;
522*5c51f124SMoriah Waterland 	char	*q;
523*5c51f124SMoriah Waterland 	char	*lasts;
524*5c51f124SMoriah Waterland 
525*5c51f124SMoriah Waterland 	/* entry assertions */
526*5c51f124SMoriah Waterland 
527*5c51f124SMoriah Waterland 	assert(a_string != (char *)NULL);
528*5c51f124SMoriah Waterland 	assert(a_index >= 0);
529*5c51f124SMoriah Waterland 	assert(a_separators != (char *)NULL);
530*5c51f124SMoriah Waterland 	assert(*a_separators != '\0');
531*5c51f124SMoriah Waterland 	assert(a_buf != (char *)NULL);
532*5c51f124SMoriah Waterland 	assert(a_bufLen > 0);
533*5c51f124SMoriah Waterland 
534*5c51f124SMoriah Waterland 	/* reset returned separator */
535*5c51f124SMoriah Waterland 
536*5c51f124SMoriah Waterland 	if (r_sep != (char *)NULL) {
537*5c51f124SMoriah Waterland 		*r_sep = '\0';
538*5c51f124SMoriah Waterland 	}
539*5c51f124SMoriah Waterland 
540*5c51f124SMoriah Waterland 	/* zero out contents of return buffer */
541*5c51f124SMoriah Waterland 
542*5c51f124SMoriah Waterland 	bzero(a_buf, a_bufLen);
543*5c51f124SMoriah Waterland 
544*5c51f124SMoriah Waterland 	/* duplicate original string before breaking down into tokens */
545*5c51f124SMoriah Waterland 
546*5c51f124SMoriah Waterland 	p = strdup(a_string);
547*5c51f124SMoriah Waterland 	assert(p != (char *)NULL);
548*5c51f124SMoriah Waterland 	if (p == (char *)NULL) {
549*5c51f124SMoriah Waterland 		return;
550*5c51f124SMoriah Waterland 	}
551*5c51f124SMoriah Waterland 	lasts = p;
552*5c51f124SMoriah Waterland 
553*5c51f124SMoriah Waterland 	/* scan for separators and return 'index'th token found */
554*5c51f124SMoriah Waterland 
555*5c51f124SMoriah Waterland 	while (q = strtok_r((char *)NULL, a_separators, &lasts)) {
556*5c51f124SMoriah Waterland 		/* retrieve separator if requested */
557*5c51f124SMoriah Waterland 
558*5c51f124SMoriah Waterland 		if (r_sep != (char *)NULL) {
559*5c51f124SMoriah Waterland 			char	*x;
560*5c51f124SMoriah Waterland 			x = strpbrk(a_string, a_separators);
561*5c51f124SMoriah Waterland 			if (x) {
562*5c51f124SMoriah Waterland 				*r_sep = *x;
563*5c51f124SMoriah Waterland 			}
564*5c51f124SMoriah Waterland 		}
565*5c51f124SMoriah Waterland 
566*5c51f124SMoriah Waterland 		/* if this is the 'index'th token requested return it */
567*5c51f124SMoriah Waterland 
568*5c51f124SMoriah Waterland 		if (a_index-- == 0) {
569*5c51f124SMoriah Waterland 			/* copy as many characters as possible to return buf */
570*5c51f124SMoriah Waterland 
571*5c51f124SMoriah Waterland 			(void) strncpy(a_buf, q, a_bufLen-1);
572*5c51f124SMoriah Waterland 			break;
573*5c51f124SMoriah Waterland 		}
574*5c51f124SMoriah Waterland 	}
575*5c51f124SMoriah Waterland 
576*5c51f124SMoriah Waterland 	/* free up copy of original input string */
577*5c51f124SMoriah Waterland 
578*5c51f124SMoriah Waterland 	free(p);
579*5c51f124SMoriah Waterland }
580*5c51f124SMoriah Waterland 
581*5c51f124SMoriah Waterland /*
582*5c51f124SMoriah Waterland  * Name:	pkgstrAddToken
583*5c51f124SMoriah Waterland  * Synopsis:	Add a token to a string
584*5c51f124SMoriah Waterland  * Description:	Append a token (sequence of one or more characters) to a
585*5c51f124SMoriah Waterland  *		string that is in allocated space - create new string if
586*5c51f124SMoriah Waterland  *		no string to append to exists
587*5c51f124SMoriah Waterland  * Arguments:	a_old - [RO, *RW] - (char **)
588*5c51f124SMoriah Waterland  *			- Pointer to handle to string to append token to
589*5c51f124SMoriah Waterland  *			  == (char *)NULL - new string is created
590*5c51f124SMoriah Waterland  *		a_new - [RO, *RO] - (char *)
591*5c51f124SMoriah Waterland  *			- Pointer to string representing token to append
592*5c51f124SMoriah Waterland  *			  to the end of the "a_old" string
593*5c51f124SMoriah Waterland  *			  == (char *)NULL - no action is performed
594*5c51f124SMoriah Waterland  *			  a_new[0] == '\0' - no action is performed
595*5c51f124SMoriah Waterland  *		a_separator - [RO, *RO] - (char)
596*5c51f124SMoriah Waterland  *			- One character placed between the old (existing)
597*5c51f124SMoriah Waterland  *			  string and the new token to be added IF the old
598*5c51f124SMoriah Waterland  *			  string exists and is not empty (zero length)
599*5c51f124SMoriah Waterland  * Returns:	void
600*5c51f124SMoriah Waterland  * CAUTION:	The old (existing) string must be allocated space (via lu_mem*
601*5c51f124SMoriah Waterland  *		or pkgstr* methods) - it must not be a static or inline
602*5c51f124SMoriah Waterland  *		character string
603*5c51f124SMoriah Waterland  * NOTE:	The old (existing) string may be freed with 'free'
604*5c51f124SMoriah Waterland  *		if a token is appended to it
605*5c51f124SMoriah Waterland  * NOTE:    	Any string returned in 'a_old' is placed in new storage for the
606*5c51f124SMoriah Waterland  *		calling method. The caller must use 'free' to dispose
607*5c51f124SMoriah Waterland  *		of the storage once the token string is no longer needed.
608*5c51f124SMoriah Waterland  */
609*5c51f124SMoriah Waterland 
610*5c51f124SMoriah Waterland void
611*5c51f124SMoriah Waterland pkgstrAddToken(char **a_old, char *a_new, char a_separator)
612*5c51f124SMoriah Waterland {
613*5c51f124SMoriah Waterland 	/* entry assertions */
614*5c51f124SMoriah Waterland 
615*5c51f124SMoriah Waterland 	assert(a_old != (char **)NULL);
616*5c51f124SMoriah Waterland 	assert(a_separator != '\0');
617*5c51f124SMoriah Waterland 
618*5c51f124SMoriah Waterland 	/* if token to add is null, just return */
619*5c51f124SMoriah Waterland 
620*5c51f124SMoriah Waterland 	if (a_new == (char *)NULL) {
621*5c51f124SMoriah Waterland 		return;
622*5c51f124SMoriah Waterland 	}
623*5c51f124SMoriah Waterland 
624*5c51f124SMoriah Waterland 	/* if token to add is empty (zero length), just return */
625*5c51f124SMoriah Waterland 
626*5c51f124SMoriah Waterland 	if (*a_new == '\0') {
627*5c51f124SMoriah Waterland 		return;
628*5c51f124SMoriah Waterland 	}
629*5c51f124SMoriah Waterland 
630*5c51f124SMoriah Waterland 	/* make sure that new token does not contain the separator */
631*5c51f124SMoriah Waterland 
632*5c51f124SMoriah Waterland 	assert(strchr(a_new, (int)a_separator) == (char *)NULL);
633*5c51f124SMoriah Waterland 
634*5c51f124SMoriah Waterland 	/* if old string is empty (zero length), deallocate */
635*5c51f124SMoriah Waterland 
636*5c51f124SMoriah Waterland 	if ((*a_old != (char *)NULL) && ((*a_old)[0] == '\0')) {
637*5c51f124SMoriah Waterland 		/* *a_old is set to NULL by free */
638*5c51f124SMoriah Waterland 		free(*a_old);
639*5c51f124SMoriah Waterland 		*a_old = (char *)NULL;
640*5c51f124SMoriah Waterland 	}
641*5c51f124SMoriah Waterland 
642*5c51f124SMoriah Waterland 	/* if old string is exists, append separator and token */
643*5c51f124SMoriah Waterland 
644*5c51f124SMoriah Waterland 	if (*a_old != (char *)NULL) {
645*5c51f124SMoriah Waterland 		char *p;
646*5c51f124SMoriah Waterland 		p = pkgstrPrintf("%s%c%s", *a_old, a_separator, a_new);
647*5c51f124SMoriah Waterland 		free(*a_old);
648*5c51f124SMoriah Waterland 		*a_old = p;
649*5c51f124SMoriah Waterland 		return;
650*5c51f124SMoriah Waterland 	}
651*5c51f124SMoriah Waterland 
652*5c51f124SMoriah Waterland 	/* old string does not exist - return duplicate of token */
653*5c51f124SMoriah Waterland 
654*5c51f124SMoriah Waterland 	assert(*a_old == (char *)NULL);
655*5c51f124SMoriah Waterland 	*a_old = strdup(a_new);
656*5c51f124SMoriah Waterland 	assert(*a_old != (char *)NULL);
657*5c51f124SMoriah Waterland }
658*5c51f124SMoriah Waterland 
659*5c51f124SMoriah Waterland /*
660*5c51f124SMoriah Waterland  * Name:	pkgstrContainsToken
661*5c51f124SMoriah Waterland  * Synopsis:	Does a given string contain a specified substring
662*5c51f124SMoriah Waterland  * Description:	Determine if a given substring exists in a larger string
663*5c51f124SMoriah Waterland  * Arguments:	a_string - [RO, *RO] - (char *)
664*5c51f124SMoriah Waterland  *			Pointer to string to look for substring in
665*5c51f124SMoriah Waterland  *		a_token - [RO, *RO] - (char *)
666*5c51f124SMoriah Waterland  *			Pointer to substring to look for in larger string
667*5c51f124SMoriah Waterland  * Results:	boolean_t
668*5c51f124SMoriah Waterland  *			B_TRUE - substring exists in larger string
669*5c51f124SMoriah Waterland  *			B_FALSE - substring does NOT exist in larger string
670*5c51f124SMoriah Waterland  * NOTE:	The substring must match on a "token" basis; that is, the
671*5c51f124SMoriah Waterland  *		substring must exist in the larger string delineated with
672*5c51f124SMoriah Waterland  *		either spaces or tabs to match.
673*5c51f124SMoriah Waterland  */
674*5c51f124SMoriah Waterland 
675*5c51f124SMoriah Waterland boolean_t
676*5c51f124SMoriah Waterland pkgstrContainsToken(char *a_string, char *a_token, char *a_separators)
677*5c51f124SMoriah Waterland {
678*5c51f124SMoriah Waterland 	char	*lasts;
679*5c51f124SMoriah Waterland 	char	*current;
680*5c51f124SMoriah Waterland 	char	*p;
681*5c51f124SMoriah Waterland 
682*5c51f124SMoriah Waterland 	/* entry assertions */
683*5c51f124SMoriah Waterland 
684*5c51f124SMoriah Waterland 	assert(a_separators != (char *)NULL);
685*5c51f124SMoriah Waterland 	assert(*a_separators != '\0');
686*5c51f124SMoriah Waterland 
687*5c51f124SMoriah Waterland 	/* if token is not supplied, return false */
688*5c51f124SMoriah Waterland 
689*5c51f124SMoriah Waterland 	if (a_token == (char *)NULL) {
690*5c51f124SMoriah Waterland 		return (B_FALSE);
691*5c51f124SMoriah Waterland 	}
692*5c51f124SMoriah Waterland 
693*5c51f124SMoriah Waterland 	/* if no string provided, return false */
694*5c51f124SMoriah Waterland 
695*5c51f124SMoriah Waterland 	if (a_string == (char *)NULL) {
696*5c51f124SMoriah Waterland 		return (B_FALSE);
697*5c51f124SMoriah Waterland 	}
698*5c51f124SMoriah Waterland 
699*5c51f124SMoriah Waterland 	/* if string empty (zero length), return false */
700*5c51f124SMoriah Waterland 
701*5c51f124SMoriah Waterland 	if (*a_string == '\0') {
702*5c51f124SMoriah Waterland 		return (B_FALSE);
703*5c51f124SMoriah Waterland 	}
704*5c51f124SMoriah Waterland 
705*5c51f124SMoriah Waterland 	/* duplicate larger string because strtok_r changes it */
706*5c51f124SMoriah Waterland 
707*5c51f124SMoriah Waterland 	p = strdup(a_string);
708*5c51f124SMoriah Waterland 	assert(p != (char *)NULL);
709*5c51f124SMoriah Waterland 	if (p == (char *)NULL) {
710*5c51f124SMoriah Waterland 		return (B_FALSE);
711*5c51f124SMoriah Waterland 	}
712*5c51f124SMoriah Waterland 
713*5c51f124SMoriah Waterland 	lasts = p;
714*5c51f124SMoriah Waterland 
715*5c51f124SMoriah Waterland 	/* scan each token looking for a match */
716*5c51f124SMoriah Waterland 
717*5c51f124SMoriah Waterland 	while ((current = strtok_r((char *)NULL, a_separators, &lasts)) !=
718*5c51f124SMoriah Waterland 			(char *)NULL) {
719*5c51f124SMoriah Waterland 		if (streq(current, a_token)) {
720*5c51f124SMoriah Waterland 			free(p);
721*5c51f124SMoriah Waterland 			return (B_TRUE);
722*5c51f124SMoriah Waterland 		}
723*5c51f124SMoriah Waterland 	}
724*5c51f124SMoriah Waterland 
725*5c51f124SMoriah Waterland 	/* free up temporary storage */
726*5c51f124SMoriah Waterland 
727*5c51f124SMoriah Waterland 	free(p);
728*5c51f124SMoriah Waterland 
729*5c51f124SMoriah Waterland 	/* not found */
730*5c51f124SMoriah Waterland 
731*5c51f124SMoriah Waterland 	return (B_FALSE);
732*5c51f124SMoriah Waterland }
733*5c51f124SMoriah Waterland 
734*5c51f124SMoriah Waterland /*
735*5c51f124SMoriah Waterland  * Name:	pkgstrRemoveToken
736*5c51f124SMoriah Waterland  * Synopsis:	Remove a token from a string
737*5c51f124SMoriah Waterland  * Description:	Remove a token (sequence of one or more characters) from a
738*5c51f124SMoriah Waterland  *		string that is in allocated space
739*5c51f124SMoriah Waterland  * Arguments:	r_string - [RO, *RW] - (char **)
740*5c51f124SMoriah Waterland  *			- Pointer to handle to string to remove token from
741*5c51f124SMoriah Waterland  *		a_token - [RO, *RO] - (char *)
742*5c51f124SMoriah Waterland  *			Pointer to token (substring) to look for and remove
743*5c51f124SMoriah Waterland  *			from r_string provided
744*5c51f124SMoriah Waterland  *		a_separators - [RO, *RO] - (char *)
745*5c51f124SMoriah Waterland  *			- String containing one or more characters that
746*5c51f124SMoriah Waterland  *			  separate one "token" from another in r_string
747*5c51f124SMoriah Waterland  *		a_index - [RO, *RO] - (int)
748*5c51f124SMoriah Waterland  *			- Index of token to remove; '0' is first matching
749*5c51f124SMoriah Waterland  *			  token, '1' is second matching token, etc.
750*5c51f124SMoriah Waterland  * Returns:	void
751*5c51f124SMoriah Waterland  * CAUTION:	The input string must be allocated space (via lu_mem* or
752*5c51f124SMoriah Waterland  *		pkgstr* methods) - it must not be a static or inline
753*5c51f124SMoriah Waterland  *		character string
754*5c51f124SMoriah Waterland  * NOTE:	The input string r_string will be freed with 'free'
755*5c51f124SMoriah Waterland  *		if the token to be removed is found
756*5c51f124SMoriah Waterland  * NOTE:    	Any token string returned is placed in new storage for the
757*5c51f124SMoriah Waterland  *		calling method. The caller must use 'free' to dispose
758*5c51f124SMoriah Waterland  *		of the storage once the token string is no longer needed.
759*5c51f124SMoriah Waterland  * Errors:	If the new token string cannot be created, the process exits
760*5c51f124SMoriah Waterland  */
761*5c51f124SMoriah Waterland 
762*5c51f124SMoriah Waterland void
763*5c51f124SMoriah Waterland pkgstrRemoveToken(char **r_string, char *a_token, char *a_separators,
764*5c51f124SMoriah Waterland 	int a_index)
765*5c51f124SMoriah Waterland {
766*5c51f124SMoriah Waterland 	char	*a_string;
767*5c51f124SMoriah Waterland 	char	*copyString;
768*5c51f124SMoriah Waterland 	char	sep = 0;
769*5c51f124SMoriah Waterland 	int	copyLength;
770*5c51f124SMoriah Waterland 	int	i;
771*5c51f124SMoriah Waterland 
772*5c51f124SMoriah Waterland 	/* entry assertions */
773*5c51f124SMoriah Waterland 
774*5c51f124SMoriah Waterland 	assert(r_string != (char **)NULL);
775*5c51f124SMoriah Waterland 	assert(a_token != (char *)NULL);
776*5c51f124SMoriah Waterland 	assert(*a_token != '\0');
777*5c51f124SMoriah Waterland 	assert(a_separators != (char *)NULL);
778*5c51f124SMoriah Waterland 	assert(*a_separators != '\0');
779*5c51f124SMoriah Waterland 
780*5c51f124SMoriah Waterland 	/* simple case: input string is null; return empty string */
781*5c51f124SMoriah Waterland 
782*5c51f124SMoriah Waterland 	a_string = *r_string;
783*5c51f124SMoriah Waterland 	if (*a_string == '\0') {
784*5c51f124SMoriah Waterland 		return;
785*5c51f124SMoriah Waterland 	}
786*5c51f124SMoriah Waterland 
787*5c51f124SMoriah Waterland 	/* simple case: token == input string; return empty string */
788*5c51f124SMoriah Waterland 
789*5c51f124SMoriah Waterland 	if (streq(a_string, a_token)) {
790*5c51f124SMoriah Waterland 		/* deallocate input string; free sets *r_string to NULL */
791*5c51f124SMoriah Waterland 
792*5c51f124SMoriah Waterland 		free(*r_string);
793*5c51f124SMoriah Waterland 		*r_string = (char *)NULL;
794*5c51f124SMoriah Waterland 		return;
795*5c51f124SMoriah Waterland 	}
796*5c51f124SMoriah Waterland 
797*5c51f124SMoriah Waterland 	/* simple case: token not in input string: return */
798*5c51f124SMoriah Waterland 
799*5c51f124SMoriah Waterland 	if (!pkgstrContainsToken(a_string, a_token, a_separators)) {
800*5c51f124SMoriah Waterland 		return;
801*5c51f124SMoriah Waterland 	}
802*5c51f124SMoriah Waterland 
803*5c51f124SMoriah Waterland 	/*
804*5c51f124SMoriah Waterland 	 * Pick apart the old string building the new one as we go along
805*5c51f124SMoriah Waterland 	 * removing the first occurance of the token provided
806*5c51f124SMoriah Waterland 	 */
807*5c51f124SMoriah Waterland 
808*5c51f124SMoriah Waterland 	copyLength = (strlen(a_string)-strlen(a_token))+2;
809*5c51f124SMoriah Waterland 	copyString = calloc(1, copyLength);
810*5c51f124SMoriah Waterland 	assert(copyString != (char *)NULL);
811*5c51f124SMoriah Waterland 	if (copyString == (char *)NULL) {
812*5c51f124SMoriah Waterland 		return;
813*5c51f124SMoriah Waterland 	}
814*5c51f124SMoriah Waterland 
815*5c51f124SMoriah Waterland 	for (i = 0; ; i++) {
816*5c51f124SMoriah Waterland 		char	*p;
817*5c51f124SMoriah Waterland 
818*5c51f124SMoriah Waterland 		p = pkgstrGetToken(&sep, a_string, i, a_separators);
819*5c51f124SMoriah Waterland 		if (p == (char *)NULL) {
820*5c51f124SMoriah Waterland 			break;
821*5c51f124SMoriah Waterland 		}
822*5c51f124SMoriah Waterland 
823*5c51f124SMoriah Waterland 		if (streq(p, a_token) && (a_index-- == 0)) {
824*5c51f124SMoriah Waterland 			continue;
825*5c51f124SMoriah Waterland 		}
826*5c51f124SMoriah Waterland 
827*5c51f124SMoriah Waterland 		if (*copyString) {
828*5c51f124SMoriah Waterland 			assert(sep != '\0');
829*5c51f124SMoriah Waterland 			(void) strncat(copyString, &sep, 1);
830*5c51f124SMoriah Waterland 		}
831*5c51f124SMoriah Waterland 
832*5c51f124SMoriah Waterland 		(void) strcat(copyString, p);
833*5c51f124SMoriah Waterland 	}
834*5c51f124SMoriah Waterland 
835*5c51f124SMoriah Waterland 	free(*r_string);
836*5c51f124SMoriah Waterland 	assert(*copyString);
837*5c51f124SMoriah Waterland 	*r_string = copyString;
838*5c51f124SMoriah Waterland }
839*5c51f124SMoriah Waterland 
840*5c51f124SMoriah Waterland /*
841*5c51f124SMoriah Waterland  * Name:	pkgstrScaleNumericString
842*5c51f124SMoriah Waterland  * Synopsis:	Convert unsigned long long to human readable form
843*5c51f124SMoriah Waterland  * Description:	Convert a string containing an unsigned long long representation
844*5c51f124SMoriah Waterland  *		and convert it into a human readable numeric string. The number
845*5c51f124SMoriah Waterland  *		is scaled down until it is small enough to be in a good human
846*5c51f124SMoriah Waterland  *		readable format i.e. in the range 0 thru scale-1.
847*5c51f124SMoriah Waterland  * Arguments:	a_buf - [RO, *RW] - (char *)
848*5c51f124SMoriah Waterland  *			Pointer to buffer containing string representation
849*5c51f124SMoriah Waterland  *			of unsigned long long to convert
850*5c51f124SMoriah Waterland  *		scale - [RO, *RO] - (unsigned long long)
851*5c51f124SMoriah Waterland  *			Value to scale the number into
852*5c51f124SMoriah Waterland  * Returns:	a_buf - contains human readable scaled representation of
853*5c51f124SMoriah Waterland  *			original value contained in the buffer
854*5c51f124SMoriah Waterland  * Note:	The value "(unsigned long long)-1" is a special case and
855*5c51f124SMoriah Waterland  *		is always converted to "-1".
856*5c51f124SMoriah Waterland  * Errors:	If the string cannot be created, the process exits
857*5c51f124SMoriah Waterland  */
858*5c51f124SMoriah Waterland 
859*5c51f124SMoriah Waterland void
860*5c51f124SMoriah Waterland pkgstrScaleNumericString(char *a_buf, unsigned long long scale)
861*5c51f124SMoriah Waterland {
862*5c51f124SMoriah Waterland static char		*M = " KMGTPE"; /* Measurement: */
863*5c51f124SMoriah Waterland 					/* kilo, mega, giga, tera, peta, exa */
864*5c51f124SMoriah Waterland 
865*5c51f124SMoriah Waterland 	unsigned long long number = 0;	/* convert this number */
866*5c51f124SMoriah Waterland 	unsigned long long save = 0;
867*5c51f124SMoriah Waterland 	char	*uom = M;    /* unit of measurement, initially ' ' (=M[0]) */
868*5c51f124SMoriah Waterland 
869*5c51f124SMoriah Waterland 	/* entry assertions */
870*5c51f124SMoriah Waterland 
871*5c51f124SMoriah Waterland 	assert(scale > (unsigned long long)0);
872*5c51f124SMoriah Waterland 	assert(scale <=  (unsigned long long)1048576);
873*5c51f124SMoriah Waterland 
874*5c51f124SMoriah Waterland 	/*
875*5c51f124SMoriah Waterland 	 * Get the number - if no number of empty number, just return
876*5c51f124SMoriah Waterland 	 */
877*5c51f124SMoriah Waterland 
878*5c51f124SMoriah Waterland 	if (a_buf == (char *)NULL) {
879*5c51f124SMoriah Waterland 		return;
880*5c51f124SMoriah Waterland 	}
881*5c51f124SMoriah Waterland 
882*5c51f124SMoriah Waterland 	if (*a_buf == '\0') {
883*5c51f124SMoriah Waterland 		(void) strcpy(a_buf, "0");
884*5c51f124SMoriah Waterland 		return;
885*5c51f124SMoriah Waterland 	}
886*5c51f124SMoriah Waterland 
887*5c51f124SMoriah Waterland 	/* convert out the number from the input buffer */
888*5c51f124SMoriah Waterland 
889*5c51f124SMoriah Waterland 	number = strtoull(a_buf, (char **)NULL, 10);
890*5c51f124SMoriah Waterland 
891*5c51f124SMoriah Waterland 	/* if conversion error, return "-1" */
892*5c51f124SMoriah Waterland 
893*5c51f124SMoriah Waterland 	if ((long long)number == (long long)-1) {
894*5c51f124SMoriah Waterland 		(void) strcpy(a_buf, "-1");
895*5c51f124SMoriah Waterland 		return;
896*5c51f124SMoriah Waterland 	}
897*5c51f124SMoriah Waterland 
898*5c51f124SMoriah Waterland 	/*
899*5c51f124SMoriah Waterland 	 * Now have number as a count of scale units.
900*5c51f124SMoriah Waterland 	 * Stop scaling when we reached exa-bytes, then something is
901*5c51f124SMoriah Waterland 	 * probably wrong with our number (it is improbably large)
902*5c51f124SMoriah Waterland 	 */
903*5c51f124SMoriah Waterland 
904*5c51f124SMoriah Waterland 	while ((number >= scale) && (*uom != 'E')) {
905*5c51f124SMoriah Waterland 		uom++; /* next unit of measurement */
906*5c51f124SMoriah Waterland 		save = number;
907*5c51f124SMoriah Waterland 		number = (number + (scale / 2)) / scale;
908*5c51f124SMoriah Waterland 	}
909*5c51f124SMoriah Waterland 
910*5c51f124SMoriah Waterland 	/* check if we should output a decimal place after the point */
911*5c51f124SMoriah Waterland 
912*5c51f124SMoriah Waterland 	if (save && ((save / scale) < 10)) {
913*5c51f124SMoriah Waterland 		/* sprintf() will round for us */
914*5c51f124SMoriah Waterland 		float fnum = (float)save / scale;
915*5c51f124SMoriah Waterland 		(void) sprintf(a_buf, "%4.1f%c", fnum, *uom);
916*5c51f124SMoriah Waterland 	} else {
917*5c51f124SMoriah Waterland 		(void) sprintf(a_buf, "%4llu%c", number, *uom);
918*5c51f124SMoriah Waterland 	}
919*5c51f124SMoriah Waterland }
920*5c51f124SMoriah Waterland 
921*5c51f124SMoriah Waterland /*
922*5c51f124SMoriah Waterland  * Name:	pkgstrLocatePathBasename
923*5c51f124SMoriah Waterland  * Synopsis:	Locate position of base name in path string
924*5c51f124SMoriah Waterland  * Description:	Locate the base name (last path item) in a path and
925*5c51f124SMoriah Waterland  *		return a pointer to the first byte of the base name
926*5c51f124SMoriah Waterland  *		within the given path
927*5c51f124SMoriah Waterland  * Arguments:	a_path - [RO, *RO] - (char *)
928*5c51f124SMoriah Waterland  *			- Pointer to string representing path to scan
929*5c51f124SMoriah Waterland  * Returns:	char *
930*5c51f124SMoriah Waterland  *			- Pointer into string of first byte of path base name
931*5c51f124SMoriah Waterland  *			- == (char *)NULL - input path is (char *)NULL
932*5c51f124SMoriah Waterland  */
933*5c51f124SMoriah Waterland 
934*5c51f124SMoriah Waterland char *
935*5c51f124SMoriah Waterland pkgstrLocatePathBasename(char *a_path)
936*5c51f124SMoriah Waterland {
937*5c51f124SMoriah Waterland 	char	*p;
938*5c51f124SMoriah Waterland 
939*5c51f124SMoriah Waterland 	/* if path is NULL, return NULL */
940*5c51f124SMoriah Waterland 
941*5c51f124SMoriah Waterland 	if (!a_path) {
942*5c51f124SMoriah Waterland 		return (a_path);
943*5c51f124SMoriah Waterland 	}
944*5c51f124SMoriah Waterland 
945*5c51f124SMoriah Waterland 	/* locate last occurance of '/' in path */
946*5c51f124SMoriah Waterland 
947*5c51f124SMoriah Waterland 	p = strrchr(a_path, '/');
948*5c51f124SMoriah Waterland 	if (p != (char *)NULL) {
949*5c51f124SMoriah Waterland 		/* base name located - return -> first byte */
950*5c51f124SMoriah Waterland 		return (p+1);
951*5c51f124SMoriah Waterland 	}
952*5c51f124SMoriah Waterland 
953*5c51f124SMoriah Waterland 	/* no occurance of '/' - entry path must be basename */
954*5c51f124SMoriah Waterland 
955*5c51f124SMoriah Waterland 	return (a_path);
956*5c51f124SMoriah Waterland }
957*5c51f124SMoriah Waterland 
958*5c51f124SMoriah Waterland /*
959*5c51f124SMoriah Waterland  * Name:	pkgstrConvertPathToBasename
960*5c51f124SMoriah Waterland  * Synopsis:	Return copy of base name in path string
961*5c51f124SMoriah Waterland  * Description:	Locate the base name (last path item) in a path and
962*5c51f124SMoriah Waterland  *		return a copy of the base name in allocated storage
963*5c51f124SMoriah Waterland  * Arguments:	a_path - [RO, *RO] - (char *)
964*5c51f124SMoriah Waterland  *			- Pointer to string representing path to scan
965*5c51f124SMoriah Waterland  * Returns:	char *
966*5c51f124SMoriah Waterland  *			- String containing path base name
967*5c51f124SMoriah Waterland  *			- == (char *)NULL - input path is (char *)NULL
968*5c51f124SMoriah Waterland  * NOTE:    	Any string returned is placed in new storage for the
969*5c51f124SMoriah Waterland  *		calling method. The caller must use 'free' to dispose
970*5c51f124SMoriah Waterland  *		of the storage once the string is no longer needed.
971*5c51f124SMoriah Waterland  * Errors:	If the string cannot be created, the process exits
972*5c51f124SMoriah Waterland  */
973*5c51f124SMoriah Waterland 
974*5c51f124SMoriah Waterland char *
975*5c51f124SMoriah Waterland pkgstrConvertPathToBasename(char *a_path)
976*5c51f124SMoriah Waterland {
977*5c51f124SMoriah Waterland 	char	*p;
978*5c51f124SMoriah Waterland 
979*5c51f124SMoriah Waterland 	/* if path is NULL, return NULL */
980*5c51f124SMoriah Waterland 
981*5c51f124SMoriah Waterland 	if (a_path == (char *)NULL) {
982*5c51f124SMoriah Waterland 		return ((char *)NULL);
983*5c51f124SMoriah Waterland 	}
984*5c51f124SMoriah Waterland 
985*5c51f124SMoriah Waterland 	/* if path is empty (zero length), return NULL */
986*5c51f124SMoriah Waterland 
987*5c51f124SMoriah Waterland 	if (*a_path == '\0') {
988*5c51f124SMoriah Waterland 		return ((char *)NULL);
989*5c51f124SMoriah Waterland 	}
990*5c51f124SMoriah Waterland 
991*5c51f124SMoriah Waterland 	/* locate last occurance of '/' in path */
992*5c51f124SMoriah Waterland 
993*5c51f124SMoriah Waterland 	p = strrchr(a_path, '/');
994*5c51f124SMoriah Waterland 	if (p == (char *)NULL) {
995*5c51f124SMoriah Waterland 		/* no occurance of '/' - entry path must be basename */
996*5c51f124SMoriah Waterland 
997*5c51f124SMoriah Waterland 		return (strdup(a_path));
998*5c51f124SMoriah Waterland 	}
999*5c51f124SMoriah Waterland 
1000*5c51f124SMoriah Waterland 	/* base name located - return string from -> first byte */
1001*5c51f124SMoriah Waterland 
1002*5c51f124SMoriah Waterland 	return (strdup(p+1));
1003*5c51f124SMoriah Waterland }
1004*5c51f124SMoriah Waterland 
1005*5c51f124SMoriah Waterland /*
1006*5c51f124SMoriah Waterland  * Name:	pkgstrConvertPathToDirname
1007*5c51f124SMoriah Waterland  * Synopsis:	Return copy of directory in path string
1008*5c51f124SMoriah Waterland  * Description:	Locate the directory name (everything but last path item) in a
1009*5c51f124SMoriah Waterland  *		path and return a copy of the dir name in allocated storage
1010*5c51f124SMoriah Waterland  * Arguments:	a_path - [RO, *RO] - (char *)
1011*5c51f124SMoriah Waterland  *			- Pointer to string representing path to scan
1012*5c51f124SMoriah Waterland  * Returns:	char *
1013*5c51f124SMoriah Waterland  *			- String containing path directory name
1014*5c51f124SMoriah Waterland  *			- == (char *)NULL - input path is (char *)NULL,
1015*5c51f124SMoriah Waterland  *			  or a_path is empty (*a_path == '\0'), or the
1016*5c51f124SMoriah Waterland  *			  a_path has no directory name in it.
1017*5c51f124SMoriah Waterland  * NOTE:    	Any string returned is placed in new storage for the
1018*5c51f124SMoriah Waterland  *		calling method. The caller must use 'free' to dispose
1019*5c51f124SMoriah Waterland  *		of the storage once the string is no longer needed.
1020*5c51f124SMoriah Waterland  * Errors:	If the string cannot be created, the process exits
1021*5c51f124SMoriah Waterland  */
1022*5c51f124SMoriah Waterland 
1023*5c51f124SMoriah Waterland char *
1024*5c51f124SMoriah Waterland pkgstrConvertPathToDirname(char *a_path)
1025*5c51f124SMoriah Waterland {
1026*5c51f124SMoriah Waterland 	char	*p;
1027*5c51f124SMoriah Waterland 	char	*retPath;
1028*5c51f124SMoriah Waterland 
1029*5c51f124SMoriah Waterland 	/* if path is NULL, return NULL */
1030*5c51f124SMoriah Waterland 
1031*5c51f124SMoriah Waterland 	if (a_path == (char *)NULL) {
1032*5c51f124SMoriah Waterland 		return ((char *)NULL);
1033*5c51f124SMoriah Waterland 	}
1034*5c51f124SMoriah Waterland 
1035*5c51f124SMoriah Waterland 	/* if path is empty (zero length), return NULL */
1036*5c51f124SMoriah Waterland 
1037*5c51f124SMoriah Waterland 	if (*a_path == '\0') {
1038*5c51f124SMoriah Waterland 		return ((char *)NULL);
1039*5c51f124SMoriah Waterland 	}
1040*5c51f124SMoriah Waterland 
1041*5c51f124SMoriah Waterland 	/* locate last occurance of '/' in path */
1042*5c51f124SMoriah Waterland 
1043*5c51f124SMoriah Waterland 	p = strrchr(a_path, '/');
1044*5c51f124SMoriah Waterland 	if (p == (char *)NULL) {
1045*5c51f124SMoriah Waterland 		/* no occurance of '/' - entire path must be basename */
1046*5c51f124SMoriah Waterland 
1047*5c51f124SMoriah Waterland 		return ((char *)NULL);
1048*5c51f124SMoriah Waterland 	}
1049*5c51f124SMoriah Waterland 
1050*5c51f124SMoriah Waterland 	/* duplicate original path */
1051*5c51f124SMoriah Waterland 
1052*5c51f124SMoriah Waterland 	retPath = strdup(a_path);
1053*5c51f124SMoriah Waterland 	assert(retPath != (char *)NULL);
1054*5c51f124SMoriah Waterland 	if (retPath == (char *)NULL) {
1055*5c51f124SMoriah Waterland 		return ((char *)NULL);
1056*5c51f124SMoriah Waterland 	}
1057*5c51f124SMoriah Waterland 
1058*5c51f124SMoriah Waterland 	/* remove all trailing '/'s from copy of path */
1059*5c51f124SMoriah Waterland 
1060*5c51f124SMoriah Waterland 	for (p = strrchr(retPath, '/');	(p > retPath) && (*p == '/'); p--) {
1061*5c51f124SMoriah Waterland 		*p = '\0';
1062*5c51f124SMoriah Waterland 	}
1063*5c51f124SMoriah Waterland 
1064*5c51f124SMoriah Waterland 	/* if entire path was '/'s, return null string - no directory present */
1065*5c51f124SMoriah Waterland 
1066*5c51f124SMoriah Waterland 	if (*retPath == '\0') {
1067*5c51f124SMoriah Waterland 		free(retPath);
1068*5c51f124SMoriah Waterland 		return ((char *)NULL);
1069*5c51f124SMoriah Waterland 	}
1070*5c51f124SMoriah Waterland 
1071*5c51f124SMoriah Waterland 	/* path has at least one non-'/' in it - return -> directory portion */
1072*5c51f124SMoriah Waterland 
1073*5c51f124SMoriah Waterland 	return (retPath);
1074*5c51f124SMoriah Waterland }
1075*5c51f124SMoriah Waterland 
1076*5c51f124SMoriah Waterland /*
1077*5c51f124SMoriah Waterland  * Name:	pkgstrConvertUllToTimeString_r
1078*5c51f124SMoriah Waterland  * Synopsis:	Convert an unsigned long long into a "time string"
1079*5c51f124SMoriah Waterland  * Description:	Given an unsigned long long, return a "time string" which is a
1080*5c51f124SMoriah Waterland  *		conversion of the unsigned long long interpreted as a number of
1081*5c51f124SMoriah Waterland  *		nanoseconds into a "hour:minute:second.ns" ascii string
1082*5c51f124SMoriah Waterland  * Arguments:	a_time - [RO, *RO] - (unsigned long long)n
1083*5c51f124SMoriah Waterland  *			- value to convert
1084*5c51f124SMoriah Waterland  *		a_buf - [RO, *RW] - (char *)
1085*5c51f124SMoriah Waterland  *			- Pointer to buffer used as storage space for the
1086*5c51f124SMoriah Waterland  *			  returned string
1087*5c51f124SMoriah Waterland  *		a_bufLen - [RO, *RO] - (int)
1088*5c51f124SMoriah Waterland  *			- Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1'
1089*5c51f124SMoriah Waterland  *			  bytes will be placed in 'a_buf'
1090*5c51f124SMoriah Waterland  * Returns:	char *
1091*5c51f124SMoriah Waterland  *			- String containing converted value
1092*5c51f124SMoriah Waterland  * NOTE:    	Any string returned is placed in new storage for the
1093*5c51f124SMoriah Waterland  *		calling method. The caller must use 'free' to dispose
1094*5c51f124SMoriah Waterland  *		of the storage once the string is no longer needed.
1095*5c51f124SMoriah Waterland  * Errors:	If the string cannot be created, the process exits
1096*5c51f124SMoriah Waterland  */
1097*5c51f124SMoriah Waterland 
1098*5c51f124SMoriah Waterland void
1099*5c51f124SMoriah Waterland pkgstrConvertUllToTimeString_r(unsigned long long a_time,
1100*5c51f124SMoriah Waterland 	char *a_buf, int a_bufLen)
1101*5c51f124SMoriah Waterland {
1102*5c51f124SMoriah Waterland 	unsigned long long	seconds;
1103*5c51f124SMoriah Waterland 	unsigned long long	minutes;
1104*5c51f124SMoriah Waterland 	unsigned long long	hours;
1105*5c51f124SMoriah Waterland 	unsigned long long	ns;
1106*5c51f124SMoriah Waterland 
1107*5c51f124SMoriah Waterland 	/* entry assertions */
1108*5c51f124SMoriah Waterland 
1109*5c51f124SMoriah Waterland 	assert(a_buf != (char *)NULL);
1110*5c51f124SMoriah Waterland 	assert(a_bufLen > 0);
1111*5c51f124SMoriah Waterland 
1112*5c51f124SMoriah Waterland 	/* if time is 0, return immediate result */
1113*5c51f124SMoriah Waterland 
1114*5c51f124SMoriah Waterland 	if (a_time == 0) {
1115*5c51f124SMoriah Waterland 		pkgstrPrintf_r(a_buf, a_bufLen, "%s", "0:00:00.000000000");
1116*5c51f124SMoriah Waterland 		return;
1117*5c51f124SMoriah Waterland 	}
1118*5c51f124SMoriah Waterland 
1119*5c51f124SMoriah Waterland 	/* break out individual time components */
1120*5c51f124SMoriah Waterland 
1121*5c51f124SMoriah Waterland 	ns = a_time % 1000000000ll;	/* nanoseconds left over from seconds */
1122*5c51f124SMoriah Waterland 	seconds = a_time / 1000000000ll;	/* total seconds */
1123*5c51f124SMoriah Waterland 	minutes = seconds / 60ll;	/* total minutes */
1124*5c51f124SMoriah Waterland 	seconds = seconds % 60ll;	/* seconds left over from minutes */
1125*5c51f124SMoriah Waterland 	hours = minutes / 60ll;		/* total hours */
1126*5c51f124SMoriah Waterland 	minutes = minutes % 60ll;	/* minutes left over from hours */
1127*5c51f124SMoriah Waterland 
1128*5c51f124SMoriah Waterland 	/* return a converted string */
1129*5c51f124SMoriah Waterland 
1130*5c51f124SMoriah Waterland 	pkgstrPrintf_r(a_buf, a_bufLen, "%llu:%02llu:%02llu.%09llu",
1131*5c51f124SMoriah Waterland 						hours, minutes, seconds, ns);
1132*5c51f124SMoriah Waterland }
1133