1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef _LINUX_STRING_H_ |
3 | #define _LINUX_STRING_H_ |
4 | |
5 | #include <linux/args.h> |
6 | #include <linux/array_size.h> |
7 | #include <linux/cleanup.h> /* for DEFINE_FREE() */ |
8 | #include <linux/compiler.h> /* for inline */ |
9 | #include <linux/types.h> /* for size_t */ |
10 | #include <linux/stddef.h> /* for NULL */ |
11 | #include <linux/err.h> /* for ERR_PTR() */ |
12 | #include <linux/errno.h> /* for E2BIG */ |
13 | #include <linux/overflow.h> /* for check_mul_overflow() */ |
14 | #include <linux/stdarg.h> |
15 | #include <uapi/linux/string.h> |
16 | |
17 | extern char *strndup_user(const char __user *, long); |
18 | extern void *memdup_user(const void __user *, size_t) __realloc_size(2); |
19 | extern void *vmemdup_user(const void __user *, size_t) __realloc_size(2); |
20 | extern void *memdup_user_nul(const void __user *, size_t); |
21 | |
22 | /** |
23 | * memdup_array_user - duplicate array from user space |
24 | * @src: source address in user space |
25 | * @n: number of array members to copy |
26 | * @size: size of one array member |
27 | * |
28 | * Return: an ERR_PTR() on failure. Result is physically |
29 | * contiguous, to be freed by kfree(). |
30 | */ |
31 | static inline __realloc_size(2, 3) |
32 | void *memdup_array_user(const void __user *src, size_t n, size_t size) |
33 | { |
34 | size_t nbytes; |
35 | |
36 | if (check_mul_overflow(n, size, &nbytes)) |
37 | return ERR_PTR(error: -EOVERFLOW); |
38 | |
39 | return memdup_user(src, nbytes); |
40 | } |
41 | |
42 | /** |
43 | * vmemdup_array_user - duplicate array from user space |
44 | * @src: source address in user space |
45 | * @n: number of array members to copy |
46 | * @size: size of one array member |
47 | * |
48 | * Return: an ERR_PTR() on failure. Result may be not |
49 | * physically contiguous. Use kvfree() to free. |
50 | */ |
51 | static inline __realloc_size(2, 3) |
52 | void *vmemdup_array_user(const void __user *src, size_t n, size_t size) |
53 | { |
54 | size_t nbytes; |
55 | |
56 | if (check_mul_overflow(n, size, &nbytes)) |
57 | return ERR_PTR(error: -EOVERFLOW); |
58 | |
59 | return vmemdup_user(src, nbytes); |
60 | } |
61 | |
62 | /* |
63 | * Include machine specific inline routines |
64 | */ |
65 | #include <asm/string.h> |
66 | |
67 | #ifndef __HAVE_ARCH_STRCPY |
68 | extern char * strcpy(char *,const char *); |
69 | #endif |
70 | #ifndef __HAVE_ARCH_STRNCPY |
71 | extern char * strncpy(char *,const char *, __kernel_size_t); |
72 | #endif |
73 | ssize_t sized_strscpy(char *, const char *, size_t); |
74 | |
75 | /* |
76 | * The 2 argument style can only be used when dst is an array with a |
77 | * known size. |
78 | */ |
79 | #define __strscpy0(dst, src, ...) \ |
80 | sized_strscpy(dst, src, sizeof(dst) + __must_be_array(dst) + \ |
81 | __must_be_cstr(dst) + __must_be_cstr(src)) |
82 | #define __strscpy1(dst, src, size) \ |
83 | sized_strscpy(dst, src, size + __must_be_cstr(dst) + __must_be_cstr(src)) |
84 | |
85 | #define __strscpy_pad0(dst, src, ...) \ |
86 | sized_strscpy_pad(dst, src, sizeof(dst) + __must_be_array(dst) + \ |
87 | __must_be_cstr(dst) + __must_be_cstr(src)) |
88 | #define __strscpy_pad1(dst, src, size) \ |
89 | sized_strscpy_pad(dst, src, size + __must_be_cstr(dst) + __must_be_cstr(src)) |
90 | |
91 | /** |
92 | * strscpy - Copy a C-string into a sized buffer |
93 | * @dst: Where to copy the string to |
94 | * @src: Where to copy the string from |
95 | * @...: Size of destination buffer (optional) |
96 | * |
97 | * Copy the source string @src, or as much of it as fits, into the |
98 | * destination @dst buffer. The behavior is undefined if the string |
99 | * buffers overlap. The destination @dst buffer is always NUL terminated, |
100 | * unless it's zero-sized. |
101 | * |
102 | * The size argument @... is only required when @dst is not an array, or |
103 | * when the copy needs to be smaller than sizeof(@dst). |
104 | * |
105 | * Preferred to strncpy() since it always returns a valid string, and |
106 | * doesn't unnecessarily force the tail of the destination buffer to be |
107 | * zero padded. If padding is desired please use strscpy_pad(). |
108 | * |
109 | * Returns the number of characters copied in @dst (not including the |
110 | * trailing %NUL) or -E2BIG if @size is 0 or the copy from @src was |
111 | * truncated. |
112 | */ |
113 | #define strscpy(dst, src, ...) \ |
114 | CONCATENATE(__strscpy, COUNT_ARGS(__VA_ARGS__))(dst, src, __VA_ARGS__) |
115 | |
116 | #define sized_strscpy_pad(dest, src, count) ({ \ |
117 | char *__dst = (dest); \ |
118 | const char *__src = (src); \ |
119 | const size_t __count = (count); \ |
120 | ssize_t __wrote; \ |
121 | \ |
122 | __wrote = sized_strscpy(__dst, __src, __count); \ |
123 | if (__wrote >= 0 && __wrote < __count) \ |
124 | memset(__dst + __wrote + 1, 0, __count - __wrote - 1); \ |
125 | __wrote; \ |
126 | }) |
127 | |
128 | /** |
129 | * strscpy_pad() - Copy a C-string into a sized buffer |
130 | * @dst: Where to copy the string to |
131 | * @src: Where to copy the string from |
132 | * @...: Size of destination buffer |
133 | * |
134 | * Copy the string, or as much of it as fits, into the dest buffer. The |
135 | * behavior is undefined if the string buffers overlap. The destination |
136 | * buffer is always %NUL terminated, unless it's zero-sized. |
137 | * |
138 | * If the source string is shorter than the destination buffer, the |
139 | * remaining bytes in the buffer will be filled with %NUL bytes. |
140 | * |
141 | * For full explanation of why you may want to consider using the |
142 | * 'strscpy' functions please see the function docstring for strscpy(). |
143 | * |
144 | * Returns: |
145 | * * The number of characters copied (not including the trailing %NULs) |
146 | * * -E2BIG if count is 0 or @src was truncated. |
147 | */ |
148 | #define strscpy_pad(dst, src, ...) \ |
149 | CONCATENATE(__strscpy_pad, COUNT_ARGS(__VA_ARGS__))(dst, src, __VA_ARGS__) |
150 | |
151 | #ifndef __HAVE_ARCH_STRCAT |
152 | extern char * strcat(char *, const char *); |
153 | #endif |
154 | #ifndef __HAVE_ARCH_STRNCAT |
155 | extern char * strncat(char *, const char *, __kernel_size_t); |
156 | #endif |
157 | #ifndef __HAVE_ARCH_STRLCAT |
158 | extern size_t strlcat(char *, const char *, __kernel_size_t); |
159 | #endif |
160 | #ifndef __HAVE_ARCH_STRCMP |
161 | extern int strcmp(const char *,const char *); |
162 | #endif |
163 | #ifndef __HAVE_ARCH_STRNCMP |
164 | extern int strncmp(const char *,const char *,__kernel_size_t); |
165 | #endif |
166 | #ifndef __HAVE_ARCH_STRCASECMP |
167 | extern int strcasecmp(const char *s1, const char *s2); |
168 | #endif |
169 | #ifndef __HAVE_ARCH_STRNCASECMP |
170 | extern int strncasecmp(const char *s1, const char *s2, size_t n); |
171 | #endif |
172 | #ifndef __HAVE_ARCH_STRCHR |
173 | extern char * strchr(const char *,int); |
174 | #endif |
175 | #ifndef __HAVE_ARCH_STRCHRNUL |
176 | extern char * strchrnul(const char *,int); |
177 | #endif |
178 | extern char * strnchrnul(const char *, size_t, int); |
179 | #ifndef __HAVE_ARCH_STRNCHR |
180 | extern char * strnchr(const char *, size_t, int); |
181 | #endif |
182 | #ifndef __HAVE_ARCH_STRRCHR |
183 | extern char * strrchr(const char *,int); |
184 | #endif |
185 | extern char * __must_check skip_spaces(const char *); |
186 | |
187 | extern char *strim(char *); |
188 | |
189 | static inline __must_check char *strstrip(char *str) |
190 | { |
191 | return strim(str); |
192 | } |
193 | |
194 | #ifndef __HAVE_ARCH_STRSTR |
195 | extern char * strstr(const char *, const char *); |
196 | #endif |
197 | #ifndef __HAVE_ARCH_STRNSTR |
198 | extern char * strnstr(const char *, const char *, size_t); |
199 | #endif |
200 | #ifndef __HAVE_ARCH_STRLEN |
201 | extern __kernel_size_t strlen(const char *); |
202 | #endif |
203 | #ifndef __HAVE_ARCH_STRNLEN |
204 | extern __kernel_size_t strnlen(const char *,__kernel_size_t); |
205 | #endif |
206 | #ifndef __HAVE_ARCH_STRPBRK |
207 | extern char * strpbrk(const char *,const char *); |
208 | #endif |
209 | #ifndef __HAVE_ARCH_STRSEP |
210 | extern char * strsep(char **,const char *); |
211 | #endif |
212 | #ifndef __HAVE_ARCH_STRSPN |
213 | extern __kernel_size_t strspn(const char *,const char *); |
214 | #endif |
215 | #ifndef __HAVE_ARCH_STRCSPN |
216 | extern __kernel_size_t strcspn(const char *,const char *); |
217 | #endif |
218 | |
219 | #ifndef __HAVE_ARCH_MEMSET |
220 | extern void * memset(void *,int,__kernel_size_t); |
221 | #endif |
222 | |
223 | #ifndef __HAVE_ARCH_MEMSET16 |
224 | extern void *memset16(uint16_t *, uint16_t, __kernel_size_t); |
225 | #endif |
226 | |
227 | #ifndef __HAVE_ARCH_MEMSET32 |
228 | extern void *memset32(uint32_t *, uint32_t, __kernel_size_t); |
229 | #endif |
230 | |
231 | #ifndef __HAVE_ARCH_MEMSET64 |
232 | extern void *memset64(uint64_t *, uint64_t, __kernel_size_t); |
233 | #endif |
234 | |
235 | static inline void *memset_l(unsigned long *p, unsigned long v, |
236 | __kernel_size_t n) |
237 | { |
238 | if (BITS_PER_LONG == 32) |
239 | return memset32(s: (uint32_t *)p, v, n); |
240 | else |
241 | return memset64(s: (uint64_t *)p, v, n); |
242 | } |
243 | |
244 | static inline void *memset_p(void **p, void *v, __kernel_size_t n) |
245 | { |
246 | if (BITS_PER_LONG == 32) |
247 | return memset32(s: (uint32_t *)p, v: (uintptr_t)v, n); |
248 | else |
249 | return memset64(s: (uint64_t *)p, v: (uintptr_t)v, n); |
250 | } |
251 | |
252 | extern void **__memcat_p(void **a, void **b); |
253 | #define memcat_p(a, b) ({ \ |
254 | BUILD_BUG_ON_MSG(!__same_type(*(a), *(b)), \ |
255 | "type mismatch in memcat_p()"); \ |
256 | (typeof(*a) *)__memcat_p((void **)(a), (void **)(b)); \ |
257 | }) |
258 | |
259 | #ifndef __HAVE_ARCH_MEMCPY |
260 | extern void * memcpy(void *,const void *,__kernel_size_t); |
261 | #endif |
262 | #ifndef __HAVE_ARCH_MEMMOVE |
263 | extern void * memmove(void *,const void *,__kernel_size_t); |
264 | #endif |
265 | #ifndef __HAVE_ARCH_MEMSCAN |
266 | extern void * memscan(void *,int,__kernel_size_t); |
267 | #endif |
268 | #ifndef __HAVE_ARCH_MEMCMP |
269 | extern int memcmp(const void *,const void *,__kernel_size_t); |
270 | #endif |
271 | #ifndef __HAVE_ARCH_BCMP |
272 | extern int bcmp(const void *,const void *,__kernel_size_t); |
273 | #endif |
274 | #ifndef __HAVE_ARCH_MEMCHR |
275 | extern void * memchr(const void *,int,__kernel_size_t); |
276 | #endif |
277 | #ifndef __HAVE_ARCH_MEMCPY_FLUSHCACHE |
278 | static inline void memcpy_flushcache(void *dst, const void *src, size_t cnt) |
279 | { |
280 | memcpy(dst, src, cnt); |
281 | } |
282 | #endif |
283 | |
284 | void *memchr_inv(const void *s, int c, size_t n); |
285 | char *strreplace(char *str, char old, char new); |
286 | |
287 | /** |
288 | * mem_is_zero - Check if an area of memory is all 0's. |
289 | * @s: The memory area |
290 | * @n: The size of the area |
291 | * |
292 | * Return: True if the area of memory is all 0's. |
293 | */ |
294 | static inline bool mem_is_zero(const void *s, size_t n) |
295 | { |
296 | return !memchr_inv(s, c: 0, n); |
297 | } |
298 | |
299 | extern void kfree_const(const void *x); |
300 | |
301 | extern char *kstrdup(const char *s, gfp_t gfp) __malloc; |
302 | extern const char *kstrdup_const(const char *s, gfp_t gfp); |
303 | extern char *kstrndup(const char *s, size_t len, gfp_t gfp); |
304 | extern void *kmemdup_noprof(const void *src, size_t len, gfp_t gfp) __realloc_size(2); |
305 | #define kmemdup(...) alloc_hooks(kmemdup_noprof(__VA_ARGS__)) |
306 | |
307 | extern void *kvmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2); |
308 | extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp); |
309 | extern void *kmemdup_array(const void *src, size_t count, size_t element_size, gfp_t gfp) |
310 | __realloc_size(2, 3); |
311 | |
312 | /* lib/argv_split.c */ |
313 | extern char **argv_split(gfp_t gfp, const char *str, int *argcp); |
314 | extern void argv_free(char **argv); |
315 | |
316 | DEFINE_FREE(argv_free, char **, if (!IS_ERR_OR_NULL(_T)) argv_free(_T)) |
317 | |
318 | /* lib/cmdline.c */ |
319 | extern int get_option(char **str, int *pint); |
320 | extern char *get_options(const char *str, int nints, int *ints); |
321 | extern unsigned long long memparse(const char *ptr, char **retptr); |
322 | extern bool parse_option_str(const char *str, const char *option); |
323 | extern char *next_arg(char *args, char **param, char **val); |
324 | |
325 | extern bool sysfs_streq(const char *s1, const char *s2); |
326 | int match_string(const char * const *array, size_t n, const char *string); |
327 | int __sysfs_match_string(const char * const *array, size_t n, const char *s); |
328 | |
329 | /** |
330 | * sysfs_match_string - matches given string in an array |
331 | * @_a: array of strings |
332 | * @_s: string to match with |
333 | * |
334 | * Helper for __sysfs_match_string(). Calculates the size of @a automatically. |
335 | */ |
336 | #define sysfs_match_string(_a, _s) __sysfs_match_string(_a, ARRAY_SIZE(_a), _s) |
337 | |
338 | #ifdef CONFIG_BINARY_PRINTF |
339 | __printf(3, 0) int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args); |
340 | __printf(3, 0) int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf); |
341 | #endif |
342 | |
343 | extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos, |
344 | const void *from, size_t available); |
345 | |
346 | int ptr_to_hashval(const void *ptr, unsigned long *hashval_out); |
347 | |
348 | /** |
349 | * strstarts - does @str start with @prefix? |
350 | * @str: string to examine |
351 | * @prefix: prefix to look for. |
352 | */ |
353 | static inline bool strstarts(const char *str, const char *prefix) |
354 | { |
355 | return strncmp(str, prefix, strlen(prefix)) == 0; |
356 | } |
357 | |
358 | size_t memweight(const void *ptr, size_t bytes); |
359 | |
360 | /** |
361 | * memzero_explicit - Fill a region of memory (e.g. sensitive |
362 | * keying data) with 0s. |
363 | * @s: Pointer to the start of the area. |
364 | * @count: The size of the area. |
365 | * |
366 | * Note: usually using memset() is just fine (!), but in cases |
367 | * where clearing out _local_ data at the end of a scope is |
368 | * necessary, memzero_explicit() should be used instead in |
369 | * order to prevent the compiler from optimising away zeroing. |
370 | * |
371 | * memzero_explicit() doesn't need an arch-specific version as |
372 | * it just invokes the one of memset() implicitly. |
373 | */ |
374 | static inline void memzero_explicit(void *s, size_t count) |
375 | { |
376 | memset(s, c: 0, n: count); |
377 | barrier_data(s); |
378 | } |
379 | |
380 | /** |
381 | * kbasename - return the last part of a pathname. |
382 | * |
383 | * @path: path to extract the filename from. |
384 | */ |
385 | static inline const char *kbasename(const char *path) |
386 | { |
387 | const char *tail = strrchr(path, '/'); |
388 | return tail ? tail + 1 : path; |
389 | } |
390 | |
391 | #if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE) |
392 | #include <linux/fortify-string.h> |
393 | #endif |
394 | #ifndef unsafe_memcpy |
395 | #define unsafe_memcpy(dst, src, bytes, justification) \ |
396 | memcpy(dst, src, bytes) |
397 | #endif |
398 | |
399 | void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count, |
400 | int pad); |
401 | |
402 | /** |
403 | * strtomem_pad - Copy NUL-terminated string to non-NUL-terminated buffer |
404 | * |
405 | * @dest: Pointer of destination character array (marked as __nonstring) |
406 | * @src: Pointer to NUL-terminated string |
407 | * @pad: Padding character to fill any remaining bytes of @dest after copy |
408 | * |
409 | * This is a replacement for strncpy() uses where the destination is not |
410 | * a NUL-terminated string, but with bounds checking on the source size, and |
411 | * an explicit padding character. If padding is not required, use strtomem(). |
412 | * |
413 | * Note that the size of @dest is not an argument, as the length of @dest |
414 | * must be discoverable by the compiler. |
415 | */ |
416 | #define strtomem_pad(dest, src, pad) do { \ |
417 | const size_t _dest_len = __must_be_byte_array(dest) + \ |
418 | __must_be_noncstr(dest) + \ |
419 | ARRAY_SIZE(dest); \ |
420 | const size_t _src_len = __must_be_cstr(src) + \ |
421 | __builtin_object_size(src, 1); \ |
422 | \ |
423 | BUILD_BUG_ON(!__builtin_constant_p(_dest_len) || \ |
424 | _dest_len == (size_t)-1); \ |
425 | memcpy_and_pad(dest, _dest_len, src, \ |
426 | strnlen(src, min(_src_len, _dest_len)), pad); \ |
427 | } while (0) |
428 | |
429 | /** |
430 | * strtomem - Copy NUL-terminated string to non-NUL-terminated buffer |
431 | * |
432 | * @dest: Pointer of destination character array (marked as __nonstring) |
433 | * @src: Pointer to NUL-terminated string |
434 | * |
435 | * This is a replacement for strncpy() uses where the destination is not |
436 | * a NUL-terminated string, but with bounds checking on the source size, and |
437 | * without trailing padding. If padding is required, use strtomem_pad(). |
438 | * |
439 | * Note that the size of @dest is not an argument, as the length of @dest |
440 | * must be discoverable by the compiler. |
441 | */ |
442 | #define strtomem(dest, src) do { \ |
443 | const size_t _dest_len = __must_be_byte_array(dest) + \ |
444 | __must_be_noncstr(dest) + \ |
445 | ARRAY_SIZE(dest); \ |
446 | const size_t _src_len = __must_be_cstr(src) + \ |
447 | __builtin_object_size(src, 1); \ |
448 | \ |
449 | BUILD_BUG_ON(!__builtin_constant_p(_dest_len) || \ |
450 | _dest_len == (size_t)-1); \ |
451 | memcpy(dest, src, strnlen(src, min(_src_len, _dest_len))); \ |
452 | } while (0) |
453 | |
454 | /** |
455 | * memtostr - Copy a possibly non-NUL-term string to a NUL-term string |
456 | * @dest: Pointer to destination NUL-terminates string |
457 | * @src: Pointer to character array (likely marked as __nonstring) |
458 | * |
459 | * This is a replacement for strncpy() uses where the source is not |
460 | * a NUL-terminated string. |
461 | * |
462 | * Note that sizes of @dest and @src must be known at compile-time. |
463 | */ |
464 | #define memtostr(dest, src) do { \ |
465 | const size_t _dest_len = __must_be_byte_array(dest) + \ |
466 | __must_be_cstr(dest) + \ |
467 | ARRAY_SIZE(dest); \ |
468 | const size_t _src_len = __must_be_noncstr(src) + \ |
469 | __builtin_object_size(src, 1); \ |
470 | const size_t _src_chars = strnlen(src, _src_len); \ |
471 | const size_t _copy_len = min(_dest_len - 1, _src_chars); \ |
472 | \ |
473 | BUILD_BUG_ON(!__builtin_constant_p(_dest_len) || \ |
474 | !__builtin_constant_p(_src_len) || \ |
475 | _dest_len == 0 || _dest_len == (size_t)-1 || \ |
476 | _src_len == 0 || _src_len == (size_t)-1); \ |
477 | memcpy(dest, src, _copy_len); \ |
478 | dest[_copy_len] = '\0'; \ |
479 | } while (0) |
480 | |
481 | /** |
482 | * memtostr_pad - Copy a possibly non-NUL-term string to a NUL-term string |
483 | * with NUL padding in the destination |
484 | * @dest: Pointer to destination NUL-terminates string |
485 | * @src: Pointer to character array (likely marked as __nonstring) |
486 | * |
487 | * This is a replacement for strncpy() uses where the source is not |
488 | * a NUL-terminated string. |
489 | * |
490 | * Note that sizes of @dest and @src must be known at compile-time. |
491 | */ |
492 | #define memtostr_pad(dest, src) do { \ |
493 | const size_t _dest_len = __must_be_byte_array(dest) + \ |
494 | __must_be_cstr(dest) + \ |
495 | ARRAY_SIZE(dest); \ |
496 | const size_t _src_len = __must_be_noncstr(src) + \ |
497 | __builtin_object_size(src, 1); \ |
498 | const size_t _src_chars = strnlen(src, _src_len); \ |
499 | const size_t _copy_len = min(_dest_len - 1, _src_chars); \ |
500 | \ |
501 | BUILD_BUG_ON(!__builtin_constant_p(_dest_len) || \ |
502 | !__builtin_constant_p(_src_len) || \ |
503 | _dest_len == 0 || _dest_len == (size_t)-1 || \ |
504 | _src_len == 0 || _src_len == (size_t)-1); \ |
505 | memcpy(dest, src, _copy_len); \ |
506 | memset(&dest[_copy_len], 0, _dest_len - _copy_len); \ |
507 | } while (0) |
508 | |
509 | /** |
510 | * memset_after - Set a value after a struct member to the end of a struct |
511 | * |
512 | * @obj: Address of target struct instance |
513 | * @v: Byte value to repeatedly write |
514 | * @member: after which struct member to start writing bytes |
515 | * |
516 | * This is good for clearing padding following the given member. |
517 | */ |
518 | #define memset_after(obj, v, member) \ |
519 | ({ \ |
520 | u8 *__ptr = (u8 *)(obj); \ |
521 | typeof(v) __val = (v); \ |
522 | memset(__ptr + offsetofend(typeof(*(obj)), member), __val, \ |
523 | sizeof(*(obj)) - offsetofend(typeof(*(obj)), member)); \ |
524 | }) |
525 | |
526 | /** |
527 | * memset_startat - Set a value starting at a member to the end of a struct |
528 | * |
529 | * @obj: Address of target struct instance |
530 | * @v: Byte value to repeatedly write |
531 | * @member: struct member to start writing at |
532 | * |
533 | * Note that if there is padding between the prior member and the target |
534 | * member, memset_after() should be used to clear the prior padding. |
535 | */ |
536 | #define memset_startat(obj, v, member) \ |
537 | ({ \ |
538 | u8 *__ptr = (u8 *)(obj); \ |
539 | typeof(v) __val = (v); \ |
540 | memset(__ptr + offsetof(typeof(*(obj)), member), __val, \ |
541 | sizeof(*(obj)) - offsetof(typeof(*(obj)), member)); \ |
542 | }) |
543 | |
544 | /** |
545 | * str_has_prefix - Test if a string has a given prefix |
546 | * @str: The string to test |
547 | * @prefix: The string to see if @str starts with |
548 | * |
549 | * A common way to test a prefix of a string is to do: |
550 | * strncmp(str, prefix, sizeof(prefix) - 1) |
551 | * |
552 | * But this can lead to bugs due to typos, or if prefix is a pointer |
553 | * and not a constant. Instead use str_has_prefix(). |
554 | * |
555 | * Returns: |
556 | * * strlen(@prefix) if @str starts with @prefix |
557 | * * 0 if @str does not start with @prefix |
558 | */ |
559 | static __always_inline size_t str_has_prefix(const char *str, const char *prefix) |
560 | { |
561 | size_t len = strlen(prefix); |
562 | return strncmp(str, prefix, len) == 0 ? len : 0; |
563 | } |
564 | |
565 | #endif /* _LINUX_STRING_H_ */ |
566 | |