1// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "fvm/format.h"
6
7zx_status_t Format::Detect(int fd, off_t offset, disk_format_t* out) {
8    uint8_t data[HEADER_SIZE];
9    if (lseek(fd, offset, SEEK_SET) < 0) {
10        fprintf(stderr, "Error seeking block device\n");
11        return ZX_ERR_IO;
12    }
13
14    if (read(fd, data, sizeof(data)) != sizeof(data)) {
15        fprintf(stderr, "Error reading block device\n");
16        return ZX_ERR_IO;
17    }
18
19    if (!memcmp(data, minfs_magic, sizeof(minfs_magic))) {
20        *out = DISK_FORMAT_MINFS;
21    } else if (!memcmp(data, blobfs_magic, sizeof(blobfs_magic))) {
22        *out = DISK_FORMAT_BLOBFS;
23    } else {
24        *out = DISK_FORMAT_UNKNOWN;
25    }
26
27    return ZX_OK;
28}
29
30zx_status_t Format::Create(const char* path, const char* type, fbl::unique_ptr<Format>* out) {
31    fbl::unique_fd fd(open(path, O_RDONLY));
32    if (!fd) {
33        fprintf(stderr, "Format::Create: Could not open %s\n", path);
34        return ZX_ERR_IO;
35    }
36
37    zx_status_t status;
38    disk_format_t part;
39    if ((status = Detect(fd.get(), 0, &part)) != ZX_OK) {
40        return status;
41    }
42
43    fbl::AllocChecker ac;
44    if (part == DISK_FORMAT_MINFS) {
45        // Found minfs partition
46        fbl::unique_ptr<Format> minfsFormat(new (&ac) MinfsFormat(fbl::move(fd), type));
47        if (!ac.check()) {
48            return ZX_ERR_NO_MEMORY;
49        }
50
51        *out = fbl::move(minfsFormat);
52        return ZX_OK;
53    } else if (part == DISK_FORMAT_BLOBFS) {
54        // Found blobfs partition
55        fbl::unique_ptr<Format> blobfsFormat(new (&ac) BlobfsFormat(fbl::move(fd), type));
56        if (!ac.check()) {
57            return ZX_ERR_NO_MEMORY;
58        }
59
60        *out = fbl::move(blobfsFormat);
61        return ZX_OK;
62    }
63
64    fprintf(stderr, "Disk format not supported\n");
65    return ZX_ERR_NOT_SUPPORTED;
66}
67
68zx_status_t Format::Check(fbl::unique_fd fd, off_t start, off_t end,
69                          const fbl::Vector<size_t>& extent_lengths, disk_format_t part) {
70    if (part == DISK_FORMAT_BLOBFS) {
71        return blobfs::blobfs_fsck(fbl::move(fd), start, end, extent_lengths);
72    } else if (part == DISK_FORMAT_MINFS) {
73        return minfs::minfs_fsck(fbl::move(fd), start, end, extent_lengths);
74    }
75
76    fprintf(stderr, "Format not supported\n");
77    return ZX_ERR_INVALID_ARGS;
78}
79