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 <inttypes.h>
6
7#include <fbl/unique_fd.h>
8
9#include "fvm/container.h"
10
11zx_status_t Container::Create(const char* path, off_t offset, off_t length,
12                              uint32_t flags, fbl::unique_ptr<Container>* container) {
13    if ((flags & ~fvm::kSparseFlagAllValid) != 0) {
14        fprintf(stderr, "Invalid flags: %08" PRIx32 "\n", flags);
15        return -1;
16    }
17
18    fbl::unique_fd fd(open(path, O_RDONLY));
19    if (!fd) {
20        fprintf(stderr, "Unable to open path %s\n", path);
21        return -1;
22    }
23
24    uint8_t data[HEADER_SIZE];
25    if (lseek(fd.get(), offset, SEEK_SET) < 0) {
26        fprintf(stderr, "Error seeking block device\n");
27        return -1;
28    }
29
30    if (read(fd.get(), data, sizeof(data)) != sizeof(data)) {
31        fprintf(stderr, "Error reading block device\n");
32        return -1;
33    }
34
35    fbl::AllocChecker ac;
36    if (!memcmp(data, fvm_magic, sizeof(fvm_magic))) {
37        fvm::fvm_t* sb = reinterpret_cast<fvm::fvm_t*>(data);
38
39        // Found fvm container
40        fbl::unique_ptr<Container> fvmContainer(new (&ac) FvmContainer(path, sb->slice_size,
41                                                                       offset, length));
42        if (!ac.check()) {
43            return ZX_ERR_NO_MEMORY;
44        }
45        *container = fbl::move(fvmContainer);
46        return ZX_OK;
47    }
48
49    fvm::sparse_image_t* image = reinterpret_cast<fvm::sparse_image_t*>(data);
50    if (image->magic == fvm::kSparseFormatMagic) {
51        if (offset > 0) {
52            fprintf(stderr, "Invalid offset for sparse file\n");
53            return ZX_ERR_INVALID_ARGS;
54        }
55
56        // Found sparse container
57        fbl::unique_ptr<Container> sparseContainer(new (&ac) SparseContainer(path,
58                                                                             image->slice_size,
59                                                                             flags));
60        if (!ac.check()) {
61            return ZX_ERR_NO_MEMORY;
62        }
63
64        *container = fbl::move(sparseContainer);
65        return ZX_OK;
66    }
67
68    fprintf(stderr, "File format not supported\n");
69    return ZX_ERR_NOT_SUPPORTED;
70}
71
72Container::Container(const char* path, size_t slice_size, uint32_t flags)
73    : dirty_(false), slice_size_(slice_size), flags_(flags) {
74    snprintf(path_, sizeof(path_), "%s", path);
75}
76
77Container::~Container() {}
78