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/store.h" 16#include <algorithm> 17#include <cstdio> 18#include <fcntl.h> 19#include <limits> 20#include <sys/stat.h> 21#include <sys/types.h> 22#include <sys/vfs.h> 23#include <unistd.h> 24#include "applypatch/transfer_manager.h" 25#include "log/log.h" 26#include "utils.h" 27 28using namespace Updater::Utils; 29 30namespace Updater { 31void Store::DoFreeSpace(const std::string &directoryPath) 32{ 33 std::vector<std::string> files; 34 if (GetFilesFromDirectory(directoryPath, files, true) <= 0) { 35 LOG(WARNING) << "Failed to get files for free space"; 36 return; 37 } 38 for (const auto &file : files) { 39 if (DeleteFile(file.c_str()) == -1) { 40 LOG(ERROR) << "Failed to delete in do free space"; 41 continue; 42 } 43 } 44} 45 46int32_t Store::FreeStore(const std::string &dirPath, const std::string &fileName) 47{ 48 if (dirPath.empty() || fileName.empty()) { 49 return -1; 50 } 51 std::string path = dirPath + "/" + fileName; 52 if (DeleteFile(path.c_str()) != -1) { 53 return 0; 54 } 55 LOG(ERROR) << "Failed to delete " << path; 56 return -1; 57} 58 59int32_t Store::CreateNewSpace(const std::string &path, bool needClear) 60{ 61 if (path.empty()) { 62 LOG(ERROR) << "path is empty."; 63 } 64 std::string dirPath = path + '/'; 65 struct stat fileStat {}; 66 LOG(INFO) << "Create dir " << dirPath; 67 if (stat(dirPath.c_str(), &fileStat) == -1) { 68 if (errno != ENOENT) { 69 LOG(ERROR) << "Create new space, failed to stat"; 70 return -1; 71 } 72 if (MkdirRecursive(dirPath, S_IRWXU) != 0) { 73 LOG(ERROR) << "Failed to make store"; 74 return -1; 75 } 76 } else { 77 if (!needClear) { 78 return 0; 79 } 80 std::vector<std::string> files {}; 81 if (GetFilesFromDirectory(dirPath, files) < 0) { 82 return -1; 83 } 84 if (files.empty()) { 85 return 0; 86 } 87 std::vector<std::string>::iterator iter = files.begin(); 88 while (iter != files.end()) { 89 if (DeleteFile(*iter) == 0) { 90 LOG(INFO) << "Delete " << *iter; 91 } 92 iter++; 93 } 94 files.clear(); 95 } 96 return 0; 97} 98 99int32_t Store::WriteDataToStore(const std::string &dirPath, const std::string &fileName, 100 const std::vector<uint8_t> &buffer, int size) 101{ 102 if (dirPath.empty()) { 103 return -1; 104 } 105 std::string pathTmp; 106 if (!fileName.empty()) { 107 pathTmp = dirPath + "/"; 108 } 109 std::string path = pathTmp + fileName; 110 pathTmp = pathTmp + fileName; 111 112 int fd = open(pathTmp.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 113 if (fd == -1) { 114 LOG(ERROR) << "Failed to create store, " << strerror(errno); 115 return -1; 116 } 117 if (size < 0 || !WriteFully(fd, buffer.data(), static_cast<size_t>(size))) { 118 if (errno == EIO) { 119 close(fd); 120 return 1; 121 } 122 LOG(ERROR) << "Write to stash failed, " << size << " blocks to " << path; 123 close(fd); 124 return -1; 125 } 126 if (fsync(fd) == -1) { 127 LOG(WARNING) << "Failed to fsync :" << strerror(errno); 128 } 129 close(fd); 130 131 int fdd = open(dirPath.c_str(), O_RDONLY | O_DIRECTORY); 132 if (fdd == -1) { 133 LOG(ERROR) << "Failed to open"; 134 return -1; 135 } 136 close(fdd); 137 return 0; 138} 139 140int32_t Store::LoadDataFromStore(const std::string &dirPath, const std::string &fileName, 141 std::vector<uint8_t> &buffer) 142{ 143 LOG(INFO) << "Store base is " << dirPath << "/" << fileName; 144 std::string path = dirPath; 145 if (!fileName.empty()) { 146 path = path + "/" + fileName; 147 } 148 struct stat fileStat {}; 149 if (stat(path.c_str(), &fileStat) == -1) { 150 LOG(DEBUG) << "Failed to stat"; 151 return -1; 152 } 153 if (fileStat.st_size % H_BLOCK_SIZE != 0) { 154 LOG(ERROR) << "Not multiple of block size 4096"; 155 return -1; 156 } 157 158 int fd = open(path.c_str(), O_RDONLY); 159 if (fd == -1) { 160 LOG(ERROR) << "Failed to create"; 161 return -1; 162 } 163 buffer.resize(fileStat.st_size); 164 if (!ReadFully(fd, buffer.data(), fileStat.st_size)) { 165 LOG(ERROR) << "Failed to read store data"; 166 close(fd); 167 fd = -1; 168 return -1; 169 } 170 close(fd); 171 fd = -1; 172 return 0; 173} 174} // namespace Updater 175