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