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_pmemdup(a, s, len); 79 return res; 80} 81 82APR_DECLARE(char *) apr_pstrndup(apr_pool_t *a, const char *s, apr_size_t n) 83{ 84 char *res; 85 const char *end; 86 87 if (s == NULL) { 88 return NULL; 89 } 90 end = memchr(s, '\0', n); 91 if (end != NULL) 92 n = end - s; 93 res = apr_palloc(a, n + 1); 94 memcpy(res, s, n); 95 res[n] = '\0'; 96 return res; 97} 98 99APR_DECLARE(char *) apr_pstrmemdup(apr_pool_t *a, const char *s, apr_size_t n) 100{ 101 char *res; 102 103 if (s == NULL) { 104 return NULL; 105 } 106 res = apr_palloc(a, n + 1); 107 memcpy(res, s, n); 108 res[n] = '\0'; 109 return res; 110} 111 112APR_DECLARE(void *) apr_pmemdup(apr_pool_t *a, const void *m, apr_size_t n) 113{ 114 void *res; 115 116 if (m == NULL) 117 return NULL; 118 res = apr_palloc(a, n); 119 memcpy(res, m, n); 120 return res; 121} 122 123APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *a, ...) 124{ 125 char *cp, *argp, *res; 126 apr_size_t saved_lengths[MAX_SAVED_LENGTHS]; 127 int nargs = 0; 128 129 /* Pass one --- find length of required string */ 130 131 apr_size_t len = 0; 132 va_list adummy; 133 134 va_start(adummy, a); 135 136 while ((cp = va_arg(adummy, char *)) != NULL) { 137 apr_size_t cplen = strlen(cp); 138 if (nargs < MAX_SAVED_LENGTHS) { 139 saved_lengths[nargs++] = cplen; 140 } 141 len += cplen; 142 } 143 144 va_end(adummy); 145 146 /* Allocate the required string */ 147 148 res = (char *) apr_palloc(a, len + 1); 149 cp = res; 150 151 /* Pass two --- copy the argument strings into the result space */ 152 153 va_start(adummy, a); 154 155 nargs = 0; 156 while ((argp = va_arg(adummy, char *)) != NULL) { 157 if (nargs < MAX_SAVED_LENGTHS) { 158 len = saved_lengths[nargs++]; 159 } 160 else { 161 len = strlen(argp); 162 } 163 164 memcpy(cp, argp, len); 165 cp += len; 166 } 167 168 va_end(adummy); 169 170 /* Return the result string */ 171 172 *cp = '\0'; 173 174 return res; 175} 176 177APR_DECLARE(char *) apr_pstrcatv(apr_pool_t *a, const struct iovec *vec, 178 apr_size_t nvec, apr_size_t *nbytes) 179{ 180 apr_size_t i; 181 apr_size_t len; 182 const struct iovec *src; 183 char *res; 184 char *dst; 185 186 /* Pass one --- find length of required string */ 187 len = 0; 188 src = vec; 189 for (i = nvec; i; i--) { 190 len += src->iov_len; 191 src++; 192 } 193 if (nbytes) { 194 *nbytes = len; 195 } 196 197 /* Allocate the required string */ 198 res = (char *) apr_palloc(a, len + 1); 199 200 /* Pass two --- copy the argument strings into the result space */ 201 src = vec; 202 dst = res; 203 for (i = nvec; i; i--) { 204 memcpy(dst, src->iov_base, src->iov_len); 205 dst += src->iov_len; 206 src++; 207 } 208 209 /* Return the result string */ 210 *dst = '\0'; 211 212 return res; 213} 214 215#if (!APR_HAVE_MEMCHR) 216void *memchr(const void *s, int c, size_t n) 217{ 218 const char *cp; 219 220 for (cp = s; n > 0; n--, cp++) { 221 if (*cp == c) 222 return (char *) cp; /* Casting away the const here */ 223 } 224 225 return NULL; 226} 227#endif 228 229#ifndef INT64_MAX 230#define INT64_MAX APR_INT64_C(0x7fffffffffffffff) 231#endif 232#ifndef INT64_MIN 233#define INT64_MIN (-APR_INT64_C(0x7fffffffffffffff) - APR_INT64_C(1)) 234#endif 235 236APR_DECLARE(apr_status_t) apr_strtoff(apr_off_t *offset, const char *nptr, 237 char **endptr, int base) 238{ 239 errno = 0; 240 *offset = APR_OFF_T_STRFN(nptr, endptr, base); 241 return APR_FROM_OS_ERROR(errno); 242} 243 244APR_DECLARE(apr_int64_t) apr_strtoi64(const char *nptr, char **endptr, int base) 245{ 246#ifdef APR_INT64_STRFN 247 errno = 0; 248 return APR_INT64_STRFN(nptr, endptr, base); 249#else 250 const char *s; 251 apr_int64_t acc; 252 apr_int64_t val; 253 int neg, any; 254 char c; 255 256 errno = 0; 257 /* 258 * Skip white space and pick up leading +/- sign if any. 259 * If base is 0, allow 0x for hex and 0 for octal, else 260 * assume decimal; if base is already 16, allow 0x. 261 */ 262 s = nptr; 263 do { 264 c = *s++; 265 } while (apr_isspace(c)); 266 if (c == '-') { 267 neg = 1; 268 c = *s++; 269 } else { 270 neg = 0; 271 if (c == '+') 272 c = *s++; 273 } 274 if ((base == 0 || base == 16) && 275 c == '0' && (*s == 'x' || *s == 'X')) { 276 c = s[1]; 277 s += 2; 278 base = 16; 279 } 280 if (base == 0) 281 base = c == '0' ? 8 : 10; 282 acc = any = 0; 283 if (base < 2 || base > 36) { 284 errno = EINVAL; 285 if (endptr != NULL) 286 *endptr = (char *)(any ? s - 1 : nptr); 287 return acc; 288 } 289 290 /* The classic bsd implementation requires div/mod operators 291 * to compute a cutoff. Benchmarking proves that is very, very 292 * evil to some 32 bit processors. Instead, look for underflow 293 * in both the mult and add/sub operation. Unlike the bsd impl, 294 * we also work strictly in a signed int64 word as we haven't 295 * implemented the unsigned type in win32. 296 * 297 * Set 'any' if any `digits' consumed; make it negative to indicate 298 * overflow. 299 */ 300 val = 0; 301 for ( ; ; c = *s++) { 302 if (c >= '0' && c <= '9') 303 c -= '0'; 304#if (('Z' - 'A') == 25) 305 else if (c >= 'A' && c <= 'Z') 306 c -= 'A' - 10; 307 else if (c >= 'a' && c <= 'z') 308 c -= 'a' - 10; 309#elif APR_CHARSET_EBCDIC 310 else if (c >= 'A' && c <= 'I') 311 c -= 'A' - 10; 312 else if (c >= 'J' && c <= 'R') 313 c -= 'J' - 19; 314 else if (c >= 'S' && c <= 'Z') 315 c -= 'S' - 28; 316 else if (c >= 'a' && c <= 'i') 317 c -= 'a' - 10; 318 else if (c >= 'j' && c <= 'r') 319 c -= 'j' - 19; 320 else if (c >= 's' && c <= 'z') 321 c -= 'z' - 28; 322#else 323#error "CANNOT COMPILE apr_strtoi64(), only ASCII and EBCDIC supported" 324#endif 325 else 326 break; 327 if (c >= base) 328 break; 329 val *= base; 330 if ( (any < 0) /* already noted an over/under flow - short circuit */ 331 || (neg && (val > acc || (val -= c) > acc)) /* underflow */ 332 || (!neg && (val < acc || (val += c) < acc))) { /* overflow */ 333 any = -1; /* once noted, over/underflows never go away */ 334#ifdef APR_STRTOI64_OVERFLOW_IS_BAD_CHAR 335 break; 336#endif 337 } else { 338 acc = val; 339 any = 1; 340 } 341 } 342 343 if (any < 0) { 344 acc = neg ? INT64_MIN : INT64_MAX; 345 errno = ERANGE; 346 } else if (!any) { 347 errno = EINVAL; 348 } 349 if (endptr != NULL) 350 *endptr = (char *)(any ? s - 1 : nptr); 351 return (acc); 352#endif 353} 354 355APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf) 356{ 357 return apr_strtoi64(buf, NULL, 10); 358} 359 360APR_DECLARE(char *) apr_itoa(apr_pool_t *p, int n) 361{ 362 const int BUFFER_SIZE = sizeof(int) * 3 + 2; 363 char *buf = apr_palloc(p, BUFFER_SIZE); 364 char *start = buf + BUFFER_SIZE - 1; 365 int negative; 366 if (n < 0) { 367 negative = 1; 368 n = -n; 369 } 370 else { 371 negative = 0; 372 } 373 *start = 0; 374 do { 375 *--start = '0' + (n % 10); 376 n /= 10; 377 } while (n); 378 if (negative) { 379 *--start = '-'; 380 } 381 return start; 382} 383 384APR_DECLARE(char *) apr_ltoa(apr_pool_t *p, long n) 385{ 386 const int BUFFER_SIZE = sizeof(long) * 3 + 2; 387 char *buf = apr_palloc(p, BUFFER_SIZE); 388 char *start = buf + BUFFER_SIZE - 1; 389 int negative; 390 if (n < 0) { 391 negative = 1; 392 n = -n; 393 } 394 else { 395 negative = 0; 396 } 397 *start = 0; 398 do { 399 *--start = (char)('0' + (n % 10)); 400 n /= 10; 401 } while (n); 402 if (negative) { 403 *--start = '-'; 404 } 405 return start; 406} 407 408APR_DECLARE(char *) apr_off_t_toa(apr_pool_t *p, apr_off_t n) 409{ 410 const int BUFFER_SIZE = sizeof(apr_off_t) * 3 + 2; 411 char *buf = apr_palloc(p, BUFFER_SIZE); 412 char *start = buf + BUFFER_SIZE - 1; 413 int negative; 414 if (n < 0) { 415 negative = 1; 416 n = -n; 417 } 418 else { 419 negative = 0; 420 } 421 *start = 0; 422 do { 423 *--start = '0' + (char)(n % 10); 424 n /= 10; 425 } while (n); 426 if (negative) { 427 *--start = '-'; 428 } 429 return start; 430} 431 432APR_DECLARE(char *) apr_strfsize(apr_off_t size, char *buf) 433{ 434 const char ord[] = "KMGTPE"; 435 const char *o = ord; 436 int remain; 437 438 if (size < 0) { 439 return strcpy(buf, " - "); 440 } 441 if (size < 973) { 442 if (apr_snprintf(buf, 5, "%3d ", (int) size) < 0) 443 return strcpy(buf, "****"); 444 return buf; 445 } 446 do { 447 remain = (int)(size & 1023); 448 size >>= 10; 449 if (size >= 973) { 450 ++o; 451 continue; 452 } 453 if (size < 9 || (size == 9 && remain < 973)) { 454 if ((remain = ((remain * 5) + 256) / 512) >= 10) 455 ++size, remain = 0; 456 if (apr_snprintf(buf, 5, "%d.%d%c", (int) size, remain, *o) < 0) 457 return strcpy(buf, "****"); 458 return buf; 459 } 460 if (remain >= 512) 461 ++size; 462 if (apr_snprintf(buf, 5, "%3d%c", (int) size, *o) < 0) 463 return strcpy(buf, "****"); 464 return buf; 465 } while (1); 466} 467 468