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