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
1018e4b8e9dSBjoern A. Zeeb /* See slab.h for kvmalloc/kvfree(). */
1028e4b8e9dSBjoern A. Zeeb static inline void *
kvmemdup(const void * src,size_t len,gfp_t gfp)1038e4b8e9dSBjoern A. Zeeb kvmemdup(const void *src, size_t len, gfp_t gfp)
1048e4b8e9dSBjoern A. Zeeb {
1058e4b8e9dSBjoern A. Zeeb void *dst;
1068e4b8e9dSBjoern A. Zeeb
1078e4b8e9dSBjoern A. Zeeb dst = kvmalloc(len, gfp);
1088e4b8e9dSBjoern A. Zeeb if (dst != NULL)
1098e4b8e9dSBjoern A. Zeeb memcpy(dst, src, len);
1108e4b8e9dSBjoern A. Zeeb return (dst);
1118e4b8e9dSBjoern A. Zeeb }
1128e4b8e9dSBjoern 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
164*039eac24SJean-Sébastien Pédron /*
165*039eac24SJean-Sébastien Pédron * This function trims whitespaces at the end of a string and returns a pointer
166*039eac24SJean-Sébastien Pédron * to the first non-whitespace character.
167*039eac24SJean-Sébastien Pédron */
168*039eac24SJean-Sébastien Pédron static inline char *
strim(char * str)169*039eac24SJean-Sébastien Pédron strim(char *str)
170*039eac24SJean-Sébastien Pédron {
171*039eac24SJean-Sébastien Pédron char *end;
172*039eac24SJean-Sébastien Pédron
173*039eac24SJean-Sébastien Pédron end = str + strlen(str);
174*039eac24SJean-Sébastien Pédron while (end >= str && (*end == '\0' || isspace(*end))) {
175*039eac24SJean-Sébastien Pédron *end = '\0';
176*039eac24SJean-Sébastien Pédron end--;
177*039eac24SJean-Sébastien Pédron }
178*039eac24SJean-Sébastien Pédron
179*039eac24SJean-Sébastien Pédron return (skip_spaces(str));
180*039eac24SJean-Sébastien Pédron }
181*039eac24SJean-Sébastien Pédron
1820f32531aSHans Petter Selasky static inline void *
memchr_inv(const void * start,int c,size_t length)1830f32531aSHans Petter Selasky memchr_inv(const void *start, int c, size_t length)
1840f32531aSHans Petter Selasky {
1850f32531aSHans Petter Selasky const u8 *ptr;
1860f32531aSHans Petter Selasky const u8 *end;
1870f32531aSHans Petter Selasky u8 ch;
1880f32531aSHans Petter Selasky
1890f32531aSHans Petter Selasky ch = c;
1900f32531aSHans Petter Selasky ptr = start;
1910f32531aSHans Petter Selasky end = ptr + length;
1920f32531aSHans Petter Selasky
1930f32531aSHans Petter Selasky while (ptr != end) {
1940f32531aSHans Petter Selasky if (*ptr != ch)
1950f32531aSHans Petter Selasky return (__DECONST(void *, ptr));
1960f32531aSHans Petter Selasky ptr++;
1970f32531aSHans Petter Selasky }
1980f32531aSHans Petter Selasky return (NULL);
1990f32531aSHans Petter Selasky }
2000f32531aSHans Petter Selasky
2011a7ba9a0SEmmanuel Vadot static inline size_t
str_has_prefix(const char * str,const char * prefix)2021a7ba9a0SEmmanuel Vadot str_has_prefix(const char *str, const char *prefix)
2031a7ba9a0SEmmanuel Vadot {
2041a7ba9a0SEmmanuel Vadot size_t len;
2051a7ba9a0SEmmanuel Vadot
2061a7ba9a0SEmmanuel Vadot len = strlen(prefix);
2071a7ba9a0SEmmanuel Vadot return (strncmp(str, prefix, len) == 0 ? len : 0);
2081a7ba9a0SEmmanuel Vadot }
2091a7ba9a0SEmmanuel Vadot
210a5e2a27dSBjoern A. Zeeb static inline char *
strreplace(char * str,char old,char new)211a5e2a27dSBjoern A. Zeeb strreplace(char *str, char old, char new)
212a5e2a27dSBjoern A. Zeeb {
213a5e2a27dSBjoern A. Zeeb char *p;
214a5e2a27dSBjoern A. Zeeb
215a5e2a27dSBjoern A. Zeeb p = strchrnul(str, old);
216a5e2a27dSBjoern A. Zeeb while (p != NULL && *p != '\0') {
217a5e2a27dSBjoern A. Zeeb *p = new;
218a5e2a27dSBjoern A. Zeeb p = strchrnul(str, old);
219a5e2a27dSBjoern A. Zeeb }
220a5e2a27dSBjoern A. Zeeb return (p);
221a5e2a27dSBjoern A. Zeeb }
222a5e2a27dSBjoern A. Zeeb
223019391bfSVladimir Kondratyev static inline ssize_t
strscpy(char * dst,const char * src,size_t len)224019391bfSVladimir Kondratyev strscpy(char* dst, const char* src, size_t len)
225019391bfSVladimir Kondratyev {
226019391bfSVladimir Kondratyev size_t i;
227019391bfSVladimir Kondratyev
228019391bfSVladimir Kondratyev if (len <= INT_MAX) {
229019391bfSVladimir Kondratyev for (i = 0; i < len; i++)
230019391bfSVladimir Kondratyev if ('\0' == (dst[i] = src[i]))
231019391bfSVladimir Kondratyev return ((ssize_t)i);
232019391bfSVladimir Kondratyev if (i != 0)
233019391bfSVladimir Kondratyev dst[--i] = '\0';
234019391bfSVladimir Kondratyev }
235019391bfSVladimir Kondratyev
236019391bfSVladimir Kondratyev return (-E2BIG);
237019391bfSVladimir Kondratyev }
238019391bfSVladimir Kondratyev
239b1a9e570SJean-Sébastien Pédron static inline ssize_t
strscpy_pad(char * dst,const char * src,size_t len)240b1a9e570SJean-Sébastien Pédron strscpy_pad(char* dst, const char* src, size_t len)
241b1a9e570SJean-Sébastien Pédron {
242b1a9e570SJean-Sébastien Pédron
243b1a9e570SJean-Sébastien Pédron bzero(dst, len);
244b1a9e570SJean-Sébastien Pédron
245b1a9e570SJean-Sébastien Pédron return (strscpy(dst, src, len));
246b1a9e570SJean-Sébastien Pédron }
247b1a9e570SJean-Sébastien Pédron
24819703887SVladimir Kondratyev static inline char *
strnchr(const char * cp,size_t n,int ch)24919703887SVladimir Kondratyev strnchr(const char *cp, size_t n, int ch)
25019703887SVladimir Kondratyev {
25119703887SVladimir Kondratyev char *p;
25219703887SVladimir Kondratyev
25319703887SVladimir Kondratyev for (p = __DECONST(char *, cp); n--; ++p) {
25419703887SVladimir Kondratyev if (*p == ch)
25519703887SVladimir Kondratyev return (p);
25619703887SVladimir Kondratyev if (*p == '\0')
25719703887SVladimir Kondratyev break;
25819703887SVladimir Kondratyev }
25919703887SVladimir Kondratyev
26019703887SVladimir Kondratyev return (NULL);
26119703887SVladimir Kondratyev }
26219703887SVladimir Kondratyev
263fa1f02baSEmmanuel Vadot static inline void *
memset32(uint32_t * b,uint32_t c,size_t len)264fa1f02baSEmmanuel Vadot memset32(uint32_t *b, uint32_t c, size_t len)
265fa1f02baSEmmanuel Vadot {
266fa1f02baSEmmanuel Vadot uint32_t *dst = b;
267fa1f02baSEmmanuel Vadot
268fa1f02baSEmmanuel Vadot while (len--)
269fa1f02baSEmmanuel Vadot *dst++ = c;
270fa1f02baSEmmanuel Vadot return (b);
271fa1f02baSEmmanuel Vadot }
272fa1f02baSEmmanuel Vadot
273fa1f02baSEmmanuel Vadot static inline void *
memset64(uint64_t * b,uint64_t c,size_t len)274fa1f02baSEmmanuel Vadot memset64(uint64_t *b, uint64_t c, size_t len)
275fa1f02baSEmmanuel Vadot {
276fa1f02baSEmmanuel Vadot uint64_t *dst = b;
277fa1f02baSEmmanuel Vadot
278fa1f02baSEmmanuel Vadot while (len--)
279fa1f02baSEmmanuel Vadot *dst++ = c;
280fa1f02baSEmmanuel Vadot return (b);
281fa1f02baSEmmanuel Vadot }
282fa1f02baSEmmanuel Vadot
283fa1f02baSEmmanuel Vadot static inline void *
memset_p(void ** p,void * v,size_t n)284fa1f02baSEmmanuel Vadot memset_p(void **p, void *v, size_t n)
285fa1f02baSEmmanuel Vadot {
286fa1f02baSEmmanuel Vadot
287fa1f02baSEmmanuel Vadot if (BITS_PER_LONG == 32)
288fa1f02baSEmmanuel Vadot return (memset32((uint32_t *)p, (uintptr_t)v, n));
289fa1f02baSEmmanuel Vadot else
290fa1f02baSEmmanuel Vadot return (memset64((uint64_t *)p, (uintptr_t)v, n));
291fa1f02baSEmmanuel Vadot }
292fa1f02baSEmmanuel Vadot
2936a647ae5SBjoern A. Zeeb static inline void
memcpy_and_pad(void * dst,size_t dstlen,const void * src,size_t len,int ch)2946a647ae5SBjoern A. Zeeb memcpy_and_pad(void *dst, size_t dstlen, const void *src, size_t len, int ch)
2956a647ae5SBjoern A. Zeeb {
2966a647ae5SBjoern A. Zeeb
2976a647ae5SBjoern A. Zeeb if (len >= dstlen) {
2986a647ae5SBjoern A. Zeeb memcpy(dst, src, dstlen);
2996a647ae5SBjoern A. Zeeb } else {
3006a647ae5SBjoern A. Zeeb memcpy(dst, src, len);
3016a647ae5SBjoern A. Zeeb /* Pad with given padding character. */
3026a647ae5SBjoern A. Zeeb memset((char *)dst + len, ch, dstlen - len);
3036a647ae5SBjoern A. Zeeb }
3046a647ae5SBjoern A. Zeeb }
3056a647ae5SBjoern A. Zeeb
3065d310ea8SBjoern A. Zeeb #define memset_startat(ptr, bytepat, smember) \
3075d310ea8SBjoern A. Zeeb ({ \
3085d310ea8SBjoern A. Zeeb uint8_t *_ptr = (uint8_t *)(ptr); \
3095d310ea8SBjoern A. Zeeb int _c = (int)(bytepat); \
3105d310ea8SBjoern A. Zeeb size_t _o = offsetof(typeof(*(ptr)), smember); \
3115d310ea8SBjoern A. Zeeb memset(_ptr + _o, _c, sizeof(*(ptr)) - _o); \
3125d310ea8SBjoern A. Zeeb })
3135d310ea8SBjoern A. Zeeb
3142d9d3583SBjoern A. Zeeb #define memset_after(ptr, bytepat, smember) \
3152d9d3583SBjoern A. Zeeb ({ \
3162d9d3583SBjoern A. Zeeb uint8_t *_ptr = (uint8_t *)(ptr); \
3172d9d3583SBjoern A. Zeeb int _c = (int)(bytepat); \
3182d9d3583SBjoern A. Zeeb size_t _o = offsetofend(typeof(*(ptr)), smember); \
3192d9d3583SBjoern A. Zeeb memset(_ptr + _o, _c, sizeof(*(ptr)) - _o); \
3202d9d3583SBjoern A. Zeeb })
3212d9d3583SBjoern A. Zeeb
322218b2ccfSBjoern A. Zeeb static inline void
memzero_explicit(void * p,size_t s)323218b2ccfSBjoern A. Zeeb memzero_explicit(void *p, size_t s)
324218b2ccfSBjoern A. Zeeb {
325218b2ccfSBjoern A. Zeeb memset(p, 0, s);
326218b2ccfSBjoern A. Zeeb __asm__ __volatile__("": :"r"(p) :"memory");
327218b2ccfSBjoern A. Zeeb }
328218b2ccfSBjoern A. Zeeb
329307f78f3SVladimir Kondratyev #endif /* _LINUXKPI_LINUX_STRING_H_ */
330