| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <fs-management/mount.h> |
| |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <new> |
| #include <string.h> |
| #include <unistd.h> |
| |
| #include <fbl/unique_fd.h> |
| #include <fbl/unique_ptr.h> |
| #include <fbl/vector.h> |
| #include <lib/fdio/limits.h> |
| #include <lib/fdio/fd.h> |
| #include <lib/fdio/fdio.h> |
| #include <lib/fdio/directory.h> |
| #include <lib/fdio/vfs.h> |
| #include <lib/zx/channel.h> |
| #include <zircon/compiler.h> |
| #include <zircon/device/vfs.h> |
| #include <zircon/processargs.h> |
| #include <zircon/syscalls.h> |
| |
| namespace { |
| |
| zx_status_t FsckNativeFs(const char* device_path, const fsck_options_t* options, |
| LaunchCallback cb, const char* cmd_path) { |
| fbl::unique_fd device_fd; |
| device_fd.reset(open(device_path, O_RDWR)); |
| if (!device_fd) { |
| fprintf(stderr, "Failed to open device\n"); |
| return ZX_ERR_BAD_STATE; |
| } |
| zx::channel block_device; |
| zx_status_t status = fdio_get_service_handle(device_fd.release(), |
| block_device.reset_and_get_address()); |
| if (status != ZX_OK) { |
| return status; |
| } |
| |
| fbl::Vector<const char*> argv; |
| argv.push_back(cmd_path); |
| if (options->verbose) { |
| argv.push_back("-v"); |
| } |
| if (options->apply_journal) { |
| argv.push_back("-j"); |
| } |
| // TODO(smklein): Add support for modify, force flags. Without them, |
| // we have "never_modify=true" and "force=true" effectively on by default. |
| argv.push_back("fsck"); |
| argv.push_back(nullptr); |
| |
| zx_handle_t hnd = block_device.release(); |
| uint32_t id = FS_HANDLE_BLOCK_DEVICE_ID; |
| auto argc = static_cast<int>(argv.size() - 1); |
| status = static_cast<zx_status_t>(cb(argc, argv.get(), &hnd, &id, 1)); |
| return status; |
| } |
| |
| zx_status_t FsckFat(const char* device_path, const fsck_options_t* options, |
| LaunchCallback cb) { |
| fbl::Vector<const char*> argv; |
| argv.push_back("/boot/bin/fsck-msdosfs"); |
| if (options->never_modify) { |
| argv.push_back("-n"); |
| } else if (options->always_modify) { |
| argv.push_back("-y"); |
| } |
| if (options->force) { |
| argv.push_back("-f"); |
| } |
| argv.push_back(device_path); |
| argv.push_back(nullptr); |
| auto argc = static_cast<int>(argv.size() - 1); |
| zx_status_t status = static_cast<zx_status_t>(cb(argc, argv.get(), nullptr, nullptr, 0)); |
| return status; |
| } |
| |
| } // namespace |
| |
| zx_status_t fsck(const char* device_path, disk_format_t df, |
| const fsck_options_t* options, LaunchCallback cb) { |
| switch (df) { |
| case DISK_FORMAT_MINFS: |
| return FsckNativeFs(device_path, options, cb, "/boot/bin/minfs"); |
| case DISK_FORMAT_FAT: |
| return FsckFat(device_path, options, cb); |
| case DISK_FORMAT_BLOBFS: |
| return FsckNativeFs(device_path, options, cb, "/boot/bin/blobfs"); |
| default: |
| return ZX_ERR_NOT_SUPPORTED; |
| } |
| } |