Branch data Line data Source code
1 : : /*
2 : : * Helper function for splitting a string into an argv-like array.
3 : : */
4 : :
5 : : #include <linux/kernel.h>
6 : : #include <linux/ctype.h>
7 : : #include <linux/string.h>
8 : : #include <linux/slab.h>
9 : : #include <linux/export.h>
10 : :
11 : : static int count_argc(const char *str)
12 : : {
13 : : int count = 0;
14 : : bool was_space;
15 : :
16 [ # # ]: 0 : for (was_space = true; *str; str++) {
17 [ # # ]: 0 : if (isspace(*str)) {
18 : : was_space = true;
19 [ # # ]: 0 : } else if (was_space) {
20 : : was_space = false;
21 : 0 : count++;
22 : : }
23 : : }
24 : :
25 : : return count;
26 : : }
27 : :
28 : : /**
29 : : * argv_free - free an argv
30 : : * @argv - the argument vector to be freed
31 : : *
32 : : * Frees an argv and the strings it points to.
33 : : */
34 : 0 : void argv_free(char **argv)
35 : : {
36 : 0 : argv--;
37 : 0 : kfree(argv[0]);
38 : 0 : kfree(argv);
39 : 0 : }
40 : : EXPORT_SYMBOL(argv_free);
41 : :
42 : : /**
43 : : * argv_split - split a string at whitespace, returning an argv
44 : : * @gfp: the GFP mask used to allocate memory
45 : : * @str: the string to be split
46 : : * @argcp: returned argument count
47 : : *
48 : : * Returns an array of pointers to strings which are split out from
49 : : * @str. This is performed by strictly splitting on white-space; no
50 : : * quote processing is performed. Multiple whitespace characters are
51 : : * considered to be a single argument separator. The returned array
52 : : * is always NULL-terminated. Returns NULL on memory allocation
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.
58 : : */
59 : 0 : char **argv_split(gfp_t gfp, const char *str, int *argcp)
60 : : {
61 : : char *argv_str;
62 : : bool was_space;
63 : : char **argv, **argv_ret;
64 : : int argc;
65 : :
66 : 0 : argv_str = kstrndup(str, KMALLOC_MAX_SIZE - 1, gfp);
67 [ # # ]: 0 : if (!argv_str)
68 : : return NULL;
69 : :
70 : : argc = count_argc(argv_str);
71 : 0 : argv = kmalloc(sizeof(*argv) * (argc + 2), gfp);
72 [ # # ]: 0 : if (!argv) {
73 : 0 : kfree(argv_str);
74 : 0 : return NULL;
75 : : }
76 : :
77 : 0 : *argv = argv_str;
78 : 0 : argv_ret = ++argv;
79 [ # # ]: 0 : for (was_space = true; *argv_str; argv_str++) {
80 [ # # ]: 0 : if (isspace(*argv_str)) {
81 : : was_space = true;
82 : 0 : *argv_str = 0;
83 [ # # ]: 0 : } else if (was_space) {
84 : : was_space = false;
85 : 0 : *argv++ = argv_str;
86 : : }
87 : : }
88 : 0 : *argv = NULL;
89 : :
90 [ # # ]: 0 : if (argcp)
91 : 0 : *argcp = argc;
92 : 0 : return argv_ret;
93 : : }
94 : : EXPORT_SYMBOL(argv_split);
|