diff options
| author | Hubert Tong <hubert.reinterpretcast@gmail.com> | 2019-03-29 23:32:47 +0000 |
|---|---|---|
| committer | Hubert Tong <hubert.reinterpretcast@gmail.com> | 2019-03-29 23:32:47 +0000 |
| commit | 24168852e8b52b0e11294e606f86f4dde195eee7 (patch) | |
| tree | 20ac0e8c483368f22fd80f5efec6ac90ed958fae | |
| parent | 4d6fb5789fca8857c5161a621892b69a23a53d25 (diff) | |
| download | bcm5719-llvm-24168852e8b52b0e11294e606f86f4dde195eee7.tar.gz bcm5719-llvm-24168852e8b52b0e11294e606f86f4dde195eee7.zip | |
[Support] Implement is_local_impl with AIX mntctl
Summary:
On AIX, we can determine whether a filesystem is remote using `mntctl`.
If the information is not found, then claim that the file is remote
(since that is the more restrictive case). Testing for the associated
interface is restored with a modified version of the unit test from
rL295768.
Reviewers: jasonliu, xingxue
Reviewed By: xingxue
Subscribers: jsji, apaprocki, Hahnfeld, zturner, krytarowski, kristina, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58801
llvm-svn: 357333
| -rw-r--r-- | llvm/lib/Support/Unix/Path.inc | 48 | ||||
| -rw-r--r-- | llvm/unittests/Support/Path.cpp | 23 |
2 files changed, 68 insertions, 3 deletions
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc index 57385baaf34..a02585c3bdc 100644 --- a/llvm/lib/Support/Unix/Path.inc +++ b/llvm/lib/Support/Unix/Path.inc @@ -55,7 +55,7 @@ #include <sys/types.h> #if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && \ - !defined(__linux__) && !defined(__FreeBSD_kernel__) + !defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(_AIX) #include <sys/statvfs.h> #define STATVFS statvfs #define FSTATVFS fstatvfs @@ -76,6 +76,14 @@ #endif #endif #include <sys/vfs.h> +#elif defined(_AIX) +#include <sys/statfs.h> + +// <sys/vmount.h> depends on `uint` to be a typedef from <sys/types.h> to +// `uint_t`; however, <sys/types.h> does not always declare `uint`. We provide +// the typedef prior to including <sys/vmount.h> to work around this issue. +typedef uint_t uint; +#include <sys/vmount.h> #else #include <sys/mount.h> #endif @@ -249,7 +257,7 @@ uint32_t file_status::getLinkCount() const { ErrorOr<space_info> disk_space(const Twine &Path) { struct STATVFS Vfs; - if (::STATVFS(Path.str().c_str(), &Vfs)) + if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs)) return std::error_code(errno, std::generic_category()); auto FrSize = STATVFS_F_FRSIZE(Vfs); space_info SpaceInfo; @@ -409,6 +417,40 @@ static bool is_local_impl(struct STATVFS &Vfs) { StringRef fstype(Vfs.f_basetype); // NFS is the only non-local fstype?? return !fstype.equals("nfs"); +#elif defined(_AIX) + // Call mntctl; try more than twice in case of timing issues with a concurrent + // mount. + int Ret; + size_t BufSize = 2048u; + std::unique_ptr<char[]> Buf; + int Tries = 3; + while (Tries--) { + Buf = llvm::make_unique<char[]>(BufSize); + Ret = mntctl(MCTL_QUERY, BufSize, Buf.get()); + if (Ret != 0) + break; + BufSize = *reinterpret_cast<unsigned int *>(Buf.get()); + Buf.reset(); + } + + if (Ret == -1) + // There was an error; "remote" is the conservative answer. + return false; + + // Look for the correct vmount entry. + char *CurObjPtr = Buf.get(); + while (Ret--) { + struct vmount *Vp = reinterpret_cast<struct vmount *>(CurObjPtr); + static_assert(sizeof(Vfs.f_fsid) == sizeof(Vp->vmt_fsid), + "fsid length mismatch"); + if (memcmp(&Vfs.f_fsid, &Vp->vmt_fsid, sizeof Vfs.f_fsid) == 0) + return (Vp->vmt_flags & MNT_REMOTE) == 0; + + CurObjPtr += Vp->vmt_length; + } + + // vmount entry not found; "remote" is the conservative answer. + return false; #else return !!(STATVFS_F_FLAG(Vfs) & MNT_LOCAL); #endif @@ -416,7 +458,7 @@ static bool is_local_impl(struct STATVFS &Vfs) { std::error_code is_local(const Twine &Path, bool &Result) { struct STATVFS Vfs; - if (::STATVFS(Path.str().c_str(), &Vfs)) + if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs)) return std::error_code(errno, std::generic_category()); Result = is_local_impl(Vfs); diff --git a/llvm/unittests/Support/Path.cpp b/llvm/unittests/Support/Path.cpp index 7ce6d2d52db..3c0f7936030 100644 --- a/llvm/unittests/Support/Path.cpp +++ b/llvm/unittests/Support/Path.cpp @@ -1492,6 +1492,29 @@ TEST_F(FileSystemTest, ReadWriteFileCanReadOrWrite) { verifyWrite(FD, "Buzz", true); } +TEST_F(FileSystemTest, is_local) { + bool TestDirectoryIsLocal; + ASSERT_NO_ERROR(fs::is_local(TestDirectory, TestDirectoryIsLocal)); + EXPECT_EQ(TestDirectoryIsLocal, fs::is_local(TestDirectory)); + + int FD; + SmallString<128> TempPath; + ASSERT_NO_ERROR( + fs::createUniqueFile(Twine(TestDirectory) + "/temp", FD, TempPath)); + FileRemover Cleanup(TempPath); + + // Make sure it exists. + ASSERT_TRUE(sys::fs::exists(Twine(TempPath))); + + bool TempFileIsLocal; + ASSERT_NO_ERROR(fs::is_local(FD, TempFileIsLocal)); + EXPECT_EQ(TempFileIsLocal, fs::is_local(FD)); + + // Expect that the file and its parent directory are equally local or equally + // remote. + EXPECT_EQ(TestDirectoryIsLocal, TempFileIsLocal); +} + TEST_F(FileSystemTest, set_current_path) { SmallString<128> path; |

