util.c 2.5 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);

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
/**
 * krealloc - reallocate memory. The contents will remain unchanged.
 * @p: object to reallocate memory for.
 * @new_size: how many bytes of memory are required.
 * @flags: the type of memory to allocate.
 *
 * The contents of the object pointed to are preserved up to the
 * lesser of the new and old sizes.  If @p is %NULL, krealloc()
 * behaves exactly like kmalloc().  If @size is 0 and @p is not a
 * %NULL pointer, the object pointed to is freed.
 */
void *krealloc(const void *p, size_t new_size, gfp_t flags)
{
	void *ret;
	size_t ks;

	if (unlikely(!new_size)) {
		kfree(p);
		return NULL;
	}

	ks = ksize(p);
	if (ks >= new_size)
		return (void *)p;

	ret = kmalloc_track_caller(new_size, flags);
	if (ret) {
		memcpy(ret, p, min(new_size, ks));
		kfree(p);
	}
	return ret;
}
EXPORT_SYMBOL(krealloc);

D
Davi Arnaut 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
/*
 * 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);