Cut a lot of chaff; Rewrote string.h completely

This commit is contained in:
Thomas Oltmann 2025-03-16 01:20:53 +01:00
parent 510a18e123
commit b5c9c0de9a
18 changed files with 37 additions and 1012 deletions

View file

@ -10,6 +10,6 @@ LD = $(CROSS_PATH)/$(ARCH)-linux-ld
# Compilation flags
CFLAGS = -std=c17 -Wall -ffreestanding -fpic -nostdlib -fstack-protector-all -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -mno-sse -mno-mmx -mno-80387
CPPFLAGS = -Ignuefi/inc -Iinclude
CPPFLAGS = -Ignuefi/inc -Iinclude -Ilibc/include
LDFLAGS = -shared -Bsymbolic -Lgnuefi -Tgnuefi/elf_$(ARCH)_efi.lds -nostdlib
LIBS = -lgnuefi -lefi

View file

@ -1,164 +1,44 @@
/*
* Copyright (c) 2011, 2012, 2013, 2014, 2017, 2024 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string.h
* String operations.
*/
#ifndef VISOR_LIBC_STRING_H
#define VISOR_LIBC_STRING_H
#ifndef _INCLUDE_STRING_H
#define _INCLUDE_STRING_H
#include <sys/cdefs.h>
#if __USE_SORTIX || __USE_POSIX
#include <sys/__/types.h>
#endif
#ifndef NULL
#define __need_NULL
#include <stddef.h>
#endif
#ifndef __size_t_defined
#define __size_t_defined
#define __need_size_t
#include <stddef.h>
#endif
int ffs(int);
int ffsl(long);
int ffsll(long long);
#if __USE_SORTIX || 2008 <= __USE_POSIX
#ifndef __locale_t_defined
#define __locale_t_defined
/* TODO: figure out what this does and typedef it properly. This is just a
temporary assignment. */
typedef int __locale_t;
typedef __locale_t locale_t;
#endif
#endif
void *memccpy(void *restrict, const void *restrict, int, size_t);
void *memchr (const void *, int, size_t);
int memcmp (const void *, const void *, size_t);
void *memcpy (void *restrict, const void *restrict, size_t);
void *memmove(void *, const void *, size_t);
void *memrchr(const void *, int, size_t);
void *memset (void *, int, size_t);
#ifdef __cplusplus
extern "C" {
#endif
char *stpcpy (char *restrict, const char *restrict);
char *stpncpy(char *restrict, const char *restrict, size_t);
void* memchr(const void*, int, size_t);
int memcmp(const void*, const void*, size_t);
void* memcpy(void* __restrict, const void* __restrict, size_t);
void* memmove(void*, const void*, size_t);
void* memset(void*, int, size_t);
char* strcat(char* __restrict, const char* __restrict);
char* strchr(const char*, int);
int strcmp(const char*, const char*);
int strcoll(const char*, const char*);
char* strcpy(char* __restrict, const char* __restrict);
size_t strcspn(const char*, const char*);
char* strerror(int errnum);
size_t strlen(const char*);
char* strncat(char* __restrict, const char* __restrict, size_t);
int strncmp(const char*, const char*, size_t);
char* strncpy(char* __restrict, const char* __restrict, size_t);
char* strpbrk(const char*, const char*);
char* strrchr(const char*, int);
size_t strspn(const char*, const char*);
char* strstr(const char*, const char*);
char* strtok(char* __restrict, const char* __restrict);
size_t strxfrm(char* __restrict, const char* __restrict, size_t);
/* Functions from early POSIX. */
#if __USE_SORTIX || __USE_POSIX
int strcasecmp(const char* a, const char* b);
int strncasecmp(const char* a, const char* b, size_t n);
#endif
/* Functions from early XOPEN. */
#if __USE_SORTIX || __USE_XOPEN
void* memccpy(void* __restrict, const void* __restrict, int, size_t);
int ffs(int);
#endif
/* Functions from XOPEN 420 gone into POSIX 2008. */
#if __USE_SORTIX || 420 <= __USE_XOPEN || 200809L <= __USE_POSIX
char* strdup(const char*);
#endif
/* Functions from POSIX 2001. */
#if __USE_SORTIX || 200112L <= __USE_POSIX
char* strerror_l(int, locale_t);
int strerror_r(int, char*, size_t);
char* strtok_r(char* __restrict, const char* __restrict, char** __restrict);
#endif
/* Functions from POSIX 2008. */
#if __USE_SORTIX || 200809L <= __USE_POSIX
char* stpcpy(char* __restrict, const char* __restrict);
char* stpncpy(char* __restrict, const char* __restrict, size_t);
int strcoll_l(const char*, const char*, locale_t);
char* strndup(const char*, size_t);
size_t strnlen(const char*, size_t);
char* strsignal(int signum);
size_t strxfrm_l(char* __restrict, const char* __restrict, size_t, locale_t);
#endif
/* Functions from POSIX 2024. */
#if __USE_SORTIX || 202405L <= __USE_POSIX
size_t strlcat(char* __restrict, const char* __restrict, size_t);
size_t strlcpy(char* __restrict, const char* __restrict, size_t);
#endif
#if __USE_SORTIX || 800 <= __USE_XOPEN
int ffsl(long int);
int ffsll(long long int);
#endif
/* Functions copied from elsewhere. */
#if __USE_SORTIX
void explicit_bzero(void*, size_t);
void* memrchr(const void*, int, size_t);
/* TODO: strcasecmp_l */
char* strchrnul(const char* str, int c);
char* stresep(char**, const char*, int);
/* TODO: strncasecmp_l */
char* strsep(char**, const char*);
int strverscmp(const char*, const char*);
int timingsafe_memcmp(const void*, const void*, size_t);
#endif
#if __USE_SORTIX
/* Duplicate S, returning an identical alloca'd string. */
#define strdupa(s) \
(__extension__ \
({ \
const char* __old = (s); \
size_t __len = strlen(__old) + 1; \
char* __new = (char*) __builtin_alloca(__len); \
(char*) memcpy(__new, __old, __len); \
}))
/* Return an alloca'd copy of at most N bytes of string. */
#define strndupa(s, n) \
(__extension__ \
({ \
__const char* __old = (s); \
size_t __len = strnlen(__old, (n)); \
char* __new = (char*) __builtin_alloca(__len + 1); \
__new[__len] = '\0'; \
(char*) memcpy(__new, __old, __len); \
}))
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
char *strcat (char *restrict, const char *restrict);
char *strchr (const char *, int);
int strcmp (const char *, const char *);
char *strchrnul(const char *, int);
int strcoll(const char *, const char *);
char *strcpy (char *restrict, const char *restrict);
size_t strcspn(const char *, const char *);
char *stresep(char **, const char *, int);
size_t strlcat(char *restrict, const char *restrict, size_t);
size_t strlcpy(char *restrict, const char *restrict, size_t);
size_t strlen (const char *);
char *strncat(char *restrict, const char *restrict, size_t);
int strncmp(const char *, const char *, size_t);
char *strncpy(char *restrict, const char *restrict, size_t);
size_t strnlen(const char *, size_t);
char *strpbrk(const char *, const char *);
char *strrchr(const char *, int);
char *strsep (char **, const char *);
size_t strspn (const char *, const char *);
char *strstr (const char *, const char *);
char *strtok_r(char *restrict, const char *restrict, char **restrict);
size_t strxfrm(char *restrict, const char *restrict, size_t);
#endif

View file

@ -1,29 +0,0 @@
/*
* Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/explicit_bzero.c
* Initializes a region of memory to a byte value in a manner that is not
* optimized away by the compiler.
*/
#include <string.h>
// TODO: Employ special compiler support to ensure this is not optimized away.
void explicit_bzero(void* dest_ptr, size_t size)
{
volatile unsigned char* dest = (volatile unsigned char*) dest_ptr;
for ( size_t i = 0; i < size; i++ )
dest[i] = 0;
}

View file

@ -1,139 +0,0 @@
/*
* Copyright (c) 2011, 2012, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/memcpy.c
* Copy memory between non-overlapping regions.
*/
#include <scram.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#if defined(__is_sortix_libk)
#include <libk.h>
#endif
inline static
void* memcpy_slow(void* restrict dst_ptr,
const void* restrict src_ptr,
size_t size)
{
unsigned char* restrict dst = (unsigned char* restrict) dst_ptr;
const unsigned char* restrict src = (const unsigned char* restrict) src_ptr;
for ( size_t i = 0; i < size; i++ )
dst[i] = src[i];
return dst_ptr;
}
void* memcpy(void* restrict dst_ptr,
const void* restrict src_ptr,
size_t size)
{
if ( dst_ptr == src_ptr || !size )
return dst_ptr;
void* dst_end = (char*) dst_ptr + size;
const void* src_end = (const char*) src_ptr + size;
if ( (dst_ptr < src_ptr && src_ptr < dst_end) ||
(src_ptr < dst_ptr && dst_ptr < src_end) )
{
#if defined(__is_sortix_libk)
libk_overlapping_memcpy();
#else
struct scram_undefined_behavior info;
info.filename = __FILE__;
info.line = __LINE__;
info.column = 0;
info.violation = "overlapping memcpy";
scram(SCRAM_UNDEFINED_BEHAVIOR, &info);
#endif
}
#if 8 < __SIZEOF_LONG__
#warning "you should add support for your unexpectedly large unsigned long."
return memcpy_slow(dst_ptr, src_ptr, size);
#else
unsigned long unalign_mask = sizeof(unsigned long) - 1;
unsigned long src_unalign = (unsigned long) src_ptr & unalign_mask;
unsigned long dst_unalign = (unsigned long) dst_ptr & unalign_mask;
if ( src_unalign != dst_unalign )
return memcpy_slow(dst_ptr, src_ptr, size);
union
{
unsigned long srcval;
const unsigned char* restrict src8;
const uint16_t* restrict src16;
const uint32_t* restrict src32;
const uint64_t* restrict src64;
const unsigned long* restrict srcul;
} su;
su.srcval = (unsigned long) src_ptr;
union
{
unsigned long dstval;
unsigned char* restrict dst8;
uint16_t* restrict dst16;
uint32_t* restrict dst32;
uint64_t* restrict dst64;
unsigned long* restrict dstul;
} du;
du.dstval = (unsigned long) dst_ptr;
if ( dst_unalign )
{
if ( 1 <= size && !(du.dstval & (1-1)) && (du.dstval & (2-1)) )
*du.dst8++ = *su.src8++,
size -= 1;
if ( 2 <= size && !(du.dstval & (2-1)) && (du.dstval & (4-1)) )
*du.dst16++ = *su.src16++,
size -= 2;
#if 8 <= __SIZEOF_LONG__
if ( 4 <= size && !(du.dstval & (4-1)) && (du.dstval & (8-1)) )
*du.dst32++ = *su.src32++,
size -= 4;
#endif
}
size_t num_copies = size / sizeof(unsigned long);
for ( size_t i = 0; i < num_copies; i++ )
*du.dstul++ = *su.srcul++;
size -= num_copies * sizeof(unsigned long);
if ( size )
{
#if 8 <= __SIZEOF_LONG__
if ( 4 <= size )
*du.dst32++ = *su.src32++,
size -= 4;
#endif
if ( 2 <= size )
*du.dst16++ = *su.src16++,
size -= 2;
if ( 1 <= size )
*du.dst8++ = *su.src8++,
size -= 1;
}
return dst_ptr;
#endif
}

View file

@ -1,59 +0,0 @@
/*
* Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/memset.c
* Initializes a region of memory to a byte value.
*/
#include <stdint.h>
#include <string.h>
#include <__/wordsize.h>
void* memset(void* dest_ptr, int value, size_t length)
{
unsigned char* dest = (unsigned char*) dest_ptr;
#if __WORDSIZE == 32 || __WORDSIZE == 64
if ( ((uintptr_t) dest_ptr & (sizeof(unsigned long) - 1)) == 0 )
{
unsigned long* ulong_dest = (unsigned long*) dest;
size_t ulong_length = length / sizeof(unsigned long);
#if __WORDSIZE == 32
unsigned long ulong_value =
(unsigned long) ((unsigned char) value) << 0 |
(unsigned long) ((unsigned char) value) << 8 |
(unsigned long) ((unsigned char) value) << 16 |
(unsigned long) ((unsigned char) value) << 24;
#elif __WORDSIZE == 64
unsigned long ulong_value =
(unsigned long) ((unsigned char) value) << 0 |
(unsigned long) ((unsigned char) value) << 8 |
(unsigned long) ((unsigned char) value) << 16 |
(unsigned long) ((unsigned char) value) << 24 |
(unsigned long) ((unsigned char) value) << 32 |
(unsigned long) ((unsigned char) value) << 40 |
(unsigned long) ((unsigned char) value) << 48 |
(unsigned long) ((unsigned char) value) << 56;
#endif
for ( size_t i = 0; i < ulong_length; i++ )
ulong_dest[i] = ulong_value;
dest += ulong_length * sizeof(unsigned long);
length -= ulong_length * sizeof(unsigned long);
}
#endif
for ( size_t i = 0; i < length; i++ )
dest[i] = (unsigned char) value;
return dest_ptr;
}

View file

@ -1,37 +0,0 @@
/*
* Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/strcasecmp.c
* Compares two strings ignoring case.
*/
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
int strcasecmp(const char* a, const char* b)
{
for ( size_t i = 0; true; i++ )
{
unsigned char ac = (unsigned char) tolower((unsigned char) a[i]);
unsigned char bc = (unsigned char) tolower((unsigned char) b[i]);
if ( ac == '\0' && bc == '\0' )
return 0;
if ( ac < bc )
return -1;
if ( ac > bc )
return 1;
}
}

View file

@ -1,26 +0,0 @@
/*
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/strcoll_l.c
* Compare two strings using the given locale.
*/
#include <string.h>
int strcoll_l(const char* s1, const char* s2, locale_t locale)
{
(void) locale;
return strcoll(s1, s2);
}

View file

@ -1,31 +0,0 @@
/*
* Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/strdup.c
* Creates a copy of a string.
*/
#include <stdlib.h>
#include <string.h>
char* strdup(const char* input)
{
size_t input_length = strlen(input);
char* result = (char*) malloc(input_length + 1);
if ( !result )
return NULL;
memcpy(result, input, input_length + 1);
return result;
}

View file

@ -1,124 +0,0 @@
/*
* Copyright (c) 2011-2016, 2020-2022, 2024 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/strerror.c
* Convert error code to a string.
*/
#include <errno.h>
#include <string.h>
char* strerror(int errnum)
{
switch ( errnum )
{
case ENOTBLK: return "Block device required";
case ENODEV: return "No such device";
case EBADF: return "Bad file descriptor";
case EOVERFLOW: return "Value too large to be stored in data type";
case ENOENT: return "No such file or directory";
case ENOSPC: return "No space left on device";
case EEXIST: return "File exists";
case EROFS: return "Read-only file system";
case EINVAL: return "Invalid argument";
case ENOTDIR: return "Not a directory";
case ENOMEM: return "Not enough memory";
case ERANGE: return "Result too large";
case EISDIR: return "Is a directory";
case EPERM: return "Operation not permitted";
case EIO: return "Input/output error";
case ENOEXEC: return "Exec format error";
case EACCES: return "Permission denied";
case ESRCH: return "No such process";
case ENOTTY: return "Not a tty";
case ECHILD: return "No child processes";
case ENOSYS: return "Function not implemented";
case ENOTSUP: return "Operation not supported";
case EBLOCKING: return "Operation is blocking";
case EINTR: return "Interrupted function call";
case ENOTEMPTY: return "Directory not empty";
case EBUSY: return "Device or resource busy";
case EPIPE: return "Broken pipe";
case EILSEQ: return "Invalid byte sequence";
case ELAKE: return "Sit by a lake";
case EMFILE: return "Too many open files";
case EAGAIN: return "Resource temporarily unavailable";
case EEOF: return "End of file";
case EBOUND: return "Out of bounds";
case EINIT: return "Not initialized";
case ENODRV: return "No such driver";
case E2BIG: return "Argument list too long";
case EFBIG: return "File too large";
case EXDEV: return "Improper link";
case ESPIPE: return "Cannot seek on stream";
case ENAMETOOLONG: return "Filename too long";
case ELOOP: return "Too many levels of symbolic links";
case EMLINK: return "Too many links";
case ENXIO: return "No such device or address";
case EPROTONOSUPPORT: return "Protocol not supported";
case EAFNOSUPPORT: return "Address family not supported";
case ENOTSOCK: return "Not a socket";
case EADDRINUSE: return "Address already in use";
case ETIMEDOUT: return "Connection timed out";
case ECONNREFUSED: return "Connection refused";
case EDOM: return "Mathematics argument out of domain of function";
case EINPROGRESS: return "Operation in progress";
case EALREADY: return "Connection already in progress";
case ESHUTDOWN: return "Cannot send after transport endpoint shutdown";
case ECONNABORTED: return "Connection aborted";
case ECONNRESET: return "Connection reset";
case EADDRNOTAVAIL: return "Address not available";
case EISCONN: return "Socket is connected";
case EFAULT: return "Bad address";
case EDESTADDRREQ: return "Destination address required";
case EHOSTUNREACH: return "Host is unreachable";
case EMSGSIZE: return "Message too long";
case ENETDOWN: return "Network is down";
case ENETRESET: return "Connection aborted by network";
case ENETUNREACH: return "Network is unreachable";
case ENOBUFS: return "No buffer space available";
case ENOMSG: return "No message of the desired type";
case ENOPROTOOPT: return "Protocol not available";
case ENOTCONN: return "Socket is not connected";
case EDEADLK: return "Resource deadlock avoided";
case ENFILE: return "Too many open files in system";
case EPROTOTYPE: return "Wrong protocol type for socket";
case ENOLCK: return "No locks available";
case ESIGPENDING: return "Signal is already pending";
case ESTALE: return "Stale file handle";
case EBADMSG: return "Bad message";
case ECANCELED: return "Operation canceled";
case EDQUOT: return "Disk quota exceeded";
case EIDRM: return "Identifier removed";
case EMULTIHOP: return "Multihop attempted";
case ENOLINK: return "Link has been severed";
case ENOTRECOVERABLE: return "State not recoverable";
case EOWNERDEAD: return "Previous owner died";
case EPROTO: return "Protocol error";
case ETXTBSY: return "Text file busy";
case ENOMOUNT: return "No such mountpoint";
case ENOMEDIUM: return "No medium found";
case EHOSTDOWN: return "Host is down";
case ESOCKTNOSUPPORT: return "Socket type is not supported";
default: return "Unknown error condition";
}
}
// TODO: After releasing Sortix 1.1, or after fixing ffmpeg, remove this symbol
// retained for compatibility. ffmpeg has a native sysroot issue where it
// accidentally taints it with the local system's headers instead of the
// sysroot headers, which accidentally pulls in an old removed symbol when
// bootstrapping on an old system.
weak_alias(strerror, sortix_strerror);

View file

@ -1,26 +0,0 @@
/*
* Copyright (c) 2013, 2024 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/strerror_l.c
* Convert error code to a string.
*/
#include <string.h>
char* strerror_l(int errnum, locale_t locale)
{
(void) locale;
return (char*) strerror(errnum);
}

View file

@ -1,32 +0,0 @@
/*
* Copyright (c) 2011, 2012, 2013, 2014, 2024 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/strerror_r.c
* Convert error code to a string.
*/
#include <errno.h>
#include <string.h>
int strerror_r(int errnum, char* dest, size_t dest_len)
{
const char* msg = strerror(errnum);
if ( !msg )
return -1;
if ( dest_len < strlen(msg) + 1 )
return errno = ERANGE;
strcpy(dest, msg);
return 0;
}

View file

@ -1,37 +0,0 @@
/*
* Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/strncasecmp.c
* Compares a prefix of two strings ignoring case.
*/
#include <string.h>
#include <ctype.h>
int strncasecmp(const char* a, const char* b, size_t max_count)
{
for ( size_t i = 0; i < max_count; i++ )
{
unsigned char ac = (unsigned char) tolower((unsigned char) a[i]);
unsigned char bc = (unsigned char) tolower((unsigned char) b[i]);
if ( ac == '\0' && bc == '\0' )
return 0;
if ( ac < bc )
return -1;
if ( ac > bc )
return 1;
}
return 0;
}

View file

@ -1,32 +0,0 @@
/*
* Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/strndup.c
* Creates a copy of a string.
*/
#include <stdlib.h>
#include <string.h>
char* strndup(const char* input, size_t n)
{
size_t input_size = strnlen(input, n);
char* result = (char*) malloc(input_size + 1);
if ( !result )
return NULL;
memcpy(result, input, input_size);
result[input_size] = 0;
return result;
}

View file

@ -1,62 +0,0 @@
/*
* Copyright (c) 2012, 2014, 2024 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/strsignal.c
* Convert signal number to a string.
*/
#include <signal.h>
#include <string.h>
char* strsignal(int signum)
{
switch ( signum )
{
case SIGHUP: return "Hangup";
case SIGINT: return "Interrupt";
case SIGQUIT: return "Quit";
case SIGILL: return "Invalid instruction";
case SIGTRAP: return "Trace/breakpoint trap";
case SIGABRT: return "Aborted";
case SIGBUS: return "Bus Error";
case SIGFPE: return "Floating point exception";
case SIGKILL: return "Killed";
case SIGUSR1: return "User defined signal 1";
case SIGSEGV: return "Segmentation fault";
case SIGUSR2: return "User defined signal 2";
case SIGPIPE: return "Broken pipe";
case SIGALRM: return "Alarm clock";
case SIGTERM: return "Terminated";
case SIGSYS: return "Bad system call";
case SIGCHLD: return "Child exited";
case SIGCONT: return "Continued";
case SIGSTOP: return "Stopped (signal)";
case SIGTSTP: return "Stopped";
case SIGTTIN: return "Stopped (tty input)";
case SIGTTOU: return "Stopped (tty output)";
case SIGURG: return "Urgent I/O condition";
case SIGXCPU: return "CPU time limit exceeded";
case SIGXFSZ: return "File size limit exceeded";
case SIGVTALRM: return "Virtual timer expired";
case SIGPWR: return "Power Fail/Restart";
case SIGWINCH: return "Window changed";
default: break;
}
if ( SIGRTMIN <= signum && signum <= SIGRTMAX )
return "Real-time signal";
return "Unknown signal value";
}

View file

@ -1,26 +0,0 @@
/*
* Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/strtok.c
* Extract tokens from strings.
*/
#include <string.h>
char* strtok(char* str, const char* delim)
{
static char* lasttokensaveptr = NULL;
return strtok_r(str, delim, &lasttokensaveptr);
}

View file

@ -1,116 +0,0 @@
/*
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/strverscmp.c
* Compares two version strings.
*/
#include <stdbool.h>
#include <string.h>
static bool is_number(char c)
{
return '0' <= c && c <= '9';
}
static int to_number(char c)
{
return c - '0';
}
int strverscmp(const char* a, const char* b)
{
for ( size_t i = 0; true; i++ )
{
// Be a regular strcmp if the strings are equal.
if ( a[i] == '\0' && b[i] == '\0' )
return 0;
if ( a[i] == b[i] )
continue;
// Be a regular strcmp if no digits are involed when they differ.
// Note: This implementation uses version number comparison if *either*
// of the first differing characters are digits, unlike glibc
// which is documented to require *both*. This behavior matches
// GNU sort -V and musl. It's also useful as "1.2.txt" compares
// before "1.2.3.txt".
bool version_string = is_number(a[i]) || is_number(b[i]);
if ( !version_string && a[i] < b[i] )
return -1;
if ( !version_string && a[i] > b[i] )
return 1;
// Because the number of leading zeroes matter, we have to find the
// entire numeric block we are currently within. We know the strings are
// equal until i, so we can simply find the number of shared digits by
// looking in the first string.
size_t digits_start = i;
while ( digits_start && is_number(a[digits_start-1]) )
digits_start--;
size_t shared_digits = i - digits_start;
// Find the number of shared leading zeroes.
size_t shared_zeroes = 0;
while ( shared_zeroes < shared_digits &&
to_number(a[digits_start + shared_zeroes]) == 0 )
shared_zeroes++;
// Try to expand the leading zeroes amount into a.
size_t a_zeroes = shared_zeroes;
while ( is_number(a[digits_start + a_zeroes]) == 0 )
a_zeroes++;
// Try to expand the leading zeroes amount into b.
size_t b_zeroes = shared_zeroes;
while ( is_number(b[digits_start + b_zeroes]) == 0 )
b_zeroes++;
// We treat strings with leading zeroes as if they have a decimal point
// in front of them, so strings with more zeroes sort lower.
if ( a_zeroes > b_zeroes )
return -1;
if ( b_zeroes > a_zeroes )
return 1;
// Find the number of consecutive digits in a where the strings differ.
size_t a_digits = a_zeroes;
while ( is_number(a[digits_start + a_digits]) )
a_digits++;
// Find the number of consecutive digits in b where the strings differ.
size_t b_digits = b_zeroes;
while ( is_number(b[digits_start + b_digits]) )
b_digits++;
// We know the strings have the same amount of leading zeroes, so we
// so if a a block is longer than the other, then the value must be
// longer as well.
if ( a_digits < b_digits )
return -1;
if ( b_digits < a_digits )
return 1;
// Finally run through the strings from where they differ and sort them
// numerically. We know this terminates because the strings differ. The
// strings have the same amount of digits, so comparing them is easy.
for ( size_t n = shared_zeroes; true; n++ )
{
if ( a[digits_start + n] < b[digits_start + n] )
return -1;
if ( b[digits_start + n] < a[digits_start + n] )
return 1;
}
}
}

View file

@ -1,26 +0,0 @@
/*
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* string/strxfrm_l.c
* Transform a string such that the result of strcmp is the same as strcoll_l.
*/
#include <string.h>
size_t strxfrm_l(char* dest, const char* src, size_t n, locale_t locale)
{
(void) locale;
return strxfrm(dest, src, n);
}

View file

@ -1,53 +0,0 @@
/* $OpenBSD: timingsafe_memcmp.c,v 1.1 2014/06/13 02:12:17 matthew Exp $ */
/*
* Copyright (c) 2014 Google Inc.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <limits.h>
#include <string.h>
// TODO: I don't fully trust that this code is _always_ timing safe in the
// presence of very smart compilers that can prove that this computes the
// same value as memcmp and could be short-circuited. We should invent and
// rely on compiler extensions that inform the compiler that sensitive
// information is involved, which forbids the compiler code generation
// from branching on the information (and such).
// TODO: We should add testcases that verify this is actually timing safe.
int timingsafe_memcmp(const void* a_ptr, const void* b_ptr, size_t size)
{
const unsigned char* a = (const unsigned char*) a_ptr;
const unsigned char* b = (const unsigned char*) b_ptr;
int result = 0;
int done = 0;
for ( size_t i = 0; i < size; i++ )
{
/* lt is -1 if a[i] < b[i]; else 0. */
int lt = (a[i] - b[i]) >> CHAR_BIT;
/* gt is -1 if a[i] > b[i]; else 0. */
int gt = (b[i] - a[i]) >> CHAR_BIT;
/* cmp is 1 if a[i] > b[i]; -1 if a[i] < b[i]; else 0. */
int cmp = lt - gt;
/* set result = cmp if !done. */
result |= cmp & ~done;
/* set done if a[i] != b[i]. */
done |= lt | gt;
}
return result;
}