|
55 | 55 |
|
56 | 56 | #include <sys/types.h>
|
57 | 57 | #if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && \
|
58 |
| - !defined(__linux__) && !defined(__FreeBSD_kernel__) |
| 58 | + !defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(_AIX) |
59 | 59 | #include <sys/statvfs.h>
|
60 | 60 | #define STATVFS statvfs
|
61 | 61 | #define FSTATVFS fstatvfs
|
|
76 | 76 | #endif
|
77 | 77 | #endif
|
78 | 78 | #include <sys/vfs.h>
|
| 79 | +#elif defined(_AIX) |
| 80 | +#include <sys/statfs.h> |
| 81 | + |
| 82 | +// <sys/vmount.h> depends on `uint` to be a typedef from <sys/types.h> to |
| 83 | +// `uint_t`; however, <sys/types.h> does not always declare `uint`. We provide |
| 84 | +// the typedef prior to including <sys/vmount.h> to work around this issue. |
| 85 | +typedef uint_t uint; |
| 86 | +#include <sys/vmount.h> |
79 | 87 | #else
|
80 | 88 | #include <sys/mount.h>
|
81 | 89 | #endif
|
@@ -249,7 +257,7 @@ uint32_t file_status::getLinkCount() const {
|
249 | 257 |
|
250 | 258 | ErrorOr<space_info> disk_space(const Twine &Path) {
|
251 | 259 | struct STATVFS Vfs;
|
252 |
| - if (::STATVFS(Path.str().c_str(), &Vfs)) |
| 260 | + if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs)) |
253 | 261 | return std::error_code(errno, std::generic_category());
|
254 | 262 | auto FrSize = STATVFS_F_FRSIZE(Vfs);
|
255 | 263 | space_info SpaceInfo;
|
@@ -409,14 +417,48 @@ static bool is_local_impl(struct STATVFS &Vfs) {
|
409 | 417 | StringRef fstype(Vfs.f_basetype);
|
410 | 418 | // NFS is the only non-local fstype??
|
411 | 419 | return !fstype.equals("nfs");
|
| 420 | +#elif defined(_AIX) |
| 421 | + // Call mntctl; try more than twice in case of timing issues with a concurrent |
| 422 | + // mount. |
| 423 | + int Ret; |
| 424 | + size_t BufSize = 2048u; |
| 425 | + std::unique_ptr<char[]> Buf; |
| 426 | + int Tries = 3; |
| 427 | + while (Tries--) { |
| 428 | + Buf = llvm::make_unique<char[]>(BufSize); |
| 429 | + Ret = mntctl(MCTL_QUERY, BufSize, Buf.get()); |
| 430 | + if (Ret != 0) |
| 431 | + break; |
| 432 | + BufSize = *reinterpret_cast<unsigned int *>(Buf.get()); |
| 433 | + Buf.reset(); |
| 434 | + } |
| 435 | + |
| 436 | + if (Ret == -1) |
| 437 | + // There was an error; "remote" is the conservative answer. |
| 438 | + return false; |
| 439 | + |
| 440 | + // Look for the correct vmount entry. |
| 441 | + char *CurObjPtr = Buf.get(); |
| 442 | + while (Ret--) { |
| 443 | + struct vmount *Vp = reinterpret_cast<struct vmount *>(CurObjPtr); |
| 444 | + static_assert(sizeof(Vfs.f_fsid) == sizeof(Vp->vmt_fsid), |
| 445 | + "fsid length mismatch"); |
| 446 | + if (memcmp(&Vfs.f_fsid, &Vp->vmt_fsid, sizeof Vfs.f_fsid) == 0) |
| 447 | + return (Vp->vmt_flags & MNT_REMOTE) == 0; |
| 448 | + |
| 449 | + CurObjPtr += Vp->vmt_length; |
| 450 | + } |
| 451 | + |
| 452 | + // vmount entry not found; "remote" is the conservative answer. |
| 453 | + return false; |
412 | 454 | #else
|
413 | 455 | return !!(STATVFS_F_FLAG(Vfs) & MNT_LOCAL);
|
414 | 456 | #endif
|
415 | 457 | }
|
416 | 458 |
|
417 | 459 | std::error_code is_local(const Twine &Path, bool &Result) {
|
418 | 460 | struct STATVFS Vfs;
|
419 |
| - if (::STATVFS(Path.str().c_str(), &Vfs)) |
| 461 | + if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs)) |
420 | 462 | return std::error_code(errno, std::generic_category());
|
421 | 463 |
|
422 | 464 | Result = is_local_impl(Vfs);
|
|
0 commit comments