util.c 1.7 KB
Newer Older
1 2 3
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/module.h>
D
Davi Arnaut 已提交
4 5
#include <linux/err.h>
#include <asm/uaccess.h>
6 7

/**
8
 * __kzalloc - allocate memory. The memory is set to zero.
9 10 11
 * @size: how many bytes of memory are required.
 * @flags: the type of memory to allocate.
 */
12
void *__kzalloc(size_t size, gfp_t flags)
13
{
14
	void *ret = kmalloc_track_caller(size, flags);
15 16 17 18
	if (ret)
		memset(ret, 0, size);
	return ret;
}
19
EXPORT_SYMBOL(__kzalloc);
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

/*
 * kstrdup - allocate space for and copy an existing string
 *
 * @s: the string to duplicate
 * @gfp: the GFP mask used in the kmalloc() call when allocating memory
 */
char *kstrdup(const char *s, gfp_t gfp)
{
	size_t len;
	char *buf;

	if (!s)
		return NULL;

	len = strlen(s) + 1;
36
	buf = kmalloc_track_caller(len, gfp);
37 38 39 40 41
	if (buf)
		memcpy(buf, s, len);
	return buf;
}
EXPORT_SYMBOL(kstrdup);
D
Davi Arnaut 已提交
42

A
Alexey Dobriyan 已提交
43 44 45 46 47 48 49 50 51 52 53
/**
 * kmemdup - duplicate region of memory
 *
 * @src: memory region to duplicate
 * @len: memory region length
 * @gfp: GFP mask to use
 */
void *kmemdup(const void *src, size_t len, gfp_t gfp)
{
	void *p;

54
	p = kmalloc_track_caller(len, gfp);
A
Alexey Dobriyan 已提交
55 56 57 58 59 60
	if (p)
		memcpy(p, src, len);
	return p;
}
EXPORT_SYMBOL(kmemdup);

D
Davi Arnaut 已提交
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
/*
 * strndup_user - duplicate an existing string from user space
 *
 * @s: The string to duplicate
 * @n: Maximum number of bytes to copy, including the trailing NUL.
 */
char *strndup_user(const char __user *s, long n)
{
	char *p;
	long length;

	length = strnlen_user(s, n);

	if (!length)
		return ERR_PTR(-EFAULT);

	if (length > n)
		return ERR_PTR(-EINVAL);

	p = kmalloc(length, GFP_KERNEL);

	if (!p)
		return ERR_PTR(-ENOMEM);

	if (copy_from_user(p, s, length)) {
		kfree(p);
		return ERR_PTR(-EFAULT);
	}

	p[length - 1] = '\0';

	return p;
}
EXPORT_SYMBOL(strndup_user);