diff --git a/src/unistd/getcwd.c b/src/unistd/getcwd.c index 103fbbb5..306dbc4f 100644 --- a/src/unistd/getcwd.c +++ b/src/unistd/getcwd.c @@ -3,17 +3,10 @@ #include #include #include "syscall.h" +#include "libc.h" -char *getcwd(char *buf, size_t size) +static char *do_getcwd(char *buf, size_t size) { - char tmp[PATH_MAX]; - if (!buf) { - buf = tmp; - size = PATH_MAX; - } else if (!size) { - errno = EINVAL; - return 0; - } long ret = syscall(SYS_getcwd, buf, size); if (ret < 0) return 0; @@ -21,5 +14,37 @@ char *getcwd(char *buf, size_t size) errno = ENOENT; return 0; } - return buf == tmp ? strdup(buf) : buf; + return buf; +} + +static char *getcwd_glibc(size_t size) +{ + char tmp[PATH_MAX]; + if (!do_getcwd(tmp, sizeof tmp)) + return 0; + size_t len = strlen(tmp) + 1; + if (!size) + size = len; + else if (size < len) { + errno = ERANGE; + return 0; + } + char *buf = malloc(size); + if (!buf) { + errno = ENOMEM; + return 0; + } + memcpy(buf, tmp, len); + return buf; +} + +char *getcwd(char *buf, size_t size) +{ + if (!buf) + return getcwd_glibc(size); + if (!size) { + errno = EINVAL; + return 0; + } + return do_getcwd(buf, size); }