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