1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/param.h> 30*0Sstevel@tonic-gate #include <libintl.h> 31*0Sstevel@tonic-gate #include <string.h> 32*0Sstevel@tonic-gate #include <stdlib.h> 33*0Sstevel@tonic-gate #include <stdarg.h> 34*0Sstevel@tonic-gate #include <stdio.h> 35*0Sstevel@tonic-gate #include <errno.h> 36*0Sstevel@tonic-gate #include <strings.h> 37*0Sstevel@tonic-gate #include <sys/types.h> 38*0Sstevel@tonic-gate #include <limits.h> 39*0Sstevel@tonic-gate #include "utils.h" 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate static char PNAME_FMT[] = "%s: "; 42*0Sstevel@tonic-gate static char ERRNO_FMT[] = ": %s\n"; 43*0Sstevel@tonic-gate static char EOL_FMT[] = "\n"; 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate static char *pname; 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate char * 48*0Sstevel@tonic-gate setprogname(char *arg0) 49*0Sstevel@tonic-gate { 50*0Sstevel@tonic-gate char *p = strrchr(arg0, '/'); 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate if (p == NULL) 53*0Sstevel@tonic-gate p = arg0; 54*0Sstevel@tonic-gate else 55*0Sstevel@tonic-gate p++; 56*0Sstevel@tonic-gate pname = p; 57*0Sstevel@tonic-gate return (pname); 58*0Sstevel@tonic-gate } 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate /*PRINTFLIKE1*/ 61*0Sstevel@tonic-gate void 62*0Sstevel@tonic-gate warn(char *format, ...) 63*0Sstevel@tonic-gate { 64*0Sstevel@tonic-gate int err = errno; 65*0Sstevel@tonic-gate va_list alist; 66*0Sstevel@tonic-gate if (pname != NULL) 67*0Sstevel@tonic-gate (void) fprintf(stderr, gettext(PNAME_FMT), pname); 68*0Sstevel@tonic-gate va_start(alist, format); 69*0Sstevel@tonic-gate (void) vfprintf(stderr, format, alist); 70*0Sstevel@tonic-gate va_end(alist); 71*0Sstevel@tonic-gate if (strchr(format, '\n') == NULL) 72*0Sstevel@tonic-gate if (err) 73*0Sstevel@tonic-gate (void) fprintf(stderr, 74*0Sstevel@tonic-gate gettext(ERRNO_FMT), strerror(err)); 75*0Sstevel@tonic-gate else 76*0Sstevel@tonic-gate (void) fprintf(stderr, gettext(EOL_FMT)); 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate } 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate static char *__metric_modifiers[] = { "K", "M", "G", "T", "P", "E", NULL }; 82*0Sstevel@tonic-gate static uint64_t __metric_scales[] = { 83*0Sstevel@tonic-gate 1000LLU, 84*0Sstevel@tonic-gate 1000LLU * 1000, 85*0Sstevel@tonic-gate 1000LLU * 1000 * 1000, 86*0Sstevel@tonic-gate 1000LLU * 1000 * 1000 * 1000, 87*0Sstevel@tonic-gate 1000LLU * 1000 * 1000 * 1000 * 1000, 88*0Sstevel@tonic-gate 1000LLU * 1000 * 1000 * 1000 * 1000 * 1000 89*0Sstevel@tonic-gate }; 90*0Sstevel@tonic-gate static scale_t __metric_scale = { __metric_modifiers, __metric_scales }; 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate static char *__binary_modifiers[] = {"K", "M", "G", "T", "P", "E", NULL}; 93*0Sstevel@tonic-gate static uint64_t __binary_scales[] = { 94*0Sstevel@tonic-gate 1024LLU, 95*0Sstevel@tonic-gate 1024LLU * 1024, 96*0Sstevel@tonic-gate 1024LLU * 1024 * 1024, 97*0Sstevel@tonic-gate 1024LLU * 1024 * 1024 * 1024, 98*0Sstevel@tonic-gate 1024LLU * 1024 * 1024 * 1024 * 1024, 99*0Sstevel@tonic-gate 1024LLU * 1024 * 1024 * 1024 * 1024 * 1024 100*0Sstevel@tonic-gate }; 101*0Sstevel@tonic-gate static scale_t __binary_scale = { __binary_modifiers, __binary_scales }; 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate scale_t *scale_metric = &__metric_scale; 104*0Sstevel@tonic-gate scale_t *scale_binary = &__binary_scale; 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate int 107*0Sstevel@tonic-gate scaledtouint64(char *scaledin, 108*0Sstevel@tonic-gate uint64_t *uint64out, 109*0Sstevel@tonic-gate int *widthout, char **modifierout, char **unitout, 110*0Sstevel@tonic-gate scale_t *scale, char *unit, int flags) { 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate double result; 113*0Sstevel@tonic-gate double value; 114*0Sstevel@tonic-gate int index = 0; 115*0Sstevel@tonic-gate uint64_t multiplier = 1; 116*0Sstevel@tonic-gate char string[SCALED_STRLEN]; 117*0Sstevel@tonic-gate char *endptr; 118*0Sstevel@tonic-gate int cmp; 119*0Sstevel@tonic-gate int hasmodifier = 0; 120*0Sstevel@tonic-gate char **modifiers = scale->modifers; 121*0Sstevel@tonic-gate uint64_t *scales = scale->scales; 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate if (modifierout) 124*0Sstevel@tonic-gate *modifierout = NULL; 125*0Sstevel@tonic-gate if (unitout) 126*0Sstevel@tonic-gate *unitout = NULL; 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate /* 129*0Sstevel@tonic-gate * first check for hex value, which cannot be scaled, as 130*0Sstevel@tonic-gate * hex letters cannot be disserned from modifier or unit letters 131*0Sstevel@tonic-gate */ 132*0Sstevel@tonic-gate if ((strncmp("0x", scaledin, 2) == 0) || 133*0Sstevel@tonic-gate (strncmp("0X", scaledin, 2) == 0)) { 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate /* unit cannot be required on hex values */ 136*0Sstevel@tonic-gate if ((unit && *unit != '\0') && 137*0Sstevel@tonic-gate !(flags & SCALED_UNIT_OPTIONAL_FLAG)) 138*0Sstevel@tonic-gate return (SCALED_INVALID_UNIT); 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate errno = 0; 141*0Sstevel@tonic-gate *uint64out = strtoull(scaledin, &endptr, 16); 142*0Sstevel@tonic-gate if (errno) { 143*0Sstevel@tonic-gate if (errno == ERANGE) 144*0Sstevel@tonic-gate return (SCALED_OVERFLOW); 145*0Sstevel@tonic-gate else 146*0Sstevel@tonic-gate return (SCALED_INVALID_NUMBER); 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate if (*endptr != '\0') 149*0Sstevel@tonic-gate return (SCALED_INVALID_NUMBER); 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate /* compute width of decimal equivalent */ 152*0Sstevel@tonic-gate if (widthout) { 153*0Sstevel@tonic-gate (void) snprintf( 154*0Sstevel@tonic-gate string, SCALED_STRLEN, "%llu", *uint64out); 155*0Sstevel@tonic-gate *widthout = strlen(string); 156*0Sstevel@tonic-gate } 157*0Sstevel@tonic-gate return (0); 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* scan out numeric value */ 161*0Sstevel@tonic-gate errno = 0; 162*0Sstevel@tonic-gate value = strtod(scaledin, &endptr); 163*0Sstevel@tonic-gate if (errno) { 164*0Sstevel@tonic-gate if (errno == ERANGE) 165*0Sstevel@tonic-gate return (SCALED_OVERFLOW); 166*0Sstevel@tonic-gate else 167*0Sstevel@tonic-gate return (SCALED_INVALID_NUMBER); 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate if (endptr == scaledin) 171*0Sstevel@tonic-gate return (SCALED_INVALID_NUMBER); 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate /* no negative values */ 174*0Sstevel@tonic-gate if (strchr(scaledin, '-')) 175*0Sstevel@tonic-gate return (SCALED_INVALID_NUMBER); 176*0Sstevel@tonic-gate if (value < 0.0) 177*0Sstevel@tonic-gate return (SCALED_INVALID_NUMBER); 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /* compute width of number string */ 181*0Sstevel@tonic-gate if (widthout) 182*0Sstevel@tonic-gate *widthout = (int)(endptr - scaledin); 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate /* check possible modifier */ 185*0Sstevel@tonic-gate if (*endptr != '\0') { 186*0Sstevel@tonic-gate index = 0; 187*0Sstevel@tonic-gate while (modifiers[index] != NULL) { 188*0Sstevel@tonic-gate if (flags & SCALED_MODIFIER_CASE_INSENSITIVE_FLAG) 189*0Sstevel@tonic-gate cmp = strncasecmp(modifiers[index], endptr, 190*0Sstevel@tonic-gate strlen(modifiers[index])); 191*0Sstevel@tonic-gate else 192*0Sstevel@tonic-gate cmp = strncmp(modifiers[index], endptr, 193*0Sstevel@tonic-gate strlen(modifiers[index])); 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate if (cmp == 0) { 196*0Sstevel@tonic-gate if (modifierout) 197*0Sstevel@tonic-gate *modifierout = modifiers[index]; 198*0Sstevel@tonic-gate endptr += strlen(modifiers[index]); 199*0Sstevel@tonic-gate multiplier = scales[index]; 200*0Sstevel@tonic-gate result = value * multiplier; 201*0Sstevel@tonic-gate if (result > UINT64_MAX) 202*0Sstevel@tonic-gate return (SCALED_OVERFLOW); 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate *uint64out = (uint64_t)result; 205*0Sstevel@tonic-gate hasmodifier = 1; 206*0Sstevel@tonic-gate break; 207*0Sstevel@tonic-gate } 208*0Sstevel@tonic-gate index++; 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate } 211*0Sstevel@tonic-gate /* if there is no modifier, value must be an integer */ 212*0Sstevel@tonic-gate if (!hasmodifier) { 213*0Sstevel@tonic-gate errno = 0; 214*0Sstevel@tonic-gate *uint64out = strtoull(scaledin, &endptr, 0); 215*0Sstevel@tonic-gate if (errno) { 216*0Sstevel@tonic-gate if (errno == ERANGE) 217*0Sstevel@tonic-gate return (SCALED_OVERFLOW); 218*0Sstevel@tonic-gate else 219*0Sstevel@tonic-gate return (SCALED_INVALID_NUMBER); 220*0Sstevel@tonic-gate } 221*0Sstevel@tonic-gate if (endptr == scaledin) 222*0Sstevel@tonic-gate return (SCALED_INVALID_NUMBER); 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate /* if unit is present when no unit is allowed, fail */ 226*0Sstevel@tonic-gate if ((unit == NULL || *unit == '\0') && (*endptr != '\0')) 227*0Sstevel@tonic-gate return (SCALED_INVALID_UNIT); 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate /* check for missing unit when unit is required */ 230*0Sstevel@tonic-gate if ((unit && *unit != '\0') && 231*0Sstevel@tonic-gate !(flags & SCALED_UNIT_OPTIONAL_FLAG) && 232*0Sstevel@tonic-gate (*endptr == '\0')) 233*0Sstevel@tonic-gate return (SCALED_INVALID_UNIT); 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate /* validate unit */ 236*0Sstevel@tonic-gate if (unit && *unit != '\0') { 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate /* allow for missing unit if it is optional */ 239*0Sstevel@tonic-gate if ((flags & SCALED_UNIT_OPTIONAL_FLAG) && 240*0Sstevel@tonic-gate (*endptr == '\0')) 241*0Sstevel@tonic-gate return (0); 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate if (flags & SCALED_UNIT_CASE_INSENSITIVE_FLAG) 244*0Sstevel@tonic-gate cmp = strncasecmp(unit, endptr, strlen(unit)); 245*0Sstevel@tonic-gate else 246*0Sstevel@tonic-gate cmp = strncmp(unit, endptr, strlen(unit)); 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate if (cmp != 0) 249*0Sstevel@tonic-gate return (SCALED_INVALID_UNIT); 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate if (*(endptr + strlen(unit)) != '\0') 252*0Sstevel@tonic-gate return (SCALED_INVALID_UNIT); 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate if (unitout) 255*0Sstevel@tonic-gate *unitout = unit; 256*0Sstevel@tonic-gate } 257*0Sstevel@tonic-gate return (0); 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate int 262*0Sstevel@tonic-gate uint64toscaled(uint64_t uint64in, int widthin, char *maxmodifierin, 263*0Sstevel@tonic-gate char *scaledout, int *widthout, char **modifierout, 264*0Sstevel@tonic-gate scale_t *scale, char *unit, int flags) { 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate int index = 0; 267*0Sstevel@tonic-gate int count; 268*0Sstevel@tonic-gate int width; 269*0Sstevel@tonic-gate int decimals = 0; 270*0Sstevel@tonic-gate char string[SCALED_STRLEN]; 271*0Sstevel@tonic-gate double value; 272*0Sstevel@tonic-gate char **modifiers = scale->modifers; 273*0Sstevel@tonic-gate uint64_t *scales = scale->scales; 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate /* don't scale if there is no reason to */ 276*0Sstevel@tonic-gate if (uint64in < scales[0] || maxmodifierin == NULL) { 277*0Sstevel@tonic-gate if (flags & SCALED_PAD_WIDTH_FLAG) 278*0Sstevel@tonic-gate width = widthin; 279*0Sstevel@tonic-gate else 280*0Sstevel@tonic-gate width = 0; 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate (void) snprintf(string, SCALED_STRLEN, "%%%dllu", width); 283*0Sstevel@tonic-gate /* LINTED */ 284*0Sstevel@tonic-gate count = snprintf(scaledout, SCALED_STRLEN, string, uint64in); 285*0Sstevel@tonic-gate if (unit && *unit != '\0') 286*0Sstevel@tonic-gate (void) strcat(scaledout, unit); 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate if (widthout) 289*0Sstevel@tonic-gate *widthout = count; 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate if (modifierout) 292*0Sstevel@tonic-gate *modifierout = NULL; 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate return (0); 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate for (index = 0; modifiers[index + 1] != NULL; index++) { 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate if (uint64in >= scales[index] && 300*0Sstevel@tonic-gate uint64in < scales[index + 1]) 301*0Sstevel@tonic-gate break; 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate if ((strncmp(modifiers[index], maxmodifierin, 304*0Sstevel@tonic-gate strlen(modifiers[index])) == 0) && 305*0Sstevel@tonic-gate (strlen(modifiers[index]) == strlen(maxmodifierin))) 306*0Sstevel@tonic-gate break; 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate } 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate value = ((double)(uint64in)) / scales[index]; 311*0Sstevel@tonic-gate if (modifierout) 312*0Sstevel@tonic-gate *modifierout = modifiers[index]; 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate count = snprintf(string, SCALED_STRLEN, "%0.0lf", value); 315*0Sstevel@tonic-gate while (count < widthin) { 316*0Sstevel@tonic-gate decimals++; 317*0Sstevel@tonic-gate (void) snprintf(string, SCALED_STRLEN, "%%0.%dlf", decimals); 318*0Sstevel@tonic-gate /* LINTED */ 319*0Sstevel@tonic-gate count = snprintf(scaledout, SCALED_STRLEN, string, value); 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate /* reduce decimal places if we've overshot the desired width */ 322*0Sstevel@tonic-gate if (count > widthin) { 323*0Sstevel@tonic-gate decimals--; 324*0Sstevel@tonic-gate break; 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate } 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate if (flags & SCALED_PAD_WIDTH_FLAG) 329*0Sstevel@tonic-gate width = widthin; 330*0Sstevel@tonic-gate else 331*0Sstevel@tonic-gate width = 0; 332*0Sstevel@tonic-gate 333*0Sstevel@tonic-gate (void) snprintf(string, SCALED_STRLEN, "%%%d.%dlf", width, decimals); 334*0Sstevel@tonic-gate /* LINTED */ 335*0Sstevel@tonic-gate count = snprintf(scaledout, SCALED_STRLEN, string, value); 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate (void) strcat(scaledout, modifiers[index]); 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate if (unit && *unit != '\0') 340*0Sstevel@tonic-gate (void) strcat(scaledout, unit); 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate if (widthout) 343*0Sstevel@tonic-gate *widthout = count; 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate return (0); 346*0Sstevel@tonic-gate } 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate int 349*0Sstevel@tonic-gate scaledtoscaled(char *scaledin, int widthin, char *maxmodifierin, 350*0Sstevel@tonic-gate char *scaledout, int *widthout, char **modifierout, 351*0Sstevel@tonic-gate scale_t *scale, char *unit, int flags) { 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate int ret; 354*0Sstevel@tonic-gate uint64_t val; 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate ret = scaledtouint64(scaledin, &val, NULL, NULL, NULL, 357*0Sstevel@tonic-gate scale, unit, flags); 358*0Sstevel@tonic-gate if (ret) 359*0Sstevel@tonic-gate return (ret); 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate ret = uint64toscaled(val, widthin, maxmodifierin, 362*0Sstevel@tonic-gate scaledout, widthout, modifierout, 363*0Sstevel@tonic-gate scale, unit, flags); 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate return (ret); 366*0Sstevel@tonic-gate } 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate int 369*0Sstevel@tonic-gate scaledeqscaled(char *scaled1, char *scaled2, 370*0Sstevel@tonic-gate scale_t *scale, char *unit, int flags) { 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate int ret; 373*0Sstevel@tonic-gate uint64_t uint64; 374*0Sstevel@tonic-gate char *modifier1; 375*0Sstevel@tonic-gate char *modifier2; 376*0Sstevel@tonic-gate char *modifier = NULL; 377*0Sstevel@tonic-gate int i; 378*0Sstevel@tonic-gate int width; 379*0Sstevel@tonic-gate int width1; 380*0Sstevel@tonic-gate int width2; 381*0Sstevel@tonic-gate char scaledA[SCALED_STRLEN]; 382*0Sstevel@tonic-gate char scaledB[SCALED_STRLEN]; 383*0Sstevel@tonic-gate char **modifiers = scale->modifers; 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate /* 386*0Sstevel@tonic-gate * remove padding flag, so strings to compare will not have 387*0Sstevel@tonic-gate * whitespace 388*0Sstevel@tonic-gate */ 389*0Sstevel@tonic-gate flags = flags & (~SCALED_PAD_WIDTH_FLAG); 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate /* determine each number's width and modifier */ 392*0Sstevel@tonic-gate ret = scaledtouint64(scaled1, &uint64, &width1, &modifier1, NULL, 393*0Sstevel@tonic-gate scale, unit, flags); 394*0Sstevel@tonic-gate if (ret) 395*0Sstevel@tonic-gate return (0); 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate ret = scaledtouint64(scaled2, &uint64, &width2, &modifier2, NULL, 398*0Sstevel@tonic-gate scale, unit, flags); 399*0Sstevel@tonic-gate if (ret) 400*0Sstevel@tonic-gate return (0); 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate /* 403*0Sstevel@tonic-gate * determine the width and modifier to use for comparison. 404*0Sstevel@tonic-gate * Use widest width and smallest modifier. 405*0Sstevel@tonic-gate * Rescale to new width and modifier 406*0Sstevel@tonic-gate */ 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate if (modifier1 == NULL || modifier2 == NULL) 409*0Sstevel@tonic-gate modifier = NULL; 410*0Sstevel@tonic-gate else { 411*0Sstevel@tonic-gate for (i = 0; modifiers[i] != NULL; i++) { 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate if (strcmp(modifier1, modifiers[i]) == 0) { 414*0Sstevel@tonic-gate modifier = modifiers[i]; 415*0Sstevel@tonic-gate break; 416*0Sstevel@tonic-gate } 417*0Sstevel@tonic-gate if (strcmp(modifier2, modifiers[i]) == 0) { 418*0Sstevel@tonic-gate modifier = modifiers[i]; 419*0Sstevel@tonic-gate break; 420*0Sstevel@tonic-gate } 421*0Sstevel@tonic-gate } 422*0Sstevel@tonic-gate } 423*0Sstevel@tonic-gate width = 0; 424*0Sstevel@tonic-gate if (width1 > width) 425*0Sstevel@tonic-gate width = width1; 426*0Sstevel@tonic-gate if (width2 > width) 427*0Sstevel@tonic-gate width = width2; 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gate /* 430*0Sstevel@tonic-gate * Convert first number to width and modifier. 431*0Sstevel@tonic-gate * This is done for the following reasons: 432*0Sstevel@tonic-gate * 1. In case first number is hecadecimal. This will convert 433*0Sstevel@tonic-gate * it to decimal 434*0Sstevel@tonic-gate * 2. In case the first number has < the minimum number of 435*0Sstevel@tonic-gate * columns. 436*0Sstevel@tonic-gate * 3. The first number is missing an optional unit string. 437*0Sstevel@tonic-gate * 4. Fix casing of modifier and unit. 438*0Sstevel@tonic-gate */ 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate ret = scaledtoscaled(scaled1, width, modifier, 441*0Sstevel@tonic-gate scaledA, NULL, NULL, scale, unit, flags); 442*0Sstevel@tonic-gate if (ret) 443*0Sstevel@tonic-gate return (0); 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate /* convert second number to width and modifier matching first number */ 446*0Sstevel@tonic-gate ret = scaledtoscaled(scaled2, width, modifier, 447*0Sstevel@tonic-gate scaledB, NULL, NULL, scale, unit, flags); 448*0Sstevel@tonic-gate if (ret) 449*0Sstevel@tonic-gate return (0); 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate /* numbers are equal if strings match */ 452*0Sstevel@tonic-gate return ((strncmp(scaledA, scaledB, strlen(scaledA)) == 0) && 453*0Sstevel@tonic-gate (strlen(scaledA) == strlen(scaledB))); 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate } 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate int 458*0Sstevel@tonic-gate scaledequint64(char *scaled, uint64_t uint64, int minwidth, 459*0Sstevel@tonic-gate scale_t *scale, char *unit, int flags) { 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate int ret; 462*0Sstevel@tonic-gate uint64_t tmpuint64; 463*0Sstevel@tonic-gate char *modifier; 464*0Sstevel@tonic-gate int width; 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate char scaledA[SCALED_STRLEN]; 467*0Sstevel@tonic-gate char scaledB[SCALED_STRLEN]; 468*0Sstevel@tonic-gate 469*0Sstevel@tonic-gate /* determine for number's width and modifier */ 470*0Sstevel@tonic-gate ret = scaledtouint64(scaled, &tmpuint64, &width, &modifier, NULL, 471*0Sstevel@tonic-gate scale, unit, flags); 472*0Sstevel@tonic-gate if (ret) 473*0Sstevel@tonic-gate return (0); 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate if (width < minwidth) 476*0Sstevel@tonic-gate width = minwidth; 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate /* 479*0Sstevel@tonic-gate * Convert first number to width and modifier. 480*0Sstevel@tonic-gate * This is done for the following reasons: 481*0Sstevel@tonic-gate * 1. In case first number is hecadecimal. This will convert 482*0Sstevel@tonic-gate * it to decimal 483*0Sstevel@tonic-gate * 2. In case the first number has < the minimum number of 484*0Sstevel@tonic-gate * columns. 485*0Sstevel@tonic-gate * 3. The first number is missing an optional unit string. 486*0Sstevel@tonic-gate * 4. Fix casing of modifier and unit. 487*0Sstevel@tonic-gate */ 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate ret = scaledtoscaled(scaled, width, modifier, 490*0Sstevel@tonic-gate scaledA, NULL, NULL, scale, unit, flags); 491*0Sstevel@tonic-gate if (ret) 492*0Sstevel@tonic-gate return (0); 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate /* convert second number to width and modifier matching first number */ 495*0Sstevel@tonic-gate ret = uint64toscaled(uint64, width, modifier, 496*0Sstevel@tonic-gate scaledB, NULL, NULL, scale, unit, flags); 497*0Sstevel@tonic-gate if (ret) 498*0Sstevel@tonic-gate return (0); 499*0Sstevel@tonic-gate 500*0Sstevel@tonic-gate /* numbers are equal if strings match */ 501*0Sstevel@tonic-gate return ((strncmp(scaledA, scaledB, strlen(scaledA)) == 0) && 502*0Sstevel@tonic-gate (strlen(scaledA) == strlen(scaledB))); 503*0Sstevel@tonic-gate } 504