2 * Copyright (c) 2000-2020 Samsung Electronics Co., Ltd. All rights reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
17 * @file file-system.cpp
18 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
20 * @brief File related operations.
25 #include <sys/types.h>
35 #include <dpl/errno_string.h>
36 #include <dpl/fstream_accessors.h>
37 #include <dpl/log/log.h>
39 #include <exception.h>
40 #include <for-each-file.h>
41 #include <file-system.h>
47 const std::string CKM_KEY_PREFIX = "key-";
48 const std::string CKM_DB_KEY_PREFIX = "db-key-";
49 const std::string CKM_LEGACY_DB_PREFIX = "db-";
50 const std::string CKM_DB_PREFIX = "db0-";
51 const std::string CKM_REMOVED_APP_PREFIX = "removed-app-";
52 const std::string CKM_LOCK_FILE = RUN_DIR "/" SERVICE_NAME "/key-manager.pid";
53 const std::string CKM_TEMP_POSTFIX = ".tmp";
55 wur std::string getPath(const std::string &prefix, uid_t uid)
58 ss << RW_DATA_DIR << "/" << prefix << uid;
62 } // namespace anonymous
64 FileSystem::FileSystem(uid_t uid)
69 std::string FileSystem::getLegacyDBPath() const
71 return getPath(CKM_LEGACY_DB_PREFIX, m_uid);
74 std::string FileSystem::getDBPath() const
76 return getPath(CKM_DB_PREFIX, m_uid);
79 std::string FileSystem::getDKEKPath() const
81 return getPath(CKM_KEY_PREFIX, m_uid);
84 std::string FileSystem::getDBDEKPath() const
86 return getPath(CKM_DB_KEY_PREFIX, m_uid);
89 std::string FileSystem::getRemovedAppsPath() const
91 return getPath(CKM_REMOVED_APP_PREFIX, m_uid);
94 RawBuffer FileSystem::loadFile(const std::string &path) const
96 std::ifstream is(path);
98 if (is.fail() && ENOENT == errno)
102 auto description = GetErrnoString(errno);
103 ThrowErr(Exc::FileSystemFailed,
104 "Error opening file: ", path, " Reason: ", description);
107 std::istreambuf_iterator<char> begin(is), end;
108 std::vector<char> buff(begin,
109 end); // This trick does not work with boost vector
111 RawBuffer buffer(buff.size());
112 memcpy(buffer.data(), buff.data(), buff.size());
116 RawBuffer FileSystem::getDKEK() const
118 return loadFile(getDKEKPath());
121 RawBuffer FileSystem::getDBDEK() const
123 return loadFile(getDBDEKPath());
126 void FileSystem::saveFile(const std::string &path,
127 const RawBuffer &buffer) const
129 std::ofstream os(path + CKM_TEMP_POSTFIX, std::ios::out |
130 std::ofstream::binary | std::ofstream::trunc);
133 ThrowErr(Exc::FileSystemFailed, "Can't open file for writing: ", path);
135 std::copy(buffer.begin(), buffer.end(), std::ostreambuf_iterator<char>(os));
137 // Prevent desynchronization in battery remove test.
139 if (fsync(FstreamAccessors<std::ofstream>::GetFd(os)) != 0) { // flush kernel space buffer
140 auto desc = GetErrnoString(errno);
141 ThrowErr(Exc::FileSystemFailed, "Failed to sync file: ", path, " Reason: ", desc);
146 ThrowErr(Exc::FileSystemFailed, "Failed to save file: ", path);
148 if (std::rename((path + CKM_TEMP_POSTFIX).c_str(), path.c_str()))
149 ThrowErr(Exc::FileSystemFailed, "Can't rename file: ", path);
152 void FileSystem::saveDKEK(const RawBuffer &buffer) const
154 std::string path(getDKEKPath());
155 saveFile(path, buffer);
158 void FileSystem::saveDBDEK(const RawBuffer &buffer) const
160 std::string path(getDBDEKPath());
161 saveFile(path, buffer);
164 void FileSystem::addRemovedApp(const ClientId &app) const
166 std::ofstream outfile;
167 outfile.open(getRemovedAppsPath(), std::ios_base::app);
168 outfile << app << std::endl;
171 if (outfile.fail()) {
172 auto desc = GetErrnoString(errno);
173 ThrowErr(Exc::FileSystemFailed,
174 "Could not update file: ", getRemovedAppsPath(), " Reason: ", desc);
178 ClientIdVector FileSystem::clearRemovedsApps() const
181 ClientIdVector removedApps;
183 std::ifstream removedAppsFile(getRemovedAppsPath());
185 if (removedAppsFile.is_open()) {
186 while (!removedAppsFile.eof()) {
187 getline(removedAppsFile, line);
190 removedApps.push_back(line);
193 removedAppsFile.close();
196 // truncate the contents
197 std::ofstream truncateFile;
198 truncateFile.open(getRemovedAppsPath(),
199 std::ofstream::out | std::ofstream::trunc);
200 truncateFile.close();
204 int FileSystem::init()
208 if ((mkdir(RW_DATA_DIR, S_IRWXU)) && (errno != EEXIST)) {
210 LogError("Error in mkdir " << RW_DATA_DIR << ". Reason: " << GetErrnoString(
212 return -1; // TODO set up some error code
218 UidVector FileSystem::getUIDsFromDBFile()
222 forEachFile(RW_DATA_DIR, [&uids](const std::string & filename) {
223 if (strncmp(filename.c_str(), CKM_KEY_PREFIX.c_str(), CKM_KEY_PREFIX.size()))
227 uids.emplace_back(static_cast<uid_t>(std::stoi((filename.c_str())
228 + CKM_KEY_PREFIX.size())));
229 } catch (const std::invalid_argument &) {
230 LogDebug("Error in extracting uid from db file. "
231 "Error=std::invalid_argument. "
232 "This will be ignored.File=" << filename);
233 } catch (const std::out_of_range &) {
234 LogDebug("Error in extracting uid from db file. "
235 "Error=std::out_of_range. "
236 "This will be ignored. File=" << filename);
245 int FileSystem::removeUserData() const
247 const auto unlinkUserPath = [](const std::string &path, const char *logDesc) {
248 if (!unlink(path.c_str()))
250 const auto err = errno;
253 LogDebug("Error in unlink user" << logDesc << ": " << path
254 << "Errno: " << err << " " << GetErrnoString(err));
258 return unlinkUserPath(getDBPath(), " database")
259 | unlinkUserPath(getLegacyDBPath(), " legacy database")
260 | unlinkUserPath(getDKEKPath(), " DKEK")
261 | unlinkUserPath(getDBDEKPath(), " DBDEK")
262 | unlinkUserPath(getRemovedAppsPath(), "'s Removed Apps File");
265 FileLock FileSystem::lock()
267 FileLock fl(CKM_LOCK_FILE.c_str());