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