subr_sbuf.c revision 212365
1/*- 2 * Copyright (c) 2000-2008 Poul-Henning Kamp 3 * Copyright (c) 2000-2008 Dag-Erling Co��dan Sm��rgrav 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer 11 * in this position and unchanged. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: head/sys/kern/subr_sbuf.c 212365 2010-09-09 16:51:52Z mdf $"); 31 32#include <sys/param.h> 33 34#ifdef _KERNEL 35#include <sys/ctype.h> 36#include <sys/kernel.h> 37#include <sys/malloc.h> 38#include <sys/systm.h> 39#include <sys/uio.h> 40#include <machine/stdarg.h> 41#else /* _KERNEL */ 42#include <ctype.h> 43#include <stdarg.h> 44#include <stdio.h> 45#include <stdlib.h> 46#include <string.h> 47#endif /* _KERNEL */ 48 49#include <sys/sbuf.h> 50 51#ifdef _KERNEL 52static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers"); 53#define SBMALLOC(size) malloc(size, M_SBUF, M_WAITOK) 54#define SBFREE(buf) free(buf, M_SBUF) 55#else /* _KERNEL */ 56#define KASSERT(e, m) 57#define SBMALLOC(size) malloc(size) 58#define SBFREE(buf) free(buf) 59#endif /* _KERNEL */ 60 61/* 62 * Predicates 63 */ 64#define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC) 65#define SBUF_ISDYNSTRUCT(s) ((s)->s_flags & SBUF_DYNSTRUCT) 66#define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED) 67#define SBUF_HASOVERFLOWED(s) ((s)->s_flags & SBUF_OVERFLOWED) 68#define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1) 69#define SBUF_FREESPACE(s) ((s)->s_size - (s)->s_len - 1) 70#define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND) 71 72/* 73 * Set / clear flags 74 */ 75#define SBUF_SETFLAG(s, f) do { (s)->s_flags |= (f); } while (0) 76#define SBUF_CLEARFLAG(s, f) do { (s)->s_flags &= ~(f); } while (0) 77 78#define SBUF_MINEXTENDSIZE 16 /* Should be power of 2. */ 79#define SBUF_MAXEXTENDSIZE PAGE_SIZE 80#define SBUF_MAXEXTENDINCR PAGE_SIZE 81 82/* 83 * Debugging support 84 */ 85#if defined(_KERNEL) && defined(INVARIANTS) 86 87static void 88_assert_sbuf_integrity(const char *fun, struct sbuf *s) 89{ 90 91 KASSERT(s != NULL, 92 ("%s called with a NULL sbuf pointer", fun)); 93 KASSERT(s->s_buf != NULL, 94 ("%s called with uninitialized or corrupt sbuf", fun)); 95 KASSERT(s->s_len < s->s_size, 96 ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size)); 97} 98 99static void 100_assert_sbuf_state(const char *fun, struct sbuf *s, int state) 101{ 102 103 KASSERT((s->s_flags & SBUF_FINISHED) == state, 104 ("%s called with %sfinished or corrupt sbuf", fun, 105 (state ? "un" : ""))); 106} 107 108#define assert_sbuf_integrity(s) _assert_sbuf_integrity(__func__, (s)) 109#define assert_sbuf_state(s, i) _assert_sbuf_state(__func__, (s), (i)) 110 111#else /* _KERNEL && INVARIANTS */ 112 113#define assert_sbuf_integrity(s) do { } while (0) 114#define assert_sbuf_state(s, i) do { } while (0) 115 116#endif /* _KERNEL && INVARIANTS */ 117 118#ifdef CTASSERT 119CTASSERT(powerof2(SBUF_MAXEXTENDSIZE)); 120CTASSERT(powerof2(SBUF_MAXEXTENDINCR)); 121#endif 122 123static int 124sbuf_extendsize(int size) 125{ 126 int newsize; 127 128 if (size < (int)SBUF_MAXEXTENDSIZE) { 129 newsize = SBUF_MINEXTENDSIZE; 130 while (newsize < size) 131 newsize *= 2; 132 } else { 133 newsize = roundup2(size, SBUF_MAXEXTENDINCR); 134 } 135 KASSERT(newsize >= size, ("%s: %d < %d\n", __func__, newsize, size)); 136 return (newsize); 137} 138 139 140/* 141 * Extend an sbuf. 142 */ 143static int 144sbuf_extend(struct sbuf *s, int addlen) 145{ 146 char *newbuf; 147 int newsize; 148 149 if (!SBUF_CANEXTEND(s)) 150 return (-1); 151 newsize = sbuf_extendsize(s->s_size + addlen); 152 newbuf = SBMALLOC(newsize); 153 if (newbuf == NULL) 154 return (-1); 155 bcopy(s->s_buf, newbuf, s->s_size); 156 if (SBUF_ISDYNAMIC(s)) 157 SBFREE(s->s_buf); 158 else 159 SBUF_SETFLAG(s, SBUF_DYNAMIC); 160 s->s_buf = newbuf; 161 s->s_size = newsize; 162 return (0); 163} 164 165/* 166 * Initialize an sbuf. 167 * If buf is non-NULL, it points to a static or already-allocated string 168 * big enough to hold at least length characters. 169 */ 170struct sbuf * 171sbuf_new(struct sbuf *s, char *buf, int length, int flags) 172{ 173 174 KASSERT(length >= 0, 175 ("attempt to create an sbuf of negative length (%d)", length)); 176 KASSERT((flags & ~SBUF_USRFLAGMSK) == 0, 177 ("%s called with invalid flags", __func__)); 178 179 flags &= SBUF_USRFLAGMSK; 180 if (s == NULL) { 181 s = SBMALLOC(sizeof(*s)); 182 if (s == NULL) 183 return (NULL); 184 bzero(s, sizeof(*s)); 185 s->s_flags = flags; 186 SBUF_SETFLAG(s, SBUF_DYNSTRUCT); 187 } else { 188 bzero(s, sizeof(*s)); 189 s->s_flags = flags; 190 } 191 s->s_size = length; 192 if (buf != NULL) { 193 s->s_buf = buf; 194 return (s); 195 } 196 if ((flags & SBUF_AUTOEXTEND) != 0) 197 s->s_size = sbuf_extendsize(s->s_size); 198 s->s_buf = SBMALLOC(s->s_size); 199 if (s->s_buf == NULL) { 200 if (SBUF_ISDYNSTRUCT(s)) 201 SBFREE(s); 202 return (NULL); 203 } 204 SBUF_SETFLAG(s, SBUF_DYNAMIC); 205 return (s); 206} 207 208#ifdef _KERNEL 209/* 210 * Create an sbuf with uio data 211 */ 212struct sbuf * 213sbuf_uionew(struct sbuf *s, struct uio *uio, int *error) 214{ 215 216 KASSERT(uio != NULL, 217 ("%s called with NULL uio pointer", __func__)); 218 KASSERT(error != NULL, 219 ("%s called with NULL error pointer", __func__)); 220 221 s = sbuf_new(s, NULL, uio->uio_resid + 1, 0); 222 if (s == NULL) { 223 *error = ENOMEM; 224 return (NULL); 225 } 226 *error = uiomove(s->s_buf, uio->uio_resid, uio); 227 if (*error != 0) { 228 sbuf_delete(s); 229 return (NULL); 230 } 231 s->s_len = s->s_size - 1; 232 *error = 0; 233 return (s); 234} 235#endif 236 237/* 238 * Clear an sbuf and reset its position. 239 */ 240void 241sbuf_clear(struct sbuf *s) 242{ 243 244 assert_sbuf_integrity(s); 245 /* don't care if it's finished or not */ 246 247 SBUF_CLEARFLAG(s, SBUF_FINISHED); 248 SBUF_CLEARFLAG(s, SBUF_OVERFLOWED); 249 s->s_len = 0; 250} 251 252/* 253 * Set the sbuf's end position to an arbitrary value. 254 * Effectively truncates the sbuf at the new position. 255 */ 256int 257sbuf_setpos(struct sbuf *s, int pos) 258{ 259 260 assert_sbuf_integrity(s); 261 assert_sbuf_state(s, 0); 262 263 KASSERT(pos >= 0, 264 ("attempt to seek to a negative position (%d)", pos)); 265 KASSERT(pos < s->s_size, 266 ("attempt to seek past end of sbuf (%d >= %d)", pos, s->s_size)); 267 268 if (pos < 0 || pos > s->s_len) 269 return (-1); 270 s->s_len = pos; 271 return (0); 272} 273 274/* 275 * Append a byte to an sbuf. This is the core function for appending 276 * to an sbuf and is the main place that deals with extending the 277 * buffer and marking overflow. 278 */ 279static void 280sbuf_put_byte(int c, struct sbuf *s) 281{ 282 283 assert_sbuf_integrity(s); 284 assert_sbuf_state(s, 0); 285 286 if (SBUF_HASOVERFLOWED(s)) 287 return; 288 if (SBUF_FREESPACE(s) <= 0) { 289 if (sbuf_extend(s, 1) < 0) { 290 SBUF_SETFLAG(s, SBUF_OVERFLOWED); 291 return; 292 } 293 } 294 s->s_buf[s->s_len++] = c; 295} 296 297/* 298 * Append a non-NUL character to an sbuf. This prototype signature is 299 * suitable for use with kvprintf(9). 300 */ 301static void 302sbuf_putc_func(int c, void *arg) 303{ 304 305 if (c != '\0') 306 sbuf_put_byte(c, arg); 307} 308 309/* 310 * Append a byte string to an sbuf. 311 */ 312int 313sbuf_bcat(struct sbuf *s, const void *buf, size_t len) 314{ 315 const char *str = buf; 316 const char *end = str + len; 317 318 assert_sbuf_integrity(s); 319 assert_sbuf_state(s, 0); 320 321 if (SBUF_HASOVERFLOWED(s)) 322 return (-1); 323 for (; str < end; str++) { 324 sbuf_put_byte(*str, s); 325 if (SBUF_HASOVERFLOWED(s)) 326 return (-1); 327 } 328 return (0); 329} 330 331#ifdef _KERNEL 332/* 333 * Copy a byte string from userland into an sbuf. 334 */ 335int 336sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len) 337{ 338 339 assert_sbuf_integrity(s); 340 assert_sbuf_state(s, 0); 341 342 if (SBUF_HASOVERFLOWED(s)) 343 return (-1); 344 if (len == 0) 345 return (0); 346 if (len > SBUF_FREESPACE(s)) { 347 sbuf_extend(s, len - SBUF_FREESPACE(s)); 348 if (SBUF_FREESPACE(s) < len) 349 len = SBUF_FREESPACE(s); 350 } 351 if (copyin(uaddr, s->s_buf + s->s_len, len) != 0) 352 return (-1); 353 s->s_len += len; 354 355 return (0); 356} 357#endif 358 359/* 360 * Copy a byte string into an sbuf. 361 */ 362int 363sbuf_bcpy(struct sbuf *s, const void *buf, size_t len) 364{ 365 366 assert_sbuf_integrity(s); 367 assert_sbuf_state(s, 0); 368 369 sbuf_clear(s); 370 return (sbuf_bcat(s, buf, len)); 371} 372 373/* 374 * Append a string to an sbuf. 375 */ 376int 377sbuf_cat(struct sbuf *s, const char *str) 378{ 379 380 assert_sbuf_integrity(s); 381 assert_sbuf_state(s, 0); 382 383 if (SBUF_HASOVERFLOWED(s)) 384 return (-1); 385 386 while (*str != '\0') { 387 sbuf_put_byte(*str, s); 388 if (SBUF_HASOVERFLOWED(s)) 389 return (-1); 390 } 391 return (0); 392} 393 394#ifdef _KERNEL 395/* 396 * Append a string from userland to an sbuf. 397 */ 398int 399sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len) 400{ 401 size_t done; 402 403 assert_sbuf_integrity(s); 404 assert_sbuf_state(s, 0); 405 406 if (SBUF_HASOVERFLOWED(s)) 407 return (-1); 408 409 if (len == 0) 410 len = SBUF_FREESPACE(s); /* XXX return 0? */ 411 if (len > SBUF_FREESPACE(s)) { 412 sbuf_extend(s, len); 413 if (SBUF_FREESPACE(s) < len) 414 len = SBUF_FREESPACE(s); 415 } 416 switch (copyinstr(uaddr, s->s_buf + s->s_len, len + 1, &done)) { 417 case ENAMETOOLONG: 418 SBUF_SETFLAG(s, SBUF_OVERFLOWED); 419 /* fall through */ 420 case 0: 421 s->s_len += done - 1; 422 break; 423 default: 424 return (-1); /* XXX */ 425 } 426 427 return (done); 428} 429#endif 430 431/* 432 * Copy a string into an sbuf. 433 */ 434int 435sbuf_cpy(struct sbuf *s, const char *str) 436{ 437 438 assert_sbuf_integrity(s); 439 assert_sbuf_state(s, 0); 440 441 sbuf_clear(s); 442 return (sbuf_cat(s, str)); 443} 444 445/* 446 * Format the given argument list and append the resulting string to an sbuf. 447 */ 448#ifdef _KERNEL 449int 450sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap) 451{ 452 453 assert_sbuf_integrity(s); 454 assert_sbuf_state(s, 0); 455 456 KASSERT(fmt != NULL, 457 ("%s called with a NULL format string", __func__)); 458 459 (void)kvprintf(fmt, sbuf_putc_func, s, 10, ap); 460 if (SBUF_HASOVERFLOWED(s)) 461 return (-1); 462 return (0); 463} 464#else /* !_KERNEL */ 465int 466sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap) 467{ 468 va_list ap_copy; 469 int len; 470 471 assert_sbuf_integrity(s); 472 assert_sbuf_state(s, 0); 473 474 KASSERT(fmt != NULL, 475 ("%s called with a NULL format string", __func__)); 476 477 if (SBUF_HASOVERFLOWED(s)) 478 return (-1); 479 480 /* 481 * For the moment, there is no way to get vsnprintf(3) to hand 482 * back a character at a time, to push everything into 483 * sbuf_putc_func() as was done for the kernel. 484 */ 485 486 do { 487 va_copy(ap_copy, ap); 488 len = vsnprintf(&s->s_buf[s->s_len], SBUF_FREESPACE(s) + 1, 489 fmt, ap_copy); 490 va_end(ap_copy); 491 } while (len > SBUF_FREESPACE(s) && 492 sbuf_extend(s, len - SBUF_FREESPACE(s)) == 0); 493 494 /* 495 * s->s_len is the length of the string, without the terminating nul. 496 * When updating s->s_len, we must subtract 1 from the length that 497 * we passed into vsnprintf() because that length includes the 498 * terminating nul. 499 * 500 * vsnprintf() returns the amount that would have been copied, 501 * given sufficient space, so don't over-increment s_len. 502 */ 503 if (SBUF_FREESPACE(s) < len) 504 len = SBUF_FREESPACE(s); 505 s->s_len += len; 506 if (!SBUF_HASROOM(s) && !SBUF_CANEXTEND(s)) 507 SBUF_SETFLAG(s, SBUF_OVERFLOWED); 508 509 KASSERT(s->s_len < s->s_size, 510 ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size)); 511 512 if (SBUF_HASOVERFLOWED(s)) 513 return (-1); 514 return (0); 515} 516#endif /* _KERNEL */ 517 518/* 519 * Format the given arguments and append the resulting string to an sbuf. 520 */ 521int 522sbuf_printf(struct sbuf *s, const char *fmt, ...) 523{ 524 va_list ap; 525 int result; 526 527 va_start(ap, fmt); 528 result = sbuf_vprintf(s, fmt, ap); 529 va_end(ap); 530 return (result); 531} 532 533/* 534 * Append a character to an sbuf. 535 */ 536int 537sbuf_putc(struct sbuf *s, int c) 538{ 539 540 sbuf_putc_func(c, s); 541 if (SBUF_HASOVERFLOWED(s)) 542 return (-1); 543 return (0); 544} 545 546/* 547 * Trim whitespace characters from end of an sbuf. 548 */ 549int 550sbuf_trim(struct sbuf *s) 551{ 552 553 assert_sbuf_integrity(s); 554 assert_sbuf_state(s, 0); 555 556 if (SBUF_HASOVERFLOWED(s)) 557 return (-1); 558 559 while (s->s_len > 0 && isspace(s->s_buf[s->s_len-1])) 560 --s->s_len; 561 562 return (0); 563} 564 565/* 566 * Check if an sbuf overflowed 567 */ 568int 569sbuf_overflowed(struct sbuf *s) 570{ 571 572 return (SBUF_HASOVERFLOWED(s)); 573} 574 575/* 576 * Finish off an sbuf. 577 */ 578void 579sbuf_finish(struct sbuf *s) 580{ 581 582 assert_sbuf_integrity(s); 583 assert_sbuf_state(s, 0); 584 585 s->s_buf[s->s_len] = '\0'; 586 SBUF_CLEARFLAG(s, SBUF_OVERFLOWED); 587 SBUF_SETFLAG(s, SBUF_FINISHED); 588} 589 590/* 591 * Return a pointer to the sbuf data. 592 */ 593char * 594sbuf_data(struct sbuf *s) 595{ 596 597 assert_sbuf_integrity(s); 598 assert_sbuf_state(s, SBUF_FINISHED); 599 600 return (s->s_buf); 601} 602 603/* 604 * Return the length of the sbuf data. 605 */ 606int 607sbuf_len(struct sbuf *s) 608{ 609 610 assert_sbuf_integrity(s); 611 /* don't care if it's finished or not */ 612 613 if (SBUF_HASOVERFLOWED(s)) 614 return (-1); 615 return (s->s_len); 616} 617 618/* 619 * Clear an sbuf, free its buffer if necessary. 620 */ 621void 622sbuf_delete(struct sbuf *s) 623{ 624 int isdyn; 625 626 assert_sbuf_integrity(s); 627 /* don't care if it's finished or not */ 628 629 if (SBUF_ISDYNAMIC(s)) 630 SBFREE(s->s_buf); 631 isdyn = SBUF_ISDYNSTRUCT(s); 632 bzero(s, sizeof(*s)); 633 if (isdyn) 634 SBFREE(s); 635} 636 637/* 638 * Check if an sbuf has been finished. 639 */ 640int 641sbuf_done(struct sbuf *s) 642{ 643 644 return (SBUF_ISFINISHED(s)); 645} 646