1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16/* 17 * Copyright (c) 1990, 1993 18 * The Regents of the University of California. All rights reserved. 19 * 20 * Redistribution and use in source and binary forms, with or without 21 * modification, are permitted provided that the following conditions 22 * are met: 23 * 1. Redistributions of source code must retain the above copyright 24 * notice, this list of conditions and the following disclaimer. 25 * 2. Redistributions in binary form must reproduce the above copyright 26 * notice, this list of conditions and the following disclaimer in the 27 * documentation and/or other materials provided with the distribution. 28 * 3. All advertising materials mentioning features or use of this software 29 * must display the following acknowledgement: 30 * This product includes software developed by the University of 31 * California, Berkeley and its contributors. 32 * 4. Neither the name of the University nor the names of its contributors 33 * may be used to endorse or promote products derived from this software 34 * without specific prior written permission. 35 * 36 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 37 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 39 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 40 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 41 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 42 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 44 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 45 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 46 * SUCH DAMAGE. 47 */ 48 49#include "apr.h" 50#include "apr_strings.h" 51#include "apr_general.h" 52#include "apr_private.h" 53#include "apr_lib.h" 54#define APR_WANT_STDIO 55#define APR_WANT_STRFUNC 56#include "apr_want.h" 57 58#ifdef HAVE_STDDEF_H 59#include <stddef.h> /* NULL */ 60#endif 61 62#ifdef HAVE_STDLIB_H 63#include <stdlib.h> /* strtol and strtoll */ 64#endif 65 66/** this is used to cache lengths in apr_pstrcat */ 67#define MAX_SAVED_LENGTHS 6 68 69APR_DECLARE(char *) apr_pstrdup(apr_pool_t *a, const char *s) 70{ 71 char *res; 72 apr_size_t len; 73 74 if (s == NULL) { 75 return NULL; 76 } 77 len = strlen(s) + 1; 78 res = apr_palloc(a, len); 79 memcpy(res, s, len); 80 return res; 81} 82 83APR_DECLARE(char *) apr_pstrndup(apr_pool_t *a, const char *s, apr_size_t n) 84{ 85 char *res; 86 const char *end; 87 88 if (s == NULL) { 89 return NULL; 90 } 91 end = memchr(s, '\0', n); 92 if (end != NULL) 93 n = end - s; 94 res = apr_palloc(a, n + 1); 95 memcpy(res, s, n); 96 res[n] = '\0'; 97 return res; 98} 99 100APR_DECLARE(char *) apr_pstrmemdup(apr_pool_t *a, const char *s, apr_size_t n) 101{ 102 char *res; 103 104 if (s == NULL) { 105 return NULL; 106 } 107 res = apr_palloc(a, n + 1); 108 memcpy(res, s, n); 109 res[n] = '\0'; 110 return res; 111} 112 113APR_DECLARE(void *) apr_pmemdup(apr_pool_t *a, const void *m, apr_size_t n) 114{ 115 void *res; 116 117 if (m == NULL) 118 return NULL; 119 res = apr_palloc(a, n); 120 memcpy(res, m, n); 121 return res; 122} 123 124APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *a, ...) 125{ 126 char *cp, *argp, *res; 127 apr_size_t saved_lengths[MAX_SAVED_LENGTHS]; 128 int nargs = 0; 129 130 /* Pass one --- find length of required string */ 131 132 apr_size_t len = 0; 133 va_list adummy; 134 135 va_start(adummy, a); 136 137 while ((cp = va_arg(adummy, char *)) != NULL) { 138 apr_size_t cplen = strlen(cp); 139 if (nargs < MAX_SAVED_LENGTHS) { 140 saved_lengths[nargs++] = cplen; 141 } 142 len += cplen; 143 } 144 145 va_end(adummy); 146 147 /* Allocate the required string */ 148 149 res = (char *) apr_palloc(a, len + 1); 150 cp = res; 151 152 /* Pass two --- copy the argument strings into the result space */ 153 154 va_start(adummy, a); 155 156 nargs = 0; 157 while ((argp = va_arg(adummy, char *)) != NULL) { 158 if (nargs < MAX_SAVED_LENGTHS) { 159 len = saved_lengths[nargs++]; 160 } 161 else { 162 len = strlen(argp); 163 } 164 165 memcpy(cp, argp, len); 166 cp += len; 167 } 168 169 va_end(adummy); 170 171 /* Return the result string */ 172 173 *cp = '\0'; 174 175 return res; 176} 177 178APR_DECLARE(char *) apr_pstrcatv(apr_pool_t *a, const struct iovec *vec, 179 apr_size_t nvec, apr_size_t *nbytes) 180{ 181 apr_size_t i; 182 apr_size_t len; 183 const struct iovec *src; 184 char *res; 185 char *dst; 186 187 /* Pass one --- find length of required string */ 188 len = 0; 189 src = vec; 190 for (i = nvec; i; i--) { 191 len += src->iov_len; 192 src++; 193 } 194 if (nbytes) { 195 *nbytes = len; 196 } 197 198 /* Allocate the required string */ 199 res = (char *) apr_palloc(a, len + 1); 200 201 /* Pass two --- copy the argument strings into the result space */ 202 src = vec; 203 dst = res; 204 for (i = nvec; i; i--) { 205 memcpy(dst, src->iov_base, src->iov_len); 206 dst += src->iov_len; 207 src++; 208 } 209 210 /* Return the result string */ 211 *dst = '\0'; 212 213 return res; 214} 215 216#if (!APR_HAVE_MEMCHR) 217void *memchr(const void *s, int c, size_t n) 218{ 219 const char *cp; 220 221 for (cp = s; n > 0; n--, cp++) { 222 if (*cp == c) 223 return (char *) cp; /* Casting away the const here */ 224 } 225 226 return NULL; 227} 228#endif 229 230#ifndef INT64_MAX 231#define INT64_MAX APR_INT64_C(0x7fffffffffffffff) 232#endif 233#ifndef INT64_MIN 234#define INT64_MIN (-APR_INT64_C(0x7fffffffffffffff) - APR_INT64_C(1)) 235#endif 236 237APR_DECLARE(apr_status_t) apr_strtoff(apr_off_t *offset, const char *nptr, 238 char **endptr, int base) 239{ 240 errno = 0; 241 *offset = APR_OFF_T_STRFN(nptr, endptr, base); 242 return APR_FROM_OS_ERROR(errno); 243} 244 245APR_DECLARE(apr_int64_t) apr_strtoi64(const char *nptr, char **endptr, int base) 246{ 247#ifdef APR_INT64_STRFN 248 errno = 0; 249 return APR_INT64_STRFN(nptr, endptr, base); 250#else 251 const char *s; 252 apr_int64_t acc; 253 apr_int64_t val; 254 int neg, any; 255 char c; 256 257 errno = 0; 258 /* 259 * Skip white space and pick up leading +/- sign if any. 260 * If base is 0, allow 0x for hex and 0 for octal, else 261 * assume decimal; if base is already 16, allow 0x. 262 */ 263 s = nptr; 264 do { 265 c = *s++; 266 } while (apr_isspace(c)); 267 if (c == '-') { 268 neg = 1; 269 c = *s++; 270 } else { 271 neg = 0; 272 if (c == '+') 273 c = *s++; 274 } 275 if ((base == 0 || base == 16) && 276 c == '0' && (*s == 'x' || *s == 'X')) { 277 c = s[1]; 278 s += 2; 279 base = 16; 280 } 281 if (base == 0) 282 base = c == '0' ? 8 : 10; 283 acc = any = 0; 284 if (base < 2 || base > 36) { 285 errno = EINVAL; 286 if (endptr != NULL) 287 *endptr = (char *)(any ? s - 1 : nptr); 288 return acc; 289 } 290 291 /* The classic bsd implementation requires div/mod operators 292 * to compute a cutoff. Benchmarking proves that is very, very 293 * evil to some 32 bit processors. Instead, look for underflow 294 * in both the mult and add/sub operation. Unlike the bsd impl, 295 * we also work strictly in a signed int64 word as we haven't 296 * implemented the unsigned type in win32. 297 * 298 * Set 'any' if any `digits' consumed; make it negative to indicate 299 * overflow. 300 */ 301 val = 0; 302 for ( ; ; c = *s++) { 303 if (c >= '0' && c <= '9') 304 c -= '0'; 305#if (('Z' - 'A') == 25) 306 else if (c >= 'A' && c <= 'Z') 307 c -= 'A' - 10; 308 else if (c >= 'a' && c <= 'z') 309 c -= 'a' - 10; 310#elif APR_CHARSET_EBCDIC 311 else if (c >= 'A' && c <= 'I') 312 c -= 'A' - 10; 313 else if (c >= 'J' && c <= 'R') 314 c -= 'J' - 19; 315 else if (c >= 'S' && c <= 'Z') 316 c -= 'S' - 28; 317 else if (c >= 'a' && c <= 'i') 318 c -= 'a' - 10; 319 else if (c >= 'j' && c <= 'r') 320 c -= 'j' - 19; 321 else if (c >= 's' && c <= 'z') 322 c -= 'z' - 28; 323#else 324#error "CANNOT COMPILE apr_strtoi64(), only ASCII and EBCDIC supported" 325#endif 326 else 327 break; 328 if (c >= base) 329 break; 330 val *= base; 331 if ( (any < 0) /* already noted an over/under flow - short circuit */ 332 || (neg && (val > acc || (val -= c) > acc)) /* underflow */ 333 || (!neg && (val < acc || (val += c) < acc))) { /* overflow */ 334 any = -1; /* once noted, over/underflows never go away */ 335#ifdef APR_STRTOI64_OVERFLOW_IS_BAD_CHAR 336 break; 337#endif 338 } else { 339 acc = val; 340 any = 1; 341 } 342 } 343 344 if (any < 0) { 345 acc = neg ? INT64_MIN : INT64_MAX; 346 errno = ERANGE; 347 } else if (!any) { 348 errno = EINVAL; 349 } 350 if (endptr != NULL) 351 *endptr = (char *)(any ? s - 1 : nptr); 352 return (acc); 353#endif 354} 355 356APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf) 357{ 358 return apr_strtoi64(buf, NULL, 10); 359} 360 361APR_DECLARE(char *) apr_itoa(apr_pool_t *p, int n) 362{ 363 const int BUFFER_SIZE = sizeof(int) * 3 + 2; 364 char *buf = apr_palloc(p, BUFFER_SIZE); 365 char *start = buf + BUFFER_SIZE - 1; 366 int negative; 367 if (n < 0) { 368 negative = 1; 369 n = -n; 370 } 371 else { 372 negative = 0; 373 } 374 *start = 0; 375 do { 376 *--start = '0' + (n % 10); 377 n /= 10; 378 } while (n); 379 if (negative) { 380 *--start = '-'; 381 } 382 return start; 383} 384 385APR_DECLARE(char *) apr_ltoa(apr_pool_t *p, long n) 386{ 387 const int BUFFER_SIZE = sizeof(long) * 3 + 2; 388 char *buf = apr_palloc(p, BUFFER_SIZE); 389 char *start = buf + BUFFER_SIZE - 1; 390 int negative; 391 if (n < 0) { 392 negative = 1; 393 n = -n; 394 } 395 else { 396 negative = 0; 397 } 398 *start = 0; 399 do { 400 *--start = (char)('0' + (n % 10)); 401 n /= 10; 402 } while (n); 403 if (negative) { 404 *--start = '-'; 405 } 406 return start; 407} 408 409APR_DECLARE(char *) apr_off_t_toa(apr_pool_t *p, apr_off_t n) 410{ 411 const int BUFFER_SIZE = sizeof(apr_off_t) * 3 + 2; 412 char *buf = apr_palloc(p, BUFFER_SIZE); 413 char *start = buf + BUFFER_SIZE - 1; 414 int negative; 415 if (n < 0) { 416 negative = 1; 417 n = -n; 418 } 419 else { 420 negative = 0; 421 } 422 *start = 0; 423 do { 424 *--start = '0' + (char)(n % 10); 425 n /= 10; 426 } while (n); 427 if (negative) { 428 *--start = '-'; 429 } 430 return start; 431} 432 433APR_DECLARE(char *) apr_strfsize(apr_off_t size, char *buf) 434{ 435 const char ord[] = "KMGTPE"; 436 const char *o = ord; 437 int remain; 438 439 if (size < 0) { 440 return strcpy(buf, " - "); 441 } 442 if (size < 973) { 443 if (apr_snprintf(buf, 5, "%3d ", (int) size) < 0) 444 return strcpy(buf, "****"); 445 return buf; 446 } 447 do { 448 remain = (int)(size & 1023); 449 size >>= 10; 450 if (size >= 973) { 451 ++o; 452 continue; 453 } 454 if (size < 9 || (size == 9 && remain < 973)) { 455 if ((remain = ((remain * 5) + 256) / 512) >= 10) 456 ++size, remain = 0; 457 if (apr_snprintf(buf, 5, "%d.%d%c", (int) size, remain, *o) < 0) 458 return strcpy(buf, "****"); 459 return buf; 460 } 461 if (remain >= 512) 462 ++size; 463 if (apr_snprintf(buf, 5, "%3d%c", (int) size, *o) < 0) 464 return strcpy(buf, "****"); 465 return buf; 466 } while (1); 467} 468 469