Bug#547902: dash only reads the first character from pipe (bash reads whole line)
On Tue, Oct 13, 2009 at 11:13:01AM +0000, Gerrit Pape wrote:
> tags 547902 + patch
> quit
[ Adding Christian to CC: ]
Christian, did you submit your patch upstream?
Cheers,
Moritz
> Hi, please see http://bugs.debian.org/547902
>
> Here's a patch from Christian Hohnstaedt <chohnstaedt@innominate.com>
>
> Thanks, Gerrit.
>
>
> ---
> Testparameter:
> for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19; do dd if=/proc/sys/net/ipv4/tcp_wmem bs=$i 2>/dev/null; done
>
> for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19; do dd if=/proc/sys/net/ipv4/tcp_wmem skip=$i bs=1 2>/dev/null |wc -c ; done
>
> diff --git a/kernel/sysctl.c b/kernel/sysctl.c
> index 9270125..038df14 100644
> --- a/kernel/sysctl.c
> +++ b/kernel/sysctl.c
> @@ -2117,17 +2117,16 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
> #define TMPBUFLEN 21
> int *i, vleft, first=1, neg, val;
> unsigned long lval;
> - size_t left, len;
> + size_t left, len, off;
>
> char buf[TMPBUFLEN], *p;
> char __user *s = buffer;
>
> - if (!tbl_data || !table->maxlen || !*lenp ||
> - (*ppos && !write)) {
> + if (!tbl_data || !table->maxlen || !*lenp) {
> *lenp = 0;
> return 0;
> }
> -
> + off = 0;
> i = (int *) tbl_data;
> vleft = table->maxlen / sizeof(*i);
> left = *lenp;
> @@ -2176,25 +2175,31 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
> if (conv(&neg, &lval, i, 1, data))
> break;
> } else {
> + loff_t diff;
> p = buf;
> - if (!first)
> - *p++ = '\t';
> -
> if (conv(&neg, &lval, i, 0, data))
> break;
>
> - sprintf(p, "%s%lu", neg ? "-" : "", lval);
> - len = strlen(buf);
> - if (len > left)
> - len = left;
> - if(copy_to_user(s, buf, len))
> - return -EFAULT;
> - left -= len;
> - s += len;
> + len = sprintf(p, "%s%s%lu", first ? "" : "\t",
> + neg ? "-" : "", lval);
> + diff = *ppos - off;
> + off += len;
> + if (diff > 0 && diff < len) {
> + p += diff;
> + len -= diff;
> + }
> + if (off > *ppos) {
> + if (len > left)
> + len = left;
> + if(copy_to_user(s, p, len))
> + return -EFAULT;
> + left -= len;
> + s += len;
> + }
> }
> }
>
> - if (!write && !first && left) {
> + if (!write && !first && left && off >= *ppos) {
> if(put_user('\n', s))
> return -EFAULT;
> left--, s++;
>
>
>
Reply to: