/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "applypatch/store.h" #include #include #include #include #include #include #include #include #include "applypatch/transfer_manager.h" #include "log/log.h" #include "utils.h" using namespace Updater::Utils; namespace Updater { void Store::DoFreeSpace(const std::string &directoryPath) { std::vector files; if (GetFilesFromDirectory(directoryPath, files, true) <= 0) { LOG(WARNING) << "Failed to get files for free space"; return; } for (const auto &file : files) { if (DeleteFile(file.c_str()) == -1) { LOG(ERROR) << "Failed to delete in do free space"; continue; } } } int32_t Store::FreeStore(const std::string &dirPath, const std::string &fileName) { if (dirPath.empty() || fileName.empty()) { return -1; } std::string path = dirPath + "/" + fileName; if (DeleteFile(path.c_str()) != -1) { return 0; } LOG(ERROR) << "Failed to delete " << path; return -1; } int32_t Store::CreateNewSpace(const std::string &path, bool needClear) { if (path.empty()) { LOG(ERROR) << "path is empty."; } std::string dirPath = path + '/'; struct stat fileStat {}; LOG(INFO) << "Create dir " << dirPath; if (stat(dirPath.c_str(), &fileStat) == -1) { if (errno != ENOENT) { LOG(ERROR) << "Create new space, failed to stat"; return -1; } if (MkdirRecursive(dirPath, S_IRWXU) != 0) { LOG(ERROR) << "Failed to make store"; return -1; } } else { if (!needClear) { return 0; } std::vector files {}; if (GetFilesFromDirectory(dirPath, files) < 0) { return -1; } if (files.empty()) { return 0; } std::vector::iterator iter = files.begin(); while (iter != files.end()) { if (DeleteFile(*iter) == 0) { LOG(INFO) << "Delete " << *iter; } iter++; } files.clear(); } return 0; } int32_t Store::WriteDataToStore(const std::string &dirPath, const std::string &fileName, const std::vector &buffer, int size) { if (dirPath.empty()) { return -1; } std::string pathTmp; if (!fileName.empty()) { pathTmp = dirPath + "/"; } std::string path = pathTmp + fileName; pathTmp = pathTmp + fileName; int fd = open(pathTmp.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fd == -1) { LOG(ERROR) << "Failed to create store, " << strerror(errno); return -1; } if (size < 0 || !WriteFully(fd, buffer.data(), static_cast(size))) { if (errno == EIO) { close(fd); return 1; } LOG(ERROR) << "Write to stash failed, " << size << " blocks to " << path; close(fd); return -1; } if (fsync(fd) == -1) { LOG(WARNING) << "Failed to fsync :" << strerror(errno); } close(fd); int fdd = open(dirPath.c_str(), O_RDONLY | O_DIRECTORY); if (fdd == -1) { LOG(ERROR) << "Failed to open"; return -1; } close(fdd); return 0; } int32_t Store::LoadDataFromStore(const std::string &dirPath, const std::string &fileName, std::vector &buffer) { LOG(INFO) << "Store base is " << dirPath << "/" << fileName; std::string path = dirPath; if (!fileName.empty()) { path = path + "/" + fileName; } struct stat fileStat {}; if (stat(path.c_str(), &fileStat) == -1) { LOG(DEBUG) << "Failed to stat"; return -1; } if (fileStat.st_size % H_BLOCK_SIZE != 0) { LOG(ERROR) << "Not multiple of block size 4096"; return -1; } int fd = open(path.c_str(), O_RDONLY); if (fd == -1) { LOG(ERROR) << "Failed to create"; return -1; } buffer.resize(fileStat.st_size); if (!ReadFully(fd, buffer.data(), fileStat.st_size)) { LOG(ERROR) << "Failed to read store data"; close(fd); fd = -1; return -1; } close(fd); fd = -1; return 0; } } // namespace Updater