Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_sbuf.c
Show First 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | |||||
#define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC) | #define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC) | ||||
#define SBUF_ISDYNSTRUCT(s) ((s)->s_flags & SBUF_DYNSTRUCT) | #define SBUF_ISDYNSTRUCT(s) ((s)->s_flags & SBUF_DYNSTRUCT) | ||||
#define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED) | #define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED) | ||||
#define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1) | #define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1) | ||||
#define SBUF_FREESPACE(s) ((s)->s_size - ((s)->s_len + 1)) | #define SBUF_FREESPACE(s) ((s)->s_size - ((s)->s_len + 1)) | ||||
#define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND) | #define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND) | ||||
#define SBUF_ISSECTION(s) ((s)->s_flags & SBUF_INSECTION) | #define SBUF_ISSECTION(s) ((s)->s_flags & SBUF_INSECTION) | ||||
#define SBUF_NULINCLUDED(s) ((s)->s_flags & SBUF_INCLUDENUL) | #define SBUF_NULINCLUDED(s) ((s)->s_flags & SBUF_INCLUDENUL) | ||||
#define SBUF_ISDRAINTOEOR(s) ((s)->s_flags & SBUF_DRAINTOEOR) | |||||
#define SBUF_DODRAINTOEOR(s) (SBUF_ISSECTION(s) && SBUF_ISDRAINTOEOR(s)) | |||||
/* | /* | ||||
* Set / clear flags | * Set / clear flags | ||||
*/ | */ | ||||
#define SBUF_SETFLAG(s, f) do { (s)->s_flags |= (f); } while (0) | #define SBUF_SETFLAG(s, f) do { (s)->s_flags |= (f); } while (0) | ||||
#define SBUF_CLEARFLAG(s, f) do { (s)->s_flags &= ~(f); } while (0) | #define SBUF_CLEARFLAG(s, f) do { (s)->s_flags &= ~(f); } while (0) | ||||
#define SBUF_MINSIZE 2 /* Min is 1 byte + nulterm. */ | #define SBUF_MINSIZE 2 /* Min is 1 byte + nulterm. */ | ||||
▲ Show 20 Lines • Show All 219 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
assert_sbuf_integrity(s); | assert_sbuf_integrity(s); | ||||
/* don't care if it's finished or not */ | /* don't care if it's finished or not */ | ||||
SBUF_CLEARFLAG(s, SBUF_FINISHED); | SBUF_CLEARFLAG(s, SBUF_FINISHED); | ||||
s->s_error = 0; | s->s_error = 0; | ||||
s->s_len = 0; | s->s_len = 0; | ||||
s->s_rec_off = 0; | |||||
s->s_sect_len = 0; | s->s_sect_len = 0; | ||||
} | } | ||||
/* | /* | ||||
* Set the sbuf's end position to an arbitrary value. | * Set the sbuf's end position to an arbitrary value. | ||||
* Effectively truncates the sbuf at the new position. | * Effectively truncates the sbuf at the new position. | ||||
*/ | */ | ||||
int | int | ||||
Show All 38 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
sbuf_drain(struct sbuf *s) | sbuf_drain(struct sbuf *s) | ||||
{ | { | ||||
int len; | int len; | ||||
KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s)); | KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s)); | ||||
KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s)); | KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s)); | ||||
len = s->s_drain_func(s->s_drain_arg, s->s_buf, s->s_len); | if (SBUF_DODRAINTOEOR(s) && s->s_rec_off == 0) | ||||
return (s->s_error = EDEADLK); | |||||
len = s->s_drain_func(s->s_drain_arg, s->s_buf, | |||||
SBUF_DODRAINTOEOR(s) ? s->s_rec_off : s->s_len); | |||||
if (len < 0) { | if (len < 0) { | ||||
s->s_error = -len; | s->s_error = -len; | ||||
return (s->s_error); | return (s->s_error); | ||||
} | } | ||||
KASSERT(len > 0 && len <= s->s_len, | KASSERT(len > 0 && len <= s->s_len, | ||||
("Bad drain amount %d for sbuf %p", len, s)); | ("Bad drain amount %d for sbuf %p", len, s)); | ||||
s->s_len -= len; | s->s_len -= len; | ||||
s->s_rec_off -= len; | |||||
/* | /* | ||||
* Fast path for the expected case where all the data was | * Fast path for the expected case where all the data was | ||||
* drained. | * drained. | ||||
*/ | */ | ||||
if (s->s_len == 0) | if (s->s_len == 0) | ||||
return (0); | return (0); | ||||
/* | /* | ||||
* Move the remaining characters to the beginning of the | * Move the remaining characters to the beginning of the | ||||
▲ Show 20 Lines • Show All 449 Lines • ▼ Show 20 Lines | sbuf_start_section(struct sbuf *s, ssize_t *old_lenp) | ||||
assert_sbuf_integrity(s); | assert_sbuf_integrity(s); | ||||
assert_sbuf_state(s, 0); | assert_sbuf_state(s, 0); | ||||
if (!SBUF_ISSECTION(s)) { | if (!SBUF_ISSECTION(s)) { | ||||
KASSERT(s->s_sect_len == 0, | KASSERT(s->s_sect_len == 0, | ||||
("s_sect_len != 0 when starting a section")); | ("s_sect_len != 0 when starting a section")); | ||||
if (old_lenp != NULL) | if (old_lenp != NULL) | ||||
*old_lenp = -1; | *old_lenp = -1; | ||||
s->s_rec_off = s->s_len; | |||||
SBUF_SETFLAG(s, SBUF_INSECTION); | SBUF_SETFLAG(s, SBUF_INSECTION); | ||||
} else { | } else { | ||||
KASSERT(old_lenp != NULL, | KASSERT(old_lenp != NULL, | ||||
("s_sect_len should be saved when starting a subsection")); | ("s_sect_len should be saved when starting a subsection")); | ||||
*old_lenp = s->s_sect_len; | *old_lenp = s->s_sect_len; | ||||
s->s_sect_len = 0; | s->s_sect_len = 0; | ||||
} | } | ||||
} | } | ||||
Show All 14 Lines | sbuf_end_section(struct sbuf *s, ssize_t old_len, size_t pad, int c) | ||||
if (pad > 1) { | if (pad > 1) { | ||||
len = roundup(s->s_sect_len, pad) - s->s_sect_len; | len = roundup(s->s_sect_len, pad) - s->s_sect_len; | ||||
for (; s->s_error == 0 && len > 0; len--) | for (; s->s_error == 0 && len > 0; len--) | ||||
sbuf_put_byte(s, c); | sbuf_put_byte(s, c); | ||||
} | } | ||||
len = s->s_sect_len; | len = s->s_sect_len; | ||||
if (old_len == -1) { | if (old_len == -1) { | ||||
s->s_sect_len = 0; | s->s_rec_off = s->s_sect_len = 0; | ||||
SBUF_CLEARFLAG(s, SBUF_INSECTION); | SBUF_CLEARFLAG(s, SBUF_INSECTION); | ||||
} else { | } else { | ||||
s->s_sect_len += old_len; | s->s_sect_len += old_len; | ||||
} | } | ||||
if (s->s_error != 0) | if (s->s_error != 0) | ||||
return (-1); | return (-1); | ||||
return (len); | return (len); | ||||
} | } |