xref: /linux/arch/s390/boot/string.c (revision d639d9fa162aadec1ae9980c4dcf6e50bd2f8290)
1 // SPDX-License-Identifier: GPL-2.0
2 #define IN_BOOT_STRING_C 1
3 #include <linux/ctype.h>
4 #include <linux/kernel.h>
5 #include <linux/errno.h>
6 #undef CONFIG_KASAN
7 #undef CONFIG_KASAN_GENERIC
8 #undef CONFIG_KMSAN
9 #include "../lib/string.c"
10 
11 /*
12  * Duplicate some functions from the common lib/string.c
13  * instead of fully including it.
14  */
15 
16 int strncmp(const char *cs, const char *ct, size_t count)
17 {
18 	unsigned char c1, c2;
19 
20 	while (count) {
21 		c1 = *cs++;
22 		c2 = *ct++;
23 		if (c1 != c2)
24 			return c1 < c2 ? -1 : 1;
25 		if (!c1)
26 			break;
27 		count--;
28 	}
29 	return 0;
30 }
31 
32 ssize_t sized_strscpy(char *dst, const char *src, size_t count)
33 {
34 	size_t len;
35 
36 	if (count == 0)
37 		return -E2BIG;
38 	len = strnlen(src, count - 1);
39 	memcpy(dst, src, len);
40 	dst[len] = '\0';
41 	return src[len] ? -E2BIG : len;
42 }
43 
44 void *memset64(uint64_t *s, uint64_t v, size_t count)
45 {
46 	return __memset64(s, v, count * sizeof(v));
47 }
48 
49 char *skip_spaces(const char *str)
50 {
51 	while (isspace(*str))
52 		++str;
53 	return (char *)str;
54 }
55 
56 char *strim(char *s)
57 {
58 	size_t size;
59 	char *end;
60 
61 	size = strlen(s);
62 	if (!size)
63 		return s;
64 
65 	end = s + size - 1;
66 	while (end >= s && isspace(*end))
67 		end--;
68 	*(end + 1) = '\0';
69 
70 	return skip_spaces(s);
71 }
72 
73 /* Works only for digits and letters, but small and fast */
74 #define TOLOWER(x) ((x) | 0x20)
75 
76 static unsigned int simple_guess_base(const char *cp)
77 {
78 	if (cp[0] == '0') {
79 		if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
80 			return 16;
81 		else
82 			return 8;
83 	} else {
84 		return 10;
85 	}
86 }
87 
88 /**
89  * simple_strtoull - convert a string to an unsigned long long
90  * @cp: The start of the string
91  * @endp: A pointer to the end of the parsed string will be placed here
92  * @base: The number base to use
93  */
94 
95 unsigned long long simple_strtoull(const char *cp, char **endp,
96 				   unsigned int base)
97 {
98 	unsigned long long result = 0;
99 
100 	if (!base)
101 		base = simple_guess_base(cp);
102 
103 	if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
104 		cp += 2;
105 
106 	while (isxdigit(*cp)) {
107 		unsigned int value;
108 
109 		value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
110 		if (value >= base)
111 			break;
112 		result = result * base + value;
113 		cp++;
114 	}
115 	if (endp)
116 		*endp = (char *)cp;
117 
118 	return result;
119 }
120 
121 long simple_strtol(const char *cp, char **endp, unsigned int base)
122 {
123 	if (*cp == '-')
124 		return -simple_strtoull(cp + 1, endp, base);
125 
126 	return simple_strtoull(cp, endp, base);
127 }
128 
129 int kstrtobool(const char *s, bool *res)
130 {
131 	if (!s)
132 		return -EINVAL;
133 
134 	switch (s[0]) {
135 	case 'y':
136 	case 'Y':
137 	case '1':
138 		*res = true;
139 		return 0;
140 	case 'n':
141 	case 'N':
142 	case '0':
143 		*res = false;
144 		return 0;
145 	case 'o':
146 	case 'O':
147 		switch (s[1]) {
148 		case 'n':
149 		case 'N':
150 			*res = true;
151 			return 0;
152 		case 'f':
153 		case 'F':
154 			*res = false;
155 			return 0;
156 		default:
157 			break;
158 		}
159 	default:
160 		break;
161 	}
162 
163 	return -EINVAL;
164 }
165