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";
54 wur std::string getPath(const std::string &prefix, uid_t uid)
57 ss << RW_DATA_DIR << "/" << prefix << uid;
61 } // namespace anonymous
63 FileSystem::FileSystem(uid_t uid)
68 std::string FileSystem::getLegacyDBPath() const
70 return getPath(CKM_LEGACY_DB_PREFIX, m_uid);
73 std::string FileSystem::getDBPath() const
75 return getPath(CKM_DB_PREFIX, m_uid);
78 std::string FileSystem::getDKEKPath() const
80 return getPath(CKM_KEY_PREFIX, m_uid);
83 std::string FileSystem::getDBDEKPath() const
85 return getPath(CKM_DB_KEY_PREFIX, m_uid);
88 std::string FileSystem::getRemovedAppsPath() const
90 return getPath(CKM_REMOVED_APP_PREFIX, m_uid);
93 RawBuffer FileSystem::loadFile(const std::string &path) const
95 std::ifstream is(path);
97 if (is.fail() && ENOENT == errno)
101 auto description = GetErrnoString(errno);
102 ThrowErr(Exc::FileSystemFailed,
103 "Error opening file: ", path, " Reason: ", description);
106 std::istreambuf_iterator<char> begin(is), end;
107 std::vector<char> buff(begin,
108 end); // This trick does not work with boost vector
110 RawBuffer buffer(buff.size());
111 memcpy(buffer.data(), buff.data(), buff.size());
115 RawBuffer FileSystem::getDKEK() const
117 return loadFile(getDKEKPath());
120 RawBuffer FileSystem::getDBDEK() const
122 return loadFile(getDBDEKPath());
125 void FileSystem::saveFile(const std::string &path,
126 const RawBuffer &buffer) const
128 std::ofstream os(path, std::ios::out | std::ofstream::binary |
129 std::ofstream::trunc);
132 ThrowErr(Exc::FileSystemFailed, "Can't open file for writing: ", path);
134 std::copy(buffer.begin(), buffer.end(), std::ostreambuf_iterator<char>(os));
136 // Prevent desynchronization in battery remove test.
138 if (fsync(FstreamAccessors<std::ofstream>::GetFd(os)) != 0) { // flush kernel space buffer
139 auto desc = GetErrnoString(errno);
140 ThrowErr(Exc::FileSystemFailed, "Failed to sync file: ", path, " Reason: ", desc);
145 ThrowErr(Exc::FileSystemFailed, "Failed to save file: ", path);
148 void FileSystem::saveDKEK(const RawBuffer &buffer) const
150 saveFile(getDKEKPath(), buffer);
153 void FileSystem::saveDBDEK(const RawBuffer &buffer) const
155 saveFile(getDBDEKPath(), buffer);
158 void FileSystem::addRemovedApp(const ClientId &app) const
160 std::ofstream outfile;
161 outfile.open(getRemovedAppsPath(), std::ios_base::app);
162 outfile << app << std::endl;
165 if (outfile.fail()) {
166 auto desc = GetErrnoString(errno);
167 ThrowErr(Exc::FileSystemFailed,
168 "Could not update file: ", getRemovedAppsPath(), " Reason: ", desc);
172 ClientIdVector FileSystem::clearRemovedsApps() const
175 ClientIdVector removedApps;
177 std::ifstream removedAppsFile(getRemovedAppsPath());
179 if (removedAppsFile.is_open()) {
180 while (!removedAppsFile.eof()) {
181 getline(removedAppsFile, line);
184 removedApps.push_back(line);
187 removedAppsFile.close();
190 // truncate the contents
191 std::ofstream truncateFile;
192 truncateFile.open(getRemovedAppsPath(),
193 std::ofstream::out | std::ofstream::trunc);
194 truncateFile.close();
198 int FileSystem::init()
202 if ((mkdir(RW_DATA_DIR, S_IRWXU)) && (errno != EEXIST)) {
204 LogError("Error in mkdir " << RW_DATA_DIR << ". Reason: " << GetErrnoString(
206 return -1; // TODO set up some error code
212 UidVector FileSystem::getUIDsFromDBFile()
216 forEachFile(RW_DATA_DIR, [&uids](const std::string & filename) {
217 if (strncmp(filename.c_str(), CKM_KEY_PREFIX.c_str(), CKM_KEY_PREFIX.size()))
221 uids.emplace_back(static_cast<uid_t>(std::stoi((filename.c_str())
222 + CKM_KEY_PREFIX.size())));
223 } catch (const std::invalid_argument &) {
224 LogDebug("Error in extracting uid from db file. "
225 "Error=std::invalid_argument. "
226 "This will be ignored.File=" << filename);
227 } catch (const std::out_of_range &) {
228 LogDebug("Error in extracting uid from db file. "
229 "Error=std::out_of_range. "
230 "This will be ignored. File=" << filename);
239 int FileSystem::removeUserData() const
241 const auto unlinkUserPath = [](const std::string &path, const char *logDesc) {
242 if (!unlink(path.c_str()))
244 const auto err = errno;
247 LogDebug("Error in unlink user" << logDesc << ": " << path
248 << "Errno: " << err << " " << GetErrnoString(err));
252 return unlinkUserPath(getDBPath(), " database")
253 | unlinkUserPath(getLegacyDBPath(), " legacy database")
254 | unlinkUserPath(getDKEKPath(), " DKEK")
255 | unlinkUserPath(getDBDEKPath(), " DBDEK")
256 | unlinkUserPath(getRemovedAppsPath(), "'s Removed Apps File");
259 FileLock FileSystem::lock()
261 FileLock fl(CKM_LOCK_FILE.c_str());