1 /* $NetBSD: utils.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $ */ 2 3 /* OpenLDAP: pkg/ldap/libraries/liblutil/utils.c,v 1.33.2.26 2009/12/02 18:34:37 hyc Exp */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2009 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17 18 #include "portable.h" 19 20 #include <stdio.h> 21 #include <ac/stdlib.h> 22 #include <ac/stdarg.h> 23 #include <ac/string.h> 24 #include <ac/ctype.h> 25 #include <ac/unistd.h> 26 #include <ac/time.h> 27 #include <ac/errno.h> 28 #ifdef HAVE_IO_H 29 #include <io.h> 30 #endif 31 #ifdef HAVE_FCNTL_H 32 #include <fcntl.h> 33 #endif 34 #ifdef _WIN32 35 #include <windows.h> 36 #endif 37 38 #include "lutil.h" 39 #include "ldap_defaults.h" 40 #include "ldap_pvt.h" 41 #include "lber_pvt.h" 42 43 #ifdef HAVE_EBCDIC 44 int _trans_argv = 1; 45 #endif 46 47 #ifdef _WIN32 48 /* Some Windows versions accept both forward and backslashes in 49 * directory paths, but we always use backslashes when generating 50 * and parsing... 51 */ 52 void lutil_slashpath( char *path ) 53 { 54 char *c, *p; 55 56 p = path; 57 while (( c=strchr( p, '/' ))) { 58 *c++ = '\\'; 59 p = c; 60 } 61 } 62 #endif 63 64 char* lutil_progname( const char* name, int argc, char *argv[] ) 65 { 66 char *progname; 67 68 if(argc == 0) { 69 return (char *)name; 70 } 71 72 #ifdef HAVE_EBCDIC 73 if (_trans_argv) { 74 int i; 75 for (i=0; i<argc; i++) __etoa(argv[i]); 76 _trans_argv = 0; 77 } 78 #endif 79 LUTIL_SLASHPATH( argv[0] ); 80 progname = strrchr ( argv[0], *LDAP_DIRSEP ); 81 progname = progname ? &progname[1] : argv[0]; 82 #ifdef _WIN32 83 { 84 size_t len = strlen( progname ); 85 if ( len > 4 && strcasecmp( &progname[len - 4], ".exe" ) == 0 ) 86 progname[len - 4] = '\0'; 87 } 88 #endif 89 return progname; 90 } 91 92 #if 0 93 size_t lutil_gentime( char *s, size_t smax, const struct tm *tm ) 94 { 95 size_t ret; 96 #ifdef HAVE_EBCDIC 97 /* We've been compiling in ASCII so far, but we want EBCDIC now since 98 * strftime only understands EBCDIC input. 99 */ 100 #pragma convlit(suspend) 101 #endif 102 ret = strftime( s, smax, "%Y%m%d%H%M%SZ", tm ); 103 #ifdef HAVE_EBCDIC 104 #pragma convlit(resume) 105 __etoa( s ); 106 #endif 107 return ret; 108 } 109 #endif 110 111 size_t lutil_localtime( char *s, size_t smax, const struct tm *tm, long delta ) 112 { 113 size_t ret; 114 char *p; 115 116 if ( smax < 16 ) { /* YYYYmmddHHMMSSZ */ 117 return 0; 118 } 119 120 #ifdef HAVE_EBCDIC 121 /* We've been compiling in ASCII so far, but we want EBCDIC now since 122 * strftime only understands EBCDIC input. 123 */ 124 #pragma convlit(suspend) 125 #endif 126 ret = strftime( s, smax, "%Y%m%d%H%M%SZ", tm ); 127 #ifdef HAVE_EBCDIC 128 #pragma convlit(resume) 129 __etoa( s ); 130 #endif 131 if ( delta == 0 || ret == 0 ) { 132 return ret; 133 } 134 135 if ( smax < 20 ) { /* YYYYmmddHHMMSS+HHMM */ 136 return 0; 137 } 138 139 p = s + 14; 140 141 if ( delta < 0 ) { 142 p[ 0 ] = '-'; 143 delta = -delta; 144 } else { 145 p[ 0 ] = '+'; 146 } 147 p++; 148 149 snprintf( p, smax - 15, "%02ld%02ld", delta / 3600, 150 ( delta % 3600 ) / 60 ); 151 152 return ret + 5; 153 } 154 155 int lutil_tm2time( struct lutil_tm *tm, struct lutil_timet *tt ) 156 { 157 static int moffset[12] = { 158 0, 31, 59, 90, 120, 159 151, 181, 212, 243, 160 273, 304, 334 }; 161 int sec; 162 163 tt->tt_usec = tm->tm_usec; 164 165 /* special case 0000/01/01+00:00:00 is returned as zero */ 166 if ( tm->tm_year == -1900 && tm->tm_mon == 0 && tm->tm_mday == 1 && 167 tm->tm_hour == 0 && tm->tm_min == 0 && tm->tm_sec == 0 ) { 168 tt->tt_sec = 0; 169 tt->tt_gsec = 0; 170 return 0; 171 } 172 173 /* tm->tm_year is years since 1900 */ 174 /* calculate days from years since 1970 (epoch) */ 175 tt->tt_sec = tm->tm_year - 70; 176 tt->tt_sec *= 365L; 177 178 /* count leap days in preceding years */ 179 tt->tt_sec += ((tm->tm_year -69) >> 2); 180 181 /* calculate days from months */ 182 tt->tt_sec += moffset[tm->tm_mon]; 183 184 /* add in this year's leap day, if any */ 185 if (((tm->tm_year & 3) == 0) && (tm->tm_mon > 1)) { 186 tt->tt_sec ++; 187 } 188 189 /* add in days in this month */ 190 tt->tt_sec += (tm->tm_mday - 1); 191 192 /* this function can handle a range of about 17408 years... */ 193 /* 86400 seconds in a day, divided by 128 = 675 */ 194 tt->tt_sec *= 675; 195 196 /* move high 7 bits into tt_gsec */ 197 tt->tt_gsec = tt->tt_sec >> 25; 198 tt->tt_sec -= tt->tt_gsec << 25; 199 200 /* get hours */ 201 sec = tm->tm_hour; 202 203 /* convert to minutes */ 204 sec *= 60L; 205 sec += tm->tm_min; 206 207 /* convert to seconds */ 208 sec *= 60L; 209 sec += tm->tm_sec; 210 211 /* add remaining seconds */ 212 tt->tt_sec <<= 7; 213 tt->tt_sec += sec; 214 215 /* return success */ 216 return 0; 217 } 218 219 int lutil_parsetime( char *atm, struct lutil_tm *tm ) 220 { 221 while (atm && tm) { 222 char *ptr = atm; 223 unsigned i, fracs; 224 225 /* Is the stamp reasonably long? */ 226 for (i=0; isdigit((unsigned char) atm[i]); i++); 227 if (i < sizeof("00000101000000")-1) 228 break; 229 230 /* 231 * parse the time into a struct tm 232 */ 233 /* 4 digit year to year - 1900 */ 234 tm->tm_year = *ptr++ - '0'; 235 tm->tm_year *= 10; tm->tm_year += *ptr++ - '0'; 236 tm->tm_year *= 10; tm->tm_year += *ptr++ - '0'; 237 tm->tm_year *= 10; tm->tm_year += *ptr++ - '0'; 238 tm->tm_year -= 1900; 239 /* month 01-12 to 0-11 */ 240 tm->tm_mon = *ptr++ - '0'; 241 tm->tm_mon *=10; tm->tm_mon += *ptr++ - '0'; 242 if (tm->tm_mon < 1 || tm->tm_mon > 12) break; 243 tm->tm_mon--; 244 245 /* day of month 01-31 */ 246 tm->tm_mday = *ptr++ - '0'; 247 tm->tm_mday *=10; tm->tm_mday += *ptr++ - '0'; 248 if (tm->tm_mday < 1 || tm->tm_mday > 31) break; 249 250 /* Hour 00-23 */ 251 tm->tm_hour = *ptr++ - '0'; 252 tm->tm_hour *=10; tm->tm_hour += *ptr++ - '0'; 253 if (tm->tm_hour < 0 || tm->tm_hour > 23) break; 254 255 /* Minute 00-59 */ 256 tm->tm_min = *ptr++ - '0'; 257 tm->tm_min *=10; tm->tm_min += *ptr++ - '0'; 258 if (tm->tm_min < 0 || tm->tm_min > 59) break; 259 260 /* Second 00-61 */ 261 tm->tm_sec = *ptr++ - '0'; 262 tm->tm_sec *=10; tm->tm_sec += *ptr++ - '0'; 263 if (tm->tm_sec < 0 || tm->tm_sec > 61) break; 264 265 /* Fractions of seconds */ 266 if ( *ptr == '.' ) { 267 ptr++; 268 for (i = 0, fracs = 0; isdigit((unsigned char) *ptr); ) { 269 i*=10; i+= *ptr++ - '0'; 270 fracs++; 271 } 272 tm->tm_usec = i; 273 if (i) { 274 for (i = fracs; i<6; i++) 275 tm->tm_usec *= 10; 276 } 277 } 278 279 /* Must be UTC */ 280 if (*ptr != 'Z') break; 281 282 return 0; 283 } 284 return -1; 285 } 286 287 /* return a broken out time, with microseconds 288 * Must be mutex-protected. 289 */ 290 #ifdef _WIN32 291 /* Windows SYSTEMTIME only has 10 millisecond resolution, so we 292 * also need to use a high resolution timer to get microseconds. 293 * This is pretty clunky. 294 */ 295 void 296 lutil_gettime( struct lutil_tm *tm ) 297 { 298 static LARGE_INTEGER cFreq; 299 static LARGE_INTEGER prevCount; 300 static int subs; 301 static int offset; 302 LARGE_INTEGER count; 303 SYSTEMTIME st; 304 305 GetSystemTime( &st ); 306 QueryPerformanceCounter( &count ); 307 308 /* It shouldn't ever go backwards, but multiple CPUs might 309 * be able to hit in the same tick. 310 */ 311 if ( count.QuadPart <= prevCount.QuadPart ) { 312 subs++; 313 } else { 314 subs = 0; 315 prevCount = count; 316 } 317 318 /* We assume Windows has at least a vague idea of 319 * when a second begins. So we align our microsecond count 320 * with the Windows millisecond count using this offset. 321 * We retain the submillisecond portion of our own count. 322 * 323 * Note - this also assumes that the relationship between 324 * the PerformanceCouunter and SystemTime stays constant; 325 * that assumption breaks if the SystemTime is adjusted by 326 * an external action. 327 */ 328 if ( !cFreq.QuadPart ) { 329 long long t; 330 int usec; 331 QueryPerformanceFrequency( &cFreq ); 332 333 /* just get sub-second portion of counter */ 334 t = count.QuadPart % cFreq.QuadPart; 335 336 /* convert to microseconds */ 337 t *= 1000000; 338 usec = t / cFreq.QuadPart; 339 340 offset = usec - st.wMilliseconds * 1000; 341 } 342 343 tm->tm_usub = subs; 344 345 /* convert to microseconds */ 346 count.QuadPart %= cFreq.QuadPart; 347 count.QuadPart *= 1000000; 348 count.QuadPart /= cFreq.QuadPart; 349 count.QuadPart -= offset; 350 351 tm->tm_usec = count.QuadPart % 1000000; 352 if ( tm->tm_usec < 0 ) 353 tm->tm_usec += 1000000; 354 355 /* any difference larger than microseconds is 356 * already reflected in st 357 */ 358 359 tm->tm_sec = st.wSecond; 360 tm->tm_min = st.wMinute; 361 tm->tm_hour = st.wHour; 362 tm->tm_mday = st.wDay; 363 tm->tm_mon = st.wMonth - 1; 364 tm->tm_year = st.wYear - 1900; 365 } 366 #else 367 void 368 lutil_gettime( struct lutil_tm *ltm ) 369 { 370 struct timeval tv; 371 static struct timeval prevTv; 372 static int subs; 373 374 #ifdef HAVE_GMTIME_R 375 struct tm tm_buf; 376 #endif 377 struct tm *tm; 378 time_t t; 379 380 gettimeofday( &tv, NULL ); 381 t = tv.tv_sec; 382 383 if ( tv.tv_sec < prevTv.tv_sec 384 || ( tv.tv_sec == prevTv.tv_sec && tv.tv_usec <= prevTv.tv_usec )) { 385 subs++; 386 } else { 387 subs = 0; 388 prevTv = tv; 389 } 390 391 ltm->tm_usub = subs; 392 393 #ifdef HAVE_GMTIME_R 394 tm = gmtime_r( &t, &tm_buf ); 395 #else 396 tm = gmtime( &t ); 397 #endif 398 399 ltm->tm_sec = tm->tm_sec; 400 ltm->tm_min = tm->tm_min; 401 ltm->tm_hour = tm->tm_hour; 402 ltm->tm_mday = tm->tm_mday; 403 ltm->tm_mon = tm->tm_mon; 404 ltm->tm_year = tm->tm_year; 405 ltm->tm_usec = tv.tv_usec; 406 } 407 #endif 408 409 /* strcopy is like strcpy except it returns a pointer to the trailing NUL of 410 * the result string. This allows fast construction of catenated strings 411 * without the overhead of strlen/strcat. 412 */ 413 char * 414 lutil_strcopy( 415 char *a, 416 const char *b 417 ) 418 { 419 if (!a || !b) 420 return a; 421 422 while ((*a++ = *b++)) ; 423 return a-1; 424 } 425 426 /* strncopy is like strcpy except it returns a pointer to the trailing NUL of 427 * the result string. This allows fast construction of catenated strings 428 * without the overhead of strlen/strcat. 429 */ 430 char * 431 lutil_strncopy( 432 char *a, 433 const char *b, 434 size_t n 435 ) 436 { 437 if (!a || !b || n == 0) 438 return a; 439 440 while ((*a++ = *b++) && n-- > 0) ; 441 return a-1; 442 } 443 444 /* memcopy is like memcpy except it returns a pointer to the byte past 445 * the end of the result buffer, set to NULL. This allows fast construction 446 * of catenated buffers. Provided for API consistency with lutil_str*copy(). 447 */ 448 char * 449 lutil_memcopy( 450 char *a, 451 const char *b, 452 size_t n 453 ) 454 { 455 AC_MEMCPY(a, b, n); 456 return a + n; 457 } 458 459 #ifndef HAVE_MKSTEMP 460 int mkstemp( char * template ) 461 { 462 #ifdef HAVE_MKTEMP 463 return open ( mktemp ( template ), O_RDWR|O_CREAT|O_EXCL, 0600 ); 464 #else 465 return -1; 466 #endif 467 } 468 #endif 469 470 #ifdef _MSC_VER 471 /* Equivalent of MS CRT's _dosmaperr(). 472 * @param lastError[in] Result of GetLastError(). 473 */ 474 static errno_t win2errno(DWORD lastError) 475 { 476 const struct { 477 DWORD windows_code; 478 errno_t errno_code; 479 } WIN2ERRNO_TABLE[] = { 480 { ERROR_SUCCESS, 0 }, 481 { ERROR_FILE_NOT_FOUND, ENOENT }, 482 { ERROR_PATH_NOT_FOUND, ENOENT }, 483 { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, 484 { ERROR_ACCESS_DENIED, EACCES }, 485 { ERROR_INVALID_HANDLE, EBADF }, 486 { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, 487 { ERROR_LOCK_VIOLATION, EACCES }, 488 { ERROR_FILE_EXISTS, EEXIST }, 489 { ERROR_INVALID_PARAMETER, EINVAL }, 490 { ERROR_FILENAME_EXCED_RANGE, ENAMETOOLONG }, 491 }; 492 const unsigned int WIN2ERRNO_TABLE_SIZE = sizeof(WIN2ERRNO_TABLE) / 493 sizeof(WIN2ERRNO_TABLE[0]); 494 const errno_t DEFAULT_ERRNO_ERROR = -1; 495 unsigned int i; 496 497 for (i = 0; i < WIN2ERRNO_TABLE_SIZE; ++i) { 498 if (WIN2ERRNO_TABLE[i].windows_code == lastError) { 499 return WIN2ERRNO_TABLE[i].errno_code; 500 } 501 } 502 return DEFAULT_ERRNO_ERROR; 503 } 504 505 struct dirent { 506 char *d_name; 507 }; 508 typedef struct DIR { 509 HANDLE dir; 510 struct dirent data; 511 int first; 512 char buf[MAX_PATH+1]; 513 } DIR; 514 DIR *opendir( char *path ) 515 { 516 char tmp[32768]; 517 int len = strlen(path); 518 DIR *d; 519 HANDLE h; 520 WIN32_FIND_DATA data; 521 522 if (len+3 >= sizeof(tmp)) { 523 errno = ENAMETOOLONG; 524 return NULL; 525 } 526 527 strcpy(tmp, path); 528 tmp[len++] = '\\'; 529 tmp[len++] = '*'; 530 tmp[len] = '\0'; 531 532 h = FindFirstFile( tmp, &data ); 533 534 if ( h == INVALID_HANDLE_VALUE ) { 535 errno = win2errno( GetLastError()); 536 return NULL; 537 } 538 539 d = ber_memalloc( sizeof(DIR) ); 540 if ( !d ) 541 return NULL; 542 d->dir = h; 543 d->data.d_name = d->buf; 544 d->first = 1; 545 strcpy(d->data.d_name, data.cFileName); 546 return d; 547 } 548 struct dirent *readdir(DIR *dir) 549 { 550 WIN32_FIND_DATA data; 551 552 if (dir->first) { 553 dir->first = 0; 554 } else { 555 if (!FindNextFile(dir->dir, &data)) 556 return NULL; 557 strcpy(dir->data.d_name, data.cFileName); 558 } 559 return &dir->data; 560 } 561 int closedir(DIR *dir) 562 { 563 FindClose(dir->dir); 564 ber_memfree(dir); 565 } 566 #endif 567 568 /* 569 * Memory Reverse Search 570 */ 571 void * 572 (lutil_memrchr)(const void *b, int c, size_t n) 573 { 574 if (n != 0) { 575 const unsigned char *s, *bb = b, cc = c; 576 577 for ( s = bb + n; s > bb; ) { 578 if ( *--s == cc ) { 579 return (void *) s; 580 } 581 } 582 } 583 584 return NULL; 585 } 586 587 int 588 lutil_atoix( int *v, const char *s, int x ) 589 { 590 char *next; 591 long i; 592 593 assert( s != NULL ); 594 assert( v != NULL ); 595 596 i = strtol( s, &next, x ); 597 if ( next == s || next[ 0 ] != '\0' ) { 598 return -1; 599 } 600 601 if ( (long)(int)i != i ) { 602 return 1; 603 } 604 605 *v = (int)i; 606 607 return 0; 608 } 609 610 int 611 lutil_atoux( unsigned *v, const char *s, int x ) 612 { 613 char *next; 614 unsigned long u; 615 616 assert( s != NULL ); 617 assert( v != NULL ); 618 619 /* strtoul() has an odd interface */ 620 if ( s[ 0 ] == '-' ) { 621 return -1; 622 } 623 624 u = strtoul( s, &next, x ); 625 if ( next == s || next[ 0 ] != '\0' ) { 626 return -1; 627 } 628 629 if ( (unsigned long)(unsigned)u != u ) { 630 return 1; 631 } 632 633 *v = u; 634 635 return 0; 636 } 637 638 int 639 lutil_atolx( long *v, const char *s, int x ) 640 { 641 char *next; 642 long l; 643 644 assert( s != NULL ); 645 assert( v != NULL ); 646 647 l = strtol( s, &next, x ); 648 if ( next == s || next[ 0 ] != '\0' ) { 649 return -1; 650 } 651 652 *v = l; 653 654 return 0; 655 } 656 657 int 658 lutil_atoulx( unsigned long *v, const char *s, int x ) 659 { 660 char *next; 661 unsigned long ul; 662 663 assert( s != NULL ); 664 assert( v != NULL ); 665 666 /* strtoul() has an odd interface */ 667 if ( s[ 0 ] == '-' ) { 668 return -1; 669 } 670 671 ul = strtoul( s, &next, x ); 672 if ( next == s || next[ 0 ] != '\0' ) { 673 return -1; 674 } 675 676 *v = ul; 677 678 return 0; 679 } 680 681 /* Multiply an integer by 100000000 and add new */ 682 typedef struct lutil_int_decnum { 683 unsigned char *buf; 684 int bufsiz; 685 int beg; 686 int len; 687 } lutil_int_decnum; 688 689 #define FACTOR1 (100000000&0xffff) 690 #define FACTOR2 (100000000>>16) 691 692 static void 693 scale( int new, lutil_int_decnum *prev, unsigned char *tmp ) 694 { 695 int i, j; 696 unsigned char *in = prev->buf+prev->beg; 697 unsigned int part; 698 unsigned char *out = tmp + prev->bufsiz - prev->len; 699 700 memset( tmp, 0, prev->bufsiz ); 701 if ( prev->len ) { 702 for ( i = prev->len-1; i>=0; i-- ) { 703 part = in[i] * FACTOR1; 704 for ( j = i; part; j-- ) { 705 part += out[j]; 706 out[j] = part & 0xff; 707 part >>= 8; 708 } 709 part = in[i] * FACTOR2; 710 for ( j = i-2; part; j-- ) { 711 part += out[j]; 712 out[j] = part & 0xff; 713 part >>= 8; 714 } 715 } 716 j++; 717 prev->beg += j; 718 prev->len -= j; 719 } 720 721 out = tmp + prev->bufsiz; 722 i = 0; 723 do { 724 i--; 725 new += out[i]; 726 out[i] = new & 0xff; 727 new >>= 8; 728 } while ( new ); 729 i = -i; 730 if ( prev->len < i ) { 731 prev->beg = prev->bufsiz - i; 732 prev->len = i; 733 } 734 AC_MEMCPY( prev->buf+prev->beg, tmp+prev->beg, prev->len ); 735 } 736 737 /* Convert unlimited length decimal or hex string to binary. 738 * Output buffer must be provided, bv_len must indicate buffer size 739 * Hex input can be "0x1234" or "'1234'H" 740 * 741 * Temporarily modifies the input string. 742 * 743 * Note: High bit of binary form is always the sign bit. If the number 744 * is supposed to be positive but has the high bit set, a zero byte 745 * is prepended. It is assumed that this has already been handled on 746 * any hex input. 747 */ 748 int 749 lutil_str2bin( struct berval *in, struct berval *out, void *ctx ) 750 { 751 char *pin, *pout, ctmp; 752 char *end; 753 int i, chunk, len, rc = 0, hex = 0; 754 if ( !out || !out->bv_val || out->bv_len < in->bv_len ) 755 return -1; 756 757 pout = out->bv_val; 758 /* Leading "0x" for hex input */ 759 if ( in->bv_len > 2 && in->bv_val[0] == '0' && 760 ( in->bv_val[1] == 'x' || in->bv_val[1] == 'X' ) ) 761 { 762 len = in->bv_len - 2; 763 pin = in->bv_val + 2; 764 hex = 1; 765 } else if ( in->bv_len > 3 && in->bv_val[0] == '\'' && 766 in->bv_val[in->bv_len-2] == '\'' && 767 in->bv_val[in->bv_len-1] == 'H' ) 768 { 769 len = in->bv_len - 3; 770 pin = in->bv_val + 1; 771 hex = 1; 772 } 773 if ( hex ) { 774 #define HEXMAX (2 * sizeof(long)) 775 unsigned long l; 776 /* Convert a longword at a time, but handle leading 777 * odd bytes first 778 */ 779 chunk = len % HEXMAX; 780 if ( !chunk ) 781 chunk = HEXMAX; 782 783 while ( len ) { 784 int ochunk; 785 ctmp = pin[chunk]; 786 pin[chunk] = '\0'; 787 errno = 0; 788 l = strtoul( pin, &end, 16 ); 789 pin[chunk] = ctmp; 790 if ( errno ) 791 return -1; 792 ochunk = (chunk + 1)/2; 793 for ( i = ochunk - 1; i >= 0; i-- ) { 794 pout[i] = l & 0xff; 795 l >>= 8; 796 } 797 pin += chunk; 798 pout += ochunk; 799 len -= chunk; 800 chunk = HEXMAX; 801 } 802 out->bv_len = pout - out->bv_val; 803 } else { 804 /* Decimal */ 805 char tmpbuf[64], *tmp; 806 lutil_int_decnum num; 807 int neg = 0; 808 long l; 809 810 len = in->bv_len; 811 pin = in->bv_val; 812 num.buf = (unsigned char *)out->bv_val; 813 num.bufsiz = out->bv_len; 814 num.beg = num.bufsiz-1; 815 num.len = 0; 816 if ( pin[0] == '-' ) { 817 neg = 0xff; 818 len--; 819 pin++; 820 } 821 822 #define DECMAX 8 /* 8 digits at a time */ 823 824 /* tmp must be at least as large as outbuf */ 825 if ( out->bv_len > sizeof(tmpbuf)) { 826 tmp = ber_memalloc_x( out->bv_len, ctx ); 827 } else { 828 tmp = tmpbuf; 829 } 830 chunk = len & (DECMAX-1); 831 if ( !chunk ) 832 chunk = DECMAX; 833 834 while ( len ) { 835 ctmp = pin[chunk]; 836 pin[chunk] = '\0'; 837 errno = 0; 838 l = strtol( pin, &end, 10 ); 839 pin[chunk] = ctmp; 840 if ( errno ) { 841 rc = -1; 842 goto decfail; 843 } 844 scale( l, &num, (unsigned char *)tmp ); 845 pin += chunk; 846 len -= chunk; 847 chunk = DECMAX; 848 } 849 /* Negate the result */ 850 if ( neg ) { 851 unsigned char *ptr; 852 853 ptr = num.buf+num.beg; 854 855 /* flip all bits */ 856 for ( i=0; i<num.len; i++ ) 857 ptr[i] ^= 0xff; 858 859 /* add 1, with carry - overflow handled below */ 860 while ( i-- && ! (ptr[i] = (ptr[i] + 1) & 0xff )) ; 861 } 862 /* Prepend sign byte if wrong sign bit */ 863 if (( num.buf[num.beg] ^ neg ) & 0x80 ) { 864 num.beg--; 865 num.len++; 866 num.buf[num.beg] = neg; 867 } 868 if ( num.beg ) 869 AC_MEMCPY( num.buf, num.buf+num.beg, num.len ); 870 out->bv_len = num.len; 871 decfail: 872 if ( tmp != tmpbuf ) { 873 ber_memfree_x( tmp, ctx ); 874 } 875 } 876 return rc; 877 } 878 879 static char time_unit[] = "dhms"; 880 881 /* Used to parse and unparse time intervals, not timestamps */ 882 int 883 lutil_parse_time( 884 const char *in, 885 unsigned long *tp ) 886 { 887 unsigned long t = 0; 888 char *s, 889 *next; 890 int sofar = -1, 891 scale[] = { 86400, 3600, 60, 1 }; 892 893 *tp = 0; 894 895 for ( s = (char *)in; s[ 0 ] != '\0'; ) { 896 unsigned long u; 897 char *what; 898 899 /* strtoul() has an odd interface */ 900 if ( s[ 0 ] == '-' ) { 901 return -1; 902 } 903 904 u = strtoul( s, &next, 10 ); 905 if ( next == s ) { 906 return -1; 907 } 908 909 if ( next[ 0 ] == '\0' ) { 910 /* assume seconds */ 911 t += u; 912 break; 913 } 914 915 what = strchr( time_unit, next[ 0 ] ); 916 if ( what == NULL ) { 917 return -1; 918 } 919 920 if ( what - time_unit <= sofar ) { 921 return -1; 922 } 923 924 sofar = what - time_unit; 925 t += u * scale[ sofar ]; 926 927 s = &next[ 1 ]; 928 } 929 930 *tp = t; 931 return 0; 932 } 933 934 int 935 lutil_unparse_time( 936 char *buf, 937 size_t buflen, 938 unsigned long t ) 939 { 940 int len, i; 941 unsigned long v[ 4 ]; 942 char *ptr = buf; 943 944 v[ 0 ] = t/86400; 945 v[ 1 ] = (t%86400)/3600; 946 v[ 2 ] = (t%3600)/60; 947 v[ 3 ] = t%60; 948 949 for ( i = 0; i < 4; i++ ) { 950 if ( v[i] > 0 || ( i == 3 && ptr == buf ) ) { 951 len = snprintf( ptr, buflen, "%lu%c", v[ i ], time_unit[ i ] ); 952 if ( len < 0 || (unsigned)len >= buflen ) { 953 return -1; 954 } 955 buflen -= len; 956 ptr += len; 957 } 958 } 959 960 return 0; 961 } 962 963 /* 964 * formatted print to string 965 * 966 * - if return code < 0, the error code returned by vsnprintf(3) is returned 967 * 968 * - if return code > 0, the buffer was not long enough; 969 * - if next is not NULL, *next will be set to buf + bufsize - 1 970 * - if len is not NULL, *len will contain the required buffer length 971 * 972 * - if return code == 0, the buffer was long enough; 973 * - if next is not NULL, *next will point to the end of the string printed so far 974 * - if len is not NULL, *len will contain the length of the string printed so far 975 */ 976 int 977 lutil_snprintf( char *buf, ber_len_t bufsize, char **next, ber_len_t *len, LDAP_CONST char *fmt, ... ) 978 { 979 va_list ap; 980 int ret; 981 982 assert( buf != NULL ); 983 assert( bufsize > 0 ); 984 assert( fmt != NULL ); 985 986 va_start( ap, fmt ); 987 ret = vsnprintf( buf, bufsize, fmt, ap ); 988 va_end( ap ); 989 990 if ( ret < 0 ) { 991 return ret; 992 } 993 994 if ( len ) { 995 *len = ret; 996 } 997 998 if ( (unsigned) ret >= bufsize ) { 999 if ( next ) { 1000 *next = &buf[ bufsize - 1 ]; 1001 } 1002 1003 return 1; 1004 } 1005 1006 if ( next ) { 1007 *next = &buf[ ret ]; 1008 } 1009 1010 return 0; 1011 } 1012 1013