Deleted Added
full compact
subr_sbuf.c (212370) subr_sbuf.c (212425)
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:

--- 13 unchanged lines hidden (view full) ---

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>
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:

--- 13 unchanged lines hidden (view full) ---

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: head/sys/kern/subr_sbuf.c 212370 2010-09-09 18:33:46Z mdf $");
30__FBSDID("$FreeBSD: head/sys/kern/subr_sbuf.c 212425 2010-09-10 16:42:16Z mdf $");
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/malloc.h>

--- 22 unchanged lines hidden (view full) ---

61#endif /* _KERNEL */
62
63/*
64 * Predicates
65 */
66#define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC)
67#define SBUF_ISDYNSTRUCT(s) ((s)->s_flags & SBUF_DYNSTRUCT)
68#define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED)
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/malloc.h>

--- 22 unchanged lines hidden (view full) ---

61#endif /* _KERNEL */
62
63/*
64 * Predicates
65 */
66#define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC)
67#define SBUF_ISDYNSTRUCT(s) ((s)->s_flags & SBUF_DYNSTRUCT)
68#define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED)
69#define SBUF_HASOVERFLOWED(s) ((s)->s_flags & SBUF_OVERFLOWED)
70#define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1)
71#define SBUF_FREESPACE(s) ((s)->s_size - (s)->s_len - 1)
72#define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND)
73
74/*
75 * Set / clear flags
76 */
77#define SBUF_SETFLAG(s, f) do { (s)->s_flags |= (f); } while (0)

--- 164 unchanged lines hidden (view full) ---

242void
243sbuf_clear(struct sbuf *s)
244{
245
246 assert_sbuf_integrity(s);
247 /* don't care if it's finished or not */
248
249 SBUF_CLEARFLAG(s, SBUF_FINISHED);
69#define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1)
70#define SBUF_FREESPACE(s) ((s)->s_size - (s)->s_len - 1)
71#define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND)
72
73/*
74 * Set / clear flags
75 */
76#define SBUF_SETFLAG(s, f) do { (s)->s_flags |= (f); } while (0)

--- 164 unchanged lines hidden (view full) ---

241void
242sbuf_clear(struct sbuf *s)
243{
244
245 assert_sbuf_integrity(s);
246 /* don't care if it's finished or not */
247
248 SBUF_CLEARFLAG(s, SBUF_FINISHED);
250 SBUF_CLEARFLAG(s, SBUF_OVERFLOWED);
251 s->s_error = 0;
252 s->s_len = 0;
253}
254
255/*
256 * Set the sbuf's end position to an arbitrary value.
257 * Effectively truncates the sbuf at the new position.
258 */

--- 35 unchanged lines hidden (view full) ---

294 * Call the drain and process the return.
295 */
296static int
297sbuf_drain(struct sbuf *s)
298{
299 int len;
300
301 KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s));
249 s->s_error = 0;
250 s->s_len = 0;
251}
252
253/*
254 * Set the sbuf's end position to an arbitrary value.
255 * Effectively truncates the sbuf at the new position.
256 */

--- 35 unchanged lines hidden (view full) ---

