diff --git a/Userspace/libc/abis/fennix/generic/bits/socket.h b/Userspace/libc/abis/fennix/generic/bits/socket.h
index 017dfa38..33b966bb 100644
--- a/Userspace/libc/abis/fennix/generic/bits/socket.h
+++ b/Userspace/libc/abis/fennix/generic/bits/socket.h
@@ -31,4 +31,8 @@ struct sockaddr
char sa_data[14];
};
+#ifdef _GNU_SOURCE
+#define SO_PEERCRED 0x1029
+#endif
+
#endif // _BITS_SOCKET_H
diff --git a/Userspace/libc/abis/fennix/generic/bits/syscalls.h b/Userspace/libc/abis/fennix/generic/bits/syscalls.h
index 1d75bd71..a80a58c4 100644
--- a/Userspace/libc/abis/fennix/generic/bits/syscalls.h
+++ b/Userspace/libc/abis/fennix/generic/bits/syscalls.h
@@ -1807,7 +1807,7 @@ typedef enum
/* Time */
/** @copydoc SYS_TIME */
-#define call_time(t) syscall1(SYS_TIME, t)
+#define call_time(t) syscall1(SYS_TIME, (scarg)t)
/** @copydoc SYS_CLOCK_GETTIME */
#define call_clock_gettime(clockid, tp) syscall2(SYS_CLOCK_GETTIME, (scarg)clockid, (scarg)tp)
diff --git a/Userspace/libc/include/bits/libc.h b/Userspace/libc/include/bits/libc.h
index 4c0d0bd2..219b1d29 100644
--- a/Userspace/libc/include/bits/libc.h
+++ b/Userspace/libc/include/bits/libc.h
@@ -70,5 +70,10 @@ int sysdep(ChangeDirectory)(const char *Pathname);
char *sysdep(GetWorkingDirectory)(char *Buffer, size_t Size);
int sysdep(Brk)(void *Address);
int sysdep(FileControl)(int Descriptor, int Command, void *Arg);
+int sysdep(ClockGetTime)(clockid_t ClockID, struct timespec *TP);
+time_t sysdep(Time)(void);
+clock_t sysdep(Clock)(void);
+int sysdep(RemoveDirectory)(const char *Pathname);
+int sysdep(Unlink)(const char *Pathname);
#endif // FENNIX_BITS_LIBC_H
diff --git a/Userspace/libc/include/iconv.h b/Userspace/libc/include/iconv.h
new file mode 100644
index 00000000..55e06c45
--- /dev/null
+++ b/Userspace/libc/include/iconv.h
@@ -0,0 +1,29 @@
+/*
+ This file is part of Fennix C Library.
+
+ Fennix C Library is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix C Library. If not, see .
+*/
+
+#ifndef _ICONV_H
+#define _ICONV_H
+
+#include
+
+typedef void *iconv_t;
+
+iconv_t iconv_open(const char *tocode, const char *fromcode);
+size_t iconv(iconv_t cd, char **restrict inbuf, size_t *restrict inbytesleft, char **restrict outbuf, size_t *restrict outbytesleft);
+int iconv_close(iconv_t cd);
+
+#endif // _ICONV_H
diff --git a/Userspace/libc/include/stddef.h b/Userspace/libc/include/stddef.h
index 70c953c8..75fcf593 100644
--- a/Userspace/libc/include/stddef.h
+++ b/Userspace/libc/include/stddef.h
@@ -27,6 +27,8 @@ extern "C"
#define NULL ((void *)0)
#endif
+#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
+
typedef struct
{
long long __a;
diff --git a/Userspace/libc/include/stdio.h b/Userspace/libc/include/stdio.h
index de19ab42..f82199f8 100644
--- a/Userspace/libc/include/stdio.h
+++ b/Userspace/libc/include/stdio.h
@@ -106,7 +106,7 @@ extern "C"
int fputs(const char *restrict s, FILE *restrict stream);
size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
FILE *freopen(const char *restrict, const char *restrict, FILE *restrict);
- int fscanf(FILE *restrict, const char *restrict, ...);
+ int fscanf(FILE *restrict stream, const char *restrict format, ...);
int fseek(FILE *stream, long offset, int whence);
int fseeko(FILE *, off_t, int);
int fsetpos(FILE *, const fpos_t *);
@@ -131,16 +131,16 @@ extern "C"
int putc_unlocked(int c, FILE *stream);
int putchar_unlocked(int c);
int puts(const char *s);
- int remove(const char *);
+ int remove(const char *path);
int rename(const char *, const char *);
int renameat(int, const char *, int, const char *);
void rewind(FILE *);
- int scanf(const char *restrict, ...);
+ int scanf(const char *restrict format, ...);
void setbuf(FILE *restrict, char *restrict);
int setvbuf(FILE *restrict, char *restrict, int, size_t);
int snprintf(char *restrict s, size_t n, const char *restrict format, ...);
int sprintf(char *restrict s, const char *restrict format, ...);
- int sscanf(const char *restrict, const char *restrict, ...);
+ int sscanf(const char *restrict s, const char *restrict format, ...);
FILE *tmpfile(void);
char *tmpnam(char *);
int ungetc(int, FILE *);
@@ -149,7 +149,7 @@ extern "C"
int vfscanf(FILE *restrict, const char *restrict, va_list);
int vprintf(const char *restrict, va_list);
int vscanf(const char *restrict, va_list);
- int vsnprintf(char *restrict, size_t, const char *restrict, va_list);
+ int vsnprintf(char *restrict s, size_t n, const char *restrict format, va_list ap);
int vsprintf(char *restrict, const char *restrict, va_list);
int vsscanf(const char *restrict, const char *restrict, va_list);
diff --git a/Userspace/libc/include/stdlib.h b/Userspace/libc/include/stdlib.h
index fb156d9f..f383de9d 100644
--- a/Userspace/libc/include/stdlib.h
+++ b/Userspace/libc/include/stdlib.h
@@ -102,7 +102,8 @@ extern "C"
double strtod(const char *, char **);
long strtol(const char *restrict nptr, char **restrict endptr, int base);
long long strtoll(const char *restrict nptr, char **restrict endptr, int base);
- unsigned long int strtoul(const char *, char **, int);
+ unsigned long int strtoul(const char *restrict str, char **restrict endptr, int base);
+ unsigned long long strtoull(const char *restrict str, char **restrict endptr, int base);
int system(const char *command);
int ttyslot(void);
int unlockpt(int);
diff --git a/Userspace/libc/include/sys/select.h b/Userspace/libc/include/sys/select.h
new file mode 100644
index 00000000..5461b957
--- /dev/null
+++ b/Userspace/libc/include/sys/select.h
@@ -0,0 +1,41 @@
+/*
+ This file is part of Fennix C Library.
+
+ Fennix C Library is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix C Library. If not, see .
+*/
+
+#ifndef _SYS_SELECT_H
+#define _SYS_SELECT_H
+
+#include
+#include
+#include
+#include
+
+#define FD_SETSIZE 1024
+
+typedef struct
+{
+ unsigned long fds_bits[(FD_SETSIZE + (8 * sizeof(unsigned long) - 1)) / (8 * sizeof(unsigned long))];
+} fd_set;
+
+#define FD_CLR(fd, fdset) ((fdset)->fds_bits[(fd) / (8 * sizeof(unsigned long))] &= ~(1UL << ((fd) % (8 * sizeof(unsigned long)))))
+#define FD_ISSET(fd, fdset) (((fdset)->fds_bits[(fd) / (8 * sizeof(unsigned long))] & (1UL << ((fd) % (8 * sizeof(unsigned long))))) != 0)
+#define FD_SET(fd, fdset) ((fdset)->fds_bits[(fd) / (8 * sizeof(unsigned long))] |= (1UL << ((fd) % (8 * sizeof(unsigned long)))))
+#define FD_ZERO(fdset) (memset((fdset), 0, sizeof(fd_set)))
+
+int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds, struct timeval *restrict timeout);
+int pselect(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds, const struct timespec *restrict timeout, const sigset_t *restrict sigmask);
+
+#endif // _SYS_SELECT_H
diff --git a/Userspace/libc/include/sys/time.h b/Userspace/libc/include/sys/time.h
new file mode 100644
index 00000000..91d2b4ce
--- /dev/null
+++ b/Userspace/libc/include/sys/time.h
@@ -0,0 +1,51 @@
+/*
+ This file is part of Fennix C Library.
+
+ Fennix C Library is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix C Library. If not, see .
+*/
+
+#ifndef _SYS_TIME_H
+#define _SYS_TIME_H
+
+#include
+#include
+#include
+
+typedef long time_t;
+typedef long suseconds_t;
+
+struct timeval
+{
+ time_t tv_sec; /* Seconds */
+ suseconds_t tv_usec; /* Microseconds */
+};
+
+struct itimerval
+{
+ struct timeval it_interval; /* Timer interval */
+ struct timeval it_value; /* Current value */
+};
+
+/* Values for the which argument of getitimer() and setitimer() */
+#define ITIMER_REAL 0
+#define ITIMER_VIRTUAL 1
+#define ITIMER_PROF 2
+
+int getitimer(int which, struct itimerval *value);
+int gettimeofday(struct timeval *restrict tp, void *restrict tzp);
+// int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds, struct timeval *restrict timeout);
+int setitimer(int which, const struct itimerval *restrict new_value, struct itimerval *restrict old_value);
+int utimes(const char *filename, const struct timeval times[2]);
+
+#endif // _SYS_TIME_H
diff --git a/Userspace/libc/include/sys/un.h b/Userspace/libc/include/sys/un.h
new file mode 100644
index 00000000..6bc1d4b9
--- /dev/null
+++ b/Userspace/libc/include/sys/un.h
@@ -0,0 +1,31 @@
+/*
+ This file is part of Fennix C Library.
+
+ Fennix C Library is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix C Library. If not, see .
+*/
+
+#ifndef _SYS_UN_H
+#define _SYS_UN_H
+
+#include
+
+#define SUN_PATH_SIZE 108
+
+struct sockaddr_un
+{
+ sa_family_t sun_family; /* Address family */
+ char sun_path[SUN_PATH_SIZE]; /* Socket pathname storage */
+};
+
+#endif // _SYS_UN_H
diff --git a/Userspace/libc/include/time.h b/Userspace/libc/include/time.h
index 00dc6d0d..4974bd2f 100644
--- a/Userspace/libc/include/time.h
+++ b/Userspace/libc/include/time.h
@@ -49,7 +49,7 @@ extern "C"
struct timespec it_value; /* Timer expiration. */
} itimerspec;
-#define CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000000
#define TIME_UTC
#define CLOCK_MONOTONIC __SYS_CLOCK_MONOTONIC
#define CLOCK_PROCESS_CPUTIME_ID __SYS_CLOCK_PROCESS_CPUTIME_ID
@@ -64,10 +64,10 @@ extern "C"
char *asctime(const struct tm *);
clock_t clock(void);
int clock_getcpuclockid(pid_t, clockid_t *);
- int clock_getres(clockid_t, struct timespec *);
- int clock_gettime(clockid_t, struct timespec *);
+ int clock_getres(clockid_t clock_id, struct timespec *res);
+ int clock_gettime(clockid_t clock_id, struct timespec *tp);
int clock_nanosleep(clockid_t, int, const struct timespec *, struct timespec *);
- int clock_settime(clockid_t, const struct timespec *);
+ int clock_settime(clockid_t clock_id, const struct timespec *tp);
char *ctime(const time_t *);
double difftime(time_t, time_t);
struct tm *getdate(const char *);
@@ -81,7 +81,7 @@ extern "C"
size_t strftime(char *restrict, size_t, const char *restrict, const struct tm *restrict);
size_t strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, locale_t);
char *strptime(const char *restrict, const char *restrict, struct tm *restrict);
- time_t time(time_t *);
+ time_t time(time_t *tloc);
int timer_create(clockid_t, struct sigevent *restrict, timer_t *restrict);
int timer_delete(timer_t);
int timer_getoverrun(timer_t);
diff --git a/Userspace/libc/include/unistd.h b/Userspace/libc/include/unistd.h
index 0ce82788..8ee77c8d 100644
--- a/Userspace/libc/include/unistd.h
+++ b/Userspace/libc/include/unistd.h
@@ -121,7 +121,7 @@ extern "C"
ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset);
ssize_t read(int fildes, void *buf, size_t nbyte);
int readlink(const char *, char *, size_t);
- int rmdir(const char *);
+ int rmdir(const char *path);
void *sbrk(intptr_t incr);
int setgid(gid_t);
int setpgid(pid_t, pid_t);
@@ -141,7 +141,7 @@ extern "C"
char *ttyname(int);
int ttyname_r(int, char *, size_t);
useconds_t ualarm(useconds_t, useconds_t);
- int unlink(const char *);
+ int unlink(const char *path);
int usleep(useconds_t);
pid_t vfork(void);
ssize_t write(int fildes, const void *buf, size_t nbyte);
diff --git a/Userspace/libc/libs/CMakeLists.txt b/Userspace/libc/libs/CMakeLists.txt
index fa561e76..df329a43 100644
--- a/Userspace/libc/libs/CMakeLists.txt
+++ b/Userspace/libc/libs/CMakeLists.txt
@@ -2,4 +2,6 @@ cmake_minimum_required(VERSION 3.10)
project(FennixStandardLibraries)
add_subdirectory(libm)
+add_subdirectory(librt)
+add_subdirectory(libpthread)
add_subdirectory(libstdc++)
diff --git a/Userspace/libc/libs/libpthread/CMakeLists.txt b/Userspace/libc/libs/libpthread/CMakeLists.txt
new file mode 100644
index 00000000..b9385d74
--- /dev/null
+++ b/Userspace/libc/libs/libpthread/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 3.10)
+project(FennixRealTimeLibrary)
+
+set(SOURCES libpthread.c)
+
+add_library(pthread STATIC ${SOURCES})
+add_library(pthread_shared SHARED ${SOURCES})
+
+target_link_options(pthread_shared PRIVATE -nostdlib)
+set_target_properties(pthread_shared PROPERTIES OUTPUT_NAME "pthread")
+
+install(TARGETS pthread pthread_shared
+ ARCHIVE DESTINATION lib
+ LIBRARY DESTINATION lib
+ PUBLIC_HEADER DESTINATION include)
diff --git a/Userspace/libc/libs/libpthread/libpthread.c b/Userspace/libc/libs/libpthread/libpthread.c
new file mode 100644
index 00000000..183ad690
--- /dev/null
+++ b/Userspace/libc/libs/libpthread/libpthread.c
@@ -0,0 +1,18 @@
+/*
+ This file is part of Fennix Userspace.
+
+ Fennix Userspace is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Userspace is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Userspace. If not, see .
+*/
+
+/* dummy file */
diff --git a/Userspace/libc/libs/librt/CMakeLists.txt b/Userspace/libc/libs/librt/CMakeLists.txt
new file mode 100644
index 00000000..06b8f9d1
--- /dev/null
+++ b/Userspace/libc/libs/librt/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 3.10)
+project(FennixRealTimeLibrary)
+
+set(SOURCES librt.c)
+
+add_library(rt STATIC ${SOURCES})
+add_library(rt_shared SHARED ${SOURCES})
+
+target_link_options(rt_shared PRIVATE -nostdlib)
+set_target_properties(rt_shared PROPERTIES OUTPUT_NAME "rt")
+
+install(TARGETS rt rt_shared
+ ARCHIVE DESTINATION lib
+ LIBRARY DESTINATION lib
+ PUBLIC_HEADER DESTINATION include)
diff --git a/Userspace/libc/libs/librt/librt.c b/Userspace/libc/libs/librt/librt.c
new file mode 100644
index 00000000..183ad690
--- /dev/null
+++ b/Userspace/libc/libs/librt/librt.c
@@ -0,0 +1,18 @@
+/*
+ This file is part of Fennix Userspace.
+
+ Fennix Userspace is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Userspace is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Userspace. If not, see .
+*/
+
+/* dummy file */
diff --git a/Userspace/libc/src/std/stdio.c b/Userspace/libc/src/std/stdio.c
index f1edb812..68738eb1 100644
--- a/Userspace/libc/src/std/stdio.c
+++ b/Userspace/libc/src/std/stdio.c
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
#include
#include
#include "../print/printf.h"
@@ -466,7 +467,24 @@ export int puts(const char *s)
return 0;
}
-export int remove(const char *);
+export int remove(const char *path)
+{
+ if (!path)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ struct stat path_stat;
+ if (sysdep(Stat)(path, &path_stat) < 0)
+ return -1;
+
+ if (S_ISDIR(path_stat.st_mode))
+ return sysdep(RemoveDirectory)(path);
+ else
+ return sysdep(Unlink)(path);
+}
+
export int rename(const char *, const char *);
export int renameat(int, const char *, int, const char *);
export void rewind(FILE *);
@@ -492,7 +510,117 @@ export int sprintf(char *restrict s, const char *restrict format, ...)
return ret;
}
-export int sscanf(const char *restrict, const char *restrict, ...);
+export int sscanf(const char *restrict s, const char *restrict format, ...)
+{
+ va_list args;
+ va_start(args, format);
+
+ const char *p = format;
+ int matchedItems = 0;
+
+ while (*p)
+ {
+ if (isspace(*p))
+ {
+ while (isspace(*p))
+ p++;
+ while (isspace(*s))
+ s++;
+ }
+ else if (*p == '%')
+ {
+ p++;
+ if (*p == '\0')
+ break;
+
+ int suppress_assignment = 0;
+ if (*p == '*')
+ {
+ suppress_assignment = 1;
+ p++;
+ }
+
+ int width = 0;
+ while (isdigit(*p))
+ {
+ width = width * 10 + (*p - '0');
+ p++;
+ }
+
+ char specifier = *p++;
+ if (specifier == '\0')
+ break;
+
+ if (specifier == 'd' || specifier == 'i')
+ {
+ int value = 0;
+ while (isdigit(*s) || (*s == '-' && value == 0))
+ {
+ if (*s == '-')
+ {
+ s++;
+ continue;
+ }
+ value = value * 10 + (*s - '0');
+ s++;
+ }
+ if (!suppress_assignment)
+ {
+ int *arg = va_arg(args, int *);
+ *arg = value;
+ matchedItems++;
+ }
+ }
+ else if (specifier == 's')
+ {
+ char *str = va_arg(args, char *);
+ while (*s && !isspace(*s) && (width == 0 || width-- > 0))
+ {
+ if (!suppress_assignment)
+ *str++ = *s;
+ s++;
+ }
+ if (!suppress_assignment)
+ *str = '\0';
+ matchedItems++;
+ }
+ else if (specifier == 'c')
+ {
+ char *ch = va_arg(args, char *);
+ if (*s && (width == 0 || width-- > 0))
+ {
+ if (!suppress_assignment)
+ *ch = *s;
+ s++;
+ matchedItems++;
+ }
+ }
+ else if (specifier == '%')
+ {
+ if (*s == '%')
+ s++;
+ else
+ break;
+ }
+ else
+ break;
+ }
+ else
+ {
+ if (*s == *p)
+ {
+ s++;
+ p++;
+ }
+ else
+ break;
+ }
+ }
+
+ va_end(args);
+ return matchedItems;
+}
+
export FILE *tmpfile(void);
export char *tmpnam(char *);
export int ungetc(int, FILE *);
@@ -526,6 +654,14 @@ export int vfprintf(FILE *restrict stream, const char *restrict format, va_list
export int vfscanf(FILE *restrict, const char *restrict, va_list);
export int vprintf(const char *restrict, va_list);
export int vscanf(const char *restrict, va_list);
-export int vsnprintf(char *restrict, size_t, const char *restrict, va_list);
+
+export int vsnprintf(char *restrict s, size_t n, const char *restrict format, va_list ap)
+{
+ int ret = vsnprintf_(s, n, format, ap);
+ if (ret < 0)
+ return ret;
+ return ret;
+}
+
export int vsprintf(char *restrict, const char *restrict, va_list);
export int vsscanf(const char *restrict, const char *restrict, va_list);
diff --git a/Userspace/libc/src/std/stdlib.c b/Userspace/libc/src/std/stdlib.c
index 6ca365ea..3d7704a6 100644
--- a/Userspace/libc/src/std/stdlib.c
+++ b/Userspace/libc/src/std/stdlib.c
@@ -334,7 +334,161 @@ export long long strtoll(const char *restrict nptr, char **restrict endptr, int
return acc;
}
-export unsigned long int strtoul(const char *, char **, int);
+export unsigned long int strtoul(const char *restrict str, char **restrict endptr, int base)
+{
+ const char *s = str;
+ unsigned long acc = 0;
+ int c;
+ unsigned long cutoff;
+ int any, cutlim;
+
+ if (base < 0 || base == 1 || base > 36)
+ {
+ errno = EINVAL;
+ if (endptr)
+ *endptr = (char *)str;
+ return 0;
+ }
+
+ while (isspace((unsigned char)*s))
+ s++;
+
+ if (*s == '+')
+ s++;
+ else if (*s == '-')
+ {
+ errno = EINVAL;
+ if (endptr)
+ *endptr = (char *)str;
+ return 0;
+ }
+
+ if ((base == 0 || base == 16) && *s == '0' && (s[1] == 'x' || s[1] == 'X'))
+ {
+ s += 2;
+ base = 16;
+ }
+ else if (base == 0)
+ base = *s == '0' ? 8 : 10;
+
+ cutoff = ULONG_MAX / base;
+ cutlim = ULONG_MAX % base;
+
+ for (acc = 0, any = 0;; c = *s++)
+ {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+
+ if (c >= base)
+ break;
+
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else
+ {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+
+ if (any < 0)
+ {
+ acc = ULONG_MAX;
+ errno = ERANGE;
+ }
+ else if (any == 0)
+ {
+ errno = EINVAL;
+ }
+
+ if (endptr)
+ *endptr = (char *)(any ? s - 1 : str);
+
+ return acc;
+}
+
+export unsigned long long strtoull(const char *restrict str, char **restrict endptr, int base)
+{
+ const char *s = str;
+ unsigned long long acc = 0;
+ int c;
+ unsigned long long cutoff;
+ int any, cutlim;
+
+ if (base < 0 || base == 1 || base > 36)
+ {
+ errno = EINVAL;
+ if (endptr)
+ *endptr = (char *)str;
+ return 0;
+ }
+
+ while (isspace((unsigned char)*s))
+ s++;
+
+ if (*s == '+')
+ s++;
+ else if (*s == '-')
+ {
+ errno = EINVAL;
+ if (endptr)
+ *endptr = (char *)str;
+ return 0;
+ }
+
+ if ((base == 0 || base == 16) && *s == '0' && (s[1] == 'x' || s[1] == 'X'))
+ {
+ s += 2;
+ base = 16;
+ }
+ else if (base == 0)
+ base = *s == '0' ? 8 : 10;
+
+ cutoff = ULLONG_MAX / base;
+ cutlim = ULLONG_MAX % base;
+
+ for (acc = 0, any = 0;; c = *s++)
+ {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+
+ if (c >= base)
+ break;
+
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else
+ {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+
+ if (any < 0)
+ {
+ acc = ULLONG_MAX;
+ errno = ERANGE;
+ }
+ else if (any == 0)
+ {
+ errno = EINVAL;
+ }
+
+ if (endptr)
+ *endptr = (char *)(any ? s - 1 : str);
+
+ return acc;
+}
export int system(const char *command)
{
diff --git a/Userspace/libc/src/std/time.c b/Userspace/libc/src/std/time.c
index 88abd75f..e4a9cfcb 100644
--- a/Userspace/libc/src/std/time.c
+++ b/Userspace/libc/src/std/time.c
@@ -30,12 +30,29 @@ export long timezone;
export char *tzname[2];
export char *asctime(const struct tm *);
-export clock_t clock(void);
+
+export clock_t clock(void)
+{
+ clock_t processor_time = sysdep(Clock)();
+ if (processor_time == (clock_t)-1)
+ {
+ errno = EOVERFLOW;
+ return (clock_t)-1;
+ }
+ return processor_time;
+}
+
export int clock_getcpuclockid(pid_t, clockid_t *);
-export int clock_getres(clockid_t, struct timespec *);
-export int clock_gettime(clockid_t, struct timespec *);
+export int clock_getres(clockid_t clock_id, struct timespec *res);
+
+export int clock_gettime(clockid_t clock_id, struct timespec *tp)
+{
+ return sysdep(ClockGetTime)(clock_id, tp);
+}
+
export int clock_nanosleep(clockid_t, int, const struct timespec *, struct timespec *);
-export int clock_settime(clockid_t, const struct timespec *);
+export int clock_settime(clockid_t clock_id, const struct timespec *tp);
+;
export char *ctime(const time_t *);
export double difftime(time_t, time_t);
export struct tm *getdate(const char *);
@@ -193,7 +210,20 @@ export int nanosleep(const struct timespec *, struct timespec *);
export size_t strftime(char *restrict, size_t, const char *restrict, const struct tm *restrict);
export size_t strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, locale_t);
export char *strptime(const char *restrict, const char *restrict, struct tm *restrict);
-export time_t time(time_t *);
+
+export time_t time(time_t *tloc)
+{
+ time_t current_time = sysdep(Time)();
+ if (current_time == (time_t)-1)
+ {
+ errno = EOVERFLOW;
+ return (time_t)-1;
+ }
+ if (tloc)
+ *tloc = current_time;
+ return current_time;
+}
+
export int timer_create(clockid_t, struct sigevent *restrict, timer_t *restrict);
export int timer_delete(timer_t);
export int timer_getoverrun(timer_t);
diff --git a/Userspace/libc/src/std/unistd.c b/Userspace/libc/src/std/unistd.c
index a7682d43..0fed008b 100644
--- a/Userspace/libc/src/std/unistd.c
+++ b/Userspace/libc/src/std/unistd.c
@@ -293,7 +293,12 @@ export ssize_t read(int fildes, void *buf, size_t nbyte)
}
export int readlink(const char *, char *, size_t);
-export int rmdir(const char *);
+
+export int rmdir(const char *path)
+{
+ return __check_errno(sysdep(RemoveDirectory)(path), -1);
+}
+
export void *sbrk(intptr_t incr);
export int setgid(gid_t);
export int setpgid(pid_t, pid_t);
@@ -334,7 +339,12 @@ export int truncate(const char *, off_t);
export char *ttyname(int);
export int ttyname_r(int, char *, size_t);
export useconds_t ualarm(useconds_t, useconds_t);
-export int unlink(const char *);
+
+export int unlink(const char *path)
+{
+ return __check_errno(sysdep(Unlink)(path), -1);
+}
+
export int usleep(useconds_t);
export pid_t vfork(void);
diff --git a/Userspace/libc/sysdeps/fennix/generic/syscalls.c b/Userspace/libc/sysdeps/fennix/generic/syscalls.c
index 6d57d26a..b57d4018 100644
--- a/Userspace/libc/sysdeps/fennix/generic/syscalls.c
+++ b/Userspace/libc/sysdeps/fennix/generic/syscalls.c
@@ -19,6 +19,8 @@
#include
#include
+extern int printf(const char *restrict format, ...);
+
void sysdep(Exit)(int Status)
{
call_exit(Status);
@@ -209,3 +211,29 @@ int sysdep(FileControl)(int Descriptor, int Command, void *Arg)
{
return call_fcntl(Descriptor, Command, Arg);
}
+
+int sysdep(ClockGetTime)(clockid_t ClockID, struct timespec *TP)
+{
+ return call_clock_gettime(ClockID, TP);
+}
+
+time_t sysdep(Time)(void)
+{
+ return call_time(NULL);
+}
+
+clock_t sysdep(Clock)()
+{
+ printf("sysdep(Clock): unimplemented\n");
+ return 0;
+}
+
+int sysdep(RemoveDirectory)(const char *Pathname)
+{
+ return call_rmdir(Pathname);
+}
+
+int sysdep(Unlink)(const char *Pathname)
+{
+ return call_unlink(Pathname);
+}