blob: 1e361b20d5afb0b96571d4706b9d8cfd4b3a6c33 [file] [log] [blame]
// Copyright 2017 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 <utility>
#include "fvm-host/format.h"
Format::Format() : fvm_ready_(false), vpart_index_(0), flags_(0) {}
zx_status_t Format::Detect(int fd, off_t offset, disk_format_t* out) {
uint8_t data[HEADER_SIZE];
if (lseek(fd, offset, SEEK_SET) < 0) {
fprintf(stderr, "Error seeking block device\n");
return ZX_ERR_IO;
}
if (read(fd, data, sizeof(data)) != sizeof(data)) {
fprintf(stderr, "Error reading block device\n");
return ZX_ERR_IO;
}
if (!memcmp(data, minfs_magic, sizeof(minfs_magic))) {
*out = DISK_FORMAT_MINFS;
} else if (!memcmp(data, blobfs_magic, sizeof(blobfs_magic))) {
*out = DISK_FORMAT_BLOBFS;
} else {
*out = DISK_FORMAT_UNKNOWN;
}
return ZX_OK;
}
zx_status_t Format::Create(const char* path, const char* type, fbl::unique_ptr<Format>* out) {
fbl::unique_fd fd(open(path, O_RDONLY));
if (!fd) {
fprintf(stderr, "Format::Create: Could not open %s\n", path);
return ZX_ERR_IO;
}
zx_status_t status;
disk_format_t part;
if ((status = Detect(fd.get(), 0, &part)) != ZX_OK) {
return status;
}
if (part == DISK_FORMAT_MINFS) {
// Found minfs partition
fbl::unique_ptr<Format> minfsFormat(new MinfsFormat(std::move(fd), type));
*out = std::move(minfsFormat);
return ZX_OK;
} else if (part == DISK_FORMAT_BLOBFS) {
// Found blobfs partition
fbl::unique_ptr<Format> blobfsFormat(new BlobfsFormat(std::move(fd), type));
*out = std::move(blobfsFormat);
return ZX_OK;
}
fprintf(stderr, "Disk format not supported\n");
return ZX_ERR_NOT_SUPPORTED;
}
zx_status_t Format::Check(fbl::unique_fd fd, off_t start, off_t end,
const fbl::Vector<size_t>& extent_lengths, disk_format_t part) {
if (part == DISK_FORMAT_BLOBFS) {
return blobfs::blobfs_fsck(std::move(fd), start, end, extent_lengths);
} else if (part == DISK_FORMAT_MINFS) {
return minfs::SparseFsck(std::move(fd), start, end, extent_lengths);
}
fprintf(stderr, "Format not supported\n");
return ZX_ERR_INVALID_ARGS;
}
zx_status_t Format::UsedDataSize(const fbl::unique_fd& fd, off_t start, off_t end,
const fbl::Vector<size_t>& extent_lengths, disk_format_t part,
uint64_t* out_size) {
if (part == DISK_FORMAT_BLOBFS) {
return blobfs::UsedDataSize(fd, out_size, start, end);
} else if (part == DISK_FORMAT_MINFS) {
fbl::unique_fd dupfd(dup(fd.get()));
if (!dupfd) {
fprintf(stderr, "Failed to duplicate fd\n");
return ZX_ERR_INTERNAL;
}
return minfs::SparseUsedDataSize(std::move(dupfd), start, end, extent_lengths, out_size);
}
fprintf(stderr, "Format not supported\n");
return ZX_ERR_INVALID_ARGS;
}
zx_status_t Format::UsedInodes(const fbl::unique_fd& fd, off_t start, off_t end,
const fbl::Vector<size_t>& extent_lengths, disk_format_t part,
uint64_t* out_inodes) {
if (part == DISK_FORMAT_BLOBFS) {
return blobfs::UsedInodes(fd, out_inodes, start, end);
} else if (part == DISK_FORMAT_MINFS) {
fbl::unique_fd dupfd(dup(fd.get()));
if (!dupfd) {
fprintf(stderr, "Failed to duplicate fd\n");
return ZX_ERR_INTERNAL;
}
return minfs::SparseUsedInodes(std::move(dupfd), start, end, extent_lengths, out_inodes);
}
fprintf(stderr, "Format not supported\n");
return ZX_ERR_INVALID_ARGS;
}
zx_status_t Format::UsedSize(const fbl::unique_fd& fd, off_t start, off_t end,
const fbl::Vector<size_t>& extent_lengths, disk_format_t part,
uint64_t* out_size) {
if (part == DISK_FORMAT_BLOBFS) {
return blobfs::UsedSize(fd, out_size, start, end);
} else if (part == DISK_FORMAT_MINFS) {
fbl::unique_fd dupfd(dup(fd.get()));
if (!dupfd) {
fprintf(stderr, "Failed to duplicate fd\n");
return ZX_ERR_INTERNAL;
}
return minfs::SparseUsedSize(std::move(dupfd), start, end, extent_lengths, out_size);
}
fprintf(stderr, "Format not supported\n");
return ZX_ERR_INVALID_ARGS;
}