1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "applypatch/data_writer.h"
16#include <cerrno>
17#include <cstdio>
18#include <fcntl.h>
19#include <memory>
20#include <string>
21#include <unistd.h>
22#include "applypatch/block_writer.h"
23#include "fs_manager/mount.h"
24#include "log/log.h"
25#include "raw_writer.h"
26
27namespace Updater {
28UpdaterEnv *DataWriter::env_ = nullptr;
29int DataWriter::OpenPath(const std::string &path)
30{
31    if (path.empty()) {
32        LOG(ERROR) << "Datawriter: partition name is empty.";
33        return -1;
34    }
35
36    if (access(path.c_str(), W_OK) < 0) {
37        LOG(ERROR) << "Datawriter: " << path << " is not writable.";
38        return -1;
39    }
40    char *realPath = realpath(path.c_str(), NULL);
41    if (realPath == nullptr) {
42        LOG(ERROR) << "realPath is NULL" << " : " << strerror(errno);
43        return -1;
44    }
45    int fd = open(realPath, O_RDWR | O_LARGEFILE);
46    free(realPath);
47    if (fd < 0) {
48        LOG(ERROR) << "Datawriter: open block device " << path << " failed " << " : " << strerror(errno);
49        return fd;
50    }
51    if (lseek(fd, 0, SEEK_SET) == -1) {
52        LOG(ERROR) << "Datawriter: seek " << path << "failed " << " : " << strerror(errno);
53        close(fd);
54        fd = -1;
55    }
56    return fd;
57}
58
59std::unique_ptr<DataWriter> DataWriter::CreateDataWriter(WriteMode mode, const std::string &path,
60    uint64_t offset)
61{
62    switch (mode) {
63        case WRITE_RAW:
64            return std::make_unique<RawWriter>(path, offset);
65        case WRITE_DECRYPT:
66            LOG(WARNING) << "Unsupported writer mode.";
67            break;
68        default:
69            break;
70    }
71    return nullptr;
72}
73
74UpdaterEnv *DataWriter::GetUpdaterEnv()
75{
76    return env_;
77}
78
79void DataWriter::SetUpdaterEnv(UpdaterEnv *env)
80{
81    env_ = env;
82}
83
84std::unique_ptr<DataWriter> DataWriter::CreateDataWriter(WriteMode mode, const std::string &path,
85    UpdaterEnv *env, uint64_t offset)
86{
87    env_ = env;
88    return CreateDataWriter(mode, path, offset);
89}
90
91std::unique_ptr<DataWriter> DataWriter::CreateDataWriter(const std::string &mode, const std::string &path,
92    const std::string &partName, uint64_t startAddr, uint64_t offset)
93{
94    if (auto it = constructorMap_.find(mode); it != constructorMap_.end()) {
95        return it->second(path, partName, startAddr, offset);
96    }
97    LOG(ERROR) << "create writer failed, can not find writer mode: " << mode;
98    return nullptr;
99}
100
101void DataWriter::ReleaseDataWriter(std::unique_ptr<DataWriter> &writer)
102{
103    writer.reset();
104}
105
106void DataWriter::RegisterDataWriter(const std::string &mode, WriterConstructor constructor)
107{
108    if (mode.empty() || constructor == nullptr) {
109        LOG(ERROR) << "invalid input";
110        return;
111    }
112    if (!constructorMap_.emplace(mode, constructor).second) {
113        LOG(ERROR) << "register writer failed, mode: " << mode;
114    }
115}
116} // namespace Updater
117