util.c revision be21f0ab0d8f10c90265066603a8d95b6037a6fa
1#include <linux/slab.h>
2#include <linux/string.h>
3#include <linux/module.h>
4#include <linux/err.h>
5#include <asm/uaccess.h>
6
7/**
8 * kstrdup - allocate space for and copy an existing string
9 * @s: the string to duplicate
10 * @gfp: the GFP mask used in the kmalloc() call when allocating memory
11 */
12char *kstrdup(const char *s, gfp_t gfp)
13{
14	size_t len;
15	char *buf;
16
17	if (!s)
18		return NULL;
19
20	len = strlen(s) + 1;
21	buf = kmalloc_track_caller(len, gfp);
22	if (buf)
23		memcpy(buf, s, len);
24	return buf;
25}
26EXPORT_SYMBOL(kstrdup);
27
28/**
29 * kstrndup - allocate space for and copy an existing string
30 * @s: the string to duplicate
31 * @max: read at most @max chars from @s
32 * @gfp: the GFP mask used in the kmalloc() call when allocating memory
33 */
34char *kstrndup(const char *s, size_t max, gfp_t gfp)
35{
36	size_t len;
37	char *buf;
38
39	if (!s)
40		return NULL;
41
42	len = strnlen(s, max);
43	buf = kmalloc_track_caller(len+1, gfp);
44	if (buf) {
45		memcpy(buf, s, len);
46		buf[len] = '\0';
47	}
48	return buf;
49}
50EXPORT_SYMBOL(kstrndup);
51
52/**
53 * kmemdup - duplicate region of memory
54 *
55 * @src: memory region to duplicate
56 * @len: memory region length
57 * @gfp: GFP mask to use
58 */
59void *kmemdup(const void *src, size_t len, gfp_t gfp)
60{
61	void *p;
62
63	p = kmalloc_track_caller(len, gfp);
64	if (p)
65		memcpy(p, src, len);
66	return p;
67}
68EXPORT_SYMBOL(kmemdup);
69
70/**
71 * krealloc - reallocate memory. The contents will remain unchanged.
72 * @p: object to reallocate memory for.
73 * @new_size: how many bytes of memory are required.
74 * @flags: the type of memory to allocate.
75 *
76 * The contents of the object pointed to are preserved up to the
77 * lesser of the new and old sizes.  If @p is %NULL, krealloc()
78 * behaves exactly like kmalloc().  If @size is 0 and @p is not a
79 * %NULL pointer, the object pointed to is freed.
80 */
81void *krealloc(const void *p, size_t new_size, gfp_t flags)
82{
83	void *ret;
84	size_t ks = 0;
85
86	if (unlikely(!new_size)) {
87		kfree(p);
88		return ZERO_SIZE_PTR;
89	}
90
91	if (p)
92		ks = ksize(p);
93
94	if (ks >= new_size)
95		return (void *)p;
96
97	ret = kmalloc_track_caller(new_size, flags);
98	if (ret && p) {
99		memcpy(ret, p, ks);
100		kfree(p);
101	}
102	return ret;
103}
104EXPORT_SYMBOL(krealloc);
105
106/*
107 * strndup_user - duplicate an existing string from user space
108 * @s: The string to duplicate
109 * @n: Maximum number of bytes to copy, including the trailing NUL.
110 */
111char *strndup_user(const char __user *s, long n)
112{
113	char *p;
114	long length;
115
116	length = strnlen_user(s, n);
117
118	if (!length)
119		return ERR_PTR(-EFAULT);
120
121	if (length > n)
122		return ERR_PTR(-EINVAL);
123
124	p = kmalloc(length, GFP_KERNEL);
125
126	if (!p)
127		return ERR_PTR(-ENOMEM);
128
129	if (copy_from_user(p, s, length)) {
130		kfree(p);
131		return ERR_PTR(-EFAULT);
132	}
133
134	p[length - 1] = '\0';
135
136	return p;
137}
138EXPORT_SYMBOL(strndup_user);
139