* Append a string from userland to an sbuf. */
| 552 | * Append a string from userland to an sbuf. |
| 553 | */ |
| 554 | int |
| 555 | sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len) |
| 556 | { |
| 557 | size_t done; |
| 558 | |
| 559 | assert_sbuf_integrity(s); |
| 560 | assert_sbuf_state(s, 0); |
| 561 | KASSERT(s->s_drain_func == NULL, |
| 562 | ("Nonsensical copyin to sbuf %p with a drain", s)); |
| 563 | |
| 564 | if (s->s_error != 0) |
| 565 | return (-1); |
| 566 | |
| 567 | if (len == 0) |
| 568 | len = SBUF_FREESPACE(s); /* XXX return 0? */ |
| 569 | if (len > SBUF_FREESPACE(s)) { |
| 570 | sbuf_extend(s, len); |
| 571 | if (SBUF_FREESPACE(s) < len) |
| 572 | len = SBUF_FREESPACE(s); |
| 573 | } |
| 574 | switch (copyinstr(uaddr, s->s_buf + s->s_len, len + 1, &done)) { |
| 575 | case ENAMETOOLONG: |
| 576 | s->s_error = ENOMEM; |
| 577 | /* fall through */ |
| 578 | case 0: |
| 579 | s->s_len += done - 1; |
| 580 | if (SBUF_ISSECTION(s)) |
| 581 | s->s_sect_len += done - 1; |
| 582 | break; |
| 583 | default: |
| 584 | return (-1); /* XXX */ |
| 585 | } |
| 586 | |
| 587 | return (done); |
| 588 | } |
| 589 | #endif |
| 590 | |
| 591 | /* |
no test coverage detected