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