From f5dd3d6fadf98a53b35d20427ca198fda42f1251 Mon Sep 17 00:00:00 2001 From: Sam Vilain Date: Mon, 2 Oct 2006 02:18:04 -0700 Subject: [PATCH] [PATCH] proc: sysctl: add _proc_do_string helper The logic in proc_do_string is worth re-using without passing in a ctl_table structure (say, we want to calculate a pointer and pass that in instead); pass in the two fields it uses from that structure as explicit arguments. Signed-off-by: Sam Vilain Cc: Serge E. Hallyn Cc: Kirill Korotaev Cc: "Eric W. Biederman" Cc: Herbert Poetzl Cc: Andrey Savochkin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sysctl.c | 95 ++++++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 44 deletions(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index ba42694f0453..8b5f4bb8ad2f 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1624,6 +1624,55 @@ static ssize_t proc_writesys(struct file * file, const char __user * buf, return do_rw_proc(1, file, (char __user *) buf, count, ppos); } +int _proc_do_string(void* data, int maxlen, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + size_t len; + char __user *p; + char c; + + if (!data || !maxlen || !*lenp || + (*ppos && !write)) { + *lenp = 0; + return 0; + } + + if (write) { + len = 0; + p = buffer; + while (len < *lenp) { + if (get_user(c, p++)) + return -EFAULT; + if (c == 0 || c == '\n') + break; + len++; + } + if (len >= maxlen) + len = maxlen-1; + if(copy_from_user(data, buffer, len)) + return -EFAULT; + ((char *) data)[len] = 0; + *ppos += *lenp; + } else { + len = strlen(data); + if (len > maxlen) + len = maxlen; + if (len > *lenp) + len = *lenp; + if (len) + if(copy_to_user(buffer, data, len)) + return -EFAULT; + if (len < *lenp) { + if(put_user('\n', ((char __user *) buffer) + len)) + return -EFAULT; + len++; + } + *lenp = len; + *ppos += len; + } + return 0; +} + /** * proc_dostring - read a string sysctl * @table: the sysctl table @@ -1645,50 +1694,8 @@ static ssize_t proc_writesys(struct file * file, const char __user * buf, int proc_dostring(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) { - size_t len; - char __user *p; - char c; - - if (!table->data || !table->maxlen || !*lenp || - (*ppos && !write)) { - *lenp = 0; - return 0; - } - - if (write) { - len = 0; - p = buffer; - while (len < *lenp) { - if (get_user(c, p++)) - return -EFAULT; - if (c == 0 || c == '\n') - break; - len++; - } - if (len >= table->maxlen) - len = table->maxlen-1; - if(copy_from_user(table->data, buffer, len)) - return -EFAULT; - ((char *) table->data)[len] = 0; - *ppos += *lenp; - } else { - len = strlen(table->data); - if (len > table->maxlen) - len = table->maxlen; - if (len > *lenp) - len = *lenp; - if (len) - if(copy_to_user(buffer, table->data, len)) - return -EFAULT; - if (len < *lenp) { - if(put_user('\n', ((char __user *) buffer) + len)) - return -EFAULT; - len++; - } - *lenp = len; - *ppos += len; - } - return 0; + return _proc_do_string(table->data, table->maxlen, write, filp, + buffer, lenp, ppos); } /*