2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Lukasz Pawelczyk <l.pawelczyk@partner.samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License
21 * @author Lukasz Pawelczyk (l.pawelczyk@partner.samsung.com)
22 * @brief File utility functions
26 #include "logger/logger.hpp"
27 #include "utils/fs.hpp"
28 #include "utils/paths.hpp"
29 #include "utils/exception.hpp"
31 #include <boost/filesystem.hpp>
38 #include <sys/mount.h>
39 #include <sys/types.h>
43 namespace security_containers {
47 std::string readFileContent(const std::string& path)
50 if (!readFileContent(path, result)) {
51 throw UtilsException();
56 bool readFileContent(const std::string& path, std::string& result)
58 std::ifstream file(path);
61 LOGD(path << ": could not open for reading");
65 file.seekg(0, std::ios::end);
66 std::streampos length = file.tellg();
68 LOGD(path << ": tellg failed");
71 result.resize(static_cast<size_t>(length));
72 file.seekg(0, std::ios::beg);
74 file.read(&result[0], length);
76 LOGD(path << ": read error");
84 bool saveFileContent(const std::string& path, const std::string& content)
86 std::ofstream file(path);
88 LOGD(path << ": could not open for writing");
91 file.write(content.data(), static_cast<std::streamsize>(content.size()));
93 LOGD(path << ": could not write to");
99 bool isCharDevice(const std::string& path)
102 return ::stat(path.c_str(), &s) == 0 && S_IFCHR == (s.st_mode & S_IFMT);
106 // NOTE: Should be the same as in systemd/src/core/mount-setup.c
107 const std::string RUN_MOUNT_POINT_OPTIONS = "mode=755,smackfstransmute=System::Run";
108 const std::string RUN_MOUNT_POINT_OPTIONS_NO_SMACK = "mode=755";
109 const unsigned long RUN_MOUNT_POINT_FLAGS = MS_NOSUID | MS_NODEV | MS_STRICTATIME;
111 bool mountTmpfs(const std::string& path, unsigned long flags, const std::string& options)
113 if (::mount("tmpfs", path.c_str(), "tmpfs", flags, options.c_str()) != 0) {
114 LOGD("Mount failed for '" << path << "', options=" << options << ": " << strerror(errno));
122 bool mountRun(const std::string& path)
124 return utils::mountTmpfs(path, RUN_MOUNT_POINT_FLAGS, RUN_MOUNT_POINT_OPTIONS)
125 || utils::mountTmpfs(path, RUN_MOUNT_POINT_FLAGS, RUN_MOUNT_POINT_OPTIONS_NO_SMACK);
128 bool umount(const std::string& path)
130 if (::umount(path.c_str()) != 0) {
131 LOGD("Umount failed for '" << path << "': " << strerror(errno));
137 bool isMountPoint(const std::string& path, bool& result)
139 std::string parentPath = dirName(path);
141 bool ret = hasSameMountPoint(path, parentPath, newResult);
147 bool hasSameMountPoint(const std::string& path1, const std::string& path2, bool& result)
151 if (::stat(path1.c_str(), &s1)) {
152 LOGD("Failed to get stat of " << path1 << ": " << strerror(errno));
156 if (::stat(path2.c_str(), &s2)) {
157 LOGD("Failed to get stat of " << path2 << ": " << strerror(errno));
161 result = (s1.st_dev == s2.st_dev);
165 bool moveFile(const std::string& src, const std::string& dst)
169 namespace fs = boost::filesystem;
170 boost::system::error_code error;
172 // The destination has to be a full path (including a file name)
173 // so it doesn't exist yet, we need to check upper level dir instead.
174 if (!hasSameMountPoint(src, dirName(dst), bResult)) {
175 LOGE("Failed to check the files' mount points");
180 fs::rename(src, dst, error);
182 LOGE("Failed to rename the file: " << error);
186 fs::copy_file(src, dst, error);
188 LOGE("Failed to copy the file: " << error);
191 fs::remove(src, error);
193 LOGE("Failed to remove the file: " << error);
194 fs::remove(dst, error);
202 bool createDir(const std::string& path, uid_t uid, uid_t gid, boost::filesystem::perms mode)
204 namespace fs = boost::filesystem;
206 fs::path dirPath(path);
207 boost::system::error_code ec;
208 bool runDirCreated = false;
209 if (!fs::exists(dirPath)) {
210 if (!fs::create_directory(dirPath, ec)) {
211 LOGE("Failed to create directory '" << path << "': "
215 runDirCreated = true;
216 } else if (!fs::is_directory(dirPath)) {
217 LOGE("Path '" << path << " already exists");
222 fs::permissions(dirPath, mode, ec);
223 if (fs::status(dirPath).permissions() != mode) {
224 LOGE("Failed to set permissions to '" << path << "': "
230 if (::chown(path.c_str(), uid, gid) != 0) {
231 // remove the directory only if it hadn't existed before
235 LOGE("chown() failed for path '" << path << "': " << strerror(errno));
243 } // namespace security_containers