292 * Call the drain and process the return.
293 */
294static int
295sbuf_drain(struct sbuf *s)
296{
297 int len;
298
299 KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s));
300 KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s));
302 len = s->s_drain_func(s->s_drain_arg, s->s_buf, s->s_len);
303 if (len < 0) {
304 s->s_error = -len;
301 len = s->s_drain_func(s->s_drain_arg, s->s_buf, s->s_len);
302 if (len < 0) {
303 s->s_error = -len;
305 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
306 return (s->s_error);
307 }
308 KASSERT(len > 0 && len <= s->s_len,
309 ("Bad drain amount %d for sbuf %p", len, s));
310 s->s_len -= len;
311 /*
312 * Fast path for the expected case where all the data was
313 * drained.

--- 15 unchanged lines hidden (view full) ---

329 */
330static void
331sbuf_put_byte(int c, struct sbuf *s)
332{
333
334 assert_sbuf_integrity(s);
335 assert_sbuf_state(s, 0);
336
304 return (s->s_error);
305 }
306 KASSERT(len > 0 && len <= s->s_len,
307 ("Bad drain amount %d for sbuf %p", len, s));
308 s->s_len -= len;
309 /*
310 * Fast path for the expected case where all the data was
311 * drained.

--- 15 unchanged lines hidden (view full) ---

327 */
328static void
329sbuf_put_byte(int c, struct sbuf *s)
330{
331
332 assert_sbuf_integrity(s);
333 assert_sbuf_state(s, 0);
334
337 if (SBUF_HASOVERFLOWED(s))
335 if (s->s_error != 0)
338 return;
339 if (SBUF_FREESPACE(s) <= 0) {
340 /*
341 * If there is a drain, use it, otherwise extend the
342 * buffer.
343 */
344 if (s->s_drain_func != NULL)
345 (void)sbuf_drain(s);
346 else if (sbuf_extend(s, 1) < 0)
336 return;
337 if (SBUF_FREESPACE(s) <= 0) {
338 /*
339 * If there is a drain, use it, otherwise extend the
340 * buffer.
341 */
342 if (s->s_drain_func != NULL)
343 (void)sbuf_drain(s);
344 else if (sbuf_extend(s, 1) < 0)
347 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
348 if (SBUF_HASOVERFLOWED(s))
345 s->s_error = ENOMEM;
346 if (s->s_error != 0)
349 return;
350 }
351 s->s_buf[s->s_len++] = c;
352}
353
354/*
355 * Append a non-NUL character to an sbuf. This prototype signature is
356 * suitable for use with kvprintf(9).

--- 13 unchanged lines hidden (view full) ---

370sbuf_bcat(struct sbuf *s, const void *buf, size_t len)
371{
372 const char *str = buf;
373 const char *end = str + len;
374
375 assert_sbuf_integrity(s);
376 assert_sbuf_state(s, 0);
377
347 return;
348 }
349 s->s_buf[s->s_len++] = c;
350}
351
352/*
353 * Append a non-NUL character to an sbuf. This prototype signature is
354 * suitable for use with kvprintf(9).

--- 13 unchanged lines hidden (view full) ---

368sbuf_bcat(struct sbuf *s, const void *buf, size_t len)
369{
370 const char *str = buf;
371 const char *end = str + len;
372
373 assert_sbuf_integrity(s);
374 assert_sbuf_state(s, 0);
375
378 if (SBUF_HASOVERFLOWED(s))
376 if (s->s_error != 0)
379 return (-1);
380 for (; str < end; str++) {
381 sbuf_put_byte(*str, s);
377 return (-1);
378 for (; str < end; str++) {
379 sbuf_put_byte(*str, s);
382 if (SBUF_HASOVERFLOWED(s))
380 if (s->s_error != 0)
383 return (-1);
384 }
385 return (0);
386}
387
388#ifdef _KERNEL
389/*
390 * Copy a byte string from userland into an sbuf.
391 */
392int
393sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len)
394{
395
396 assert_sbuf_integrity(s);
397 assert_sbuf_state(s, 0);
398 KASSERT(s->s_drain_func == NULL,
399 ("Nonsensical copyin to sbuf %p with a drain", s));
400
381 return (-1);
382 }
383 return (0);
384}
385
386#ifdef _KERNEL
387/*
388 * Copy a byte string from userland into an sbuf.
389 */
390int
391sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len)
392{
393
394 assert_sbuf_integrity(s);
395 assert_sbuf_state(s, 0);
396 KASSERT(s->s_drain_func == NULL,
397 ("Nonsensical copyin to sbuf %p with a drain", s));
398
401 if (SBUF_HASOVERFLOWED(s))
399 if (s->s_error != 0)
402 return (-1);
403 if (len == 0)
404 return (0);
405 if (len > SBUF_FREESPACE(s)) {
406 sbuf_extend(s, len - SBUF_FREESPACE(s));
407 if (SBUF_FREESPACE(s) < len)
408 len = SBUF_FREESPACE(s);
409 }

--- 24 unchanged lines hidden (view full) ---

434 */
435int
436sbuf_cat(struct sbuf *s, const char *str)
437{
438
439 assert_sbuf_integrity(s);
440 assert_sbuf_state(s, 0);
441
400 return (-1);
401 if (len == 0)
402 return (0);
403 if (len > SBUF_FREESPACE(s)) {
404 sbuf_extend(s, len - SBUF_FREESPACE(s));
405 if (SBUF_FREESPACE(s) < len)
406 len = SBUF_FREESPACE(s);
407 }

--- 24 unchanged lines hidden (view full) ---

432 */
433int
434sbuf_cat(struct sbuf *s, const char *str)
435{
436
437 assert_sbuf_integrity(s);
438 assert_sbuf_state(s, 0);
439
442 if (SBUF_HASOVERFLOWED(s))
440 if (s->s_error != 0)
443 return (-1);
444
445 while (*str != '\0') {
446 sbuf_put_byte(*str, s);
441 return (-1);
442
443 while (*str != '\0') {
444 sbuf_put_byte(*str, s);
447 if (SBUF_HASOVERFLOWED(s))
445 if (s->s_error != 0)
448 return (-1);
449 }
450 return (0);
451}
452
453#ifdef _KERNEL
454/*
455 * Append a string from userland to an sbuf.
456 */
457int
458sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len)
459{
460 size_t done;
461
462 assert_sbuf_integrity(s);
463 assert_sbuf_state(s, 0);
464 KASSERT(s->s_drain_func == NULL,
465 ("Nonsensical copyin to sbuf %p with a drain", s));
466
446 return (-1);
447 }
448 return (0);
449}
450
451#ifdef _KERNEL
452/*
453 * Append a string from userland to an sbuf.
454 */
455int
456sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len)
457{
458 size_t done;
459
460 assert_sbuf_integrity(s);
461 assert_sbuf_state(s, 0);
462 KASSERT(s->s_drain_func == NULL,
463 ("Nonsensical copyin to sbuf %p with a drain", s));
464
467 if (SBUF_HASOVERFLOWED(s))
465 if (s->s_error != 0)
468 return (-1);
469
470 if (len == 0)
471 len = SBUF_FREESPACE(s); /* XXX return 0? */
472 if (len > SBUF_FREESPACE(s)) {
473 sbuf_extend(s, len);
474 if (SBUF_FREESPACE(s) < len)
475 len = SBUF_FREESPACE(s);
476 }
477 switch (copyinstr(uaddr, s->s_buf + s->s_len, len + 1, &done)) {
478 case ENAMETOOLONG:
466 return (-1);
467
468 if (len == 0)
469 len = SBUF_FREESPACE(s); /* XXX return 0? */
470 if (len > SBUF_FREESPACE(s)) {
471 sbuf_extend(s, len);
472 if (SBUF_FREESPACE(s) < len)
473 len = SBUF_FREESPACE(s);
474 }
475 switch (copyinstr(uaddr, s->s_buf + s->s_len, len + 1, &done)) {
476 case ENAMETOOLONG:
479 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
477 s->s_error = ENOMEM;
480 /* fall through */
481 case 0:
482 s->s_len += done - 1;
483 break;
484 default:
485 return (-1); /* XXX */
486 }
487

--- 25 unchanged lines hidden (view full) ---

513
514 assert_sbuf_integrity(s);
515 assert_sbuf_state(s, 0);
516
517 KASSERT(fmt != NULL,
518 ("%s called with a NULL format string", __func__));
519
520 (void)kvprintf(fmt, sbuf_putc_func, s, 10, ap);
478 /* fall through */
479 case 0:
480 s->s_len += done - 1;
481 break;
482 default:
483 return (-1); /* XXX */
484 }
485

--- 25 unchanged lines hidden (view full) ---

511
512 assert_sbuf_integrity(s);
513 assert_sbuf_state(s, 0);
514
515 KASSERT(fmt != NULL,
516 ("%s called with a NULL format string", __func__));
517
518 (void)kvprintf(fmt, sbuf_putc_func, s, 10, ap);
521 if (SBUF_HASOVERFLOWED(s))
519 if (s->s_error != 0)
522 return (-1);
523 return (0);
524}
525#else /* !_KERNEL */
526int
527sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
528{
529 va_list ap_copy;
530 int error, len;
531
532 assert_sbuf_integrity(s);
533 assert_sbuf_state(s, 0);
534
535 KASSERT(fmt != NULL,
536 ("%s called with a NULL format string", __func__));
537
520 return (-1);
521 return (0);
522}
523#else /* !_KERNEL */
524int
525sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
526{
527 va_list ap_copy;
528 int error, len;
529
530 assert_sbuf_integrity(s);
531 assert_sbuf_state(s, 0);
532
533 KASSERT(fmt != NULL,
534 ("%s called with a NULL format string", __func__));
535
538 if (SBUF_HASOVERFLOWED(s))
536 if (s->s_error != 0)
539 return (-1);
540
541 /*
542 * For the moment, there is no way to get vsnprintf(3) to hand
543 * back a character at a time, to push everything into
544 * sbuf_putc_func() as was done for the kernel.
545 *
546 * In userspace, while drains are useful, there's generally

--- 26 unchanged lines hidden (view full) ---

573 *
574 * vsnprintf() returns the amount that would have been copied,
575 * given sufficient space, so don't over-increment s_len.
576 */
577 if (SBUF_FREESPACE(s) < len)
578 len = SBUF_FREESPACE(s);
579 s->s_len += len;
580 if (!SBUF_HASROOM(s) && !SBUF_CANEXTEND(s))
537 return (-1);
538
539 /*
540 * For the moment, there is no way to get vsnprintf(3) to hand
541 * back a character at a time, to push everything into
542 * sbuf_putc_func() as was done for the kernel.
543 *
544 * In userspace, while drains are useful, there's generally

--- 26 unchanged lines hidden (view full) ---

571 *
572 * vsnprintf() returns the amount that would have been copied,
573 * given sufficient space, so don't over-increment s_len.
574 */
575 if (SBUF_FREESPACE(s) < len)
576 len = SBUF_FREESPACE(s);
577 s->s_len += len;
578 if (!SBUF_HASROOM(s) && !SBUF_CANEXTEND(s))
581 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
579 s->s_error = ENOMEM;
582
583 KASSERT(s->s_len < s->s_size,
584 ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size));
585
580
581 KASSERT(s->s_len < s->s_size,
582 ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size));
583
586 if (SBUF_HASOVERFLOWED(s))
584 if (s->s_error != 0)
587 return (-1);
588 return (0);
589}
590#endif /* _KERNEL */
591
592/*
593 * Format the given arguments and append the resulting string to an sbuf.
594 */

