aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/stdlib/realpath.336
-rw-r--r--lib/libc/stdlib/realpath.c10
-rw-r--r--lib/libc/tests/stdlib/cxa_thread_atexit_nothr_test.cc11
-rw-r--r--lib/libc/tests/stdlib/cxa_thread_atexit_test.cc10
4 files changed, 35 insertions, 32 deletions
diff --git a/lib/libc/stdlib/realpath.3 b/lib/libc/stdlib/realpath.3
index 76f40249963b..a17ddee0b2f1 100644
--- a/lib/libc/stdlib/realpath.3
+++ b/lib/libc/stdlib/realpath.3
@@ -28,7 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd October 10, 2025
+.Dd March 18, 2026
.Dt REALPATH 3
.Os
.Sh NAME
@@ -75,27 +75,24 @@ must exist when
is called, and all but the last component must name either directories or
symlinks pointing to the directories.
.Sh "RETURN VALUES"
-The
+On success, the
.Fn realpath
function returns
.Fa resolved_path
-on success.
-If the function was supplied
-.Dv NULL
-as
-.Fa resolved_path ,
-and operation did not cause errors, the returned value is
-a null-terminated string in a buffer allocated by a call to
-.Fn malloc 3 .
+if it was not
+.Dv NULL ,
+or a pointer to a null-terminated string which must be freed by the
+caller if it was.
If an error occurs,
.Fn realpath
returns
.Dv NULL ,
and if
.Fa resolved_path
-is not
+was not
.Dv NULL ,
-the array that it points to contains the pathname which caused the problem.
+the array that it points to contains the pathname which caused the
+problem.
.Sh ERRORS
The function
.Fn realpath
@@ -107,6 +104,9 @@ for any of the errors specified for the library functions
and
.Xr getcwd 3 .
.Sh SEE ALSO
+.Xr basename 3 ,
+.Xr dirname 3 ,
+.Xr free 3 ,
.Xr getcwd 3
.Sh STANDARDS
The
@@ -118,15 +118,3 @@ The
.Fn realpath
function first appeared in
.Bx 4.4 .
-.Sh CAVEATS
-This implementation of
-.Fn realpath
-differs slightly from the Solaris implementation.
-The
-.Bx 4.4
-version always returns absolute pathnames,
-whereas the Solaris implementation will,
-under certain circumstances, return a relative
-.Fa resolved_path
-when given a relative
-.Fa pathname .
diff --git a/lib/libc/stdlib/realpath.c b/lib/libc/stdlib/realpath.c
index 18f29e95ee6b..9dc0cc4d3dd4 100644
--- a/lib/libc/stdlib/realpath.c
+++ b/lib/libc/stdlib/realpath.c
@@ -98,7 +98,6 @@ realpath1(const char *path, char *resolved)
left_len = 0;
}
- prev_len = resolved_len;
if (resolved[resolved_len - 1] != '/') {
if (resolved_len + 1 >= PATH_MAX) {
errno = ENAMETOOLONG;
@@ -129,7 +128,9 @@ realpath1(const char *path, char *resolved)
/*
* Append the next path component and lstat() it.
*/
- resolved_len = strlcat(resolved, next_token, PATH_MAX);
+ prev_len = resolved_len;
+ resolved_len += strlcpy(resolved + prev_len, next_token,
+ PATH_MAX - prev_len);
if (resolved_len >= PATH_MAX) {
errno = ENAMETOOLONG;
return (NULL);
@@ -141,8 +142,11 @@ realpath1(const char *path, char *resolved)
* directory is not a directory. Rewind the path
* to correctly indicate where the error lies.
*/
- if (errno == EACCES || errno == ENOTDIR)
+ if (errno == EACCES || errno == ENOTDIR) {
+ if (prev_len > 1)
+ prev_len--;
resolved[prev_len] = '\0';
+ }
return (NULL);
}
if (S_ISLNK(sb.st_mode)) {
diff --git a/lib/libc/tests/stdlib/cxa_thread_atexit_nothr_test.cc b/lib/libc/tests/stdlib/cxa_thread_atexit_nothr_test.cc
index 0b3b9497a6bd..d70c6b1b88dc 100644
--- a/lib/libc/tests/stdlib/cxa_thread_atexit_nothr_test.cc
+++ b/lib/libc/tests/stdlib/cxa_thread_atexit_nothr_test.cc
@@ -30,7 +30,10 @@
#include <cstdio>
#include <cstdlib>
+#define AGAIN_CALL_LIMIT 20
+
static FILE *output = NULL;
+static int again_counter = 0;
struct Foo {
Foo() { ATF_REQUIRE(fprintf(output, "Created\n") > 0); }
@@ -79,14 +82,16 @@ extern "C" int __cxa_thread_atexit(void (*)(void *), void *, void *);
static void
again(void *arg)
{
-
- __cxa_thread_atexit(again, arg, &output);
+ if (again_counter < AGAIN_CALL_LIMIT) {
+ again_counter++;
+ __cxa_thread_atexit(again, arg, &output);
+ }
}
ATF_TEST_CASE_WITHOUT_HEAD(cxx__thread_inf_dtors);
ATF_TEST_CASE_BODY(cxx__thread_inf_dtors)
{
-
+ skip("Skip since we only have main thread");
again(NULL);
}
diff --git a/lib/libc/tests/stdlib/cxa_thread_atexit_test.cc b/lib/libc/tests/stdlib/cxa_thread_atexit_test.cc
index 628a70b510d1..6a5587698d37 100644
--- a/lib/libc/tests/stdlib/cxa_thread_atexit_test.cc
+++ b/lib/libc/tests/stdlib/cxa_thread_atexit_test.cc
@@ -30,7 +30,10 @@
#include <cstdlib>
#include <thread>
+#define AGAIN_CALL_LIMIT 20
+
static FILE *output = NULL;
+static int again_counter = 0;
struct Foo {
Foo() { ATF_REQUIRE(fprintf(output, "Created\n") > 0); }
@@ -52,8 +55,10 @@ extern "C" int __cxa_thread_atexit(void (*)(void *), void *, void *);
static void
again(void *arg)
{
-
- __cxa_thread_atexit(again, arg, &output);
+ if (again_counter < AGAIN_CALL_LIMIT) {
+ ++again_counter;
+ __cxa_thread_atexit(again, arg, &output);
+ }
}
struct Baz {
@@ -164,6 +169,7 @@ ATF_TEST_CASE_BODY(cxx__thread_inf_dtors)
std::thread t([]() { e.use(); });
t.join();
+ ATF_REQUIRE_EQ(again_counter, AGAIN_CALL_LIMIT);
}
ATF_INIT_TEST_CASES(tcs)