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