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$"); 31 32 #include <sys/param.h> 33 34 #ifdef _KERNEL 35 #include <sys/ctype.h> 36 #include <sys/errno.h> 37 #include <sys/kernel.h> 38 #include <sys/malloc.h> 39 #include <sys/systm.h> 40 #include <sys/uio.h> 41 #include <machine/stdarg.h> 42 #else /* _KERNEL */ 43 #include <ctype.h> 44 #include <errno.h> 45 #include <stdarg.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #endif /* _KERNEL */ 50 51 #include <sys/sbuf.h> 52 53 #ifdef _KERNEL 54 static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers"); 55 #define SBMALLOC(size) malloc(size, M_SBUF, M_WAITOK|M_ZERO) 56 #define SBFREE(buf) free(buf, M_SBUF) 57 #else /* _KERNEL */ 58 #define KASSERT(e, m) 59 #define SBMALLOC(size) calloc(1, size) 60 #define SBFREE(buf) free(buf) 61 #endif /* _KERNEL */ 62 63 /* 64 * Predicates 65 */ 66 #define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC) 67 #define SBUF_ISDYNSTRUCT(s) ((s)->s_flags & SBUF_DYNSTRUCT) 68 #define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED) 69 #define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1) 70 #define SBUF_FREESPACE(s) ((s)->s_size - ((s)->s_len + 1)) 71 #define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND) 72 #define SBUF_ISSECTION(s) ((s)->s_flags & SBUF_INSECTION) 73 #define SBUF_NULINCLUDED(s) ((s)->s_flags & SBUF_INCLUDENUL) 74 75 /* 76 * Set / clear flags 77 */ 78 #define SBUF_SETFLAG(s, f) do { (s)->s_flags |= (f); } while (0) 79 #define SBUF_CLEARFLAG(s, f) do { (s)->s_flags &= ~(f); } while (0) 80 81 #define SBUF_MINSIZE 2 /* Min is 1 byte + nulterm. */ 82 #define SBUF_MINEXTENDSIZE 16 /* Should be power of 2. */ 83 84 #ifdef PAGE_SIZE 85 #define SBUF_MAXEXTENDSIZE PAGE_SIZE 86 #define SBUF_MAXEXTENDINCR PAGE_SIZE 87 #else 88 #define SBUF_MAXEXTENDSIZE 4096 89 #define SBUF_MAXEXTENDINCR 4096 90 #endif 91 92 /* 93 * Debugging support 94 */ 95 #if defined(_KERNEL) && defined(INVARIANTS) 96 97 static void 98 _assert_sbuf_integrity(const char *fun, struct sbuf *s) 99 { 100 101 KASSERT(s != NULL, 102 ("%s called with a NULL sbuf pointer", fun)); 103 KASSERT(s->s_buf != NULL, 104 ("%s called with uninitialized or corrupt sbuf", fun)); 105 if (SBUF_ISFINISHED(s) && SBUF_NULINCLUDED(s)) { 106 KASSERT(s->s_len <= s->s_size, 107 ("wrote past end of sbuf (%jd >= %jd)", 108 (intmax_t)s->s_len, (intmax_t)s->s_size)); 109 } else { 110 KASSERT(s->s_len < s->s_size, 111 ("wrote past end of sbuf (%jd >= %jd)", 112 (intmax_t)s->s_len, (intmax_t)s->s_size)); 113 } 114 } 115 116 static void 117 _assert_sbuf_state(const char *fun, struct sbuf *s, int state) 118 { 119 120 KASSERT((s->s_flags & SBUF_FINISHED) == state, 121 ("%s called with %sfinished or corrupt sbuf", fun, 122 (state ? "un" : ""))); 123 } 124 125 #define assert_sbuf_integrity(s) _assert_sbuf_integrity(__func__, (s)) 126 #define assert_sbuf_state(s, i) _assert_sbuf_state(__func__, (s), (i)) 127 128 #else /* _KERNEL && INVARIANTS */ 129 130 #define assert_sbuf_integrity(s) do { } while (0) 131 #define assert_sbuf_state(s, i) do { } while (0) 132 133 #endif /* _KERNEL && INVARIANTS */ 134 135 #ifdef CTASSERT 136 CTASSERT(powerof2(SBUF_MAXEXTENDSIZE)); 137 CTASSERT(powerof2(SBUF_MAXEXTENDINCR)); 138 #endif 139 140 static int 141 sbuf_extendsize(int size) 142 { 143 int newsize; 144 145 if (size < (int)SBUF_MAXEXTENDSIZE) { 146 newsize = SBUF_MINEXTENDSIZE; 147 while (newsize < size) 148 newsize *= 2; 149 } else { 150 newsize = roundup2(size, SBUF_MAXEXTENDINCR); 151 } 152 KASSERT(newsize >= size, ("%s: %d < %d\n", __func__, newsize, size)); 153 return (newsize); 154 } 155 156 /* 157 * Extend an sbuf. 158 */ 159 static int 160 sbuf_extend(struct sbuf *s, int addlen) 161 { 162 char *newbuf; 163 int newsize; 164 165 if (!SBUF_CANEXTEND(s)) 166 return (-1); 167 newsize = sbuf_extendsize(s->s_size + addlen); 168 newbuf = SBMALLOC(newsize); 169 if (newbuf == NULL) 170 return (-1); 171 memcpy(newbuf, s->s_buf, s->s_size); 172 if (SBUF_ISDYNAMIC(s)) 173 SBFREE(s->s_buf); 174 else 175 SBUF_SETFLAG(s, SBUF_DYNAMIC); 176 s->s_buf = newbuf; 177 s->s_size = newsize; 178 return (0); 179 } 180 181 /* 182 * Initialize the internals of an sbuf. 183 * If buf is non-NULL, it points to a static or already-allocated string 184 * big enough to hold at least length characters. 185 */ 186 static struct sbuf * 187 sbuf_newbuf(struct sbuf *s, char *buf, int length, int flags) 188 { 189 190 memset(s, 0, sizeof(*s)); 191 s->s_flags = flags; 192 s->s_size = length; 193 s->s_buf = buf; 194 195 if ((s->s_flags & SBUF_AUTOEXTEND) == 0) { 196 KASSERT(s->s_size >= SBUF_MINSIZE, 197 ("attempt to create an sbuf smaller than %d bytes", 198 SBUF_MINSIZE)); 199 } 200 201 if (s->s_buf != NULL) 202 return (s); 203 204 if ((flags & SBUF_AUTOEXTEND) != 0) 205 s->s_size = sbuf_extendsize(s->s_size); 206 207 s->s_buf = SBMALLOC(s->s_size); 208 if (s->s_buf == NULL) 209 return (NULL); 210 SBUF_SETFLAG(s, SBUF_DYNAMIC); 211 return (s); 212 } 213 214 /* 215 * Initialize an sbuf. 216 * If buf is non-NULL, it points to a static or already-allocated string 217 * big enough to hold at least length characters. 218 */ 219 struct sbuf * 220 sbuf_new(struct sbuf *s, char *buf, int length, int flags) 221 { 222 223 KASSERT(length >= 0, 224 ("attempt to create an sbuf of negative length (%d)", length)); 225 KASSERT((flags & ~SBUF_USRFLAGMSK) == 0, 226 ("%s called with invalid flags", __func__)); 227 228 flags &= SBUF_USRFLAGMSK; 229 if (s != NULL) 230 return (sbuf_newbuf(s, buf, length, flags)); 231 232 s = SBMALLOC(sizeof(*s)); 233 if (s == NULL) 234 return (NULL); 235 if (sbuf_newbuf(s, buf, length, flags) == NULL) { 236 SBFREE(s); 237 return (NULL); 238 } 239 SBUF_SETFLAG(s, SBUF_DYNSTRUCT); 240 return (s); 241 } 242 243 #ifdef _KERNEL 244 /* 245 * Create an sbuf with uio data 246 */ 247 struct sbuf * 248 sbuf_uionew(struct sbuf *s, struct uio *uio, int *error) 249 { 250 251 KASSERT(uio != NULL, 252 ("%s called with NULL uio pointer", __func__)); 253 KASSERT(error != NULL, 254 ("%s called with NULL error pointer", __func__)); 255 256 s = sbuf_new(s, NULL, uio->uio_resid + 1, 0); 257 if (s == NULL) { 258 *error = ENOMEM; 259 return (NULL); 260 } 261 *error = uiomove(s->s_buf, uio->uio_resid, uio); 262 if (*error != 0) { 263 sbuf_delete(s); 264 return (NULL); 265 } 266 s->s_len = s->s_size - 1; 267 if (SBUF_ISSECTION(s)) 268 s->s_sect_len = s->s_size - 1; 269 *error = 0; 270 return (s); 271 } 272 #endif 273 274 int 275 sbuf_get_flags(struct sbuf *s) 276 { 277 278 return (s->s_flags & SBUF_USRFLAGMSK); 279 } 280 281 void 282 sbuf_clear_flags(struct sbuf *s, int flags) 283 { 284 285 s->s_flags &= ~(flags & SBUF_USRFLAGMSK); 286 } 287 288 void 289 sbuf_set_flags(struct sbuf *s, int flags) 290 { 291 292 293 s->s_flags |= (flags & SBUF_USRFLAGMSK); 294 } 295 296 /* 297 * Clear an sbuf and reset its position. 298 */ 299 void 300 sbuf_clear(struct sbuf *s) 301 { 302 303 assert_sbuf_integrity(s); 304 /* don't care if it's finished or not */ 305 306 SBUF_CLEARFLAG(s, SBUF_FINISHED); 307 s->s_error = 0; 308 s->s_len = 0; 309 s->s_sect_len = 0; 310 } 311 312 /* 313 * Set the sbuf's end position to an arbitrary value. 314 * Effectively truncates the sbuf at the new position. 315 */ 316 int 317 sbuf_setpos(struct sbuf *s, ssize_t pos) 318 { 319 320 assert_sbuf_integrity(s); 321 assert_sbuf_state(s, 0); 322 323 KASSERT(pos >= 0, 324 ("attempt to seek to a negative position (%jd)", (intmax_t)pos)); 325 KASSERT(pos < s->s_size, 326 ("attempt to seek past end of sbuf (%jd >= %jd)", 327 (intmax_t)pos, (intmax_t)s->s_size)); 328 KASSERT(!SBUF_ISSECTION(s), 329 ("attempt to seek when in a section")); 330 331 if (pos < 0 || pos > s->s_len) 332 return (-1); 333 s->s_len = pos; 334 return (0); 335 } 336 337 /* 338 * Set up a drain function and argument on an sbuf to flush data to 339 * when the sbuf buffer overflows. 340 */ 341 void 342 sbuf_set_drain(struct sbuf *s, sbuf_drain_func *func, void *ctx) 343 { 344 345 assert_sbuf_state(s, 0); 346 assert_sbuf_integrity(s); 347 KASSERT(func == s->s_drain_func || s->s_len == 0, 348 ("Cannot change drain to %p on non-empty sbuf %p", func, s)); 349 s->s_drain_func = func; 350 s->s_drain_arg = ctx; 351 } 352 353 /* 354 * Call the drain and process the return. 355 */ 356 static int 357 sbuf_drain(struct sbuf *s) 358 { 359 int len; 360 361 KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s)); 362 KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s)); 363 len = s->s_drain_func(s->s_drain_arg, s->s_buf, s->s_len); 364 if (len < 0) { 365 s->s_error = -len; 366 return (s->s_error); 367 } 368 KASSERT(len > 0 && len <= s->s_len, 369 ("Bad drain amount %d for sbuf %p", len, s)); 370 s->s_len -= len; 371 /* 372 * Fast path for the expected case where all the data was 373 * drained. 374 */ 375 if (s->s_len == 0) 376 return (0); 377 /* 378 * Move the remaining characters to the beginning of the 379 * string. 380 */ 381 memmove(s->s_buf, s->s_buf + len, s->s_len); 382 return (0); 383 } 384 385 /* 386 * Append a byte to an sbuf. This is the core function for appending 387 * to an sbuf and is the main place that deals with extending the 388 * buffer and marking overflow. 389 */ 390 static void 391 sbuf_put_byte(struct sbuf *s, int c) 392 { 393 394 assert_sbuf_integrity(s); 395 assert_sbuf_state(s, 0); 396 397 if (s->s_error != 0) 398 return; 399 if (SBUF_FREESPACE(s) <= 0) { 400 /* 401 * If there is a drain, use it, otherwise extend the 402 * buffer. 403 */ 404 if (s->s_drain_func != NULL) 405 (void)sbuf_drain(s); 406 else if (sbuf_extend(s, 1) < 0) 407 s->s_error = ENOMEM; 408 if (s->s_error != 0) 409 return; 410 } 411 s->s_buf[s->s_len++] = c; 412 if (SBUF_ISSECTION(s)) 413 s->s_sect_len++; 414 } 415 416 /* 417 * Append a byte string to an sbuf. 418 */ 419 int 420 sbuf_bcat(struct sbuf *s, const void *buf, size_t len) 421 { 422 const char *str = buf; 423 const char *end = str + len; 424 425 assert_sbuf_integrity(s); 426 assert_sbuf_state(s, 0); 427 428 if (s->s_error != 0) 429 return (-1); 430 for (; str < end; str++) { 431 sbuf_put_byte(s, *str); 432 if (s->s_error != 0) 433 return (-1); 434 } 435 return (0); 436 } 437 438 #ifdef _KERNEL 439 /* 440 * Copy a byte string from userland into an sbuf. 441 */ 442 int 443 sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len) 444 { 445 446 assert_sbuf_integrity(s); 447 assert_sbuf_state(s, 0); 448 KASSERT(s->s_drain_func == NULL, 449 ("Nonsensical copyin to sbuf %p with a drain", s)); 450 451 if (s->s_error != 0) 452 return (-1); 453 if (len == 0) 454 return (0); 455 if (len > SBUF_FREESPACE(s)) { 456 sbuf_extend(s, len - SBUF_FREESPACE(s)); 457 if (SBUF_FREESPACE(s) < len) 458 len = SBUF_FREESPACE(s); 459 } 460 if (copyin(uaddr, s->s_buf + s->s_len, len) != 0) 461 return (-1); 462 s->s_len += len; 463 464 return (0); 465 } 466 #endif 467 468 /* 469 * Copy a byte string into an sbuf. 470 */ 471 int 472 sbuf_bcpy(struct sbuf *s, const void *buf, size_t len) 473 { 474 475 assert_sbuf_integrity(s); 476 assert_sbuf_state(s, 0); 477 478 sbuf_clear(s); 479 return (sbuf_bcat(s, buf, len)); 480 } 481 482 /* 483 * Append a string to an sbuf. 484 */ 485 int 486 sbuf_cat(struct sbuf *s, const char *str) 487 { 488 489 assert_sbuf_integrity(s); 490 assert_sbuf_state(s, 0); 491 492 if (s->s_error != 0) 493 return (-1); 494 495 while (*str != '\0') { 496 sbuf_put_byte(s, *str++); 497 if (s->s_error != 0) 498 return (-1); 499 } 500 return (0); 501 } 502 503 #ifdef _KERNEL 504 /* 505 * Append a string from userland to an sbuf. 506 */ 507 int 508 sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len) 509 { 510 size_t done; 511 512 assert_sbuf_integrity(s); 513 assert_sbuf_state(s, 0); 514 KASSERT(s->s_drain_func == NULL, 515 ("Nonsensical copyin to sbuf %p with a drain", s)); 516 517 if (s->s_error != 0) 518 return (-1); 519 520 if (len == 0) 521 len = SBUF_FREESPACE(s); /* XXX return 0? */ 522 if (len > SBUF_FREESPACE(s)) { 523 sbuf_extend(s, len); 524 if (SBUF_FREESPACE(s) < len) 525 len = SBUF_FREESPACE(s); 526 } 527 switch (copyinstr(uaddr, s->s_buf + s->s_len, len + 1, &done)) { 528 case ENAMETOOLONG: 529 s->s_error = ENOMEM; 530 /* fall through */ 531 case 0: 532 s->s_len += done - 1; 533 if (SBUF_ISSECTION(s)) 534 s->s_sect_len += done - 1; 535 break; 536 default: 537 return (-1); /* XXX */ 538 } 539 540 return (done); 541 } 542 #endif 543 544 /* 545 * Copy a string into an sbuf. 546 */ 547 int 548 sbuf_cpy(struct sbuf *s, const char *str) 549 { 550 551 assert_sbuf_integrity(s); 552 assert_sbuf_state(s, 0); 553 554 sbuf_clear(s); 555 return (sbuf_cat(s, str)); 556 } 557 558 /* 559 * Format the given argument list and append the resulting string to an sbuf. 560 */ 561 #ifdef _KERNEL 562 563 /* 564 * Append a non-NUL character to an sbuf. This prototype signature is 565 * suitable for use with kvprintf(9). 566 */ 567 static void 568 sbuf_putc_func(int c, void *arg) 569 { 570 571 if (c != '\0') 572 sbuf_put_byte(arg, c); 573 } 574 575 int 576 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap) 577 { 578 579 assert_sbuf_integrity(s); 580 assert_sbuf_state(s, 0); 581 582 KASSERT(fmt != NULL, 583 ("%s called with a NULL format string", __func__)); 584 585 (void)kvprintf(fmt, sbuf_putc_func, s, 10, ap); 586 if (s->s_error != 0) 587 return (-1); 588 return (0); 589 } 590 #else /* !_KERNEL */ 591 int 592 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap) 593 { 594 va_list ap_copy; 595 int error, len; 596 597 assert_sbuf_integrity(s); 598 assert_sbuf_state(s, 0); 599 600 KASSERT(fmt != NULL, 601 ("%s called with a NULL format string", __func__)); 602 603 if (s->s_error != 0) 604 return (-1); 605 606 /* 607 * For the moment, there is no way to get vsnprintf(3) to hand 608 * back a character at a time, to push everything into 609 * sbuf_putc_func() as was done for the kernel. 610 * 611 * In userspace, while drains are useful, there's generally 612 * not a problem attempting to malloc(3) on out of space. So 613 * expand a userland sbuf if there is not enough room for the 614 * data produced by sbuf_[v]printf(3). 615 */ 616 617 error = 0; 618 do { 619 va_copy(ap_copy, ap); 620 len = vsnprintf(&s->s_buf[s->s_len], SBUF_FREESPACE(s) + 1, 621 fmt, ap_copy); 622 va_end(ap_copy); 623 624 if (SBUF_FREESPACE(s) >= len) 625 break; 626 /* Cannot print with the current available space. */ 627 if (s->s_drain_func != NULL && s->s_len > 0) 628 error = sbuf_drain(s); 629 else 630 error = sbuf_extend(s, len - SBUF_FREESPACE(s)); 631 } while (error == 0); 632 633 /* 634 * s->s_len is the length of the string, without the terminating nul. 635 * When updating s->s_len, we must subtract 1 from the length that 636 * we passed into vsnprintf() because that length includes the 637 * terminating nul. 638 * 639 * vsnprintf() returns the amount that would have been copied, 640 * given sufficient space, so don't over-increment s_len. 641 */ 642 if (SBUF_FREESPACE(s) < len) 643 len = SBUF_FREESPACE(s); 644 s->s_len += len; 645 if (SBUF_ISSECTION(s)) 646 s->s_sect_len += len; 647 if (!SBUF_HASROOM(s) && !SBUF_CANEXTEND(s)) 648 s->s_error = ENOMEM; 649 650 KASSERT(s->s_len < s->s_size, 651 ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size)); 652 653 if (s->s_error != 0) 654 return (-1); 655 return (0); 656 } 657 #endif /* _KERNEL */ 658 659 /* 660 * Format the given arguments and append the resulting string to an sbuf. 661 */ 662 int 663 sbuf_printf(struct sbuf *s, const char *fmt, ...) 664 { 665 va_list ap; 666 int result; 667 668 va_start(ap, fmt); 669 result = sbuf_vprintf(s, fmt, ap); 670 va_end(ap); 671 return (result); 672 } 673 674 /* 675 * Append a character to an sbuf. 676 */ 677 int 678 sbuf_putc(struct sbuf *s, int c) 679 { 680 681 sbuf_put_byte(s, c); 682 if (s->s_error != 0) 683 return (-1); 684 return (0); 685 } 686 687 /* 688 * Trim whitespace characters from end of an sbuf. 689 */ 690 int 691 sbuf_trim(struct sbuf *s) 692 { 693 694 assert_sbuf_integrity(s); 695 assert_sbuf_state(s, 0); 696 KASSERT(s->s_drain_func == NULL, 697 ("%s makes no sense on sbuf %p with drain", __func__, s)); 698 699 if (s->s_error != 0) 700 return (-1); 701 702 while (s->s_len > 0 && isspace(s->s_buf[s->s_len-1])) { 703 --s->s_len; 704 if (SBUF_ISSECTION(s)) 705 s->s_sect_len--; 706 } 707 708 return (0); 709 } 710 711 /* 712 * Check if an sbuf has an error. 713 */ 714 int 715 sbuf_error(const struct sbuf *s) 716 { 717 718 return (s->s_error); 719 } 720 721 /* 722 * Finish off an sbuf. 723 */ 724 int 725 sbuf_finish(struct sbuf *s) 726 { 727 728 assert_sbuf_integrity(s); 729 assert_sbuf_state(s, 0); 730 731 s->s_buf[s->s_len] = '\0'; 732 if (SBUF_NULINCLUDED(s)) 733 s->s_len++; 734 if (s->s_drain_func != NULL) { 735 while (s->s_len > 0 && s->s_error == 0) 736 s->s_error = sbuf_drain(s); 737 } 738 SBUF_SETFLAG(s, SBUF_FINISHED); 739 #ifdef _KERNEL 740 return (s->s_error); 741 #else 742 if (s->s_error != 0) { 743 errno = s->s_error; 744 return (-1); 745 } 746 return (0); 747 #endif 748 } 749 750 /* 751 * Return a pointer to the sbuf data. 752 */ 753 char * 754 sbuf_data(struct sbuf *s) 755 { 756 757 assert_sbuf_integrity(s); 758 assert_sbuf_state(s, SBUF_FINISHED); 759 KASSERT(s->s_drain_func == NULL, 760 ("%s makes no sense on sbuf %p with drain", __func__, s)); 761 762 return (s->s_buf); 763 } 764 765 /* 766 * Return the length of the sbuf data. 767 */ 768 ssize_t 769 sbuf_len(struct sbuf *s) 770 { 771 772 assert_sbuf_integrity(s); 773 /* don't care if it's finished or not */ 774 KASSERT(s->s_drain_func == NULL, 775 ("%s makes no sense on sbuf %p with drain", __func__, s)); 776 777 if (s->s_error != 0) 778 return (-1); 779 780 /* If finished, nulterm is already in len, else add one. */ 781 if (SBUF_NULINCLUDED(s) && !SBUF_ISFINISHED(s)) 782 return (s->s_len + 1); 783 return (s->s_len); 784 } 785 786 /* 787 * Clear an sbuf, free its buffer if necessary. 788 */ 789 void 790 sbuf_delete(struct sbuf *s) 791 { 792 int isdyn; 793 794 assert_sbuf_integrity(s); 795 /* don't care if it's finished or not */ 796 797 if (SBUF_ISDYNAMIC(s)) 798 SBFREE(s->s_buf); 799 isdyn = SBUF_ISDYNSTRUCT(s); 800 memset(s, 0, sizeof(*s)); 801 if (isdyn) 802 SBFREE(s); 803 } 804 805 /* 806 * Check if an sbuf has been finished. 807 */ 808 int 809 sbuf_done(const struct sbuf *s) 810 { 811 812 return (SBUF_ISFINISHED(s)); 813 } 814 815 /* 816 * Start a section. 817 */ 818 void 819 sbuf_start_section(struct sbuf *s, ssize_t *old_lenp) 820 { 821 822 assert_sbuf_integrity(s); 823 assert_sbuf_state(s, 0); 824 825 if (!SBUF_ISSECTION(s)) { 826 KASSERT(s->s_sect_len == 0, 827 ("s_sect_len != 0 when starting a section")); 828 if (old_lenp != NULL) 829 *old_lenp = -1; 830 SBUF_SETFLAG(s, SBUF_INSECTION); 831 } else { 832 KASSERT(old_lenp != NULL, 833 ("s_sect_len should be saved when starting a subsection")); 834 *old_lenp = s->s_sect_len; 835 s->s_sect_len = 0; 836 } 837 } 838 839 /* 840 * End the section padding to the specified length with the specified 841 * character. 842 */ 843 ssize_t 844 sbuf_end_section(struct sbuf *s, ssize_t old_len, size_t pad, int c) 845 { 846 ssize_t len; 847 848 assert_sbuf_integrity(s); 849 assert_sbuf_state(s, 0); 850 KASSERT(SBUF_ISSECTION(s), 851 ("attempt to end a section when not in a section")); 852 853 if (pad > 1) { 854 len = roundup(s->s_sect_len, pad) - s->s_sect_len; 855 for (; s->s_error == 0 && len > 0; len--) 856 sbuf_put_byte(s, c); 857 } 858 len = s->s_sect_len; 859 if (old_len == -1) { 860 s->s_sect_len = 0; 861 SBUF_CLEARFLAG(s, SBUF_INSECTION); 862 } else { 863 s->s_sect_len += old_len; 864 } 865 if (s->s_error != 0) 866 return (-1); 867 return (len); 868 } 869