1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at
6fb299fa2Sopenharmony_ci *
7fb299fa2Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb299fa2Sopenharmony_ci *
9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and
13fb299fa2Sopenharmony_ci * limitations under the License.
14fb299fa2Sopenharmony_ci */
15fb299fa2Sopenharmony_ci#include "applypatch/store.h"
16fb299fa2Sopenharmony_ci#include <algorithm>
17fb299fa2Sopenharmony_ci#include <cstdio>
18fb299fa2Sopenharmony_ci#include <fcntl.h>
19fb299fa2Sopenharmony_ci#include <limits>
20fb299fa2Sopenharmony_ci#include <sys/stat.h>
21fb299fa2Sopenharmony_ci#include <sys/types.h>
22fb299fa2Sopenharmony_ci#include <sys/vfs.h>
23fb299fa2Sopenharmony_ci#include <unistd.h>
24fb299fa2Sopenharmony_ci#include "applypatch/transfer_manager.h"
25fb299fa2Sopenharmony_ci#include "log/log.h"
26fb299fa2Sopenharmony_ci#include "utils.h"
27fb299fa2Sopenharmony_ci
28fb299fa2Sopenharmony_ciusing namespace Updater::Utils;
29fb299fa2Sopenharmony_ci
30fb299fa2Sopenharmony_cinamespace Updater {
31fb299fa2Sopenharmony_civoid Store::DoFreeSpace(const std::string &directoryPath)
32fb299fa2Sopenharmony_ci{
33fb299fa2Sopenharmony_ci    std::vector<std::string> files;
34fb299fa2Sopenharmony_ci    if (GetFilesFromDirectory(directoryPath, files, true) <= 0) {
35fb299fa2Sopenharmony_ci        LOG(WARNING) << "Failed to get files for free space";
36fb299fa2Sopenharmony_ci        return;
37fb299fa2Sopenharmony_ci    }
38fb299fa2Sopenharmony_ci    for (const auto &file : files) {
39fb299fa2Sopenharmony_ci        if (DeleteFile(file.c_str()) == -1) {
40fb299fa2Sopenharmony_ci            LOG(ERROR) << "Failed to delete in do free space";
41fb299fa2Sopenharmony_ci            continue;
42fb299fa2Sopenharmony_ci        }
43fb299fa2Sopenharmony_ci    }
44fb299fa2Sopenharmony_ci}
45fb299fa2Sopenharmony_ci
46fb299fa2Sopenharmony_ciint32_t Store::FreeStore(const std::string &dirPath, const std::string &fileName)
47fb299fa2Sopenharmony_ci{
48fb299fa2Sopenharmony_ci    if (dirPath.empty() || fileName.empty()) {
49fb299fa2Sopenharmony_ci        return -1;
50fb299fa2Sopenharmony_ci    }
51fb299fa2Sopenharmony_ci    std::string path = dirPath + "/" + fileName;
52fb299fa2Sopenharmony_ci    if (DeleteFile(path.c_str()) != -1) {
53fb299fa2Sopenharmony_ci        return 0;
54fb299fa2Sopenharmony_ci    }
55fb299fa2Sopenharmony_ci    LOG(ERROR) << "Failed to delete " << path;
56fb299fa2Sopenharmony_ci    return -1;
57fb299fa2Sopenharmony_ci}
58fb299fa2Sopenharmony_ci
59fb299fa2Sopenharmony_ciint32_t Store::CreateNewSpace(const std::string &path, bool needClear)
60fb299fa2Sopenharmony_ci{
61fb299fa2Sopenharmony_ci    if (path.empty()) {
62fb299fa2Sopenharmony_ci        LOG(ERROR) << "path is empty.";
63fb299fa2Sopenharmony_ci    }
64fb299fa2Sopenharmony_ci    std::string dirPath = path + '/';
65fb299fa2Sopenharmony_ci    struct stat fileStat {};
66fb299fa2Sopenharmony_ci    LOG(INFO) << "Create dir " << dirPath;
67fb299fa2Sopenharmony_ci    if (stat(dirPath.c_str(), &fileStat) == -1) {
68fb299fa2Sopenharmony_ci        if (errno != ENOENT) {
69fb299fa2Sopenharmony_ci            LOG(ERROR) << "Create new space, failed to stat";
70fb299fa2Sopenharmony_ci            return -1;
71fb299fa2Sopenharmony_ci        }
72fb299fa2Sopenharmony_ci        if (MkdirRecursive(dirPath, S_IRWXU) != 0) {
73fb299fa2Sopenharmony_ci            LOG(ERROR) << "Failed to make store";
74fb299fa2Sopenharmony_ci            return -1;
75fb299fa2Sopenharmony_ci        }
76fb299fa2Sopenharmony_ci    } else {
77fb299fa2Sopenharmony_ci        if (!needClear) {
78fb299fa2Sopenharmony_ci            return 0;
79fb299fa2Sopenharmony_ci        }
80fb299fa2Sopenharmony_ci        std::vector<std::string> files {};
81fb299fa2Sopenharmony_ci        if (GetFilesFromDirectory(dirPath, files) < 0) {
82fb299fa2Sopenharmony_ci            return -1;
83fb299fa2Sopenharmony_ci        }
84fb299fa2Sopenharmony_ci        if (files.empty()) {
85fb299fa2Sopenharmony_ci            return 0;
86fb299fa2Sopenharmony_ci        }
87fb299fa2Sopenharmony_ci        std::vector<std::string>::iterator iter = files.begin();
88fb299fa2Sopenharmony_ci        while (iter != files.end()) {
89fb299fa2Sopenharmony_ci            if (DeleteFile(*iter) == 0) {
90fb299fa2Sopenharmony_ci                LOG(INFO) << "Delete " << *iter;
91fb299fa2Sopenharmony_ci            }
92fb299fa2Sopenharmony_ci            iter++;
93fb299fa2Sopenharmony_ci        }
94fb299fa2Sopenharmony_ci        files.clear();
95fb299fa2Sopenharmony_ci    }
96fb299fa2Sopenharmony_ci    return 0;
97fb299fa2Sopenharmony_ci}
98fb299fa2Sopenharmony_ci
99fb299fa2Sopenharmony_ciint32_t Store::WriteDataToStore(const std::string &dirPath, const std::string &fileName,
100fb299fa2Sopenharmony_ci    const std::vector<uint8_t> &buffer, int size)
101fb299fa2Sopenharmony_ci{
102fb299fa2Sopenharmony_ci    if (dirPath.empty()) {
103fb299fa2Sopenharmony_ci        return -1;
104fb299fa2Sopenharmony_ci    }
105fb299fa2Sopenharmony_ci    std::string pathTmp;
106fb299fa2Sopenharmony_ci    if (!fileName.empty()) {
107fb299fa2Sopenharmony_ci        pathTmp = dirPath + "/";
108fb299fa2Sopenharmony_ci    }
109fb299fa2Sopenharmony_ci    std::string path = pathTmp + fileName;
110fb299fa2Sopenharmony_ci    pathTmp = pathTmp + fileName;
111fb299fa2Sopenharmony_ci
112fb299fa2Sopenharmony_ci    int fd = open(pathTmp.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
113fb299fa2Sopenharmony_ci    if (fd == -1) {
114fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to create store, " << strerror(errno);
115fb299fa2Sopenharmony_ci        return -1;
116fb299fa2Sopenharmony_ci    }
117fb299fa2Sopenharmony_ci    if (size < 0 || !WriteFully(fd, buffer.data(), static_cast<size_t>(size))) {
118fb299fa2Sopenharmony_ci        if (errno == EIO) {
119fb299fa2Sopenharmony_ci            close(fd);
120fb299fa2Sopenharmony_ci            return 1;
121fb299fa2Sopenharmony_ci        }
122fb299fa2Sopenharmony_ci        LOG(ERROR) << "Write to stash failed, " << size << " blocks to " << path;
123fb299fa2Sopenharmony_ci        close(fd);
124fb299fa2Sopenharmony_ci        return -1;
125fb299fa2Sopenharmony_ci    }
126fb299fa2Sopenharmony_ci    if (fsync(fd) == -1) {
127fb299fa2Sopenharmony_ci        LOG(WARNING) << "Failed to fsync :" << strerror(errno);
128fb299fa2Sopenharmony_ci    }
129fb299fa2Sopenharmony_ci    close(fd);
130fb299fa2Sopenharmony_ci
131fb299fa2Sopenharmony_ci    int fdd = open(dirPath.c_str(), O_RDONLY | O_DIRECTORY);
132fb299fa2Sopenharmony_ci    if (fdd == -1) {
133fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to open";
134fb299fa2Sopenharmony_ci        return -1;
135fb299fa2Sopenharmony_ci    }
136fb299fa2Sopenharmony_ci    close(fdd);
137fb299fa2Sopenharmony_ci    return 0;
138fb299fa2Sopenharmony_ci}
139fb299fa2Sopenharmony_ci
140fb299fa2Sopenharmony_ciint32_t Store::LoadDataFromStore(const std::string &dirPath, const std::string &fileName,
141fb299fa2Sopenharmony_ci    std::vector<uint8_t> &buffer)
142fb299fa2Sopenharmony_ci{
143fb299fa2Sopenharmony_ci    LOG(INFO) << "Store base is " << dirPath << "/" << fileName;
144fb299fa2Sopenharmony_ci    std::string path = dirPath;
145fb299fa2Sopenharmony_ci    if (!fileName.empty()) {
146fb299fa2Sopenharmony_ci        path = path + "/" + fileName;
147fb299fa2Sopenharmony_ci    }
148fb299fa2Sopenharmony_ci    struct stat fileStat {};
149fb299fa2Sopenharmony_ci    if (stat(path.c_str(), &fileStat) == -1) {
150fb299fa2Sopenharmony_ci        LOG(DEBUG) << "Failed to stat";
151fb299fa2Sopenharmony_ci        return -1;
152fb299fa2Sopenharmony_ci    }
153fb299fa2Sopenharmony_ci    if (fileStat.st_size % H_BLOCK_SIZE != 0) {
154fb299fa2Sopenharmony_ci        LOG(ERROR) << "Not multiple of block size 4096";
155fb299fa2Sopenharmony_ci        return -1;
156fb299fa2Sopenharmony_ci    }
157fb299fa2Sopenharmony_ci
158fb299fa2Sopenharmony_ci    int fd = open(path.c_str(), O_RDONLY);
159fb299fa2Sopenharmony_ci    if (fd == -1) {
160fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to create";
161fb299fa2Sopenharmony_ci        return -1;
162fb299fa2Sopenharmony_ci    }
163fb299fa2Sopenharmony_ci    buffer.resize(fileStat.st_size);
164fb299fa2Sopenharmony_ci    if (!ReadFully(fd, buffer.data(), fileStat.st_size)) {
165fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to read store data";
166fb299fa2Sopenharmony_ci        close(fd);
167fb299fa2Sopenharmony_ci        fd = -1;
168fb299fa2Sopenharmony_ci        return -1;
169fb299fa2Sopenharmony_ci    }
170fb299fa2Sopenharmony_ci    close(fd);
171fb299fa2Sopenharmony_ci    fd = -1;
172fb299fa2Sopenharmony_ci    return 0;
173fb299fa2Sopenharmony_ci}
174fb299fa2Sopenharmony_ci} // namespace Updater
175