cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

string.c (6497B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include "string2.h"
      3#include <linux/kernel.h>
      4#include <linux/string.h>
      5#include <stdlib.h>
      6
      7#include <linux/ctype.h>
      8
      9const char *graph_dotted_line =
     10	"---------------------------------------------------------------------"
     11	"---------------------------------------------------------------------"
     12	"---------------------------------------------------------------------";
     13const char *dots =
     14	"....................................................................."
     15	"....................................................................."
     16	".....................................................................";
     17
     18#define K 1024LL
     19/*
     20 * perf_atoll()
     21 * Parse (\d+)(b|B|kb|KB|mb|MB|gb|GB|tb|TB) (e.g. "256MB")
     22 * and return its numeric value
     23 */
     24s64 perf_atoll(const char *str)
     25{
     26	s64 length;
     27	char *p;
     28	char c;
     29
     30	if (!isdigit(str[0]))
     31		goto out_err;
     32
     33	length = strtoll(str, &p, 10);
     34	switch (c = *p++) {
     35		case 'b': case 'B':
     36			if (*p)
     37				goto out_err;
     38
     39			__fallthrough;
     40		case '\0':
     41			return length;
     42		default:
     43			goto out_err;
     44		/* two-letter suffices */
     45		case 'k': case 'K':
     46			length <<= 10;
     47			break;
     48		case 'm': case 'M':
     49			length <<= 20;
     50			break;
     51		case 'g': case 'G':
     52			length <<= 30;
     53			break;
     54		case 't': case 'T':
     55			length <<= 40;
     56			break;
     57	}
     58	/* we want the cases to match */
     59	if (islower(c)) {
     60		if (strcmp(p, "b") != 0)
     61			goto out_err;
     62	} else {
     63		if (strcmp(p, "B") != 0)
     64			goto out_err;
     65	}
     66	return length;
     67
     68out_err:
     69	return -1;
     70}
     71
     72/* Character class matching */
     73static bool __match_charclass(const char *pat, char c, const char **npat)
     74{
     75	bool complement = false, ret = true;
     76
     77	if (*pat == '!') {
     78		complement = true;
     79		pat++;
     80	}
     81	if (*pat++ == c)	/* First character is special */
     82		goto end;
     83
     84	while (*pat && *pat != ']') {	/* Matching */
     85		if (*pat == '-' && *(pat + 1) != ']') {	/* Range */
     86			if (*(pat - 1) <= c && c <= *(pat + 1))
     87				goto end;
     88			if (*(pat - 1) > *(pat + 1))
     89				goto error;
     90			pat += 2;
     91		} else if (*pat++ == c)
     92			goto end;
     93	}
     94	if (!*pat)
     95		goto error;
     96	ret = false;
     97
     98end:
     99	while (*pat && *pat != ']')	/* Searching closing */
    100		pat++;
    101	if (!*pat)
    102		goto error;
    103	*npat = pat + 1;
    104	return complement ? !ret : ret;
    105
    106error:
    107	return false;
    108}
    109
    110/* Glob/lazy pattern matching */
    111static bool __match_glob(const char *str, const char *pat, bool ignore_space,
    112			bool case_ins)
    113{
    114	while (*str && *pat && *pat != '*') {
    115		if (ignore_space) {
    116			/* Ignore spaces for lazy matching */
    117			if (isspace(*str)) {
    118				str++;
    119				continue;
    120			}
    121			if (isspace(*pat)) {
    122				pat++;
    123				continue;
    124			}
    125		}
    126		if (*pat == '?') {	/* Matches any single character */
    127			str++;
    128			pat++;
    129			continue;
    130		} else if (*pat == '[')	/* Character classes/Ranges */
    131			if (__match_charclass(pat + 1, *str, &pat)) {
    132				str++;
    133				continue;
    134			} else
    135				return false;
    136		else if (*pat == '\\') /* Escaped char match as normal char */
    137			pat++;
    138		if (case_ins) {
    139			if (tolower(*str) != tolower(*pat))
    140				return false;
    141		} else if (*str != *pat)
    142			return false;
    143		str++;
    144		pat++;
    145	}
    146	/* Check wild card */
    147	if (*pat == '*') {
    148		while (*pat == '*')
    149			pat++;
    150		if (!*pat)	/* Tail wild card matches all */
    151			return true;
    152		while (*str)
    153			if (__match_glob(str++, pat, ignore_space, case_ins))
    154				return true;
    155	}
    156	return !*str && !*pat;
    157}
    158
    159/**
    160 * strglobmatch - glob expression pattern matching
    161 * @str: the target string to match
    162 * @pat: the pattern string to match
    163 *
    164 * This returns true if the @str matches @pat. @pat can includes wildcards
    165 * ('*','?') and character classes ([CHARS], complementation and ranges are
    166 * also supported). Also, this supports escape character ('\') to use special
    167 * characters as normal character.
    168 *
    169 * Note: if @pat syntax is broken, this always returns false.
    170 */
    171bool strglobmatch(const char *str, const char *pat)
    172{
    173	return __match_glob(str, pat, false, false);
    174}
    175
    176bool strglobmatch_nocase(const char *str, const char *pat)
    177{
    178	return __match_glob(str, pat, false, true);
    179}
    180
    181/**
    182 * strlazymatch - matching pattern strings lazily with glob pattern
    183 * @str: the target string to match
    184 * @pat: the pattern string to match
    185 *
    186 * This is similar to strglobmatch, except this ignores spaces in
    187 * the target string.
    188 */
    189bool strlazymatch(const char *str, const char *pat)
    190{
    191	return __match_glob(str, pat, true, false);
    192}
    193
    194/**
    195 * strtailcmp - Compare the tail of two strings
    196 * @s1: 1st string to be compared
    197 * @s2: 2nd string to be compared
    198 *
    199 * Return 0 if whole of either string is same as another's tail part.
    200 */
    201int strtailcmp(const char *s1, const char *s2)
    202{
    203	int i1 = strlen(s1);
    204	int i2 = strlen(s2);
    205	while (--i1 >= 0 && --i2 >= 0) {
    206		if (s1[i1] != s2[i2])
    207			return s1[i1] - s2[i2];
    208	}
    209	return 0;
    210}
    211
    212char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints)
    213{
    214	/*
    215	 * FIXME: replace this with an expression using log10() when we
    216	 * find a suitable implementation, maybe the one in the dvb drivers...
    217	 *
    218	 * "%s == %d || " = log10(MAXINT) * 2 + 8 chars for the operators
    219	 */
    220	size_t size = nints * 28 + 1; /* \0 */
    221	size_t i, printed = 0;
    222	char *expr = malloc(size);
    223
    224	if (expr) {
    225		const char *or_and = "||", *eq_neq = "==";
    226		char *e = expr;
    227
    228		if (!in) {
    229			or_and = "&&";
    230			eq_neq = "!=";
    231		}
    232
    233		for (i = 0; i < nints; ++i) {
    234			if (printed == size)
    235				goto out_err_overflow;
    236
    237			if (i > 0)
    238				printed += scnprintf(e + printed, size - printed, " %s ", or_and);
    239			printed += scnprintf(e + printed, size - printed,
    240					     "%s %s %d", var, eq_neq, ints[i]);
    241		}
    242	}
    243
    244	return expr;
    245
    246out_err_overflow:
    247	free(expr);
    248	return NULL;
    249}
    250
    251/* Like strpbrk(), but not break if it is right after a backslash (escaped) */
    252char *strpbrk_esc(char *str, const char *stopset)
    253{
    254	char *ptr;
    255
    256	do {
    257		ptr = strpbrk(str, stopset);
    258		if (ptr == str ||
    259		    (ptr == str + 1 && *(ptr - 1) != '\\'))
    260			break;
    261		str = ptr + 1;
    262	} while (ptr && *(ptr - 1) == '\\' && *(ptr - 2) != '\\');
    263
    264	return ptr;
    265}
    266
    267/* Like strdup, but do not copy a single backslash */
    268char *strdup_esc(const char *str)
    269{
    270	char *s, *d, *p, *ret = strdup(str);
    271
    272	if (!ret)
    273		return NULL;
    274
    275	d = strchr(ret, '\\');
    276	if (!d)
    277		return ret;
    278
    279	s = d + 1;
    280	do {
    281		if (*s == '\0') {
    282			*d = '\0';
    283			break;
    284		}
    285		p = strchr(s + 1, '\\');
    286		if (p) {
    287			memmove(d, s, p - s);
    288			d += p - s;
    289			s = p + 1;
    290		} else
    291			memmove(d, s, strlen(s) + 1);
    292	} while (p);
    293
    294	return ret;
    295}
    296
    297unsigned int hex(char c)
    298{
    299	if (c >= '0' && c <= '9')
    300		return c - '0';
    301	if (c >= 'a' && c <= 'f')
    302		return c - 'a' + 10;
    303	return c - 'A' + 10;
    304}