blob: 848ec85b89beb2790a872711a95f4662b78f488e [file] [log] [blame]
// Copyright 2018 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 <dirent.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <blkctl/blkctl.h>
#include <blkctl/command.h>
#include <fbl/auto_call.h>
#include <zircon/assert.h>
#include <zircon/device/block.h>
#include <zircon/device/device.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/types.h>
#include "generic.h"
namespace blkctl {
namespace generic {
zx_status_t Help::Run() {
BlkCtl* cmdline = this->cmdline();
cmdline->Usage();
return ZX_OK;
}
zx_status_t List::Run() {
zx_status_t rc;
BlkCtl* cmdline = this->cmdline();
if ((rc = cmdline->ArgsDone()) != ZX_OK) {
return rc;
}
DIR* dptr = opendir(kDevClassBlock);
ZX_DEBUG_ASSERT(dptr);
auto cleanup = fbl::MakeAutoCall([&] { closedir(dptr); });
struct dirent* dent;
printf("%8s %s\n", "ID", "Topological path");
while ((dent = readdir(dptr))) {
char* id = dent->d_name;
char path[PATH_MAX];
snprintf(path, sizeof(path), "%s/%s", kDevClassBlock, id);
fbl::unique_fd fd(open(path, O_RDONLY));
if (!fd || ioctl_device_get_topo_path(fd.get(), path, sizeof(path)) < 0) {
continue;
}
printf("%8s -> %s\n", id, path);
}
return ZX_OK;
}
zx_status_t Dump::Run() {
zx_status_t rc;
BlkCtl* cmdline = this->cmdline();
char buf[PATH_MAX];
ssize_t res;
const char* dev;
int fd;
if ((rc = cmdline->GetStrArg("device", &dev)) != ZX_OK || (rc = cmdline->ArgsDone()) != ZX_OK ||
(rc = OpenReadable(dev, &fd)) != ZX_OK) {
return rc;
}
// Topological path
printf("%16s: ", "Topological path");
res = ioctl_device_get_topo_path(fd, buf, sizeof(buf));
if (res >= 0) {
printf("%s", buf);
} else if (res != ZX_ERR_NOT_SUPPORTED) {
rc = static_cast<zx_status_t>(res);
fprintf(stderr, "ioctl_device_get_topo_path failed: %s\n", zx_status_get_string(rc));
return rc;
}
printf("\n");
// Block name
printf("%16s: ", "Name");
res = ioctl_block_get_name(fd, buf, sizeof(buf));
if (res >= 0) {
printf("%s", buf);
} else if (res != ZX_ERR_NOT_SUPPORTED) {
rc = static_cast<zx_status_t>(res);
fprintf(stderr, "ioctl_block_get_name failed: %s\n", zx_status_get_string(rc));
return rc;
}
printf("\n");
// Block info
block_info_t info;
res = ioctl_block_get_info(fd, &info);
if (res >= 0) {
} else if (res != ZX_ERR_NOT_SUPPORTED) {
rc = static_cast<zx_status_t>(res);
fprintf(stderr, "ioctl_block_get_info failed: %s\n", zx_status_get_string(rc));
return rc;
}
printf("%16s: %" PRIu64 "\n", "Block count", info.block_count);
printf("%16s: %" PRIu32 "\n", "Block size", info.block_size);
printf("%16s: %" PRIu32 "\n", "Max transfer", info.max_transfer_size);
printf("%16s: %08" PRIx32 "\n", "Flags", info.flags);
// Optional type guid
printf("%16s: ", "Type GUID");
uint8_t guid[GUID_LEN];
res = ioctl_block_get_type_guid(fd, guid, sizeof(guid));
if (res >= 0) {
PrintGuid(guid, static_cast<size_t>(res));
} else if (res != ZX_ERR_NOT_SUPPORTED) {
rc = static_cast<zx_status_t>(res);
fprintf(stderr, "ioctl_block_get_type_guid failed: %s\n", zx_status_get_string(rc));
return rc;
}
printf("\n");
// Optional instance guid
res = ioctl_block_get_partition_guid(fd, guid, sizeof(guid));
if (res >= 0) {
printf("%16s: ", "Instance GUID");
PrintGuid(guid, static_cast<size_t>(res));
printf("\n");
} else if (res != ZX_ERR_NOT_SUPPORTED) {
rc = static_cast<zx_status_t>(res);
fprintf(stderr, "ioctl_block_get_partition_guid failed: %s\n", zx_status_get_string(rc));
return rc;
}
return ZX_OK;
}
} // namespace generic
} // namespace blkctl