blob: baabebb33020961171179c52bd21072536c96913 [file] [log] [blame]
// 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 <fidl/fuchsia.fshost/cpp/wire.h>
#include <getopt.h>
#include <lib/service/llcpp/service.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <filesystem>
#include <string>
#include "src/storage/fshost/constants.h"
bool verbose = false;
#define xprintf(fmt...) \
do { \
if (verbose) \
printf(fmt); \
} while (0)
int usage(void) {
fprintf(stderr,
"usage: umount [ <option>* ] <mount-name>\n"
"options:\n"
" -v|--verbose : Verbose mode\n"
" --fshost-path : The path to the fshost admin service (if different from the default)\n"
" -h|--help : Display this message\n");
return EXIT_FAILURE;
}
int main(int argc, char** argv) {
std::string fshost_path(fshost::kHubAdminServicePath);
while (1) {
static struct option opts[] = {
{"help", no_argument, NULL, 'h'},
{"verbose", no_argument, NULL, 'v'},
{"fshost-path", required_argument, NULL, 'p'},
{NULL, 0, NULL, 0},
};
int opt_index;
int c = getopt_long(argc, argv, "v", opts, &opt_index);
if (c < 0) {
break;
}
switch (c) {
case 'v':
verbose = true;
break;
case 'p':
fshost_path = optarg;
break;
case 'h':
default:
return usage();
}
}
argc -= optind;
argv += optind;
if (argc < 1) {
return usage();
}
std::filesystem::path path(argv[0]);
if (path.parent_path() != "/mnt") {
std::error_code error;
auto directory = std::filesystem::canonical(path.parent_path(), error);
if (error) {
fprintf(stderr, "Bad mount path: %s\n\n", strerror(error.value()));
return usage();
}
if (directory != "/mnt") {
fprintf(stderr, "Only mounts in /mnt are supported.\n\n");
return usage();
}
}
std::string mount_name = path.filename();
xprintf("Unmount path: /mnt/%s\n", mount_name.c_str());
auto client_or = service::Connect<fuchsia_fshost::Admin>(fshost_path.c_str());
if (client_or.is_error()) {
fprintf(stderr, "Error connecting to fshost (@ %s): %s\n", fshost_path.c_str(),
client_or.status_string());
return EXIT_FAILURE;
}
auto result = fidl::WireCall(*client_or)->Unmount(fidl::StringView::FromExternal(mount_name));
if (!result.ok()) {
fprintf(stderr, "Error unmounting, fidl error: %s\n", result.FormatDescription().c_str());
return EXIT_FAILURE;
}
if (result->is_error()) {
fprintf(stderr, "Error unmounting: %s\n", zx_status_get_string(result->error_value()));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}