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 <exception.h>
41 #include <file-system.h>
45 const std::string CKM_DATA_PATH = "/opt/data/ckm/";
46 const std::string CKM_KEY_PREFIX = "key-";
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 = "/var/run/key-manager.pid";
52 } // namespace anonymous
56 FileSystem::FileSystem(uid_t uid)
60 std::string FileSystem::getDBPath() const
63 ss << CKM_DATA_PATH << CKM_DB_PREFIX << m_uid;
67 std::string FileSystem::getDKEKPath() const {
69 ss << CKM_DATA_PATH << CKM_KEY_PREFIX << m_uid;
73 std::string FileSystem::getDBDEKPath() const {
75 ss << CKM_DATA_PATH << CKM_DB_KEY_PREFIX << m_uid;
79 std::string FileSystem::getRemovedAppsPath() const {
81 ss << CKM_DATA_PATH << CKM_REMOVED_APP_PREFIX << m_uid;
85 RawBuffer FileSystem::loadFile(const std::string &path) const {
86 std::ifstream is(path);
88 if (is.fail() && ENOENT == errno)
92 auto description = GetErrnoString(errno);
93 ThrowErr(Exc::FileSystemFailed,
94 "Error opening file: ", path, " Reason: ", description);
97 std::istreambuf_iterator<char> begin(is),end;
98 std::vector<char> buff(begin,end); // This trick does not work with boost vector
100 RawBuffer buffer(buff.size());
101 memcpy(buffer.data(), buff.data(), buff.size());
105 RawBuffer FileSystem::getDKEK() const
107 return loadFile(getDKEKPath());
110 RawBuffer FileSystem::getDBDEK() const
112 return loadFile(getDBDEKPath());
115 void FileSystem::saveFile(const std::string &path, const RawBuffer &buffer) const {
116 std::ofstream os(path, std::ios::out | std::ofstream::binary | std::ofstream::trunc);
117 std::copy(buffer.begin(), buffer.end(), std::ostreambuf_iterator<char>(os));
119 // Prevent desynchronization in batter remove test.
121 fsync(FstreamAccessors<std::ofstream>::GetFd(os)); // flush kernel space buffer
125 ThrowErr(Exc::FileSystemFailed, "Failed to save file: ", path);
128 void FileSystem::saveDKEK(const RawBuffer &buffer) const {
129 saveFile(getDKEKPath(), buffer);
132 void FileSystem::saveDBDEK(const RawBuffer &buffer) const {
133 saveFile(getDBDEKPath(), buffer);
136 void FileSystem::addRemovedApp(const std::string &smackLabel) const
138 std::ofstream outfile;
139 outfile.open(getRemovedAppsPath(), std::ios_base::app);
140 outfile << smackLabel << std::endl;
142 if (outfile.fail()) {
143 auto desc = GetErrnoString(errno);
144 ThrowErr(Exc::FileSystemFailed,
145 "Could not update file: ", getRemovedAppsPath(), " Reason: ", desc);
149 AppLabelVector FileSystem::clearRemovedsApps() const
152 AppLabelVector removedApps;
154 std::ifstream removedAppsFile(getRemovedAppsPath());
155 if (removedAppsFile.is_open()) {
156 while (! removedAppsFile.eof() ) {
157 getline (removedAppsFile,line);
159 removedApps.push_back(line);
161 removedAppsFile.close();
163 // truncate the contents
164 std::ofstream truncateFile;
165 truncateFile.open(getRemovedAppsPath(), std::ofstream::out | std::ofstream::trunc);
166 truncateFile.close();
170 int FileSystem::init() {
172 if ((mkdir(CKM_DATA_PATH.c_str(), 0700)) && (errno != EEXIST)) {
174 LogError("Error in mkdir " << CKM_DATA_PATH << ". Reason: " << GetErrnoString(err));
175 return -1; // TODO set up some error code
180 UidVector FileSystem::getUIDsFromDBFile() {
182 std::unique_ptr<DIR, std::function<int(DIR*)>>
183 dirp(::opendir(CKM_DATA_PATH.c_str()), ::closedir);
187 LogError("Error in opendir. Data directory could not be read. Error: " << GetErrnoString(err));
191 size_t len = offsetof(struct dirent, d_name) + pathconf(CKM_DATA_PATH.c_str(), _PC_NAME_MAX) + 1;
192 std::unique_ptr<struct dirent, std::function<void(void*)>>
193 pEntry(static_cast<struct dirent*>(::malloc(len)), ::free);
196 LogError("Memory allocation failed.");
200 struct dirent* pDirEntry = NULL;
202 while ( (!readdir_r(dirp.get(), pEntry.get(), &pDirEntry)) && pDirEntry ) {
203 // Ignore files with diffrent prefix
204 if (strncmp(pDirEntry->d_name, CKM_KEY_PREFIX.c_str(), CKM_KEY_PREFIX.size())) {
208 // We find database. Let's extract user id.
210 uids.push_back(static_cast<uid_t>(std::stoi((pDirEntry->d_name)+CKM_KEY_PREFIX.size())));
211 } catch (const std::invalid_argument) {
212 LogDebug("Error in extracting uid from db file. Error=std::invalid_argument."
213 "This will be ignored.File=" << pDirEntry->d_name << "");
214 } catch(const std::out_of_range) {
215 LogDebug("Error in extracting uid from db file. Error=std::out_of_range."
216 "This will be ignored. File="<< pDirEntry->d_name << "");
223 int FileSystem::removeUserData() const {
224 int err, retCode = 0;
226 if (unlink(getDBPath().c_str())) {
229 LogDebug("Error in unlink user database: " << getDBPath()
230 << "Errno: " << errno << " " << GetErrnoString(err));
233 if (unlink(getDKEKPath().c_str())) {
236 LogDebug("Error in unlink user DKEK: " << getDKEKPath()
237 << "Errno: " << errno << " " << GetErrnoString(err));
240 if (unlink(getDBDEKPath().c_str())) {
243 LogDebug("Error in unlink user DBDEK: " << getDBDEKPath()
244 << "Errno: " << errno << " " << GetErrnoString(err));
247 if (unlink(getRemovedAppsPath().c_str())) {
250 LogDebug("Error in unlink user's Removed Apps File: " << getRemovedAppsPath()
251 << "Errno: " << errno << " " << GetErrnoString(err));
257 FileLock FileSystem::lock()
259 FileLock fl(CKM_LOCK_FILE.c_str());