aboutsummaryrefslogtreecommitdiffstats
path: root/lib/argv_split.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-04-29 22:47:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-29 22:47:50 -0400
commit56847d857cb0c3ee78c22ce776a26f88d9ffd4d4 (patch)
treea85bcf204a53e45d26f6a3984f16ddd525eef3e7 /lib/argv_split.c
parent191a712090bb8a10e6f129360eeed2d68f3d4c9a (diff)
parent8d564368a9a3197f43e56dadf4a18c5738849f94 (diff)
Merge branch 'akpm' (incoming from Andrew)
Merge second batch of fixes from Andrew Morton: - various misc bits - some printk updates - a new "SRAM" driver. - MAINTAINERS updates - the backlight driver queue - checkpatch updates - a few init/ changes - a huge number of drivers/rtc changes - fatfs updates - some lib/idr.c work - some renaming of the random driver interfaces * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (285 commits) net: rename random32 to prandom net/core: remove duplicate statements by do-while loop net/core: rename random32() to prandom_u32() net/netfilter: rename random32() to prandom_u32() net/sched: rename random32() to prandom_u32() net/sunrpc: rename random32() to prandom_u32() scsi: rename random32() to prandom_u32() lguest: rename random32() to prandom_u32() uwb: rename random32() to prandom_u32() video/uvesafb: rename random32() to prandom_u32() mmc: rename random32() to prandom_u32() drbd: rename random32() to prandom_u32() kernel/: rename random32() to prandom_u32() mm/: rename random32() to prandom_u32() lib/: rename random32() to prandom_u32() x86: rename random32() to prandom_u32() x86: pageattr-test: remove srandom32 call uuid: use prandom_bytes() raid6test: use prandom_bytes() sctp: convert sctp_assoc_set_id() to use idr_alloc_cyclic() ...
Diffstat (limited to 'lib/argv_split.c')
-rw-r--r--lib/argv_split.c87
1 files changed, 40 insertions, 47 deletions
diff --git a/lib/argv_split.c b/lib/argv_split.c
index 1e9a6cbc3689..e927ed0e18a8 100644
--- a/lib/argv_split.c
+++ b/lib/argv_split.c
@@ -8,23 +8,17 @@
8#include <linux/slab.h> 8#include <linux/slab.h>
9#include <linux/export.h> 9#include <linux/export.h>
10 10
11static const char *skip_arg(const char *cp)
12{
13 while (*cp && !isspace(*cp))
14 cp++;
15
16 return cp;
17}
18
19static int count_argc(const char *str) 11static int count_argc(const char *str)
20{ 12{
21 int count = 0; 13 int count = 0;
14 bool was_space;
22 15
23 while (*str) { 16 for (was_space = true; *str; str++) {
24 str = skip_spaces(str); 17 if (isspace(*str)) {
25 if (*str) { 18 was_space = true;
19 } else if (was_space) {
20 was_space = false;
26 count++; 21 count++;
27 str = skip_arg(str);
28 } 22 }
29 } 23 }
30 24
@@ -39,10 +33,8 @@ static int count_argc(const char *str)
39 */ 33 */
40void argv_free(char **argv) 34void argv_free(char **argv)
41{ 35{
42 char **p; 36 argv--;
43 for (p = argv; *p; p++) 37 kfree(argv[0]);
44 kfree(*p);
45
46 kfree(argv); 38 kfree(argv);
47} 39}
48EXPORT_SYMBOL(argv_free); 40EXPORT_SYMBOL(argv_free);
@@ -59,43 +51,44 @@ EXPORT_SYMBOL(argv_free);
59 * considered to be a single argument separator. The returned array 51 * considered to be a single argument separator. The returned array
60 * is always NULL-terminated. Returns NULL on memory allocation 52 * is always NULL-terminated. Returns NULL on memory allocation
61 * failure. 53 * failure.
54 *
55 * The source string at `str' may be undergoing concurrent alteration via
56 * userspace sysctl activity (at least). The argv_split() implementation
57 * attempts to handle this gracefully by taking a local copy to work on.
62 */ 58 */
63char **argv_split(gfp_t gfp, const char *str, int *argcp) 59char **argv_split(gfp_t gfp, const char *str, int *argcp)
64{ 60{
65 int argc = count_argc(str); 61 char *argv_str;
66 char **argv = kzalloc(sizeof(*argv) * (argc+1), gfp); 62 bool was_space;
67 char **argvp; 63 char **argv, **argv_ret;
68 64 int argc;
69 if (argv == NULL) 65
70 goto out; 66 argv_str = kstrndup(str, KMALLOC_MAX_SIZE - 1, gfp);
71 67 if (!argv_str)
72 if (argcp) 68 return NULL;
73 *argcp = argc; 69
74 70 argc = count_argc(argv_str);
75 argvp = argv; 71 argv = kmalloc(sizeof(*argv) * (argc + 2), gfp);
76 72 if (!argv) {
77 while (*str) { 73 kfree(argv_str);
78 str = skip_spaces(str); 74 return NULL;
79 75 }
80 if (*str) {
81 const char *p = str;
82 char *t;
83
84 str = skip_arg(str);
85 76
86 t = kstrndup(p, str-p, gfp); 77 *argv = argv_str;
87 if (t == NULL) 78 argv_ret = ++argv;
88 goto fail; 79 for (was_space = true; *argv_str; argv_str++) {
89 *argvp++ = t; 80 if (isspace(*argv_str)) {
81 was_space = true;
82 *argv_str = 0;
83 } else if (was_space) {
84 was_space = false;
85 *argv++ = argv_str;
90 } 86 }
91 } 87 }
92 *argvp = NULL; 88 *argv = NULL;
93
94 out:
95 return argv;
96 89
97 fail: 90 if (argcp)
98 argv_free(argv); 91 *argcp = argc;
99 return NULL; 92 return argv_ret;
100} 93}
101EXPORT_SYMBOL(argv_split); 94EXPORT_SYMBOL(argv_split);