From f4944a2d6d73af36ebacb0c057f2d842d66e8e8e Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Sun, 19 Apr 2026 14:38:54 -0300 Subject: [PATCH] Fix getcwd: return char* (POSIX) instead of int ulibc getcwd() returned int (0 on success, -1 on error) but POSIX specifies char* (buf on success, NULL on error). Bash and other ported software call getcwd expecting a pointer return; getting 0 (NULL) on success caused: shell-init: error retrieving current directory: getcwd: cannot access parent directories: Bad address The kernel syscall already returns 0 on success, so the fix is in the ulibc wrapper: return buf on success, NULL on error (setting errno). This matches the newlib wrapper in posix_stubs.c which had the correct signature all along. Updated all internal callers (sh, pwd, realpath) from int-style checks (>= 0 / < 0) to pointer-style checks (truthy / !ptr). --- user/cmds/pwd/pwd.c | 2 +- user/cmds/sh/sh.c | 6 +++--- user/ulibc/include/unistd.h | 2 +- user/ulibc/src/stdlib.c | 2 +- user/ulibc/src/unistd.c | 6 ++++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/user/cmds/pwd/pwd.c b/user/cmds/pwd/pwd.c index 5c5395bb..fc21ff7e 100644 --- a/user/cmds/pwd/pwd.c +++ b/user/cmds/pwd/pwd.c @@ -13,7 +13,7 @@ int main(void) { char buf[256]; - if (getcwd(buf, sizeof(buf)) >= 0) + if (getcwd(buf, sizeof(buf))) printf("%s\n", buf); else { fprintf(stderr, "pwd: error\n"); diff --git a/user/cmds/sh/sh.c b/user/cmds/sh/sh.c index 30817262..c7443e3e 100644 --- a/user/cmds/sh/sh.c +++ b/user/cmds/sh/sh.c @@ -656,7 +656,7 @@ static void run_simple(char* cmd) { fprintf(stderr, "cd: %s: No such file or directory\n", dir); else { char cwd[256]; - if (getcwd(cwd, sizeof(cwd)) >= 0) + if (getcwd(cwd, sizeof(cwd))) var_set("PWD", cwd, 1); } goto restore_redir; @@ -664,7 +664,7 @@ static void run_simple(char* cmd) { if (strcmp(argv[0], "pwd") == 0) { char cwd[256]; - if (getcwd(cwd, sizeof(cwd)) >= 0) + if (getcwd(cwd, sizeof(cwd))) printf("%s\n", cwd); else fprintf(stderr, "pwd: error\n"); @@ -979,7 +979,7 @@ static void print_prompt(void) { if (!user) user = "root"; if (!host) host = "adros"; - if (getcwd(cwd, sizeof(cwd)) < 0) strcpy(cwd, "?"); + if (!getcwd(cwd, sizeof(cwd))) strcpy(cwd, "?"); printf("%s@%s:%s$ ", user, host, cwd); fflush(stdout); diff --git a/user/ulibc/include/unistd.h b/user/ulibc/include/unistd.h index 31244d0d..3ca39ff1 100644 --- a/user/ulibc/include/unistd.h +++ b/user/ulibc/include/unistd.h @@ -34,7 +34,7 @@ int execve(const char* path, char* const argv[], char* const envp[]); int getpid(void); int getppid(void); int chdir(const char* path); -int getcwd(char* buf, size_t size); +char* getcwd(char* buf, size_t size); int mkdir(const char* path, ...); /* mode_t optional in AdrOS */ int unlink(const char* path); int rmdir(const char* path); diff --git a/user/ulibc/src/stdlib.c b/user/ulibc/src/stdlib.c index 56f49655..2c9b4a8e 100644 --- a/user/ulibc/src/stdlib.c +++ b/user/ulibc/src/stdlib.c @@ -176,7 +176,7 @@ char* realpath(const char* path, char* resolved) { int tpos = 0; if (path[0] != '/') { - if (getcwd(tmp, sizeof(tmp)) < 0) return (void*)0; + if (!getcwd(tmp, sizeof(tmp))) return (void*)0; tpos = (int)strlen(tmp); if (tpos > 0 && tmp[tpos - 1] != '/') tmp[tpos++] = '/'; } diff --git a/user/ulibc/src/unistd.c b/user/ulibc/src/unistd.c index 3f7d9194..34c6ac94 100644 --- a/user/ulibc/src/unistd.c +++ b/user/ulibc/src/unistd.c @@ -69,8 +69,10 @@ int chdir(const char* path) { return __syscall_ret(_syscall1(SYS_CHDIR, (int)path)); } -int getcwd(char* buf, size_t size) { - return __syscall_ret(_syscall2(SYS_GETCWD, (int)buf, (int)size)); +char* getcwd(char* buf, size_t size) { + int r = _syscall2(SYS_GETCWD, (int)buf, (int)size); + if (r < 0) { errno = -r; return NULL; } + return buf; } int mkdir(const char* path, ...) { -- 2.43.0