mirror of
https://git.proxmox.com/git/efi-boot-shim
synced 2025-07-14 09:14:09 +00:00
285 lines
4.3 KiB
C
285 lines
4.3 KiB
C
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
/*
|
|
* string.c - implementations we need for string finctions
|
|
*/
|
|
#define SHIM_STRING_C_
|
|
#include "shim.h"
|
|
|
|
#ifdef SHIM_UNIT_TEST
|
|
#define strlen shim_strlen
|
|
#ifdef strcmp
|
|
#undef strcmp
|
|
#endif
|
|
#define strcmp shim_strcmp
|
|
#ifdef strncmp
|
|
#undef strncmp
|
|
#endif
|
|
#define strncmp shim_strncmp
|
|
#define strncasecmp shim_strncasecmp
|
|
#define strcasecmp shim_strcasecmp
|
|
#define strrchr shim_strrchr
|
|
#define strlen shim_strlen
|
|
#define strnlen shim_strnlen
|
|
#define strcpy shim_strcpy
|
|
#ifdef strncpy
|
|
#undef strncpy
|
|
#endif
|
|
#define strncpy shim_strncpy
|
|
#ifdef strdup
|
|
#undef strdup
|
|
#endif
|
|
#define strdup shim_strdup
|
|
#ifdef strndup
|
|
#undef strndup
|
|
#endif
|
|
#define strndup shim_strndup
|
|
#ifdef stpcpy
|
|
#undef stpcpy
|
|
#endif
|
|
#define stpcpy shim_stpcpy
|
|
#define strchrnul shim_strchrnul
|
|
#ifdef strchr
|
|
#undef strchr
|
|
#endif
|
|
#define strchr shim_strchr
|
|
#endif
|
|
|
|
size_t
|
|
strlen(const char *s1)
|
|
{
|
|
size_t len;
|
|
|
|
for (len = 0; *s1; s1 += 1, len += 1)
|
|
;
|
|
return len;
|
|
}
|
|
|
|
int
|
|
strcmp(const char *s1p, const char *s2p)
|
|
{
|
|
const uint8_t *s1 = (const uint8_t *)s1p;
|
|
const uint8_t *s2 = (const uint8_t *)s2p;
|
|
|
|
while (*s1) {
|
|
if (*s1 != *s2) {
|
|
break;
|
|
}
|
|
|
|
s1 += 1;
|
|
s2 += 1;
|
|
}
|
|
|
|
return *s1 - *s2;
|
|
}
|
|
|
|
int
|
|
strncmp(const char *s1p, const char *s2p, size_t len)
|
|
{
|
|
const uint8_t *s1 = (const uint8_t *)s1p;
|
|
const uint8_t *s2 = (const uint8_t *)s2p;
|
|
|
|
while (*s1 && len) {
|
|
if (*s1 != *s2) {
|
|
break;
|
|
}
|
|
|
|
s1 += 1;
|
|
s2 += 1;
|
|
len -= 1;
|
|
}
|
|
|
|
return len ? *s1 - *s2 : 0;
|
|
}
|
|
|
|
/* Based on AsciiStriCmp() in edk2 MdePkg/Library/BaseLib/String.c */
|
|
int
|
|
strncasecmp(const char *s1p, const char *s2p, size_t n)
|
|
{
|
|
const uint8_t *s1 = (const uint8_t *)s1p;
|
|
const uint8_t *s2 = (const uint8_t *)s2p;
|
|
|
|
while (*s1 && n) {
|
|
if (toupper(*s1) != toupper(*s2)) {
|
|
break;
|
|
}
|
|
|
|
s1 += 1;
|
|
s2 += 1;
|
|
n -= 1;
|
|
}
|
|
|
|
return n ? *s1 - *s2 : 0;
|
|
}
|
|
|
|
/* Based on AsciiStriCmp() in edk2 MdePkg/Library/BaseLib/String.c */
|
|
int
|
|
strcasecmp(const char *str1, const char *str2)
|
|
{
|
|
uint8_t c1, c2;
|
|
|
|
c1 = toupper(*str1);
|
|
c2 = toupper(*str2);
|
|
while ((*str1 != '\0') && (c1 == c2)) {
|
|
str1++;
|
|
str2++;
|
|
c1 = toupper(*str1);
|
|
c2 = toupper(*str2);
|
|
}
|
|
|
|
return c1 - c2;
|
|
}
|
|
|
|
/* Scan a string for the last occurrence of a character */
|
|
char *
|
|
strrchr(const char *str, int c)
|
|
{
|
|
char *save;
|
|
|
|
for (save = NULL;; ++str) {
|
|
if (*str == c) {
|
|
save = (char *)str;
|
|
}
|
|
if (*str == 0) {
|
|
return (save);
|
|
}
|
|
}
|
|
}
|
|
|
|
NONNULL(1)
|
|
size_t
|
|
strnlen(const char *s, size_t n)
|
|
{
|
|
size_t i;
|
|
for (i = 0; i < n; i++)
|
|
if (s[i] == '\0')
|
|
break;
|
|
return i;
|
|
}
|
|
|
|
RETURNS_NONNULL NONNULL(1, 2)
|
|
char *
|
|
strcpy(char *dest, const char *src)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; src[i] != '\0'; i++)
|
|
dest[i] = src[i];
|
|
|
|
dest[i] = '\0';
|
|
return dest;
|
|
}
|
|
|
|
RETURNS_NONNULL NONNULL(1, 2)
|
|
char *
|
|
strncpy(char *dest, const char *src, size_t n)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < n && src[i] != '\0'; i++)
|
|
dest[i] = src[i];
|
|
if (i < n)
|
|
dest[i] = '\0';
|
|
|
|
return dest;
|
|
}
|
|
|
|
RETURNS_NONNULL NONNULL(1, 2)
|
|
char *
|
|
strcat(char *dest, const char *src)
|
|
{
|
|
size_t dest_len = strlen(dest);
|
|
size_t i;
|
|
|
|
for (i = 0; src[i] != '\0'; i++)
|
|
dest[dest_len + i] = src[i];
|
|
dest[dest_len + i] = '\0';
|
|
|
|
return dest;
|
|
}
|
|
|
|
NONNULL(1)
|
|
char *
|
|
strdup(const char *const src)
|
|
{
|
|
size_t len;
|
|
char *news = NULL;
|
|
|
|
len = strlen(src);
|
|
news = AllocateZeroPool(len + 1);
|
|
if (news)
|
|
strncpy(news, src, len);
|
|
return news;
|
|
}
|
|
|
|
NONNULL(1)
|
|
char *
|
|
strndup(const char *const src, const size_t srcmax)
|
|
{
|
|
size_t len;
|
|
char *news = NULL;
|
|
|
|
len = strnlen(src, srcmax);
|
|
news = AllocateZeroPool(len + 1);
|
|
if (news)
|
|
strncpy(news, src, len);
|
|
return news;
|
|
}
|
|
|
|
RETURNS_NONNULL NONNULL(1, 2)
|
|
char *
|
|
stpcpy(char *dest, const char *const src)
|
|
{
|
|
size_t i = 0;
|
|
for (i = 0; src[i]; i++)
|
|
dest[i] = src[i];
|
|
dest[i] = '\000';
|
|
return &dest[i];
|
|
}
|
|
|
|
RETURNS_NONNULL NONNULL(1)
|
|
char *
|
|
strchrnul(const char *s, int c)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; s[i] != '\000' && s[i] != c; i++)
|
|
;
|
|
|
|
return (char *)&s[i];
|
|
}
|
|
|
|
NONNULL(1)
|
|
char *
|
|
strchr(const char *s, int c)
|
|
{
|
|
const char *s1;
|
|
|
|
s1 = strchrnul(s, c);
|
|
if (!s1 || s1[0] == '\000')
|
|
return NULL;
|
|
|
|
return (char *)s1;
|
|
}
|
|
|
|
char *
|
|
translate_slashes(char *out, const char *str)
|
|
{
|
|
int i;
|
|
int j;
|
|
if (str == NULL || out == NULL)
|
|
return NULL;
|
|
|
|
for (i = 0, j = 0; str[i] != '\0'; i++, j++) {
|
|
if (str[i] == '\\') {
|
|
out[j] = '/';
|
|
if (str[i + 1] == '\\')
|
|
i++;
|
|
} else
|
|
out[j] = str[i];
|
|
}
|
|
out[j] = '\0';
|
|
return out;
|
|
}
|
|
|
|
// vim:fenc=utf-8:tw=75:noet
|