| 545 | |
| 546 | |
| 547 | Try<Nothing> unmountAll(const string& target, int flags) |
| 548 | { |
| 549 | Try<fs::MountTable> mountTable = fs::MountTable::read("/proc/mounts"); |
| 550 | if (mountTable.isError()) { |
| 551 | return Error("Failed to read mount table: " + mountTable.error()); |
| 552 | } |
| 553 | |
| 554 | foreach (const MountTable::Entry& entry, |
| 555 | adaptor::reverse(mountTable->entries)) { |
| 556 | if (strings::startsWith(entry.dir, target)) { |
| 557 | Try<Nothing> unmount = fs::unmount(entry.dir, flags); |
| 558 | if (unmount.isError()) { |
| 559 | return unmount; |
| 560 | } |
| 561 | |
| 562 | // This normally should not fail even if the entry is not in |
| 563 | // mtab or mtab doesn't exist or is not writable. However we |
| 564 | // still catch the error here in case there's an error somewhere |
| 565 | // else while running this command. |
| 566 | // TODO(xujyan): Consider using `setmntent(3)` to implement this. |
| 567 | const Option<int> status = |
| 568 | os::spawn("umount", {"umount", "--fake", entry.dir}); |
| 569 | |
| 570 | const string message = |
| 571 | "Failed to clean up '" + entry.dir + "' in /etc/mtab"; |
| 572 | |
| 573 | if (status.isNone()) { |
| 574 | return ErrnoError(message); |
| 575 | } |
| 576 | |
| 577 | if (!WSUCCEEDED(status.get())) { |
| 578 | return Error(message + ": " + WSTRINGIFY(status.get())); |
| 579 | } |
| 580 | } |
| 581 | } |
| 582 | |
| 583 | return Nothing(); |
| 584 | } |
| 585 | |
| 586 | |
| 587 | Try<Nothing> pivot_root( |