diff options
author | Moriah Waterland <Moriah.Waterland@Sun.COM> | 2009-06-03 20:16:25 -0600 |
---|---|---|
committer | Moriah Waterland <Moriah.Waterland@Sun.COM> | 2009-06-03 20:16:25 -0600 |
commit | 5c51f1241dbbdf2656d0e10011981411ed0c9673 (patch) | |
tree | 0f30a2e38fe4e5d53a5a67264ba548577d82a86f /usr/src/lib/libpkg/common/pkgstr.c | |
parent | 2b79d384d32b4ea1e278466cd9b0f3bb56daae22 (diff) | |
download | illumos-joyent-5c51f1241dbbdf2656d0e10011981411ed0c9673.tar.gz |
6739234 move SVR4 packaging to ONNV gate
Diffstat (limited to 'usr/src/lib/libpkg/common/pkgstr.c')
-rw-r--r-- | usr/src/lib/libpkg/common/pkgstr.c | 1132 |
1 files changed, 1132 insertions, 0 deletions
diff --git a/usr/src/lib/libpkg/common/pkgstr.c b/usr/src/lib/libpkg/common/pkgstr.c new file mode 100644 index 0000000000..8df053e570 --- /dev/null +++ b/usr/src/lib/libpkg/common/pkgstr.c @@ -0,0 +1,1132 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * Module: pkgstr.c + * Synopsis: general string services + * Taxonomy: project private + * Debug Flag: str + * Description: + * + * This module implements general string utility services + * + * Public Methods: + * + * pkgstrAddToken - Add a token to a string + * pkgstrContainsToken - Determine if a string contains a specified token + * pkgstrConvertPathToBasename - Return copy of base name in path string + * pkgstrConvertPathToDirname - Return copy of directory name in path string + * pkgstrConvertUllToTimeString_r - convert unsigned long long to time string + * pkgstrExpandTokens - Expand tokens from string appending tokens to another + * pkgstrGetToken - Get a token from a string + * pkgstrGetToken_r - Get a token from a string into a fixed buffer + * pkgstrLocatePathBasename - Locate position of base name in path string + * pkgstrNumTokens - Determine number of tokens in string + * pkgstrPrintf - Create a string from a printf style format and arguments + * pkgstrPrintf_r - Create a string from a printf style format and arguments + * into a fixed buffer + * pkgstrRemoveToken - Remove a token from a string + * pkgstrRemoveLeadingWhitespace - remove leading whitespace from string + * pkgstrScaleNumericString - Convert unsigned long long to human + * readable form + */ + +/* + * Unix Includes + */ + +#define __EXTENSIONS__ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libintl.h> +#include <limits.h> +#include <sys/types.h> +#include <assert.h> +#include <errno.h> +#include <libintl.h> +#include <ctype.h> +#include <unistd.h> +#include <strings.h> +#include <stdarg.h> + +/* + * pkglib Includes + */ + +#include "pkglib.h" +#include "pkgstrct.h" +#include "libintl.h" +#include "pkglocale.h" + +/* + * External definitions + */ + +/* + * Public methods + */ + +/* + * Name: pkgstrRemoveLeadingWhitespace + * Synopsis: Remove leading whitespace from string + * Description: Remove all leading whitespace characters from a string + * Arguments: a_str - [RO, *RW] - (char **) + * Pointer to handle to string (in allocated storage) to + * remove all leading whitespace from + * Returns: void + * The input string is modified as follows: + * == (char *)NULL: + * - input string was (char *)NULL + * - input string is all whitespace + * != (char *)NULL: + * - copy of input string with leading + * whitespace removed + * CAUTION: The input string must be allocated space (via mem* or + * pkgstr* methods) - it must not be a static or inline + * character string + * NOTE: The input string a_str will be freed with 'free' + * if it is all whitespace, or if it contains any leading + * whitespace characters + * NOTE: Any string returned is placed in new storage for the + * calling method. The caller must use 'free' to dispose + * of the storage once the string is no longer needed. + * Errors: If the string cannot be created, the process exits + */ + +void +pkgstrRemoveLeadingWhitespace(char **a_str) +{ + char *o_str; + + /* entry assertions */ + + assert(a_str != (char **)NULL); + + /* if string is null, just return */ + + if (*a_str == (char *)NULL) { + return; + } + o_str = *a_str; + + /* if string is empty, deallocate and return NULL */ + + if (*o_str == '\0') { + /* free string - handle is reset to NULL by free */ + free(*a_str); + *a_str = (char *)NULL; + return; + } + + /* if first character is not a space, just return */ + + if (!isspace(*o_str)) { + return; + } + + /* advance past all space characters */ + + while ((*o_str != '\0') && (isspace(*o_str))) { + o_str++; + } + + /* if string was all space characters, deallocate and return NULL */ + + if (*o_str == '\0') { + /* free string - *a_str is reset to NULL by free */ + free(*a_str); + *a_str = (char *)NULL; + return; + } + + /* have non-space/null byte, return dup, deallocate original */ + + o_str = strdup(o_str); + assert(o_str != (char *)NULL); + if (o_str != (char *)NULL) { + free(*a_str); + *a_str = o_str; + } +} + +unsigned long +pkgstrNumTokens(char *a_string, char *a_separators) +{ + int index; + + if (a_string == (char *)NULL) { + return (0); + } + + if (*a_string == '\0') { + return (0); + } + + for (index = 0 ; ; index ++) { + char *p; + + p = pkgstrGetToken((char *)NULL, a_string, index, a_separators); + if (p == (char *)NULL) { + return (index); + } + free(p); + } +} + +/* + * Name: pkgstrPrintf_r + * Synopsis: Create string from printf style format and arguments + * Description: Call to convert a printf style format and arguments into a + * string of characters placed in allocated storage + * Arguments: a_buf - [RO, *RW] - (char *) + * - Pointer to buffer used as storage space for the + * returned string created + * a_bufLen - [RO, *RO] - (int) + * - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1' + * bytes will be placed in 'a_buf' - the returned + * string is always null terminated + * a_format - [RO, RO*] (char *) + * printf-style format for string to be formatted + * VARG_LIST - [RO] (?) + * arguments as appropriate to 'format' specified + * Returns: void + */ + +/*PRINTFLIKE3*/ +void +pkgstrPrintf_r(char *a_buf, int a_bufLen, char *a_format, ...) +{ + va_list ap; + size_t vres = 0; + + /* entry assertions */ + + assert(a_format != (char *)NULL); + assert(*a_format != '\0'); + assert(a_buf != (char *)NULL); + assert(a_bufLen > 1); + + /* generate the results of the printf conversion */ + + va_start(ap, a_format); + vres = vsnprintf(a_buf, a_bufLen-1, a_format, ap); + va_end(ap); + + assert(vres > 0); + assert(vres < a_bufLen); + + a_buf[a_bufLen-1] = '\0'; +} + +/* + * Name: pkgstrPrintf + * Synopsis: Create string from printf style format and arguments + * Description: Call to convert a printf style format and arguments into a + * string of characters placed in allocated storage + * Arguments: format - [RO, RO*] (char *) + * printf-style format for string to be formatted + * VARG_LIST - [RO] (?) + * arguments as appropriate to 'format' specified + * Returns: char * + * A string representing the printf conversion results + * NOTE: Any string returned is placed in new storage for the + * calling method. The caller must use 'free' to dispose + * of the storage once the string is no longer needed. + * Errors: If the string cannot be created, the process exits + */ + +/*PRINTFLIKE1*/ +char * +pkgstrPrintf(char *a_format, ...) +{ + va_list ap; + size_t vres = 0; + char bfr[1]; + char *rstr = (char *)NULL; + + /* entry assertions */ + + assert(a_format != (char *)NULL); + assert(*a_format != '\0'); + + /* determine size of the message in bytes */ + + va_start(ap, a_format); + vres = vsnprintf(bfr, 1, a_format, ap); + va_end(ap); + + assert(vres > 0); + assert(vres < LINE_MAX); + + /* allocate storage to hold the message */ + + rstr = (char *)calloc(1, vres+2); + assert(rstr != (char *)NULL); + if (rstr == (char *)NULL) { + return ((char *)NULL); + } + + /* generate the results of the printf conversion */ + + va_start(ap, a_format); + vres = vsnprintf(rstr, vres+1, a_format, ap); + va_end(ap); + + assert(vres > 0); + assert(vres < LINE_MAX); + assert(*rstr != '\0'); + + /* return the results */ + + return (rstr); +} + +/* + * Name: pkgstrExpandTokens + * Synopsis: Expand tokens from string appending tokens to another + * Description: Given a string and a list of one or more separators, + * expand each token from the string and append those tokens + * to a string that is in allocated space - create new string + * if no string to append to exists. + * Arguments: a_old - [RO, *RW] - (char **) + * - Pointer to handle to string to append token to + * == (char *)NULL - new string is created + * a_separator - [RO, *RO] - (char *) + * - separator to end tokens returned + * a_separators - [RO, *RO] - (char *) + * - String containing one or more characters that + * can separate one "token" from a_string from another + * Returns: void + * NOTE: Any token string returned is placed in new storage for the + * calling method. The caller must use 'free' to dispose + * of the storage once the token string is no longer needed. + */ + +void +pkgstrExpandTokens(char **a_old, char *a_string, char a_separator, + char *a_separators) +{ + int i; + char sep[2] = {'\0', '\0'}; + + /* convert single separator character into character string */ + + sep[0] = a_separator; + + /* + * iterate extracting tokens from the source string and adding + * those tokens to the target string when the tokens are not + * already present in the target string + */ + + for (i = 0; ; i++) { + char *p; + + /* extract the next matching token from the source string */ + + p = pkgstrGetToken((char *)NULL, a_string, i, a_separators); + + /* return if no token is available */ + + if (p == (char *)NULL) { + return; + } + + /* + * obtained token from source string: if the token is not + * in the target string, add the token to the target string + */ + + if (pkgstrContainsToken(*a_old, p, sep) == B_FALSE) { + pkgstrAddToken(a_old, p, *sep); + } + + /* free up temporary storage used by token from source string */ + + free(p); + } + /*NOTREACHED*/ +} + + +/* + * Name: pkgstrGetToken + * Synopsis: Get a separator delimited token from a string + * Description: Given a string and a list of one or more separators, + * return the position specified token (sequence of one or + * more characters that do not include any of the separators) + * Arguments: r_sep - [*RW] - (char *) + * - separator that ended the token returned + * - NOTE: this is a pointer to a "char", e.g.: + * - char a; + * - pkgstrGetToken(&a, ...) + * a_string - [RO, *RO] - (char *) + * - pointer to string to extract token from + * a_index - [RO, *RO] - (int) + * - Index of token to return; '0' is first matching + * token, '1' is second matching token, etc. + * a_separators - [RO, *RO] - (char *) + * - String containing one or more characters that + * can separate one "token" from another + * Returns: char * + * == (char *)NULL - no token matching criteria found + * != (char *)NULL - token matching criteria + * NOTE: Any token string returned is placed in new storage for the + * calling method. The caller must use 'free' to dispose + * of the storage once the token string is no longer needed. + */ + +char * +pkgstrGetToken(char *r_sep, char *a_string, int a_index, char *a_separators) +{ + char *p; + char *q; + char *lasts; + + /* entry assertions */ + + assert(a_string != (char *)NULL); + assert(a_index >= 0); + assert(a_separators != (char *)NULL); + assert(*a_separators != '\0'); + + /* if returned separator requested, reset to null until token found */ + + if (r_sep != (char *)NULL) { + *r_sep = '\0'; + } + + /* duplicate original string before breaking down into tokens */ + + p = strdup(a_string); + assert(p != (char *)NULL); + if (p == (char *)NULL) { + return ((char *)NULL); + } + lasts = p; + + /* scan for separators and return 'index'th token found */ + + while (q = strtok_r((char *)NULL, a_separators, &lasts)) { + /* retrieve separator if requested */ + + if (r_sep != (char *)NULL) { + char *x; + + x = strpbrk(a_string, a_separators); + if (x) { + *r_sep = *x; + } + } + + /* if this is the 'index'th token requested return it */ + + if (a_index-- == 0) { + char *tmp; + + /* duplicate token into its own storage */ + + tmp = strdup(q); + assert(tmp != (char *)NULL); + if (tmp == (char *)NULL) { + return ((char *)NULL); + } + + /* free up copy of original input string */ + + free(p); + + /* return token found */ + + return (tmp); + } + } + + /* + * token not found + */ + + /* free up copy of original input string */ + + free(p); + + /* return NULL pointer (token not found) */ + + return ((char *)NULL); +} + +/* + * Name: pkgstrGetToken + * Synopsis: Get separator delimited token from a string into a fixed buffer + * Description: Given a string and a list of one or more separators, + * return the position specified token (sequence of one or + * more characters that do not include any of the separators) + * into a specified buffer of a fixed maximum size + * Arguments: r_sep - [*RW] - (char *) + * - separator that ended the token returned + * - NOTE: this is a pointer to a "char", e.g.: + * - char a; + * - pkgstrGetToken(&a, ...) + * a_string - [RO, *RO] - (char *) + * - pointer to string to extract token from + * a_index - [RO, *RO] - (int) + * - Index of token to return; '0' is first matching + * token, '1' is second matching token, etc. + * a_separators - [RO, *RO] - (char *) + * - String containing one or more characters that + * can separate one "token" from another + * a_buf - [RO, *RW] - (char *) + * - Pointer to buffer used as storage space for the + * returned token - the returned token is always + * null terminated + * a_buf[0] == '\0' - no token meeting criteria found + * a_buf[0] != '\0' - token meeting criteria returned + * a_bufLen - [RO, *RO] - (int) + * - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1' + * bytes will be placed in 'a_buf' - the returned + * token is always null terminated + * Returns: void + */ + +void +pkgstrGetToken_r(char *r_sep, char *a_string, int a_index, + char *a_separators, char *a_buf, int a_bufLen) +{ + char *p; + char *q; + char *lasts; + + /* entry assertions */ + + assert(a_string != (char *)NULL); + assert(a_index >= 0); + assert(a_separators != (char *)NULL); + assert(*a_separators != '\0'); + assert(a_buf != (char *)NULL); + assert(a_bufLen > 0); + + /* reset returned separator */ + + if (r_sep != (char *)NULL) { + *r_sep = '\0'; + } + + /* zero out contents of return buffer */ + + bzero(a_buf, a_bufLen); + + /* duplicate original string before breaking down into tokens */ + + p = strdup(a_string); + assert(p != (char *)NULL); + if (p == (char *)NULL) { + return; + } + lasts = p; + + /* scan for separators and return 'index'th token found */ + + while (q = strtok_r((char *)NULL, a_separators, &lasts)) { + /* retrieve separator if requested */ + + if (r_sep != (char *)NULL) { + char *x; + x = strpbrk(a_string, a_separators); + if (x) { + *r_sep = *x; + } + } + + /* if this is the 'index'th token requested return it */ + + if (a_index-- == 0) { + /* copy as many characters as possible to return buf */ + + (void) strncpy(a_buf, q, a_bufLen-1); + break; + } + } + + /* free up copy of original input string */ + + free(p); +} + +/* + * Name: pkgstrAddToken + * Synopsis: Add a token to a string + * Description: Append a token (sequence of one or more characters) to a + * string that is in allocated space - create new string if + * no string to append to exists + * Arguments: a_old - [RO, *RW] - (char **) + * - Pointer to handle to string to append token to + * == (char *)NULL - new string is created + * a_new - [RO, *RO] - (char *) + * - Pointer to string representing token to append + * to the end of the "a_old" string + * == (char *)NULL - no action is performed + * a_new[0] == '\0' - no action is performed + * a_separator - [RO, *RO] - (char) + * - One character placed between the old (existing) + * string and the new token to be added IF the old + * string exists and is not empty (zero length) + * Returns: void + * CAUTION: The old (existing) string must be allocated space (via lu_mem* + * or pkgstr* methods) - it must not be a static or inline + * character string + * NOTE: The old (existing) string may be freed with 'free' + * if a token is appended to it + * NOTE: Any string returned in 'a_old' is placed in new storage for the + * calling method. The caller must use 'free' to dispose + * of the storage once the token string is no longer needed. + */ + +void +pkgstrAddToken(char **a_old, char *a_new, char a_separator) +{ + /* entry assertions */ + + assert(a_old != (char **)NULL); + assert(a_separator != '\0'); + + /* if token to add is null, just return */ + + if (a_new == (char *)NULL) { + return; + } + + /* if token to add is empty (zero length), just return */ + + if (*a_new == '\0') { + return; + } + + /* make sure that new token does not contain the separator */ + + assert(strchr(a_new, (int)a_separator) == (char *)NULL); + + /* if old string is empty (zero length), deallocate */ + + if ((*a_old != (char *)NULL) && ((*a_old)[0] == '\0')) { + /* *a_old is set to NULL by free */ + free(*a_old); + *a_old = (char *)NULL; + } + + /* if old string is exists, append separator and token */ + + if (*a_old != (char *)NULL) { + char *p; + p = pkgstrPrintf("%s%c%s", *a_old, a_separator, a_new); + free(*a_old); + *a_old = p; + return; + } + + /* old string does not exist - return duplicate of token */ + + assert(*a_old == (char *)NULL); + *a_old = strdup(a_new); + assert(*a_old != (char *)NULL); +} + +/* + * Name: pkgstrContainsToken + * Synopsis: Does a given string contain a specified substring + * Description: Determine if a given substring exists in a larger string + * Arguments: a_string - [RO, *RO] - (char *) + * Pointer to string to look for substring in + * a_token - [RO, *RO] - (char *) + * Pointer to substring to look for in larger string + * Results: boolean_t + * B_TRUE - substring exists in larger string + * B_FALSE - substring does NOT exist in larger string + * NOTE: The substring must match on a "token" basis; that is, the + * substring must exist in the larger string delineated with + * either spaces or tabs to match. + */ + +boolean_t +pkgstrContainsToken(char *a_string, char *a_token, char *a_separators) +{ + char *lasts; + char *current; + char *p; + + /* entry assertions */ + + assert(a_separators != (char *)NULL); + assert(*a_separators != '\0'); + + /* if token is not supplied, return false */ + + if (a_token == (char *)NULL) { + return (B_FALSE); + } + + /* if no string provided, return false */ + + if (a_string == (char *)NULL) { + return (B_FALSE); + } + + /* if string empty (zero length), return false */ + + if (*a_string == '\0') { + return (B_FALSE); + } + + /* duplicate larger string because strtok_r changes it */ + + p = strdup(a_string); + assert(p != (char *)NULL); + if (p == (char *)NULL) { + return (B_FALSE); + } + + lasts = p; + + /* scan each token looking for a match */ + + while ((current = strtok_r((char *)NULL, a_separators, &lasts)) != + (char *)NULL) { + if (streq(current, a_token)) { + free(p); + return (B_TRUE); + } + } + + /* free up temporary storage */ + + free(p); + + /* not found */ + + return (B_FALSE); +} + +/* + * Name: pkgstrRemoveToken + * Synopsis: Remove a token from a string + * Description: Remove a token (sequence of one or more characters) from a + * string that is in allocated space + * Arguments: r_string - [RO, *RW] - (char **) + * - Pointer to handle to string to remove token from + * a_token - [RO, *RO] - (char *) + * Pointer to token (substring) to look for and remove + * from r_string provided + * a_separators - [RO, *RO] - (char *) + * - String containing one or more characters that + * separate one "token" from another in r_string + * a_index - [RO, *RO] - (int) + * - Index of token to remove; '0' is first matching + * token, '1' is second matching token, etc. + * Returns: void + * CAUTION: The input string must be allocated space (via lu_mem* or + * pkgstr* methods) - it must not be a static or inline + * character string + * NOTE: The input string r_string will be freed with 'free' + * if the token to be removed is found + * NOTE: Any token string returned is placed in new storage for the + * calling method. The caller must use 'free' to dispose + * of the storage once the token string is no longer needed. + * Errors: If the new token string cannot be created, the process exits + */ + +void +pkgstrRemoveToken(char **r_string, char *a_token, char *a_separators, + int a_index) +{ + char *a_string; + char *copyString; + char sep = 0; + int copyLength; + int i; + + /* entry assertions */ + + assert(r_string != (char **)NULL); + assert(a_token != (char *)NULL); + assert(*a_token != '\0'); + assert(a_separators != (char *)NULL); + assert(*a_separators != '\0'); + + /* simple case: input string is null; return empty string */ + + a_string = *r_string; + if (*a_string == '\0') { + return; + } + + /* simple case: token == input string; return empty string */ + + if (streq(a_string, a_token)) { + /* deallocate input string; free sets *r_string to NULL */ + + free(*r_string); + *r_string = (char *)NULL; + return; + } + + /* simple case: token not in input string: return */ + + if (!pkgstrContainsToken(a_string, a_token, a_separators)) { + return; + } + + /* + * Pick apart the old string building the new one as we go along + * removing the first occurance of the token provided + */ + + copyLength = (strlen(a_string)-strlen(a_token))+2; + copyString = calloc(1, copyLength); + assert(copyString != (char *)NULL); + if (copyString == (char *)NULL) { + return; + } + + for (i = 0; ; i++) { + char *p; + + p = pkgstrGetToken(&sep, a_string, i, a_separators); + if (p == (char *)NULL) { + break; + } + + if (streq(p, a_token) && (a_index-- == 0)) { + continue; + } + + if (*copyString) { + assert(sep != '\0'); + (void) strncat(copyString, &sep, 1); + } + + (void) strcat(copyString, p); + } + + free(*r_string); + assert(*copyString); + *r_string = copyString; +} + +/* + * Name: pkgstrScaleNumericString + * Synopsis: Convert unsigned long long to human readable form + * Description: Convert a string containing an unsigned long long representation + * and convert it into a human readable numeric string. The number + * is scaled down until it is small enough to be in a good human + * readable format i.e. in the range 0 thru scale-1. + * Arguments: a_buf - [RO, *RW] - (char *) + * Pointer to buffer containing string representation + * of unsigned long long to convert + * scale - [RO, *RO] - (unsigned long long) + * Value to scale the number into + * Returns: a_buf - contains human readable scaled representation of + * original value contained in the buffer + * Note: The value "(unsigned long long)-1" is a special case and + * is always converted to "-1". + * Errors: If the string cannot be created, the process exits + */ + +void +pkgstrScaleNumericString(char *a_buf, unsigned long long scale) +{ +static char *M = " KMGTPE"; /* Measurement: */ + /* kilo, mega, giga, tera, peta, exa */ + + unsigned long long number = 0; /* convert this number */ + unsigned long long save = 0; + char *uom = M; /* unit of measurement, initially ' ' (=M[0]) */ + + /* entry assertions */ + + assert(scale > (unsigned long long)0); + assert(scale <= (unsigned long long)1048576); + + /* + * Get the number - if no number of empty number, just return + */ + + if (a_buf == (char *)NULL) { + return; + } + + if (*a_buf == '\0') { + (void) strcpy(a_buf, "0"); + return; + } + + /* convert out the number from the input buffer */ + + number = strtoull(a_buf, (char **)NULL, 10); + + /* if conversion error, return "-1" */ + + if ((long long)number == (long long)-1) { + (void) strcpy(a_buf, "-1"); + return; + } + + /* + * Now have number as a count of scale units. + * Stop scaling when we reached exa-bytes, then something is + * probably wrong with our number (it is improbably large) + */ + + while ((number >= scale) && (*uom != 'E')) { + uom++; /* next unit of measurement */ + save = number; + number = (number + (scale / 2)) / scale; + } + + /* check if we should output a decimal place after the point */ + + if (save && ((save / scale) < 10)) { + /* sprintf() will round for us */ + float fnum = (float)save / scale; + (void) sprintf(a_buf, "%4.1f%c", fnum, *uom); + } else { + (void) sprintf(a_buf, "%4llu%c", number, *uom); + } +} + +/* + * Name: pkgstrLocatePathBasename + * Synopsis: Locate position of base name in path string + * Description: Locate the base name (last path item) in a path and + * return a pointer to the first byte of the base name + * within the given path + * Arguments: a_path - [RO, *RO] - (char *) + * - Pointer to string representing path to scan + * Returns: char * + * - Pointer into string of first byte of path base name + * - == (char *)NULL - input path is (char *)NULL + */ + +char * +pkgstrLocatePathBasename(char *a_path) +{ + char *p; + + /* if path is NULL, return NULL */ + + if (!a_path) { + return (a_path); + } + + /* locate last occurance of '/' in path */ + + p = strrchr(a_path, '/'); + if (p != (char *)NULL) { + /* base name located - return -> first byte */ + return (p+1); + } + + /* no occurance of '/' - entry path must be basename */ + + return (a_path); +} + +/* + * Name: pkgstrConvertPathToBasename + * Synopsis: Return copy of base name in path string + * Description: Locate the base name (last path item) in a path and + * return a copy of the base name in allocated storage + * Arguments: a_path - [RO, *RO] - (char *) + * - Pointer to string representing path to scan + * Returns: char * + * - String containing path base name + * - == (char *)NULL - input path is (char *)NULL + * NOTE: Any string returned is placed in new storage for the + * calling method. The caller must use 'free' to dispose + * of the storage once the string is no longer needed. + * Errors: If the string cannot be created, the process exits + */ + +char * +pkgstrConvertPathToBasename(char *a_path) +{ + char *p; + + /* if path is NULL, return NULL */ + + if (a_path == (char *)NULL) { + return ((char *)NULL); + } + + /* if path is empty (zero length), return NULL */ + + if (*a_path == '\0') { + return ((char *)NULL); + } + + /* locate last occurance of '/' in path */ + + p = strrchr(a_path, '/'); + if (p == (char *)NULL) { + /* no occurance of '/' - entry path must be basename */ + + return (strdup(a_path)); + } + + /* base name located - return string from -> first byte */ + + return (strdup(p+1)); +} + +/* + * Name: pkgstrConvertPathToDirname + * Synopsis: Return copy of directory in path string + * Description: Locate the directory name (everything but last path item) in a + * path and return a copy of the dir name in allocated storage + * Arguments: a_path - [RO, *RO] - (char *) + * - Pointer to string representing path to scan + * Returns: char * + * - String containing path directory name + * - == (char *)NULL - input path is (char *)NULL, + * or a_path is empty (*a_path == '\0'), or the + * a_path has no directory name in it. + * NOTE: Any string returned is placed in new storage for the + * calling method. The caller must use 'free' to dispose + * of the storage once the string is no longer needed. + * Errors: If the string cannot be created, the process exits + */ + +char * +pkgstrConvertPathToDirname(char *a_path) +{ + char *p; + char *retPath; + + /* if path is NULL, return NULL */ + + if (a_path == (char *)NULL) { + return ((char *)NULL); + } + + /* if path is empty (zero length), return NULL */ + + if (*a_path == '\0') { + return ((char *)NULL); + } + + /* locate last occurance of '/' in path */ + + p = strrchr(a_path, '/'); + if (p == (char *)NULL) { + /* no occurance of '/' - entire path must be basename */ + + return ((char *)NULL); + } + + /* duplicate original path */ + + retPath = strdup(a_path); + assert(retPath != (char *)NULL); + if (retPath == (char *)NULL) { + return ((char *)NULL); + } + + /* remove all trailing '/'s from copy of path */ + + for (p = strrchr(retPath, '/'); (p > retPath) && (*p == '/'); p--) { + *p = '\0'; + } + + /* if entire path was '/'s, return null string - no directory present */ + + if (*retPath == '\0') { + free(retPath); + return ((char *)NULL); + } + + /* path has at least one non-'/' in it - return -> directory portion */ + + return (retPath); +} + +/* + * Name: pkgstrConvertUllToTimeString_r + * Synopsis: Convert an unsigned long long into a "time string" + * Description: Given an unsigned long long, return a "time string" which is a + * conversion of the unsigned long long interpreted as a number of + * nanoseconds into a "hour:minute:second.ns" ascii string + * Arguments: a_time - [RO, *RO] - (unsigned long long)n + * - value to convert + * a_buf - [RO, *RW] - (char *) + * - Pointer to buffer used as storage space for the + * returned string + * a_bufLen - [RO, *RO] - (int) + * - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1' + * bytes will be placed in 'a_buf' + * Returns: char * + * - String containing converted value + * NOTE: Any string returned is placed in new storage for the + * calling method. The caller must use 'free' to dispose + * of the storage once the string is no longer needed. + * Errors: If the string cannot be created, the process exits + */ + +void +pkgstrConvertUllToTimeString_r(unsigned long long a_time, + char *a_buf, int a_bufLen) +{ + unsigned long long seconds; + unsigned long long minutes; + unsigned long long hours; + unsigned long long ns; + + /* entry assertions */ + + assert(a_buf != (char *)NULL); + assert(a_bufLen > 0); + + /* if time is 0, return immediate result */ + + if (a_time == 0) { + pkgstrPrintf_r(a_buf, a_bufLen, "%s", "0:00:00.000000000"); + return; + } + + /* break out individual time components */ + + ns = a_time % 1000000000ll; /* nanoseconds left over from seconds */ + seconds = a_time / 1000000000ll; /* total seconds */ + minutes = seconds / 60ll; /* total minutes */ + seconds = seconds % 60ll; /* seconds left over from minutes */ + hours = minutes / 60ll; /* total hours */ + minutes = minutes % 60ll; /* minutes left over from hours */ + + /* return a converted string */ + + pkgstrPrintf_r(a_buf, a_bufLen, "%llu:%02llu:%02llu.%09llu", + hours, minutes, seconds, ns); +} |