From ae0d0c9e7699f403970579277e77d747f9c61091 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 21 Feb 2024 18:58:24 +0000 Subject: [PATCH] Clarify _PC_REC_INCR_XFER_SIZE and _PC_REC_MAX_XFER_SIZE. The -1 from pathconf()/fpathconf() with these isn't the "I don't know what you're talking about" -1/EINVAL, but the "I understand the question, but don't have an answer for you --- you'll have to try it and see" -1. Bug: http://b/326245682 Test: treehugger Change-Id: I67be277f3ffd9b5a355787ae7ffc4a31e32b0128 --- libc/bionic/pathconf.cpp | 19 +++++++------------ tests/unistd_test.cpp | 40 +++++++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/libc/bionic/pathconf.cpp b/libc/bionic/pathconf.cpp index 9724f4436..9bbecc36f 100644 --- a/libc/bionic/pathconf.cpp +++ b/libc/bionic/pathconf.cpp @@ -107,14 +107,6 @@ static long __pathconf(const struct statfs& s, int name) { case _PC_REC_MIN_XFER_SIZE: return s.f_bsize; -#if 0 - case _PC_REC_INCR_XFER_SIZE: - case _PC_REC_MAX_XFER_SIZE: -#endif - - case _PC_SYMLINK_MAX: - return -1; /* no limit */ - case _PC_CHOWN_RESTRICTED: return _POSIX_CHOWN_RESTRICTED; @@ -125,12 +117,15 @@ static long __pathconf(const struct statfs& s, int name) { return _POSIX_VDISABLE; case _PC_ASYNC_IO: - return -1; - case _PC_PRIO_IO: - return -1; - + case _PC_REC_INCR_XFER_SIZE: + case _PC_REC_MAX_XFER_SIZE: + case _PC_SYMLINK_MAX: case _PC_SYNC_IO: + // No API to answer these: the caller will have to "try it and see". + // This differs from the next case in not setting errno to EINVAL, + // since we did understand the question --- we just don't have a + // good answer. return -1; default: diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp index 88f5851c1..6c08972e6 100644 --- a/tests/unistd_test.cpp +++ b/tests/unistd_test.cpp @@ -753,22 +753,36 @@ TEST(UNISTD_TEST, gethostname) { TEST(UNISTD_TEST, pathconf_fpathconf) { TemporaryFile tf; - long rc = 0L; + long l; + // As a file system's block size is always power of 2, the configure values // for ALLOC and XFER should be power of 2 as well. - rc = pathconf(tf.path, _PC_ALLOC_SIZE_MIN); - ASSERT_TRUE(rc > 0 && powerof2(rc)); - rc = pathconf(tf.path, _PC_REC_MIN_XFER_SIZE); - ASSERT_TRUE(rc > 0 && powerof2(rc)); - rc = pathconf(tf.path, _PC_REC_XFER_ALIGN); - ASSERT_TRUE(rc > 0 && powerof2(rc)); + l = pathconf(tf.path, _PC_ALLOC_SIZE_MIN); + ASSERT_TRUE(l > 0 && powerof2(l)); + l = pathconf(tf.path, _PC_REC_MIN_XFER_SIZE); + ASSERT_TRUE(l > 0 && powerof2(l)); + l = pathconf(tf.path, _PC_REC_XFER_ALIGN); + ASSERT_TRUE(l > 0 && powerof2(l)); - rc = fpathconf(tf.fd, _PC_ALLOC_SIZE_MIN); - ASSERT_TRUE(rc > 0 && powerof2(rc)); - rc = fpathconf(tf.fd, _PC_REC_MIN_XFER_SIZE); - ASSERT_TRUE(rc > 0 && powerof2(rc)); - rc = fpathconf(tf.fd, _PC_REC_XFER_ALIGN); - ASSERT_TRUE(rc > 0 && powerof2(rc)); + l = fpathconf(tf.fd, _PC_ALLOC_SIZE_MIN); + ASSERT_TRUE(l > 0 && powerof2(l)); + l = fpathconf(tf.fd, _PC_REC_MIN_XFER_SIZE); + ASSERT_TRUE(l > 0 && powerof2(l)); + l = fpathconf(tf.fd, _PC_REC_XFER_ALIGN); + ASSERT_TRUE(l > 0 && powerof2(l)); + + // Check that the "I can't answer that, you'll have to try it and see" + // cases don't set errno. + int names[] = { + _PC_ASYNC_IO, _PC_PRIO_IO, _PC_REC_INCR_XFER_SIZE, _PC_REC_MAX_XFER_SIZE, _PC_SYMLINK_MAX, + _PC_SYNC_IO, -1}; + for (size_t i = 0; names[i] != -1; i++) { + errno = 0; + ASSERT_EQ(-1, pathconf(tf.path, names[i])) << names[i]; + ASSERT_ERRNO(0) << names[i]; + ASSERT_EQ(-1, fpathconf(tf.fd, names[i])) << names[i]; + ASSERT_ERRNO(0) << names[i]; + } } TEST(UNISTD_TEST, _POSIX_constants) {