Skip to content

Commit 678f19f

Browse files
azhan92alisonzhang4jh7370
authored
[Support] Report EISDIR when opening a directory (#79880)
The test `llvm/unittests/Support/CommandLineTest.cpp` that handles errors in expansion of response files was previously disabled for AIX. Originally the code was dependent on `read` returning `EISDIR` which occurs on platforms such as Linux. However, other platforms such as AIX allow use of `read` on file descriptors for directories. This change updates `readNativeFile` to produce `EISDIR` on AIX and z/OS when used on a directory (instead of relying on the call to `read` to do so). --------- Co-authored-by: Alison Zhang <[email protected]> Co-authored-by: James Henderson <[email protected]>
1 parent 0ab3f16 commit 678f19f

File tree

4 files changed

+31
-4
lines changed

4 files changed

+31
-4
lines changed

llvm/lib/Support/Unix/Path.inc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,15 @@ Expected<size_t> readNativeFile(file_t FD, MutableArrayRef<char> Buf) {
11911191
ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size);
11921192
if (ssize_t(NumRead) == -1)
11931193
return errorCodeToError(errnoAsErrorCode());
1194+
// The underlying operation on these platforms allow opening directories
1195+
// for reading in more cases than other platforms.
1196+
#if defined(__MVS__) || defined(_AIX)
1197+
struct stat Status;
1198+
if (fstat(FD, &Status) == -1)
1199+
return errorCodeToError(errnoAsErrorCode());
1200+
if (S_ISDIR(Status.st_mode))
1201+
return errorCodeToError(make_error_code(errc::is_a_directory));
1202+
#endif
11941203
return NumRead;
11951204
}
11961205

llvm/test/tools/llvm-symbolizer/input-file-err.test

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
Failing on AIX due to D153595. The test expects a different error message from the one given on AIX.
2-
XFAIL: target={{.*}}-aix{{.*}}
31
RUN: not llvm-addr2line -e %p/Inputs/nonexistent 0x12 2>&1 | FileCheck %s --check-prefix=CHECK-NONEXISTENT-A2L -DMSG=%errc_ENOENT
42
RUN: not llvm-addr2line -e %p/Inputs/nonexistent 2>&1 | FileCheck %s --check-prefix=CHECK-NONEXISTENT-A2L -DMSG=%errc_ENOENT
53
CHECK-NONEXISTENT-A2L: llvm-addr2line{{.*}}: error: '{{.*}}Inputs/nonexistent': [[MSG]]

llvm/unittests/Support/CommandLineTest.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,15 +1117,13 @@ TEST(CommandLineTest, BadResponseFile) {
11171117
ASSERT_STREQ(Argv[0], "clang");
11181118
ASSERT_STREQ(Argv[1], AFileExp.c_str());
11191119

1120-
#if !defined(_AIX) && !defined(__MVS__)
11211120
std::string ADirExp = std::string("@") + std::string(ADir.path());
11221121
Argv = {"clang", ADirExp.c_str()};
11231122
Res = cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv);
11241123
ASSERT_FALSE(Res);
11251124
ASSERT_EQ(2U, Argv.size());
11261125
ASSERT_STREQ(Argv[0], "clang");
11271126
ASSERT_STREQ(Argv[1], ADirExp.c_str());
1128-
#endif
11291127
}
11301128

11311129
TEST(CommandLineTest, SetDefaultValue) {

llvm/unittests/Support/Path.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1757,6 +1757,28 @@ TEST_F(FileSystemTest, OpenFileForRead) {
17571757
#endif
17581758
}
17591759

1760+
TEST_F(FileSystemTest, OpenDirectoryAsFileForRead) {
1761+
std::string Buf(5, '?');
1762+
Expected<fs::file_t> FD = fs::openNativeFileForRead(TestDirectory);
1763+
#ifdef _WIN32
1764+
EXPECT_EQ(errorToErrorCode(FD.takeError()), errc::is_a_directory);
1765+
#else
1766+
ASSERT_THAT_EXPECTED(FD, Succeeded());
1767+
auto Close = make_scope_exit([&] { fs::closeFile(*FD); });
1768+
Expected<size_t> BytesRead =
1769+
fs::readNativeFile(*FD, MutableArrayRef(&*Buf.begin(), Buf.size()));
1770+
EXPECT_EQ(errorToErrorCode(BytesRead.takeError()), errc::is_a_directory);
1771+
#endif
1772+
}
1773+
1774+
TEST_F(FileSystemTest, OpenDirectoryAsFileForWrite) {
1775+
int FD;
1776+
std::error_code EC = fs::openFileForWrite(Twine(TestDirectory), FD);
1777+
if (!EC)
1778+
::close(FD);
1779+
EXPECT_EQ(EC, errc::is_a_directory);
1780+
}
1781+
17601782
static void createFileWithData(const Twine &Path, bool ShouldExistBefore,
17611783
fs::CreationDisposition Disp, StringRef Data) {
17621784
int FD;

0 commit comments

Comments
 (0)