xref: /onnv-gate/usr/src/cmd/prctl/utils.c (revision 13093:48f2dbca79a2)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
54891Svk199839  * Common Development and Distribution License (the "License").
64891Svk199839  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*13093SRoger.Faulkner@Oracle.COM 
220Sstevel@tonic-gate /*
23*13093SRoger.Faulkner@Oracle.COM  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/param.h>
270Sstevel@tonic-gate #include <libintl.h>
280Sstevel@tonic-gate #include <string.h>
290Sstevel@tonic-gate #include <stdlib.h>
300Sstevel@tonic-gate #include <stdarg.h>
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <errno.h>
330Sstevel@tonic-gate #include <strings.h>
340Sstevel@tonic-gate #include <sys/types.h>
350Sstevel@tonic-gate #include <limits.h>
360Sstevel@tonic-gate #include "utils.h"
370Sstevel@tonic-gate 
380Sstevel@tonic-gate static char PNAME_FMT[] = "%s: ";
390Sstevel@tonic-gate static char ERRNO_FMT[] = ": %s\n";
400Sstevel@tonic-gate static char EOL_FMT[] = "\n";
410Sstevel@tonic-gate 
420Sstevel@tonic-gate static char *pname;
430Sstevel@tonic-gate 
440Sstevel@tonic-gate char *
setpname(char * arg0)45*13093SRoger.Faulkner@Oracle.COM setpname(char *arg0)
460Sstevel@tonic-gate {
470Sstevel@tonic-gate 	char *p = strrchr(arg0, '/');
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 	if (p == NULL)
500Sstevel@tonic-gate 		p = arg0;
510Sstevel@tonic-gate 	else
520Sstevel@tonic-gate 		p++;
530Sstevel@tonic-gate 	pname = p;
540Sstevel@tonic-gate 	return (pname);
550Sstevel@tonic-gate }
560Sstevel@tonic-gate 
570Sstevel@tonic-gate /*PRINTFLIKE1*/
580Sstevel@tonic-gate void
warn(const char * format,...)594891Svk199839 warn(const char *format, ...)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate 	int err = errno;
620Sstevel@tonic-gate 	va_list alist;
630Sstevel@tonic-gate 	if (pname != NULL)
640Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(PNAME_FMT), pname);
650Sstevel@tonic-gate 	va_start(alist, format);
660Sstevel@tonic-gate 	(void) vfprintf(stderr, format, alist);
670Sstevel@tonic-gate 	va_end(alist);
680Sstevel@tonic-gate 	if (strchr(format, '\n') == NULL)
690Sstevel@tonic-gate 		if (err)
700Sstevel@tonic-gate 			(void) fprintf(stderr,
710Sstevel@tonic-gate 			    gettext(ERRNO_FMT), strerror(err));
720Sstevel@tonic-gate 		else
730Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(EOL_FMT));
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 
760Sstevel@tonic-gate }
770Sstevel@tonic-gate 
780Sstevel@tonic-gate static char *__metric_modifiers[] = { "K", "M", "G", "T", "P", "E", NULL };
790Sstevel@tonic-gate static uint64_t __metric_scales[] = {
800Sstevel@tonic-gate     1000LLU,
810Sstevel@tonic-gate     1000LLU * 1000,
820Sstevel@tonic-gate     1000LLU * 1000 * 1000,
830Sstevel@tonic-gate     1000LLU * 1000 * 1000 * 1000,
840Sstevel@tonic-gate     1000LLU * 1000 * 1000 * 1000 * 1000,
850Sstevel@tonic-gate     1000LLU * 1000 * 1000 * 1000 * 1000 * 1000
860Sstevel@tonic-gate };
870Sstevel@tonic-gate static scale_t __metric_scale = { __metric_modifiers, __metric_scales };
880Sstevel@tonic-gate 
890Sstevel@tonic-gate static char *__binary_modifiers[] = {"K", "M", "G", "T", "P", "E", NULL};
900Sstevel@tonic-gate static uint64_t __binary_scales[] = {
910Sstevel@tonic-gate     1024LLU,
920Sstevel@tonic-gate     1024LLU * 1024,
930Sstevel@tonic-gate     1024LLU * 1024 * 1024,
940Sstevel@tonic-gate     1024LLU * 1024 * 1024 * 1024,
950Sstevel@tonic-gate     1024LLU * 1024 * 1024 * 1024 * 1024,
960Sstevel@tonic-gate     1024LLU * 1024 * 1024 * 1024 * 1024 * 1024
970Sstevel@tonic-gate };
980Sstevel@tonic-gate static scale_t __binary_scale = { __binary_modifiers, __binary_scales };
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate scale_t *scale_metric = &__metric_scale;
1010Sstevel@tonic-gate scale_t *scale_binary = &__binary_scale;
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate int
scaledtouint64(char * scaledin,uint64_t * uint64out,int * widthout,char ** modifierout,char ** unitout,scale_t * scale,char * unit,int flags)1040Sstevel@tonic-gate scaledtouint64(char *scaledin,
1050Sstevel@tonic-gate     uint64_t *uint64out,
1060Sstevel@tonic-gate     int *widthout, char **modifierout, char **unitout,
1070Sstevel@tonic-gate     scale_t *scale, char *unit, int flags) {
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	double result;
1100Sstevel@tonic-gate 	double value;
1110Sstevel@tonic-gate 	int index = 0;
1120Sstevel@tonic-gate 	uint64_t multiplier = 1;
1130Sstevel@tonic-gate 	char string[SCALED_STRLEN];
1140Sstevel@tonic-gate 	char *endptr;
1150Sstevel@tonic-gate 	int cmp;
1160Sstevel@tonic-gate 	int hasmodifier = 0;
1170Sstevel@tonic-gate 	char **modifiers = scale->modifers;
1180Sstevel@tonic-gate 	uint64_t *scales = scale->scales;
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	if (modifierout)
1210Sstevel@tonic-gate 		*modifierout = NULL;
1220Sstevel@tonic-gate 	if (unitout)
1230Sstevel@tonic-gate 		*unitout = NULL;
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	/*
1260Sstevel@tonic-gate 	 * first check for hex value, which cannot be scaled, as
1270Sstevel@tonic-gate 	 * hex letters cannot be disserned from modifier or unit letters
1280Sstevel@tonic-gate 	 */
1290Sstevel@tonic-gate 	if ((strncmp("0x", scaledin, 2) == 0) ||
1300Sstevel@tonic-gate 	    (strncmp("0X", scaledin, 2) == 0)) {
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 		/* unit cannot be required on hex values */
1330Sstevel@tonic-gate 		if ((unit && *unit != '\0') &&
1340Sstevel@tonic-gate 		    !(flags & SCALED_UNIT_OPTIONAL_FLAG))
1350Sstevel@tonic-gate 			return (SCALED_INVALID_UNIT);
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 		errno = 0;
1380Sstevel@tonic-gate 		*uint64out = strtoull(scaledin, &endptr, 16);
1390Sstevel@tonic-gate 		if (errno) {
1400Sstevel@tonic-gate 			if (errno == ERANGE)
1410Sstevel@tonic-gate 				return (SCALED_OVERFLOW);
1420Sstevel@tonic-gate 			else
1430Sstevel@tonic-gate 				return (SCALED_INVALID_NUMBER);
1440Sstevel@tonic-gate 		}
1450Sstevel@tonic-gate 		if (*endptr != '\0')
1460Sstevel@tonic-gate 			return (SCALED_INVALID_NUMBER);
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 		/* compute width of decimal equivalent */
1490Sstevel@tonic-gate 		if (widthout) {
1500Sstevel@tonic-gate 			(void) snprintf(
1510Sstevel@tonic-gate 			    string, SCALED_STRLEN, "%llu", *uint64out);
1520Sstevel@tonic-gate 			*widthout = strlen(string);
1530Sstevel@tonic-gate 		}
1540Sstevel@tonic-gate 		return (0);
1550Sstevel@tonic-gate 	}
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	/* scan out numeric value */
1580Sstevel@tonic-gate 	errno = 0;
1590Sstevel@tonic-gate 	value = strtod(scaledin, &endptr);
1600Sstevel@tonic-gate 	if (errno) {
1610Sstevel@tonic-gate 		if (errno == ERANGE)
1620Sstevel@tonic-gate 			return (SCALED_OVERFLOW);
1630Sstevel@tonic-gate 		else
1640Sstevel@tonic-gate 			return (SCALED_INVALID_NUMBER);
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate 	if (endptr == scaledin)
1680Sstevel@tonic-gate 		return (SCALED_INVALID_NUMBER);
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	/* no negative values */
1710Sstevel@tonic-gate 	if (strchr(scaledin, '-'))
1720Sstevel@tonic-gate 		return (SCALED_INVALID_NUMBER);
1730Sstevel@tonic-gate 	if (value < 0.0)
1740Sstevel@tonic-gate 		return (SCALED_INVALID_NUMBER);
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	/* compute width of number string */
1780Sstevel@tonic-gate 	if (widthout)
1790Sstevel@tonic-gate 		*widthout = (int)(endptr - scaledin);
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	/* check possible modifier */
1820Sstevel@tonic-gate 	if (*endptr != '\0') {
1830Sstevel@tonic-gate 		index = 0;
1840Sstevel@tonic-gate 		while (modifiers[index] != NULL) {
1850Sstevel@tonic-gate 			if (flags & SCALED_MODIFIER_CASE_INSENSITIVE_FLAG)
1860Sstevel@tonic-gate 				cmp = strncasecmp(modifiers[index], endptr,
1870Sstevel@tonic-gate 				    strlen(modifiers[index]));
1880Sstevel@tonic-gate 			else
1890Sstevel@tonic-gate 				cmp = strncmp(modifiers[index], endptr,
1900Sstevel@tonic-gate 				    strlen(modifiers[index]));
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 			if (cmp == 0) {
1930Sstevel@tonic-gate 				if (modifierout)
1940Sstevel@tonic-gate 					*modifierout = modifiers[index];
1950Sstevel@tonic-gate 				endptr += strlen(modifiers[index]);
1960Sstevel@tonic-gate 				multiplier = scales[index];
1970Sstevel@tonic-gate 				result = value * multiplier;
1980Sstevel@tonic-gate 				if (result > UINT64_MAX)
1990Sstevel@tonic-gate 					return (SCALED_OVERFLOW);
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 				*uint64out = (uint64_t)result;
2020Sstevel@tonic-gate 				hasmodifier = 1;
2030Sstevel@tonic-gate 				break;
2040Sstevel@tonic-gate 			}
2050Sstevel@tonic-gate 			index++;
2060Sstevel@tonic-gate 		}
2070Sstevel@tonic-gate 	}
2080Sstevel@tonic-gate 	/* if there is no modifier, value must be an integer */
2090Sstevel@tonic-gate 	if (!hasmodifier) {
2100Sstevel@tonic-gate 		errno = 0;
2110Sstevel@tonic-gate 		*uint64out = strtoull(scaledin, &endptr, 0);
2120Sstevel@tonic-gate 		if (errno) {
2130Sstevel@tonic-gate 			if (errno == ERANGE)
2140Sstevel@tonic-gate 				return (SCALED_OVERFLOW);
2150Sstevel@tonic-gate 			else
2160Sstevel@tonic-gate 				return (SCALED_INVALID_NUMBER);
2170Sstevel@tonic-gate 		}
2180Sstevel@tonic-gate 		if (endptr == scaledin)
2190Sstevel@tonic-gate 			return (SCALED_INVALID_NUMBER);
2200Sstevel@tonic-gate 	}
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	/* if unit is present when no unit is allowed, fail */
2230Sstevel@tonic-gate 	if ((unit == NULL || *unit == '\0') && (*endptr != '\0'))
2240Sstevel@tonic-gate 		return (SCALED_INVALID_UNIT);
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	/* check for missing unit when unit is required */
2270Sstevel@tonic-gate 	if ((unit && *unit != '\0') &&
2280Sstevel@tonic-gate 	    !(flags & SCALED_UNIT_OPTIONAL_FLAG) &&
2290Sstevel@tonic-gate 	    (*endptr == '\0'))
2300Sstevel@tonic-gate 		return (SCALED_INVALID_UNIT);
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	/* validate unit */
2330Sstevel@tonic-gate 	if (unit && *unit != '\0') {
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 		/* allow for missing unit if it is optional */
2360Sstevel@tonic-gate 		if ((flags & SCALED_UNIT_OPTIONAL_FLAG) &&
2370Sstevel@tonic-gate 		    (*endptr == '\0'))
2380Sstevel@tonic-gate 			return (0);
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 		if (flags & SCALED_UNIT_CASE_INSENSITIVE_FLAG)
2410Sstevel@tonic-gate 			cmp = strncasecmp(unit, endptr, strlen(unit));
2420Sstevel@tonic-gate 		else
2430Sstevel@tonic-gate 			cmp = strncmp(unit, endptr, strlen(unit));
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 		if (cmp != 0)
2460Sstevel@tonic-gate 			return (SCALED_INVALID_UNIT);
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 		if (*(endptr + strlen(unit)) != '\0')
2490Sstevel@tonic-gate 			return (SCALED_INVALID_UNIT);
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 		if (unitout)
2520Sstevel@tonic-gate 			*unitout = unit;
2530Sstevel@tonic-gate 	}
2540Sstevel@tonic-gate 	return (0);
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate int
uint64toscaled(uint64_t uint64in,int widthin,char * maxmodifierin,char * scaledout,int * widthout,char ** modifierout,scale_t * scale,char * unit,int flags)2590Sstevel@tonic-gate uint64toscaled(uint64_t uint64in, int widthin, char *maxmodifierin,
2600Sstevel@tonic-gate     char *scaledout, int *widthout, char **modifierout,
2610Sstevel@tonic-gate     scale_t *scale, char *unit, int flags) {
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	int index = 0;
2640Sstevel@tonic-gate 	int count;
2650Sstevel@tonic-gate 	int width;
2660Sstevel@tonic-gate 	int decimals = 0;
2670Sstevel@tonic-gate 	char string[SCALED_STRLEN];
2680Sstevel@tonic-gate 	double value;
2690Sstevel@tonic-gate 	char **modifiers = scale->modifers;
2700Sstevel@tonic-gate 	uint64_t *scales = scale->scales;
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	/* don't scale if there is no reason to */
2730Sstevel@tonic-gate 	if (uint64in < scales[0] || maxmodifierin == NULL) {
2740Sstevel@tonic-gate 		if (flags & SCALED_PAD_WIDTH_FLAG)
2750Sstevel@tonic-gate 			width = widthin;
2760Sstevel@tonic-gate 		else
2770Sstevel@tonic-gate 			width = 0;
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 		(void) snprintf(string, SCALED_STRLEN, "%%%dllu", width);
2800Sstevel@tonic-gate 		/* LINTED */
2810Sstevel@tonic-gate 		count = snprintf(scaledout, SCALED_STRLEN, string, uint64in);
2820Sstevel@tonic-gate 		if (unit && *unit != '\0')
2830Sstevel@tonic-gate 			(void) strcat(scaledout, unit);
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 		if (widthout)
2860Sstevel@tonic-gate 			*widthout = count;
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate 		if (modifierout)
2890Sstevel@tonic-gate 			*modifierout = NULL;
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 		return (0);
2920Sstevel@tonic-gate 	}
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	for (index = 0; modifiers[index + 1] != NULL; index++) {
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 		if (uint64in >= scales[index] &&
2970Sstevel@tonic-gate 		    uint64in < scales[index + 1])
2980Sstevel@tonic-gate 			break;
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 		if ((strncmp(modifiers[index], maxmodifierin,
3010Sstevel@tonic-gate 		    strlen(modifiers[index])) == 0) &&
3020Sstevel@tonic-gate 		    (strlen(modifiers[index]) == strlen(maxmodifierin)))
3030Sstevel@tonic-gate 			break;
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	}
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 	value = ((double)(uint64in)) / scales[index];
3080Sstevel@tonic-gate 	if (modifierout)
3090Sstevel@tonic-gate 		*modifierout = modifiers[index];
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	count = snprintf(string, SCALED_STRLEN, "%0.0lf", value);
3120Sstevel@tonic-gate 	while (count < widthin) {
3130Sstevel@tonic-gate 		decimals++;
3140Sstevel@tonic-gate 		(void) snprintf(string, SCALED_STRLEN, "%%0.%dlf", decimals);
3150Sstevel@tonic-gate 		/* LINTED */
3160Sstevel@tonic-gate 		count = snprintf(scaledout, SCALED_STRLEN, string, value);
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 		/* reduce decimal places if we've overshot the desired width */
3190Sstevel@tonic-gate 		if (count > widthin) {
3200Sstevel@tonic-gate 			decimals--;
3210Sstevel@tonic-gate 			break;
3220Sstevel@tonic-gate 		}
3230Sstevel@tonic-gate 	}
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	if (flags & SCALED_PAD_WIDTH_FLAG)
3260Sstevel@tonic-gate 		width = widthin;
3270Sstevel@tonic-gate 	else
3280Sstevel@tonic-gate 		width = 0;
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	(void) snprintf(string, SCALED_STRLEN, "%%%d.%dlf", width, decimals);
3310Sstevel@tonic-gate 	/* LINTED */
3320Sstevel@tonic-gate 	count = snprintf(scaledout, SCALED_STRLEN, string, value);
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	(void) strcat(scaledout, modifiers[index]);
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	if (unit && *unit != '\0')
3370Sstevel@tonic-gate 		(void) strcat(scaledout, unit);
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 	if (widthout)
3400Sstevel@tonic-gate 		*widthout = count;
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 	return (0);
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate int
scaledtoscaled(char * scaledin,int widthin,char * maxmodifierin,char * scaledout,int * widthout,char ** modifierout,scale_t * scale,char * unit,int flags)3460Sstevel@tonic-gate scaledtoscaled(char *scaledin, int widthin, char *maxmodifierin,
3470Sstevel@tonic-gate     char *scaledout, int *widthout, char **modifierout,
3480Sstevel@tonic-gate     scale_t *scale, char *unit, int flags) {
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 	int ret;
3510Sstevel@tonic-gate 	uint64_t val;
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	ret = scaledtouint64(scaledin, &val, NULL, NULL, NULL,
3540Sstevel@tonic-gate 	    scale, unit, flags);
3550Sstevel@tonic-gate 	if (ret)
3560Sstevel@tonic-gate 		return (ret);
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 	ret = uint64toscaled(val, widthin, maxmodifierin,
3590Sstevel@tonic-gate 	    scaledout, widthout, modifierout,
3600Sstevel@tonic-gate 	    scale, unit, flags);
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	return (ret);
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate int
scaledeqscaled(char * scaled1,char * scaled2,scale_t * scale,char * unit,int flags)3660Sstevel@tonic-gate scaledeqscaled(char *scaled1, char *scaled2,
3670Sstevel@tonic-gate     scale_t *scale, char *unit, int flags) {
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	int ret;
3700Sstevel@tonic-gate 	uint64_t uint64;
3710Sstevel@tonic-gate 	char *modifier1;
3720Sstevel@tonic-gate 	char *modifier2;
3730Sstevel@tonic-gate 	char *modifier = NULL;
3740Sstevel@tonic-gate 	int i;
3750Sstevel@tonic-gate 	int width;
3760Sstevel@tonic-gate 	int width1;
3770Sstevel@tonic-gate 	int width2;
3780Sstevel@tonic-gate 	char scaledA[SCALED_STRLEN];
3790Sstevel@tonic-gate 	char scaledB[SCALED_STRLEN];
3800Sstevel@tonic-gate 	char **modifiers = scale->modifers;
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 	/*
3830Sstevel@tonic-gate 	 * remove padding flag, so strings to compare will not have
3840Sstevel@tonic-gate 	 * whitespace
3850Sstevel@tonic-gate 	 */
3860Sstevel@tonic-gate 	flags = flags & (~SCALED_PAD_WIDTH_FLAG);
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	/* determine each number's width and modifier */
3890Sstevel@tonic-gate 	ret = scaledtouint64(scaled1, &uint64, &width1, &modifier1, NULL,
3900Sstevel@tonic-gate 	    scale, unit, flags);
3910Sstevel@tonic-gate 	if (ret)
3920Sstevel@tonic-gate 		return (0);
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 	ret = scaledtouint64(scaled2, &uint64, &width2, &modifier2, NULL,
3950Sstevel@tonic-gate 	    scale, unit, flags);
3960Sstevel@tonic-gate 	if (ret)
3970Sstevel@tonic-gate 		return (0);
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	/*
4000Sstevel@tonic-gate 	 * determine the width and modifier to use for comparison.
4010Sstevel@tonic-gate 	 * Use widest width and smallest modifier.
4020Sstevel@tonic-gate 	 * Rescale to new width and modifier
4030Sstevel@tonic-gate 	 */
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	if (modifier1 == NULL || modifier2 == NULL)
4060Sstevel@tonic-gate 		modifier = NULL;
4070Sstevel@tonic-gate 	else {
4080Sstevel@tonic-gate 		for (i = 0; modifiers[i] != NULL; i++) {
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 			if (strcmp(modifier1, modifiers[i]) == 0) {
4110Sstevel@tonic-gate 				modifier = modifiers[i];
4120Sstevel@tonic-gate 				break;
4130Sstevel@tonic-gate 			}
4140Sstevel@tonic-gate 			if (strcmp(modifier2, modifiers[i]) == 0) {
4150Sstevel@tonic-gate 				modifier = modifiers[i];
4160Sstevel@tonic-gate 				break;
4170Sstevel@tonic-gate 			}
4180Sstevel@tonic-gate 		}
4190Sstevel@tonic-gate 	}
4200Sstevel@tonic-gate 	width = 0;
4210Sstevel@tonic-gate 	if (width1 > width)
4220Sstevel@tonic-gate 		width = width1;
4230Sstevel@tonic-gate 	if (width2 > width)
4240Sstevel@tonic-gate 		width = width2;
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 	/*
4270Sstevel@tonic-gate 	 * Convert first number to width and modifier.
4280Sstevel@tonic-gate 	 * This is done for the following reasons:
4290Sstevel@tonic-gate 	 *	1. In case first number is hecadecimal.  This will convert
4300Sstevel@tonic-gate 	 *	   it to decimal
4310Sstevel@tonic-gate 	 *	2. In case the first number has < the minimum number of
4320Sstevel@tonic-gate 	 *	   columns.
4330Sstevel@tonic-gate 	 *	3. The first number is missing an optional unit string.
4340Sstevel@tonic-gate 	 *	4. Fix casing of modifier and unit.
4350Sstevel@tonic-gate 	 */
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	ret = scaledtoscaled(scaled1, width, modifier,
4380Sstevel@tonic-gate 	    scaledA, NULL, NULL, scale, unit, flags);
4390Sstevel@tonic-gate 	if (ret)
4400Sstevel@tonic-gate 		return (0);
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	/* convert second number to width and modifier matching first number */
4430Sstevel@tonic-gate 	ret = scaledtoscaled(scaled2, width, modifier,
4440Sstevel@tonic-gate 	    scaledB, NULL, NULL, scale, unit, flags);
4450Sstevel@tonic-gate 	if (ret)
4460Sstevel@tonic-gate 		return (0);
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	/* numbers are equal if strings match */
4490Sstevel@tonic-gate 	return ((strncmp(scaledA, scaledB, strlen(scaledA)) == 0) &&
4500Sstevel@tonic-gate 	    (strlen(scaledA) == strlen(scaledB)));
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate }
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate int
scaledequint64(char * scaled,uint64_t uint64,int minwidth,scale_t * scale,char * unit,int flags)4550Sstevel@tonic-gate scaledequint64(char *scaled, uint64_t uint64, int minwidth,
4560Sstevel@tonic-gate     scale_t *scale, char *unit, int flags) {
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	int ret;
4590Sstevel@tonic-gate 	uint64_t tmpuint64;
4600Sstevel@tonic-gate 	char *modifier;
4610Sstevel@tonic-gate 	int width;
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	char scaledA[SCALED_STRLEN];
4640Sstevel@tonic-gate 	char scaledB[SCALED_STRLEN];
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 	/* determine for number's width and modifier */
4670Sstevel@tonic-gate 	ret = scaledtouint64(scaled, &tmpuint64, &width, &modifier, NULL,
4680Sstevel@tonic-gate 	    scale, unit, flags);
4690Sstevel@tonic-gate 	if (ret)
4700Sstevel@tonic-gate 		return (0);
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate 	if (width < minwidth)
4730Sstevel@tonic-gate 		width = minwidth;
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 	/*
4760Sstevel@tonic-gate 	 * Convert first number to width and modifier.
4770Sstevel@tonic-gate 	 * This is done for the following reasons:
4780Sstevel@tonic-gate 	 *	1. In case first number is hecadecimal.  This will convert
4790Sstevel@tonic-gate 	 *	   it to decimal
4800Sstevel@tonic-gate 	 *	2. In case the first number has < the minimum number of
4810Sstevel@tonic-gate 	 *	   columns.
4820Sstevel@tonic-gate 	 *	3. The first number is missing an optional unit string.
4830Sstevel@tonic-gate 	 *	4. Fix casing of modifier and unit.
4840Sstevel@tonic-gate 	 */
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 	ret = scaledtoscaled(scaled, width, modifier,
4870Sstevel@tonic-gate 	    scaledA, NULL, NULL, scale, unit, flags);
4880Sstevel@tonic-gate 	if (ret)
4890Sstevel@tonic-gate 		return (0);
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	/* convert second number to width and modifier matching first number */
4920Sstevel@tonic-gate 	ret = uint64toscaled(uint64, width, modifier,
4930Sstevel@tonic-gate 	    scaledB, NULL, NULL, scale, unit, flags);
4940Sstevel@tonic-gate 	if (ret)
4950Sstevel@tonic-gate 		return (0);
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	/* numbers are equal if strings match */
4980Sstevel@tonic-gate 	return ((strncmp(scaledA, scaledB, strlen(scaledA)) == 0) &&
4990Sstevel@tonic-gate 	    (strlen(scaledA) == strlen(scaledB)));
5000Sstevel@tonic-gate }
501