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