Blame view

mm/util.c 2.67 KB
30992c97a   Matt Mackall   [PATCH] slob: int...
1
2
3
  #include <linux/slab.h>
  #include <linux/string.h>
  #include <linux/module.h>
96840aa00   Davi Arnaut   [PATCH] strndup_u...
4
5
  #include <linux/err.h>
  #include <asm/uaccess.h>
30992c97a   Matt Mackall   [PATCH] slob: int...
6
7
  
  /**
30992c97a   Matt Mackall   [PATCH] slob: int...
8
   * kstrdup - allocate space for and copy an existing string
30992c97a   Matt Mackall   [PATCH] slob: int...
9
10
11
12
13
14
15
16
17
18
19
20
   * @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;
1d2c8eea6   Christoph Hellwig   [PATCH] slab: cle...
21
  	buf = kmalloc_track_caller(len, gfp);
30992c97a   Matt Mackall   [PATCH] slob: int...
22
23
24
25
26
  	if (buf)
  		memcpy(buf, s, len);
  	return buf;
  }
  EXPORT_SYMBOL(kstrdup);
96840aa00   Davi Arnaut   [PATCH] strndup_u...
27

1a2f67b45   Alexey Dobriyan   [PATCH] kmemdup: ...
28
  /**
1e66df3ee   Jeremy Fitzhardinge   add kstrndup
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
   * kstrndup - allocate space for and copy an existing string
   * @s: the string to duplicate
   * @max: read at most @max chars from @s
   * @gfp: the GFP mask used in the kmalloc() call when allocating memory
   */
  char *kstrndup(const char *s, size_t max, gfp_t gfp)
  {
  	size_t len;
  	char *buf;
  
  	if (!s)
  		return NULL;
  
  	len = strnlen(s, max);
  	buf = kmalloc_track_caller(len+1, gfp);
  	if (buf) {
  		memcpy(buf, s, len);
  		buf[len] = '\0';
  	}
  	return buf;
  }
  EXPORT_SYMBOL(kstrndup);
  
  /**
1a2f67b45   Alexey Dobriyan   [PATCH] kmemdup: ...
53
54
55
56
57
58
59
60
61
   * 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;
1d2c8eea6   Christoph Hellwig   [PATCH] slab: cle...
62
  	p = kmalloc_track_caller(len, gfp);
1a2f67b45   Alexey Dobriyan   [PATCH] kmemdup: ...
63
64
65
66
67
  	if (p)
  		memcpy(p, src, len);
  	return p;
  }
  EXPORT_SYMBOL(kmemdup);
ef2ad80c7   Christoph Lameter   Slab allocators: ...
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  /**
   * 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;
ef8b4520b   Christoph Lameter   Slab allocators: ...
82
  	size_t ks = 0;
ef2ad80c7   Christoph Lameter   Slab allocators: ...
83
84
85
  
  	if (unlikely(!new_size)) {
  		kfree(p);
6cb8f9132   Christoph Lameter   Slab allocators: ...
86
  		return ZERO_SIZE_PTR;
ef2ad80c7   Christoph Lameter   Slab allocators: ...
87
  	}
ef8b4520b   Christoph Lameter   Slab allocators: ...
88
89
  	if (p)
  		ks = ksize(p);
ef2ad80c7   Christoph Lameter   Slab allocators: ...
90
91
92
93
  	if (ks >= new_size)
  		return (void *)p;
  
  	ret = kmalloc_track_caller(new_size, flags);
be21f0ab0   Adrian Bunk   fix mm/util.c:kre...
94
95
  	if (ret && p) {
  		memcpy(ret, p, ks);
ef2ad80c7   Christoph Lameter   Slab allocators: ...
96
97
98
99
100
  		kfree(p);
  	}
  	return ret;
  }
  EXPORT_SYMBOL(krealloc);
96840aa00   Davi Arnaut   [PATCH] strndup_u...
101
102
  /*
   * strndup_user - duplicate an existing string from user space
96840aa00   Davi Arnaut   [PATCH] strndup_u...
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
129
130
131
132
133
   * @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);