95 lines · 2.1 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * Helper function for splitting a string into an argv-like array. */ #include <linux/kernel.h>#include <linux/ctype.h>#include <linux/string.h>#include <linux/slab.h>#include <linux/export.h> static int count_argc(const char *str){	int count = 0;	bool was_space; 	for (was_space = true; *str; str++) {		if (isspace(*str)) {			was_space = true;		} else if (was_space) {			was_space = false;			count++;		}	} 	return count;} /** * argv_free - free an argv * @argv - the argument vector to be freed * * Frees an argv and the strings it points to. */void argv_free(char **argv){	argv--;	kfree(argv[0]);	kfree(argv);}EXPORT_SYMBOL(argv_free); /** * argv_split - split a string at whitespace, returning an argv * @gfp: the GFP mask used to allocate memory * @str: the string to be split * @argcp: returned argument count * * Returns an array of pointers to strings which are split out from * @str.  This is performed by strictly splitting on white-space; no * quote processing is performed.  Multiple whitespace characters are * considered to be a single argument separator.  The returned array * is always NULL-terminated.  Returns NULL on memory allocation * failure. * * The source string at `str' may be undergoing concurrent alteration via * userspace sysctl activity (at least).  The argv_split() implementation * attempts to handle this gracefully by taking a local copy to work on. */char **argv_split(gfp_t gfp, const char *str, int *argcp){	char *argv_str;	bool was_space;	char **argv, **argv_ret;	int argc; 	argv_str = kstrndup(str, KMALLOC_MAX_SIZE - 1, gfp);	if (!argv_str)		return NULL; 	argc = count_argc(argv_str);	argv = kmalloc_array(argc + 2, sizeof(*argv), gfp);	if (!argv) {		kfree(argv_str);		return NULL;	} 	*argv = argv_str;	argv_ret = ++argv;	for (was_space = true; *argv_str; argv_str++) {		if (isspace(*argv_str)) {			was_space = true;			*argv_str = 0;		} else if (was_space) {			was_space = false;			*argv++ = argv_str;		}	}	*argv = NULL; 	if (argcp)		*argcp = argc;	return argv_ret;}EXPORT_SYMBOL(argv_split);