add kstrndup
[linux-2.6.git] / 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;
85
86         if (unlikely(!new_size)) {
87                 kfree(p);
88                 return ZERO_SIZE_PTR;
89         }
90
91         ks = ksize(p);
92         if (ks >= new_size)
93                 return (void *)p;
94
95         ret = kmalloc_track_caller(new_size, flags);
96         if (ret) {
97                 memcpy(ret, p, min(new_size, ks));
98                 kfree(p);
99         }
100         return ret;
101 }
102 EXPORT_SYMBOL(krealloc);
103
104 /*
105  * strndup_user - duplicate an existing string from user space
106  * @s: The string to duplicate
107  * @n: Maximum number of bytes to copy, including the trailing NUL.
108  */
109 char *strndup_user(const char __user *s, long n)
110 {
111         char *p;
112         long length;
113
114         length = strnlen_user(s, n);
115
116         if (!length)
117                 return ERR_PTR(-EFAULT);
118
119         if (length > n)
120                 return ERR_PTR(-EINVAL);
121
122         p = kmalloc(length, GFP_KERNEL);
123
124         if (!p)
125                 return ERR_PTR(-ENOMEM);
126
127         if (copy_from_user(p, s, length)) {
128                 kfree(p);
129                 return ERR_PTR(-EFAULT);
130         }
131
132         p[length - 1] = '\0';
133
134         return p;
135 }
136 EXPORT_SYMBOL(strndup_user);