feat: libc - add strndup, scandir, alphasort, usleep, ftruncate, M_PI constants

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018Ae69wJS7sueQMUwNxV3nX
This commit is contained in:
2026-08-07 21:26:25 +02:00
co-authored by Claude Opus 5
parent 53a9965e7c
commit fe10216f8b
7 changed files with 157 additions and 1 deletions
+130
View File
@@ -571,6 +571,18 @@ char *strdup(const char *s) {
return d;
}
char *strndup(const char *s, size_t n) {
size_t len = 0;
char *d;
if (s == NULL) return NULL;
while (len < n && s[len] != '\0') len++;
d = (char *)malloc(len + 1);
if (d == NULL) return NULL;
memcpy(d, s, len);
d[len] = '\0';
return d;
}
const char *strerror(int errnum) {
switch (errnum) {
case 0: return "success";
@@ -2047,6 +2059,49 @@ int write(int fd, const void *buf, size_t count) {
return ret;
}
/*
* ftruncate: EXTEND ONLY.
*
* The kernel has no truncate syscall, so growth is emulated by writing zeros
* at the tail. Shrinking cannot be emulated and fails with ENOSYS rather than
* silently reporting success -- a caller that believes a file shrank when it
* did not is worse off than one told it is unsupported.
*/
int ftruncate(int fd, long length) {
unsigned long size;
static const unsigned char zeros[512] = { 0 };
if (fd < 0 || length < 0) {
errno = EINVAL;
return -1;
}
size = (unsigned long)_zos_syscall1(SYS_GETSIZE, (long)fd);
if ((unsigned long)length == size)
return 0;
if ((unsigned long)length < size) {
errno = ENOSYS; /* no kernel truncate; cannot shrink */
return -1;
}
while (size < (unsigned long)length) {
unsigned long chunk = (unsigned long)length - size;
int written;
if (chunk > sizeof(zeros)) chunk = sizeof(zeros);
written = (int)_zos_syscall4(SYS_FWRITE, (long)fd, (long)zeros,
(long)size, (long)chunk);
if (written <= 0) {
errno = EIO;
return -1;
}
size += (unsigned long)written;
}
return 0;
}
/*
* Positioned I/O. SYS_READ/SYS_FWRITE already take an explicit file position,
* so these pass the caller's offset straight through and never consult or
@@ -2273,6 +2328,68 @@ struct dirent *readdir(DIR *dirp) {
return &dirp->entry;
}
/*
* scandir/alphasort, built on opendir/readdir. The array and every entry are
* malloc'd; the caller frees each entry then the array, as POSIX requires.
*/
int alphasort(const struct dirent **a, const struct dirent **b) {
return strcmp((*a)->d_name, (*b)->d_name);
}
int scandir(const char *dirp, struct dirent ***namelist,
int (*filter)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **)) {
DIR *d;
struct dirent *ent;
struct dirent **list = NULL;
size_t count = 0, cap = 0;
if (dirp == NULL || namelist == NULL) {
errno = EINVAL;
return -1;
}
d = opendir(dirp);
if (d == NULL) return -1;
while ((ent = readdir(d)) != NULL) {
struct dirent *copy;
if (filter != NULL && filter(ent) == 0) continue;
if (count == cap) {
size_t newcap = (cap == 0) ? 16 : cap * 2;
struct dirent **grown =
(struct dirent **)realloc(list, newcap * sizeof(*list));
if (grown == NULL) goto nomem;
list = grown;
cap = newcap;
}
copy = (struct dirent *)malloc(sizeof(*copy));
if (copy == NULL) goto nomem;
*copy = *ent;
list[count++] = copy;
}
closedir(d);
if (compar != NULL && count > 1) {
qsort(list, count, sizeof(*list),
(int (*)(const void *, const void *))compar);
}
*namelist = list;
return (int)count;
nomem:
while (count > 0) free(list[--count]);
free(list);
closedir(d);
errno = ENOMEM;
return -1;
}
int closedir(DIR *dirp) {
if (dirp == NULL) {
errno = EINVAL;
@@ -3037,6 +3154,19 @@ unsigned int sleep(unsigned int seconds) {
return 0;
}
/*
* Sub-second sleeps. The kernel only offers millisecond granularity, so
* anything finer rounds UP to 1ms rather than to zero -- a caller asking for a
* short delay wants to yield, not to spin.
*/
int usleep(unsigned long usec) {
unsigned long ms = usec / 1000UL;
if (ms == 0 && usec != 0)
ms = 1;
_zos_syscall1(SYS_SLEEP_MS, (long)ms);
return 0;
}
/* ========================================================================
math.h: modf and C99 float variants (wrappers over the double
implementations; assumed present by hosted libstdc++)