2 * Copyright (c) 2000 - 2014 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 FileSystem.cpp
18 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
20 * @brief Sample service implementation.
25 #include <sys/types.h>
36 #include <dpl/errno_string.h>
37 #include <dpl/fstream_accessors.h>
38 #include <dpl/log/log.h>
40 #include <file-system.h>
44 const std::string CKM_DATA_PATH = "/opt/data/ckm/";
45 const std::string CKM_KEY_PREFIX = "key-";
46 const std::string CKM_KEY_BACKUP_PREFIX = "key-backup-";
47 const std::string CKM_DB_KEY_PREFIX = "db-key-";
48 const std::string CKM_DB_PREFIX = "db-";
49 const std::string CKM_REMOVED_APP_PREFIX = "removed-app-";
50 const std::string CKM_LOCK_FILE = "/run/key-manager.pid";
52 } // namespace anonymous
56 FileSystem::FileSystem(const ClientID &clientID)
57 : m_clientID(clientID)
60 std::string FileSystem::getDBPath() const
63 ss << CKM_DATA_PATH << CKM_DB_PREFIX << m_clientID;
67 std::string FileSystem::getDKEKPath() const {
69 ss << CKM_DATA_PATH << CKM_KEY_PREFIX << m_clientID;
73 std::string FileSystem::getDKEKBackupPath() const {
75 ss << CKM_DATA_PATH << CKM_KEY_BACKUP_PREFIX << m_clientID;
79 std::string FileSystem::getDBDEKPath() const {
81 ss << CKM_DATA_PATH << CKM_DB_KEY_PREFIX << m_clientID;
85 std::string FileSystem::getRemovedAppsPath() const {
87 ss << CKM_DATA_PATH << CKM_REMOVED_APP_PREFIX << m_clientID;
91 RawBuffer FileSystem::loadFile(const std::string &path) const {
92 std::ifstream is(path);
94 if (is.fail() && ENOENT == errno)
98 auto description = GetErrnoString(errno);
99 LogError("Error opening file: " << path << " Reason: " << description);
100 ThrowMsg(Exception::OpenFailed,
101 "Error opening file: " << path << " Reason: " << description);
104 std::istreambuf_iterator<char> begin(is),end;
105 std::vector<char> buff(begin,end); // This trick does not work with boost vector
107 RawBuffer buffer(buff.size());
108 memcpy(buffer.data(), buff.data(), buff.size());
112 RawBuffer FileSystem::getDKEK() const
114 return loadFile(getDKEKPath());
117 RawBuffer FileSystem::getDKEKBackup() const
119 return loadFile(getDKEKBackupPath());
122 RawBuffer FileSystem::getDBDEK() const
124 return loadFile(getDBDEKPath());
127 void FileSystem::saveFile(const std::string &path, const RawBuffer &buffer) const {
128 std::ofstream os(path, std::ios::out | std::ofstream::binary | std::ofstream::trunc);
129 std::copy(buffer.begin(), buffer.end(), std::ostreambuf_iterator<char>(os));
131 // Prevent desynchronization in batter remove test.
133 fsync(FstreamAccessors<std::ofstream>::GetFd(os)); // flush kernel space buffer
137 ThrowMsg(Exception::SaveFailed, "Failed to save file: " << path);
140 void FileSystem::saveDKEK(const RawBuffer &buffer) const {
141 saveFile(getDKEKPath(), buffer);
144 void FileSystem::moveFile(const std::string &from, const std::string &to) const {
145 if (0 == ::rename(from.c_str(), to.c_str())) {
148 auto description = GetErrnoString(errno);
149 LogError("Error during rename file DKEKBackup to DKEK: " << description);
150 ThrowMsg(Exception::RenameFailed,
151 "Error during rename file DKEKBackup to DKEK: " << description);
154 void FileSystem::restoreDKEK() const {
155 moveFile(getDKEKBackupPath(), getDKEKPath());
158 void FileSystem::createDKEKBackup() const {
159 moveFile(getDKEKPath(), getDKEKBackupPath());
162 void FileSystem::removeDKEKBackup() const {
163 if (0 == unlink(getDKEKBackupPath().c_str())) {
166 // Backup is accessible only during "change password transaction"
167 auto description = GetErrnoString(errno);
168 LogDebug("Error in unlink file DKEKBackup: " << description);
171 void FileSystem::saveDBDEK(const RawBuffer &buffer) const {
172 saveFile(getDBDEKPath(), buffer);
175 void FileSystem::addRemovedApp(const std::string &smackLabel) const
177 std::ofstream outfile;
178 outfile.open(getRemovedAppsPath(), std::ios_base::app);
179 outfile << smackLabel << std::endl;
181 if (outfile.fail()) {
182 auto desc = GetErrnoString(errno);
183 LogError("Could not update file: " << getRemovedAppsPath() << " Reason: " << desc);
184 ThrowMsg(Exception::SaveFailed,
185 "Could not update file: " << getRemovedAppsPath() << " Reason: " << desc);
189 AppLabelVector FileSystem::clearRemovedsApps() const
192 AppLabelVector removedApps;
194 std::ifstream removedAppsFile(getRemovedAppsPath());
195 if (removedAppsFile.is_open()) {
196 while (! removedAppsFile.eof() ) {
197 getline (removedAppsFile,line);
199 removedApps.push_back(line);
201 removedAppsFile.close();
203 // truncate the contents
204 std::ofstream truncateFile;
205 truncateFile.open(getRemovedAppsPath(), std::ofstream::out | std::ofstream::trunc);
206 truncateFile.close();
210 int FileSystem::init() {
212 if ((mkdir(CKM_DATA_PATH.c_str(), 0700)) && (errno != EEXIST)) {
214 LogError("Error in mkdir " << CKM_DATA_PATH << ". Reason: " << GetErrnoString(err));
215 return -1; // TODO set up some error code
220 ClientIDVector FileSystem::getClientIDsFromDBFile(const std::string zone) {
221 ClientIDVector clientIDVec;
222 std::unique_ptr<DIR, std::function<int(DIR*)>>
223 dirp(::opendir(CKM_DATA_PATH.c_str()), ::closedir);
227 LogError("Error in opendir. Data directory could not be read. Error: " << GetErrnoString(err));
228 return ClientIDVector();
231 size_t len = offsetof(struct dirent, d_name) + pathconf(CKM_DATA_PATH.c_str(), _PC_NAME_MAX) + 1;
232 std::unique_ptr<struct dirent, std::function<void(void*)>>
233 pEntry(static_cast<struct dirent*>(::malloc(len)), ::free);
236 LogError("Memory allocation failed.");
237 return ClientIDVector();
240 struct dirent* pDirEntry = NULL;
242 while ( (!readdir_r(dirp.get(), pEntry.get(), &pDirEntry)) && pDirEntry ) {
243 if (strncmp(pDirEntry->d_name, CKM_KEY_PREFIX.c_str(), CKM_KEY_PREFIX.size())) {
244 LogDebug("Not DomainKEK file.");
247 #ifdef DB_PER_ZONE_ENABLE
248 if (strlen(pDirEntry->d_name + CKM_KEY_PREFIX.size()) <= zone.size()) {
249 LogError("Should not happen. "
250 "Key file[" << pDirEntry->d_name << "] clientID(zone + uid) length should be longer than zone name size");
253 if (strncmp(pDirEntry->d_name + CKM_KEY_PREFIX.size(), zone.c_str(), zone.size())) {
254 LogDebug("Another zone's DomainKEK file.");
261 clientIDVec.push_back(pDirEntry->d_name + CKM_KEY_PREFIX.size());
262 } catch (const std::invalid_argument) {
263 LogError("Error in extracting uid from db file. Error=std::invalid_argument."
264 "This will be ignored.File=" << pDirEntry->d_name << "");
265 } catch(const std::out_of_range) {
266 LogError("Error in extracting uid from db file. Error=std::out_of_range."
267 "This will be ignored. File="<< pDirEntry->d_name << "");
273 int FileSystem::removeUserData() const {
275 if (removeFile(getDBPath())
276 || removeFile(getDKEKPath())
277 || removeFile(getDKEKBackupPath())
278 || removeFile(getDBDEKPath())
279 || removeFile(getRemovedAppsPath())) {
287 int FileSystem::removeFile(const std::string &path) const
289 if (access(path.c_str(), F_OK) == 0
290 && unlink(path.c_str()) != 0) {
294 LogError("Unlink Path[" << path
295 << "] Errno[" << errno
296 << "] ErrnoString[" << GetErrnoString(err) << "]");
304 FileLock FileSystem::lock()
306 FileLock fl(CKM_LOCK_FILE.c_str());