Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen...
[linux-2.6] / mm / util.c
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  */
12 char *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 }
26 EXPORT_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  */
34 char *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 }
50 EXPORT_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  */
59 void *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 }
68 EXPORT_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  */
81 void *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 }
104 EXPORT_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  */
111 char *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 }
138 EXPORT_SYMBOL(strndup_user);