xref: /freebsd-src/sys/compat/linuxkpi/common/include/linux/string.h (revision 8e4b8e9d807aa379d2a1c3aaac2537ba7d6bf0bf)
18d59ecb2SHans Petter Selasky /*-
28d59ecb2SHans Petter Selasky  * Copyright (c) 2010 Isilon Systems, Inc.
38d59ecb2SHans Petter Selasky  * Copyright (c) 2010 iX Systems, Inc.
48d59ecb2SHans Petter Selasky  * Copyright (c) 2010 Panasas, Inc.
50f32531aSHans Petter Selasky  * Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
68d59ecb2SHans Petter Selasky  * All rights reserved.
78d59ecb2SHans Petter Selasky  *
88d59ecb2SHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
98d59ecb2SHans Petter Selasky  * modification, are permitted provided that the following conditions
108d59ecb2SHans Petter Selasky  * are met:
118d59ecb2SHans Petter Selasky  * 1. Redistributions of source code must retain the above copyright
128d59ecb2SHans Petter Selasky  *    notice unmodified, this list of conditions, and the following
138d59ecb2SHans Petter Selasky  *    disclaimer.
148d59ecb2SHans Petter Selasky  * 2. Redistributions in binary form must reproduce the above copyright
158d59ecb2SHans Petter Selasky  *    notice, this list of conditions and the following disclaimer in the
168d59ecb2SHans Petter Selasky  *    documentation and/or other materials provided with the distribution.
178d59ecb2SHans Petter Selasky  *
188d59ecb2SHans Petter Selasky  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
198d59ecb2SHans Petter Selasky  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
208d59ecb2SHans Petter Selasky  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
218d59ecb2SHans Petter Selasky  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
228d59ecb2SHans Petter Selasky  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
238d59ecb2SHans Petter Selasky  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
248d59ecb2SHans Petter Selasky  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
258d59ecb2SHans Petter Selasky  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
268d59ecb2SHans Petter Selasky  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
278d59ecb2SHans Petter Selasky  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
288d59ecb2SHans Petter Selasky  */
29307f78f3SVladimir Kondratyev #ifndef	_LINUXKPI_LINUX_STRING_H_
30307f78f3SVladimir Kondratyev #define	_LINUXKPI_LINUX_STRING_H_
318d59ecb2SHans Petter Selasky 
320f32531aSHans Petter Selasky #include <sys/ctype.h>
330f32531aSHans Petter Selasky 
348d59ecb2SHans Petter Selasky #include <linux/types.h>
358d59ecb2SHans Petter Selasky #include <linux/gfp.h>
368d59ecb2SHans Petter Selasky #include <linux/slab.h>
370f32531aSHans Petter Selasky #include <linux/uaccess.h>
380f32531aSHans Petter Selasky #include <linux/err.h>
39fa1f02baSEmmanuel Vadot #include <linux/bitops.h> /* for BITS_PER_LONG */
403208d4adSVladimir Kondratyev #include <linux/overflow.h>
41d91cf060SJean-Sébastien Pédron #include <linux/stdarg.h>
428d59ecb2SHans Petter Selasky 
438d59ecb2SHans Petter Selasky #include <sys/libkern.h>
448d59ecb2SHans Petter Selasky 
45510ebed7SHans Petter Selasky #define	strnicmp(...) strncasecmp(__VA_ARGS__)
468d59ecb2SHans Petter Selasky 
470f32531aSHans Petter Selasky static inline int
match_string(const char * const * table,int n,const char * key)480f32531aSHans Petter Selasky match_string(const char *const *table, int n, const char *key)
490f32531aSHans Petter Selasky {
500f32531aSHans Petter Selasky 	int i;
510f32531aSHans Petter Selasky 
520f32531aSHans Petter Selasky 	for (i = 0; i != n && table[i] != NULL; i++) {
530f32531aSHans Petter Selasky 		if (strcmp(table[i], key) == 0)
540f32531aSHans Petter Selasky 			return (i);
550f32531aSHans Petter Selasky 	}
560f32531aSHans Petter Selasky 	return (-EINVAL);
570f32531aSHans Petter Selasky }
580f32531aSHans Petter Selasky 
590f32531aSHans Petter Selasky static inline void *
memdup_user(const void * ptr,size_t len)600f32531aSHans Petter Selasky memdup_user(const void *ptr, size_t len)
610f32531aSHans Petter Selasky {
620f32531aSHans Petter Selasky 	void *retval;
630f32531aSHans Petter Selasky 	int error;
640f32531aSHans Petter Selasky 
650f32531aSHans Petter Selasky 	retval = malloc(len, M_KMALLOC, M_WAITOK);
660f32531aSHans Petter Selasky 	error = linux_copyin(ptr, retval, len);
670f32531aSHans Petter Selasky 	if (error != 0) {
680f32531aSHans Petter Selasky 		free(retval, M_KMALLOC);
690f32531aSHans Petter Selasky 		return (ERR_PTR(error));
700f32531aSHans Petter Selasky 	}
710f32531aSHans Petter Selasky 	return (retval);
720f32531aSHans Petter Selasky }
730f32531aSHans Petter Selasky 
748d59ecb2SHans Petter Selasky static inline void *
memdup_user_nul(const void * ptr,size_t len)7510ee3d30SHans Petter Selasky memdup_user_nul(const void *ptr, size_t len)
7610ee3d30SHans Petter Selasky {
7710ee3d30SHans Petter Selasky 	char *retval;
7810ee3d30SHans Petter Selasky 	int error;
7910ee3d30SHans Petter Selasky 
8010ee3d30SHans Petter Selasky 	retval = malloc(len + 1, M_KMALLOC, M_WAITOK);
8110ee3d30SHans Petter Selasky 	error = linux_copyin(ptr, retval, len);
8210ee3d30SHans Petter Selasky 	if (error != 0) {
8310ee3d30SHans Petter Selasky 		free(retval, M_KMALLOC);
8410ee3d30SHans Petter Selasky 		return (ERR_PTR(error));
8510ee3d30SHans Petter Selasky 	}
8610ee3d30SHans Petter Selasky 	retval[len] = '\0';
8710ee3d30SHans Petter Selasky 	return (retval);
8810ee3d30SHans Petter Selasky }
8910ee3d30SHans Petter Selasky 
9010ee3d30SHans Petter Selasky static inline void *
kmemdup(const void * src,size_t len,gfp_t gfp)918d59ecb2SHans Petter Selasky kmemdup(const void *src, size_t len, gfp_t gfp)
928d59ecb2SHans Petter Selasky {
938d59ecb2SHans Petter Selasky 	void *dst;
948d59ecb2SHans Petter Selasky 
958d59ecb2SHans Petter Selasky 	dst = kmalloc(len, gfp);
960f32531aSHans Petter Selasky 	if (dst != NULL)
978d59ecb2SHans Petter Selasky 		memcpy(dst, src, len);
988d59ecb2SHans Petter Selasky 	return (dst);
998d59ecb2SHans Petter Selasky }
1008d59ecb2SHans Petter Selasky 
101*8e4b8e9dSBjoern A. Zeeb /* See slab.h for kvmalloc/kvfree(). */
102*8e4b8e9dSBjoern A. Zeeb static inline void *
kvmemdup(const void * src,size_t len,gfp_t gfp)103*8e4b8e9dSBjoern A. Zeeb kvmemdup(const void *src, size_t len, gfp_t gfp)
104*8e4b8e9dSBjoern A. Zeeb {
105*8e4b8e9dSBjoern A. Zeeb 	void *dst;
106*8e4b8e9dSBjoern A. Zeeb 
107*8e4b8e9dSBjoern A. Zeeb 	dst = kvmalloc(len, gfp);
108*8e4b8e9dSBjoern A. Zeeb 	if (dst != NULL)
109*8e4b8e9dSBjoern A. Zeeb 		memcpy(dst, src, len);
110*8e4b8e9dSBjoern A. Zeeb 	return (dst);
111*8e4b8e9dSBjoern A. Zeeb }
112*8e4b8e9dSBjoern A. Zeeb 
1130f32531aSHans Petter Selasky static inline char *
strndup_user(const char __user * ustr,long n)114a11195dfSJake Freeland strndup_user(const char __user *ustr, long n)
115a11195dfSJake Freeland {
116a11195dfSJake Freeland 	if (n < 1)
117a11195dfSJake Freeland 		return (ERR_PTR(-EINVAL));
118a11195dfSJake Freeland 
119a11195dfSJake Freeland 	return (memdup_user_nul(ustr, n - 1));
120a11195dfSJake Freeland }
121a11195dfSJake Freeland 
122a11195dfSJake Freeland static inline char *
kstrdup(const char * string,gfp_t gfp)1230f32531aSHans Petter Selasky kstrdup(const char *string, gfp_t gfp)
1240f32531aSHans Petter Selasky {
1250f32531aSHans Petter Selasky 	char *retval;
1260f32531aSHans Petter Selasky 	size_t len;
1270f32531aSHans Petter Selasky 
12834c2f79dSVladimir Kondratyev 	if (string == NULL)
12934c2f79dSVladimir Kondratyev 		return (NULL);
1300f32531aSHans Petter Selasky 	len = strlen(string) + 1;
1310f32531aSHans Petter Selasky 	retval = kmalloc(len, gfp);
1320f32531aSHans Petter Selasky 	if (retval != NULL)
1330f32531aSHans Petter Selasky 		memcpy(retval, string, len);
1340f32531aSHans Petter Selasky 	return (retval);
1350f32531aSHans Petter Selasky }
1360f32531aSHans Petter Selasky 
1370f32531aSHans Petter Selasky static inline char *
kstrndup(const char * string,size_t len,gfp_t gfp)1380f32531aSHans Petter Selasky kstrndup(const char *string, size_t len, gfp_t gfp)
1390f32531aSHans Petter Selasky {
1400f32531aSHans Petter Selasky 	char *retval;
1410f32531aSHans Petter Selasky 
14234c2f79dSVladimir Kondratyev 	if (string == NULL)
14334c2f79dSVladimir Kondratyev 		return (NULL);
1440f32531aSHans Petter Selasky 	retval = kmalloc(len + 1, gfp);
1450f32531aSHans Petter Selasky 	if (retval != NULL)
1460f32531aSHans Petter Selasky 		strncpy(retval, string, len);
1470f32531aSHans Petter Selasky 	return (retval);
1480f32531aSHans Petter Selasky }
1490f32531aSHans Petter Selasky 
150510ebed7SHans Petter Selasky static inline const char *
kstrdup_const(const char * src,gfp_t gfp)151510ebed7SHans Petter Selasky kstrdup_const(const char *src, gfp_t gfp)
152510ebed7SHans Petter Selasky {
153510ebed7SHans Petter Selasky 	return (kmemdup(src, strlen(src) + 1, gfp));
154510ebed7SHans Petter Selasky }
155510ebed7SHans Petter Selasky 
1560f32531aSHans Petter Selasky static inline char *
skip_spaces(const char * str)1570f32531aSHans Petter Selasky skip_spaces(const char *str)
1580f32531aSHans Petter Selasky {
1590f32531aSHans Petter Selasky 	while (isspace(*str))
1600f32531aSHans Petter Selasky 		++str;
1610f32531aSHans Petter Selasky 	return (__DECONST(char *, str));
1620f32531aSHans Petter Selasky }
1630f32531aSHans Petter Selasky 
1640f32531aSHans Petter Selasky static inline void *
memchr_inv(const void * start,int c,size_t length)1650f32531aSHans Petter Selasky memchr_inv(const void *start, int c, size_t length)
1660f32531aSHans Petter Selasky {
1670f32531aSHans Petter Selasky 	const u8 *ptr;
1680f32531aSHans Petter Selasky 	const u8 *end;
1690f32531aSHans Petter Selasky 	u8 ch;
1700f32531aSHans Petter Selasky 
1710f32531aSHans Petter Selasky 	ch = c;
1720f32531aSHans Petter Selasky 	ptr = start;
1730f32531aSHans Petter Selasky 	end = ptr + length;
1740f32531aSHans Petter Selasky 
1750f32531aSHans Petter Selasky 	while (ptr != end) {
1760f32531aSHans Petter Selasky 		if (*ptr != ch)
1770f32531aSHans Petter Selasky 			return (__DECONST(void *, ptr));
1780f32531aSHans Petter Selasky 		ptr++;
1790f32531aSHans Petter Selasky 	}
1800f32531aSHans Petter Selasky 	return (NULL);
1810f32531aSHans Petter Selasky }
1820f32531aSHans Petter Selasky 
1831a7ba9a0SEmmanuel Vadot static inline size_t
str_has_prefix(const char * str,const char * prefix)1841a7ba9a0SEmmanuel Vadot str_has_prefix(const char *str, const char *prefix)
1851a7ba9a0SEmmanuel Vadot {
1861a7ba9a0SEmmanuel Vadot 	size_t len;
1871a7ba9a0SEmmanuel Vadot 
1881a7ba9a0SEmmanuel Vadot 	len = strlen(prefix);
1891a7ba9a0SEmmanuel Vadot 	return (strncmp(str, prefix, len) == 0 ? len : 0);
1901a7ba9a0SEmmanuel Vadot }
1911a7ba9a0SEmmanuel Vadot 
192a5e2a27dSBjoern A. Zeeb static inline char *
strreplace(char * str,char old,char new)193a5e2a27dSBjoern A. Zeeb strreplace(char *str, char old, char new)
194a5e2a27dSBjoern A. Zeeb {
195a5e2a27dSBjoern A. Zeeb 	char *p;
196a5e2a27dSBjoern A. Zeeb 
197a5e2a27dSBjoern A. Zeeb 	p = strchrnul(str, old);
198a5e2a27dSBjoern A. Zeeb 	while (p != NULL && *p != '\0') {
199a5e2a27dSBjoern A. Zeeb 		*p = new;
200a5e2a27dSBjoern A. Zeeb 		p = strchrnul(str, old);
201a5e2a27dSBjoern A. Zeeb 	}
202a5e2a27dSBjoern A. Zeeb 	return (p);
203a5e2a27dSBjoern A. Zeeb }
204a5e2a27dSBjoern A. Zeeb 
205019391bfSVladimir Kondratyev static inline ssize_t
strscpy(char * dst,const char * src,size_t len)206019391bfSVladimir Kondratyev strscpy(char* dst, const char* src, size_t len)
207019391bfSVladimir Kondratyev {
208019391bfSVladimir Kondratyev 	size_t i;
209019391bfSVladimir Kondratyev 
210019391bfSVladimir Kondratyev 	if (len <= INT_MAX) {
211019391bfSVladimir Kondratyev 		for (i = 0; i < len; i++)
212019391bfSVladimir Kondratyev 			if ('\0' == (dst[i] = src[i]))
213019391bfSVladimir Kondratyev 				return ((ssize_t)i);
214019391bfSVladimir Kondratyev 		if (i != 0)
215019391bfSVladimir Kondratyev 			dst[--i] = '\0';
216019391bfSVladimir Kondratyev 	}
217019391bfSVladimir Kondratyev 
218019391bfSVladimir Kondratyev 	return (-E2BIG);
219019391bfSVladimir Kondratyev }
220019391bfSVladimir Kondratyev 
221b1a9e570SJean-Sébastien Pédron static inline ssize_t
strscpy_pad(char * dst,const char * src,size_t len)222b1a9e570SJean-Sébastien Pédron strscpy_pad(char* dst, const char* src, size_t len)
223b1a9e570SJean-Sébastien Pédron {
224b1a9e570SJean-Sébastien Pédron 
225b1a9e570SJean-Sébastien Pédron 	bzero(dst, len);
226b1a9e570SJean-Sébastien Pédron 
227b1a9e570SJean-Sébastien Pédron 	return (strscpy(dst, src, len));
228b1a9e570SJean-Sébastien Pédron }
229b1a9e570SJean-Sébastien Pédron 
23019703887SVladimir Kondratyev static inline char *
strnchr(const char * cp,size_t n,int ch)23119703887SVladimir Kondratyev strnchr(const char *cp, size_t n, int ch)
23219703887SVladimir Kondratyev {
23319703887SVladimir Kondratyev 	char *p;
23419703887SVladimir Kondratyev 
23519703887SVladimir Kondratyev 	for (p = __DECONST(char *, cp); n--; ++p) {
23619703887SVladimir Kondratyev 		if (*p == ch)
23719703887SVladimir Kondratyev 			return (p);
23819703887SVladimir Kondratyev 		if (*p == '\0')
23919703887SVladimir Kondratyev 			break;
24019703887SVladimir Kondratyev 	}
24119703887SVladimir Kondratyev 
24219703887SVladimir Kondratyev 	return (NULL);
24319703887SVladimir Kondratyev }
24419703887SVladimir Kondratyev 
245fa1f02baSEmmanuel Vadot static inline void *
memset32(uint32_t * b,uint32_t c,size_t len)246fa1f02baSEmmanuel Vadot memset32(uint32_t *b, uint32_t c, size_t len)
247fa1f02baSEmmanuel Vadot {
248fa1f02baSEmmanuel Vadot 	uint32_t *dst = b;
249fa1f02baSEmmanuel Vadot 
250fa1f02baSEmmanuel Vadot 	while (len--)
251fa1f02baSEmmanuel Vadot 		*dst++ = c;
252fa1f02baSEmmanuel Vadot 	return (b);
253fa1f02baSEmmanuel Vadot }
254fa1f02baSEmmanuel Vadot 
255fa1f02baSEmmanuel Vadot static inline void *
memset64(uint64_t * b,uint64_t c,size_t len)256fa1f02baSEmmanuel Vadot memset64(uint64_t *b, uint64_t c, size_t len)
257fa1f02baSEmmanuel Vadot {
258fa1f02baSEmmanuel Vadot 	uint64_t *dst = b;
259fa1f02baSEmmanuel Vadot 
260fa1f02baSEmmanuel Vadot 	while (len--)
261fa1f02baSEmmanuel Vadot 		*dst++ = c;
262fa1f02baSEmmanuel Vadot 	return (b);
263fa1f02baSEmmanuel Vadot }
264fa1f02baSEmmanuel Vadot 
265fa1f02baSEmmanuel Vadot static inline void *
memset_p(void ** p,void * v,size_t n)266fa1f02baSEmmanuel Vadot memset_p(void **p, void *v, size_t n)
267fa1f02baSEmmanuel Vadot {
268fa1f02baSEmmanuel Vadot 
269fa1f02baSEmmanuel Vadot 	if (BITS_PER_LONG == 32)
270fa1f02baSEmmanuel Vadot 		return (memset32((uint32_t *)p, (uintptr_t)v, n));
271fa1f02baSEmmanuel Vadot 	else
272fa1f02baSEmmanuel Vadot 		return (memset64((uint64_t *)p, (uintptr_t)v, n));
273fa1f02baSEmmanuel Vadot }
274fa1f02baSEmmanuel Vadot 
2756a647ae5SBjoern A. Zeeb static inline void
memcpy_and_pad(void * dst,size_t dstlen,const void * src,size_t len,int ch)2766a647ae5SBjoern A. Zeeb memcpy_and_pad(void *dst, size_t dstlen, const void *src, size_t len, int ch)
2776a647ae5SBjoern A. Zeeb {
2786a647ae5SBjoern A. Zeeb 
2796a647ae5SBjoern A. Zeeb 	if (len >= dstlen) {
2806a647ae5SBjoern A. Zeeb 		memcpy(dst, src, dstlen);
2816a647ae5SBjoern A. Zeeb 	} else {
2826a647ae5SBjoern A. Zeeb 		memcpy(dst, src, len);
2836a647ae5SBjoern A. Zeeb 		/* Pad with given padding character. */
2846a647ae5SBjoern A. Zeeb 		memset((char *)dst + len, ch, dstlen - len);
2856a647ae5SBjoern A. Zeeb 	}
2866a647ae5SBjoern A. Zeeb }
2876a647ae5SBjoern A. Zeeb 
2885d310ea8SBjoern A. Zeeb #define	memset_startat(ptr, bytepat, smember)				\
2895d310ea8SBjoern A. Zeeb ({									\
2905d310ea8SBjoern A. Zeeb 	uint8_t *_ptr = (uint8_t *)(ptr);				\
2915d310ea8SBjoern A. Zeeb 	int _c = (int)(bytepat);					\
2925d310ea8SBjoern A. Zeeb 	size_t _o = offsetof(typeof(*(ptr)), smember);			\
2935d310ea8SBjoern A. Zeeb 	memset(_ptr + _o, _c, sizeof(*(ptr)) - _o);			\
2945d310ea8SBjoern A. Zeeb })
2955d310ea8SBjoern A. Zeeb 
2962d9d3583SBjoern A. Zeeb #define	memset_after(ptr, bytepat, smember)				\
2972d9d3583SBjoern A. Zeeb ({									\
2982d9d3583SBjoern A. Zeeb 	uint8_t *_ptr = (uint8_t *)(ptr);				\
2992d9d3583SBjoern A. Zeeb 	int _c = (int)(bytepat);					\
3002d9d3583SBjoern A. Zeeb 	size_t _o = offsetofend(typeof(*(ptr)), smember);		\
3012d9d3583SBjoern A. Zeeb 	memset(_ptr + _o, _c, sizeof(*(ptr)) - _o);			\
3022d9d3583SBjoern A. Zeeb })
3032d9d3583SBjoern A. Zeeb 
304218b2ccfSBjoern A. Zeeb static inline void
memzero_explicit(void * p,size_t s)305218b2ccfSBjoern A. Zeeb memzero_explicit(void *p, size_t s)
306218b2ccfSBjoern A. Zeeb {
307218b2ccfSBjoern A. Zeeb 	memset(p, 0, s);
308218b2ccfSBjoern A. Zeeb 	__asm__ __volatile__("": :"r"(p) :"memory");
309218b2ccfSBjoern A. Zeeb }
310218b2ccfSBjoern A. Zeeb 
311307f78f3SVladimir Kondratyev #endif	/* _LINUXKPI_LINUX_STRING_H_ */
312