--- 12 unchanged lines hidden (view full) ---

607/*
608 * Append a character to an sbuf.
609 */
610int
611sbuf_putc(struct sbuf *s, int c)
612{
613
614 sbuf_putc_func(c, s);
585 return (-1);
586 return (0);
587}
588#endif /* _KERNEL */
589
590/*
591 * Format the given arguments and append the resulting string to an sbuf.
592 */

--- 12 unchanged lines hidden (view full) ---

605/*
606 * Append a character to an sbuf.
607 */
608int
609sbuf_putc(struct sbuf *s, int c)
610{
611
612 sbuf_putc_func(c, s);
615 if (SBUF_HASOVERFLOWED(s))
613 if (s->s_error != 0)
616 return (-1);
617 return (0);
618}
619
620/*
621 * Trim whitespace characters from end of an sbuf.
622 */
623int
624sbuf_trim(struct sbuf *s)
625{
626
627 assert_sbuf_integrity(s);
628 assert_sbuf_state(s, 0);
629 KASSERT(s->s_drain_func == NULL,
630 ("%s makes no sense on sbuf %p with drain", __func__, s));
631
614 return (-1);
615 return (0);
616}
617
618/*
619 * Trim whitespace characters from end of an sbuf.
620 */
621int
622sbuf_trim(struct sbuf *s)
623{
624
625 assert_sbuf_integrity(s);
626 assert_sbuf_state(s, 0);
627 KASSERT(s->s_drain_func == NULL,
628 ("%s makes no sense on sbuf %p with drain", __func__, s));
629
632 if (SBUF_HASOVERFLOWED(s))
630 if (s->s_error != 0)
633 return (-1);
634
635 while (s->s_len > 0 && isspace(s->s_buf[s->s_len-1]))
636 --s->s_len;
637
638 return (0);
639}
640
641/*
631 return (-1);
632
633 while (s->s_len > 0 && isspace(s->s_buf[s->s_len-1]))
634 --s->s_len;
635
636 return (0);
637}
638
639/*
642 * Check if an sbuf overflowed
640 * Check if an sbuf has an error.
643 */
644int
641 */
642int
645sbuf_overflowed(struct sbuf *s)
643sbuf_error(struct sbuf *s)
646{
647
644{
645
648 return (SBUF_HASOVERFLOWED(s));
646 return (s->s_error);
649}
650
651/*
652 * Finish off an sbuf.
653 */
654int
655sbuf_finish(struct sbuf *s)
656{
647}
648
649/*
650 * Finish off an sbuf.
651 */
652int
653sbuf_finish(struct sbuf *s)
654{
657 int error = 0;
655 int error;
658
659 assert_sbuf_integrity(s);
660 assert_sbuf_state(s, 0);
661
656
657 assert_sbuf_integrity(s);
658 assert_sbuf_state(s, 0);
659
660 error = s->s_error;
662 if (s->s_drain_func != NULL) {
661 if (s->s_drain_func != NULL) {
663 error = s->s_error;
664 while (s->s_len > 0 && error == 0)
665 error = sbuf_drain(s);
662 while (s->s_len > 0 && error == 0)
663 error = sbuf_drain(s);
666 } else if (SBUF_HASOVERFLOWED(s))
667 error = ENOMEM;
664 }
668 s->s_buf[s->s_len] = '\0';
665 s->s_buf[s->s_len] = '\0';
669 SBUF_CLEARFLAG(s, SBUF_OVERFLOWED);
666 s->s_error = 0;
670 SBUF_SETFLAG(s, SBUF_FINISHED);
671#ifdef _KERNEL
672 return (error);
673#else
674 errno = error;
675 return (-1);
676#endif
677}

--- 20 unchanged lines hidden (view full) ---

698sbuf_len(struct sbuf *s)
699{
700
701 assert_sbuf_integrity(s);
702 /* don't care if it's finished or not */
703 KASSERT(s->s_drain_func == NULL,
704 ("%s makes no sense on sbuf %p with drain", __func__, s));
705
667 SBUF_SETFLAG(s, SBUF_FINISHED);
668#ifdef _KERNEL
669 return (error);
670#else
671 errno = error;
672 return (-1);
673#endif
674}

--- 20 unchanged lines hidden (view full) ---

695sbuf_len(struct sbuf *s)
696{
697
698 assert_sbuf_integrity(s);
699 /* don't care if it's finished or not */
700 KASSERT(s->s_drain_func == NULL,
701 ("%s makes no sense on sbuf %p with drain", __func__, s));
702
706 if (SBUF_HASOVERFLOWED(s))
703 if (s->s_error != 0)
707 return (-1);
708 return (s->s_len);
709}
710
711/*
712 * Clear an sbuf, free its buffer if necessary.
713 */
714void

--- 24 unchanged lines hidden ---
704 return (-1);
705 return (s->s_len);
706}
707
708/*
709 * Clear an sbuf, free its buffer if necessary.
710 */
711void

--- 24 unchanged lines hidden ---