xref: /linux/arch/s390/boot/string.c (revision f271df9d41c216f6189c40fa1cb83839a6117c3e)
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 	uint64_t *xs = s;
47 
48 	while (count--)
49 		*xs++ = v;
50 	return s;
51 }
52 
53 char *skip_spaces(const char *str)
54 {
55 	while (isspace(*str))
56 		++str;
57 	return (char *)str;
58 }
59 
60 char *strim(char *s)
61 {
62 	size_t size;
63 	char *end;
64 
65 	size = strlen(s);
66 	if (!size)
67 		return s;
68 
69 	end = s + size - 1;
70 	while (end >= s && isspace(*end))
71 		end--;
72 	*(end + 1) = '\0';
73 
74 	return skip_spaces(s);
75 }
76 
77 /* Works only for digits and letters, but small and fast */
78 #define TOLOWER(x) ((x) | 0x20)
79 
80 static unsigned int simple_guess_base(const char *cp)
81 {
82 	if (cp[0] == '0') {
83 		if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
84 			return 16;
85 		else
86 			return 8;
87 	} else {
88 		return 10;
89 	}
90 }
91 
92 /**
93  * simple_strtoull - convert a string to an unsigned long long
94  * @cp: The start of the string
95  * @endp: A pointer to the end of the parsed string will be placed here
96  * @base: The number base to use
97  */
98 
99 unsigned long long simple_strtoull(const char *cp, char **endp,
100 				   unsigned int base)
101 {
102 	unsigned long long result = 0;
103 
104 	if (!base)
105 		base = simple_guess_base(cp);
106 
107 	if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
108 		cp += 2;
109 
110 	while (isxdigit(*cp)) {
111 		unsigned int value;
112 
113 		value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
114 		if (value >= base)
115 			break;
116 		result = result * base + value;
117 		cp++;
118 	}
119 	if (endp)
120 		*endp = (char *)cp;
121 
122 	return result;
123 }
124 
125 long simple_strtol(const char *cp, char **endp, unsigned int base)
126 {
127 	if (*cp == '-')
128 		return -simple_strtoull(cp + 1, endp, base);
129 
130 	return simple_strtoull(cp, endp, base);
131 }
132 
133 int kstrtobool(const char *s, bool *res)
134 {
135 	if (!s)
136 		return -EINVAL;
137 
138 	switch (s[0]) {
139 	case 'y':
140 	case 'Y':
141 	case '1':
142 		*res = true;
143 		return 0;
144 	case 'n':
145 	case 'N':
146 	case '0':
147 		*res = false;
148 		return 0;
149 	case 'o':
150 	case 'O':
151 		switch (s[1]) {
152 		case 'n':
153 		case 'N':
154 			*res = true;
155 			return 0;
156 		case 'f':
157 		case 'F':
158 			*res = false;
159 			return 0;
160 		default:
161 			break;
162 		}
163 	default:
164 		break;
165 	}
166 
167 	return -EINVAL;
168 }
169