utils re-factoring: communicate errors via exceptions (with errno). Cleanups. 21/59021/14
authorMaciej J. Karpiuk <m.karpiuk2@samsung.com>
Mon, 8 Feb 2016 13:12:43 +0000 (14:12 +0100)
committerMaciej J. Karpiuk <m.karpiuk2@samsung.com>
Mon, 15 Feb 2016 12:36:26 +0000 (13:36 +0100)
Change-Id: Ia81205e9fc425e1160e8bf9474f143db13b7c252

32 files changed:
common/utils/channel.cpp
common/utils/credentials.cpp [new file with mode: 0644]
common/utils/credentials.hpp [new file with mode: 0644]
common/utils/exception.hpp
common/utils/fd-utils.cpp
common/utils/fd-utils.hpp
common/utils/file-wait.cpp
common/utils/fs.cpp
common/utils/fs.hpp
common/utils/img.cpp
common/utils/inotify.cpp
common/utils/signal.cpp
common/utils/signal.hpp
common/utils/signalfd.cpp
common/utils/signalfd.hpp
common/utils/smack.cpp [new file with mode: 0644]
common/utils/smack.hpp [new file with mode: 0644]
common/utils/value-latch.hpp
common/utils/vt.cpp
libs/cargo-ipc/epoll/event-poll.cpp
libs/cargo-json/CMakeLists.txt
libs/cargo-json/cargo-json.hpp
libs/cargo-json/internals/fs-utils.cpp [deleted file]
libs/cargo-json/internals/fs-utils.hpp [deleted file]
libs/cargo-json/libcargo-json.pc.in
libs/cargo-sqlite-json/cargo-sqlite-json.hpp
packaging/cargo.spec
tests/unit_tests/CMakeLists.txt
tests/unit_tests/cargo-ipc/ut-ipc.cpp
tests/unit_tests/cargo/ut-cargo.cpp
tests/unit_tests/utils/ut-fs.cpp
tests/unit_tests/utils/ut-inotify.cpp

index 98b716dda6e9ed1bd5ec1edceccf780ae17ea5fc..fb650715dfc2eb8e4b1ab1a5df15598ee45b6d58 100644 (file)
@@ -49,10 +49,7 @@ Channel::Channel(const bool closeOnExec)
     };
 
     if (::socketpair(AF_LOCAL, flags, 0, mSockets.data()) < 0) {
-        const std::string msg = "socketpair() failed: " +
-                                utils::getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in socketpair()", errno);
     }
 }
 
diff --git a/common/utils/credentials.cpp b/common/utils/credentials.cpp
new file mode 100644 (file)
index 0000000..4215d02
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Maciej Karpiuk (m.karpiuk2@samsung.com)
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+/**
+ * @file
+ * @author  Maciej Karpiuk (m.karpiuk2@samsung.com)
+ * @brief   Credential management related functions
+ */
+
+#include "utils/credentials.hpp"
+#include "utils/exception.hpp"
+#include "logger/logger.hpp"
+
+#include <unistd.h>
+#include <grp.h>
+#include <vector>
+
+namespace utils {
+
+// ------------------- syscall wrappers -------------------
+void setgroups(const std::vector<gid_t>& gids)
+{
+    if (::setgroups(gids.size(), gids.data()) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in setgroups()", errno);
+    }
+}
+
+void setregid(const gid_t rgid, const gid_t egid)
+{
+    if (::setregid(rgid, egid) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in setregid()", errno);
+    }
+}
+
+void setreuid(const uid_t ruid, const uid_t euid)
+{
+    if (::setreuid(ruid, euid) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in setreuid()", errno);
+    }
+}
+
+pid_t setsid()
+{
+    pid_t pid = ::setsid();
+    if (pid == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in setsid()", errno);
+    }
+    return pid;
+}
+
+} // namespace utils
diff --git a/common/utils/credentials.hpp b/common/utils/credentials.hpp
new file mode 100644 (file)
index 0000000..fa1abb1
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Maciej Karpiuk (m.karpiuk2@samsung.com)
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+/**
+ * @file
+ * @author  Maciej Karpiuk (m.karpiuk2@samsung.com)
+ * @brief   Credential management related functions
+ */
+
+#include <sys/types.h>
+#include <vector>
+
+namespace utils {
+
+// ------------------- syscall wrappers -------------------
+// Throw exception on error
+void setgroups(const std::vector<gid_t>& groups);
+void setregid(const gid_t rgid, const gid_t egid);
+void setreuid(const uid_t ruid, const uid_t euid);
+pid_t setsid();
+
+
+} // namespace utils
index 01bb3800da6f6a779f045d2f9a304596359b7fa6..18a87cabee42af88d7ccde564cdbe248adcdb400 100644 (file)
 #ifndef COMMON_UTILS_EXCEPTION_HPP
 #define COMMON_UTILS_EXCEPTION_HPP
 
+#include "logger/logger.hpp"
 #include <stdexcept>
 
 namespace utils {
 
+/**
+ * Return string describing error number
+ * it is wrapper for strerror_r
+ */
+std::string getSystemErrorMessage();
+std::string getSystemErrorMessage(int err);
 
 /**
  * Base class for exceptions in utils
  */
-struct UtilsException: public std::runtime_error {
+struct UtilsException : public std::runtime_error {
+    explicit UtilsException(const std::string& error,
+                            int errno_,
+                            const char *file,
+                            const char *func,
+                            int line,
+                            logger::LogLevel level = logger::LogLevel::DEBUG)
+        :   std::runtime_error(error),
+            mErrno(errno_),
+            mFile(std::string(file?file:__FILE__)),
+            mFunc(std::string(func?func:__func__)),
+            mLine((line!=-1)?__LINE__:line),
+            mLevel(level) {
+        if (logger::Logger::getLogLevel() <= mLevel) {
+            logger::Logger::logMessage(mLevel,
+                                       (mErrno!=0)?(error + " (errno: " + getSystemErrorMessage(mErrno) + ")"):error,
+                                       mFile,
+                                       mLine,
+                                       mFunc,
+                                       PROJECT_SOURCE_DIR);
+        }
+    }
 
-    explicit UtilsException(const std::string& error) : std::runtime_error(error) {}
-};
+    explicit UtilsException(const std::string& error, int errno_)
+        :  UtilsException(error, errno_, nullptr, nullptr, -1) {}
 
-struct EventFDException: public UtilsException {
+    explicit UtilsException(const std::string& error)
+        :  UtilsException(error, errno) {}
 
-    explicit EventFDException(const std::string& error) : UtilsException(error) {}
+    const int mErrno;
+    const std::string mFile;
+    const std::string mFunc;
+    const int mLine;
+    logger::LogLevel mLevel;
 };
 
-struct ProvisionExistsException: public UtilsException {
+#define THROW_UTILS_EXCEPTION__(LEVEL, MSG, ERRNO, FILE, LINE, FUNC)\
+    do {                                                            \
+        int errnoTmp = ERRNO;                                       \
+        std::ostringstream messageStream__;                         \
+        messageStream__ << MSG;                                     \
+        throw UtilsException(messageStream__.str(),                 \
+                             errnoTmp,                              \
+                             FILE,                                  \
+                             FUNC,                                  \
+                             LINE,                                  \
+                             logger::LogLevel::LEVEL);              \
+    } while (0)
+
+#define THROW_UTILS_EXCEPTION_W(MSG) \
+    THROW_UTILS_EXCEPTION__(WARN, MSG, 0, __FILE__, __LINE__, __func__)
+
+#define THROW_UTILS_EXCEPTION_ERRNO_W(MSG, ERRNO) \
+    THROW_UTILS_EXCEPTION__(WARN, MSG, ERRNO, __FILE__, __LINE__, __func__)
+
+#define THROW_UTILS_EXCEPTION_D(MSG) \
+    THROW_UTILS_EXCEPTION__(DEBUG, MSG, 0, __FILE__, __LINE__, __func__)
 
-    explicit ProvisionExistsException(const std::string& error) : UtilsException(error) {}
+#define THROW_UTILS_EXCEPTION_ERRNO_D(MSG, ERRNO) \
+    THROW_UTILS_EXCEPTION__(DEBUG, MSG, ERRNO, __FILE__, __LINE__, __func__)
+
+#define THROW_UTILS_EXCEPTION_E(MSG) \
+    THROW_UTILS_EXCEPTION__(ERROR, MSG, 0, __FILE__, __LINE__, __func__)
+
+#define THROW_UTILS_EXCEPTION_ERRNO_E(MSG, ERRNO) \
+    THROW_UTILS_EXCEPTION__(ERROR, MSG, ERRNO, __FILE__, __LINE__, __func__)
+
+struct EventFDException: public UtilsException {
+
+    explicit EventFDException(const std::string& error) : UtilsException(error) {}
 };
 
-/**
- * Return string describing error number
- * it is wrapper for strerror_r
- */
-std::string getSystemErrorMessage();
-std::string getSystemErrorMessage(int err);
 
 } // namespace utils
 
index 2c37a13b37413c4d47e965510a1a3934dc4ac16a..99bf9eee1b90efb5ae41025581fb3526d00553bc 100644 (file)
@@ -64,9 +64,8 @@ void waitForEvent(int fd,
     for (;;) {
         chr::milliseconds timeoutMS = chr::duration_cast<chr::milliseconds>(deadline - chr::high_resolution_clock::now());
         if (timeoutMS.count() < 0) {
-            LOGE("Timeout while waiting for event: " << std::hex << event <<
+            THROW_UTILS_EXCEPTION_E("Timeout while waiting for event: " << std::hex << event <<
                  " on fd: " << std::dec << fd);
-            throw UtilsException("Timeout");
         }
 
         int ret = ::poll(fds, 1 /*fds size*/, timeoutMS.count());
@@ -75,15 +74,11 @@ void waitForEvent(int fd,
             if (errno == EINTR) {
                 continue;
             }
-            const std::string msg = "Error in poll: " + getSystemErrorMessage();
-            LOGE(msg);
-            throw UtilsException(msg);
+            THROW_UTILS_EXCEPTION_ERRNO_E("Error in poll", errno);
         }
 
         if (ret == 0) {
-            const std::string msg = "Timeout in read";
-            LOGE(msg);
-            throw UtilsException(msg);
+            THROW_UTILS_EXCEPTION_E("Timeout in read");
         }
 
         if (fds[0].revents & event) {
@@ -92,9 +87,7 @@ void waitForEvent(int fd,
         }
 
         if (fds[0].revents & POLLHUP) {
-            const std::string msg = "Peer disconnected";
-            LOGW(msg);
-            throw UtilsException(msg);
+            THROW_UTILS_EXCEPTION_W("Peer disconnected");
         }
     }
 }
@@ -103,9 +96,7 @@ void setFDFlag(const int fd, const int getOp, const int setOp, const int flag, c
 {
     int ret = ::fcntl(fd, getOp);
     if (ret == -1) {
-        std::string msg = "fcntl(): Failed to get FD flags: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_ERRNO_E("fcntl(): Failed to get FD flags", errno);
     }
 
     if (set) {
@@ -115,9 +106,7 @@ void setFDFlag(const int fd, const int getOp, const int setOp, const int flag, c
     }
 
     if (ret == -1) {
-        std::string msg = "fcntl(): Failed to set FD flag: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_ERRNO_E("fcntl(): Failed to set FD flag", errno);
     }
 }
 
@@ -129,7 +118,6 @@ int open(const std::string &path, int flags, mode_t mode)
     assert(!((flags & O_CREAT) == O_CREAT || (flags & O_TMPFILE) == O_TMPFILE) || mode != static_cast<unsigned>(-1));
 
     int fd;
-
     for (;;) {
         fd = ::open(path.c_str(), flags, mode);
 
@@ -138,9 +126,7 @@ int open(const std::string &path, int flags, mode_t mode)
                 LOGT("open() interrupted by a signal, retrying");
                 continue;
             }
-            const std::string msg = "open() failed: " + path + ": " + getSystemErrorMessage();
-            LOGE(msg);
-            throw UtilsException(msg);
+            THROW_UTILS_EXCEPTION_ERRNO_E(path + ": open() failed", errno);
         }
         break;
     }
@@ -148,7 +134,7 @@ int open(const std::string &path, int flags, mode_t mode)
     return fd;
 }
 
-void close(int fd)
+void close(int fd) noexcept
 {
     if (fd < 0) {
         return;
@@ -173,9 +159,7 @@ void shutdown(int fd)
     }
 
     if (-1 == ::shutdown(fd, SHUT_RDWR)) {
-        std::string msg = "shutdown() failed: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_ERRNO_E("shutdown() failed", errno);
     }
 }
 
@@ -183,9 +167,7 @@ int ioctl(int fd, unsigned long request, void *argp)
 {
     int ret = ::ioctl(fd, request, argp);
     if (ret == -1) {
-        const std::string msg = "ioctl() failed: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_ERRNO_E("ioctl() failed", errno);
     }
     return ret;
 }
@@ -198,9 +180,7 @@ int dup2(int oldFD, int newFD, bool closeOnExec)
     }
     int fd = dup3(oldFD, newFD, flags);
     if (fd == -1) {
-        const std::string msg = "dup3() failed: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_ERRNO_E("dup3() failed", errno);
     }
     return fd;
 }
@@ -225,9 +205,7 @@ void write(int fd, const void* bufferPtr, const size_t size, int timeoutMS)
             // Neglected errors
             LOGD("Retrying write");
         } else {
-            const std::string msg = "Error during writing: " + getSystemErrorMessage();
-            LOGE(msg);
-            throw UtilsException(msg);
+            THROW_UTILS_EXCEPTION_ERRNO_E("Error during write()", errno);
         }
 
         waitForEvent(fd, POLLOUT, deadline);
@@ -251,17 +229,13 @@ void read(int fd, void* bufferPtr, const size_t size, int timeoutMS)
                 break;
             }
             if (n == 0) {
-                const std::string msg = "Peer disconnected";
-                LOGW(msg);
-                throw UtilsException(msg);
+                THROW_UTILS_EXCEPTION_W("Peer disconnected");
             }
         } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
             // Neglected errors
             LOGD("Retrying read");
         } else {
-            const std::string msg = "Error during reading: " + getSystemErrorMessage();
-            LOGE(msg);
-            throw UtilsException(msg);
+            THROW_UTILS_EXCEPTION_ERRNO_E("Error during read()", errno);
         }
 
         waitForEvent(fd, POLLIN, deadline);
@@ -271,10 +245,8 @@ void read(int fd, void* bufferPtr, const size_t size, int timeoutMS)
 unsigned int getMaxFDNumber()
 {
     struct rlimit rlim;
-    if (-1 ==  getrlimit(RLIMIT_NOFILE, &rlim)) {
-        const std::string msg = "Error during getrlimit: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+    if (-1 ==  ::getrlimit(RLIMIT_NOFILE, &rlim)) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error during getrlimit()", errno);
     }
     return rlim.rlim_cur;
 }
@@ -284,10 +256,8 @@ void setMaxFDNumber(unsigned int limit)
     struct rlimit rlim;
     rlim.rlim_cur = limit;
     rlim.rlim_max = limit;
-    if (-1 ==  setrlimit(RLIMIT_NOFILE, &rlim)) {
-        const std::string msg = "Error during setrlimit: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+    if (-1 ==  ::setrlimit(RLIMIT_NOFILE, &rlim)) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error during setrlimit()", errno);
     }
 }
 
@@ -340,10 +310,10 @@ int fdRecv(int socket, const unsigned int timeoutMS)
             if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
                 // Neglected errors, retry
             } else {
-                throw UtilsException("Error during recvmsg: " + getSystemErrorMessage());
+                THROW_UTILS_EXCEPTION_ERRNO_E("Error during recvmsg()", errno);
             }
         } else if (ret == 0) {
-            throw UtilsException("Peer disconnected");
+            THROW_UTILS_EXCEPTION_W("Peer disconnected");
         } else {
             // We receive only 1 byte of data. No need to repeat
             break;
@@ -355,11 +325,11 @@ int fdRecv(int socket, const unsigned int timeoutMS)
     struct cmsghdr *cmhp;
     cmhp = CMSG_FIRSTHDR(&msgh);
     if (cmhp == NULL || cmhp->cmsg_len != CMSG_LEN(sizeof(int))) {
-        throw UtilsException("Bad cmsg length");
+        THROW_UTILS_EXCEPTION_D("Bad cmsg length");
     } else if (cmhp->cmsg_level != SOL_SOCKET) {
-        throw UtilsException("cmsg_level != SOL_SOCKET");
+        THROW_UTILS_EXCEPTION_D("cmsg_level != SOL_SOCKET");
     } else if (cmhp->cmsg_type != SCM_RIGHTS) {
-        throw UtilsException("cmsg_type != SCM_RIGHTS");
+        THROW_UTILS_EXCEPTION_D("cmsg_type != SCM_RIGHTS");
     }
 
     return *(reinterpret_cast<int*>(CMSG_DATA(cmhp)));
@@ -411,7 +381,7 @@ bool fdSend(int socket, int fd, const unsigned int timeoutMS)
             if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
                 // Neglected errors, retry
             } else {
-                throw UtilsException("Error during sendmsg: " + getSystemErrorMessage());
+                THROW_UTILS_EXCEPTION_ERRNO_E("Error during sendmsg()", errno);
             }
         } else if (ret == 0) {
             // Retry the sending
@@ -438,4 +408,3 @@ void setNonBlocking(int fd, bool nonBlocking)
 }
 
 } // namespace utils
-
index 60aed450522a994358f40301c4d61f94b3bd1da4..8dffd462e485232c5f669c4595bf31548f5e2d18 100644 (file)
@@ -31,6 +31,9 @@
 
 namespace utils {
 
+// TODO: add check for errno==EINTR where applicable
+// (as few syscall wrappers already have it)
+
 /**
  * Open a file.
  */
@@ -39,7 +42,7 @@ int open(const std::string &path, int flags, mode_t mode = -1);
 /**
  * Close the file descriptor.
  */
-void close(int fd);
+void close(int fd) noexcept;
 
 /**
  * Shut down part of a full-duplex connection
index 222a93cb4db7fe8b0a55ff2041f7bf4ea46a5f7b..6438b55a8bc41400fb1850cf358a9983d001e84c 100644 (file)
@@ -68,8 +68,8 @@ void waitForFile(const std::string& file, const unsigned int timeoutMs)
         poll.dispatchIteration(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count());
     }
 
-    if(isWaiting) {
-        throw UtilsException("No such file: " + file);
+    if (isWaiting) {
+        THROW_UTILS_EXCEPTION_D("No such file: " << file);
     }
 }
 
index 12f4f7ff0409b2dd1fc0a90773c014de5c439433..dcd970a8079be06620a82e3ffb7568aa87a4f098 100644 (file)
 #include "config.hpp"
 
 #include "logger/logger.hpp"
+#include "utils/fd-utils.hpp"
 #include "utils/fs.hpp"
 #include "utils/paths.hpp"
+#include "utils/smack.hpp"
+#include "utils/text.hpp"
 #include "utils/exception.hpp"
 
 #include <boost/filesystem.hpp>
 #include <sys/types.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/syscall.h>
 
 #include <iostream>
 
-
 namespace fs = boost::filesystem;
 
 namespace utils {
 
-std::string readFileStream(const std::string& path)
+
+// ------------------- syscalls -------------------
+bool remove(const std::string& path)
 {
-    std::ifstream file(path);
+    if (::remove(path.c_str()) == -1) {
+        if (errno == ENOENT) {
+            LOGW(path << ": not removed, path does not exist");
+            return false;
+        }
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": failed to remove", errno);
+    }
 
-    if (!file) {
-        throw UtilsException("Read failed");
+    return true;
+}
+
+struct ::stat stat(const std::string & path)
+{
+    struct ::stat s;
+    if (::stat(path.c_str(), &s) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": failed to get stat", errno);
     }
-    // 2 x faster then std::istreambuf_iterator
-    std::stringstream content;
-    content << file.rdbuf();
-    return content.str();
+    return s;
 }
 
-bool readFileStream(const std::string& path, std::string& result)
+struct ::statfs statfs(const std::string & path)
 {
-    std::ifstream file(path);
+    int rc;
+    struct ::statfs s;
+    do {
+        rc = ::statfs(path.c_str(), &s);
+    } while (rc == -1 && errno == EINTR);
 
-    if (!file) {
-        return false;
+    if (rc == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": failed to get statfs", errno);
+    }
+    return s;
+}
+
+bool access(const std::string& path, int mode)
+{
+    if (::access(path.c_str(), mode) == -1) {
+        if (errno == EACCES) {
+            return false;
+        }
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": trying to access() failed", errno);
     }
-    std::stringstream content;
-    content << file.rdbuf();
-    result = content.str();
     return true;
 }
 
-std::string readFileContent(const std::string& path)
+void mount(const std::string& source,
+           const std::string& target,
+           const std::string& filesystemtype,
+           unsigned long mountflags,
+           const std::string& data)
 {
-    std::string result;
+    int ret = ::mount(source.c_str(),
+                      target.c_str(),
+                      filesystemtype.c_str(),
+                      mountflags,
+                      data.c_str());
+    if (ret == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Mount operation failure: source path: "
+             << source
+             << ", target path: "
+             << target
+             << ", filesystemtype: "
+             << filesystemtype
+             << ", mountflags: "
+             << std::to_string(mountflags)
+             << ", data: "
+             << data, errno);
+    }
+}
 
-    if (!readFileContent(path, result)) {
-        throw UtilsException("Read failed");
+void umount(const std::string& path, int flags)
+{
+    if (::umount2(path.c_str(), flags) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": umount failed", errno);
+    }
+}
+
+void mkfifo(const std::string& path, mode_t mode)
+{
+    if (::mkfifo(path.c_str(), mode) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": failed to create fifo", errno);
+    }
+}
+
+void chown(const std::string& path, uid_t uid, gid_t gid)
+{
+    // set owner
+    if (::chown(path.c_str(), uid, gid) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": chown() failed", errno);
+    }
+}
+
+void lchown(const std::string& path, uid_t uid, gid_t gid)
+{
+    // set owner of a symlink
+    if (::lchown(path.c_str(), uid, gid) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": lchown() failed", errno);
+    }
+}
+
+void chmod(const std::string& path, mode_t mode)
+{
+    if (::chmod(path.c_str(), mode) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": chmod() failed", errno);
+    }
+}
+
+void link(const std::string& src, const std::string& dst)
+{
+    if (::link(src.c_str(), dst.c_str()) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("path=host:" << src << ": failed to hard link to path=host:" << dst, errno);
+    }
+}
+
+void symlink(const std::string& target, const std::string& linkpath)
+{
+    if (::symlink(target.c_str(), linkpath.c_str()) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E(target << ": symlink(" << linkpath << ") failed", errno);
+    }
+}
+
+void fchdir(int fd)
+{
+    if (::fchdir(fd) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("fd:" << std::to_string(fd) << ": fchdir() failed", errno);
+    }
+}
+
+void chdir(const std::string& path)
+{
+    if (::chdir(path.c_str()) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": chdir() failed", errno);
+    }
+}
+
+bool mkdir(const std::string& path, mode_t mode)
+{
+    if (::mkdir(path.c_str(), mode) == -1) {
+        if (errno == EEXIST) {
+            return false;
+        }
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": mkdir() failed", errno);
+    }
+    return true;
+}
+
+bool rmdir(const std::string& path)
+{
+    if (::rmdir(path.c_str()) == -1) {
+        if (errno == ENOENT) {
+            LOGW(path << ": not removed, directory does not exist");
+            return false;
+        }
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": failed to rmdir", errno);
+    }
+
+    return true;
+}
+
+void mknod(const std::string& path, mode_t mode, dev_t dev)
+{
+    if (::mknod(path.c_str(), mode, dev) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": mknod() failed", errno);
+    }
+}
+
+void pivot_root(const std::string& new_root, const std::string& put_old)
+{
+    if (::syscall(SYS_pivot_root, new_root.c_str(), put_old.c_str()) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E(new_root << ": pivot_root() failed", errno);
     }
-    return result;
 }
 
-bool readFileContent(const std::string& path, std::string& result)
+
+// ------------------- higher level functions -------------------
+std::string readFileStream(const std::string& path)
 {
     std::ifstream file(path);
 
     if (!file) {
-        LOGD(path << ": could not open for reading");
-        return false;
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": read failed", errno);
+    }
+    // 2 x faster then std::istreambuf_iterator
+    std::stringstream content;
+    content << file.rdbuf();
+    return content.str();
+}
+
+std::string readFileContent(const std::string& path)
+{
+    std::ifstream file(path);
+
+    if (!file) {
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": could not open for reading", errno);
     }
 
     file.seekg(0, std::ios::end);
     std::streampos length = file.tellg();
     if (length < 0) {
-        LOGD(path << ": tellg failed");
-        return false;
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": tellg failed", errno);
     }
+    std::string result;
     result.resize(static_cast<size_t>(length));
     file.seekg(0, std::ios::beg);
 
     file.read(&result[0], length);
     if (!file) {
-        LOGD(path << ": read error");
-        result.clear();
-        return false;
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": read error", errno);
     }
-
-    return true;
+    return result;
 }
 
-bool saveFileContent(const std::string& path, const std::string& content)
+void saveFileContent(const std::string& path, const std::string& content)
 {
     std::ofstream file(path);
     if (!file) {
-        LOGD(path << ": could not open for writing");
-        return false;
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": could not open for writing", errno);
     }
     file.write(content.data(), static_cast<std::streamsize>(content.size()));
     if (!file) {
-        LOGD(path << ": could not write to");
-        return false;
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": could not write to", errno);
     }
-    return true;
 }
 
-bool readFirstLineOfFile(const std::string& path, std::string& ret)
+void readFirstLineOfFile(const std::string& path, std::string& ret)
 {
     std::ifstream file(path);
     if (!file) {
-        LOGD(path << ": could not open for reading");
-        return false;
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": could not open for reading", errno);
     }
 
     std::getline(file, ret);
     if (!file) {
-        LOGD(path << ": read error");
-        return false;
-    }
-    return true;
-}
-
-bool removeFile(const std::string& path)
-{
-    if (::remove(path.c_str())) {
-        if (errno != ENOENT) {
-            LOGE(path << ": failed to delete: " << getSystemErrorMessage());
-            return false;
-        }
+        THROW_UTILS_EXCEPTION_ERRNO_E(path << ": read error", errno);
     }
-    LOGD(path << ": successfuly removed.");
-
-    return true;
 }
 
 bool exists(const std::string& path, int inodeType)
@@ -161,7 +297,7 @@ bool exists(const std::string& path, int inodeType)
     try {
         assertExists(path, inodeType);
         return true;
-    } catch(...) {
+    } catch(const UtilsException &) {
         return false;
     }
 }
@@ -169,30 +305,18 @@ bool exists(const std::string& path, int inodeType)
 void assertExists(const std::string& path, int inodeType)
 {
     if (path.empty()) {
-        const std::string msg = "Empty path";
-        LOGE(msg);
-        throw UtilsException(msg);
-    }
-
-    struct stat s;
-    if (::stat(path.c_str(), &s)) {
-        const std::string msg = "Error in stat() " + path + ": " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_E("Empty path");
     }
 
+    struct stat s = utils::stat(path);
     if (inodeType != 0) {
         if (!(s.st_mode & inodeType)) {
-            const std::string msg = "Not an expected inode type, expected: " + std::to_string(inodeType) +
-                                    ", while actual: " + std::to_string(s.st_mode);
-            LOGE(msg);
-            throw UtilsException(msg);
+            THROW_UTILS_EXCEPTION_E(path << ": not an expected inode type, expected: " << std::to_string(inodeType) <<
+                                  ", while actual: " << std::to_string(s.st_mode));
         }
 
-        if (inodeType == S_IFDIR && ::access(path.c_str(), X_OK) < 0) {
-            const std::string msg = "Not a traversable directory";
-            LOGE(msg);
-            throw UtilsException(msg);
+        if (inodeType == S_IFDIR && !utils::access(path, X_OK)) {
+            THROW_UTILS_EXCEPTION_ERRNO_E(path << ": not a traversable directory", errno);
         }
     }
 }
@@ -230,9 +354,7 @@ bool isAbsolute(const std::string& path)
 void assertIsAbsolute(const std::string& path)
 {
     if (!isAbsolute(path)) {
-        const std::string msg = "Given path '" + path + "' must be absolute!";
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_D(path << ": must be absolute!");
     }
 }
 
@@ -243,127 +365,84 @@ const std::string RUN_MOUNT_POINT_OPTIONS = "mode=755,smackfstransmute=System::R
 const std::string RUN_MOUNT_POINT_OPTIONS_NO_SMACK = "mode=755";
 const unsigned long RUN_MOUNT_POINT_FLAGS = MS_NOSUID | MS_NODEV | MS_STRICTATIME;
 
-bool mountTmpfs(const std::string& path, unsigned long flags, const std::string& options)
+int mountTmpfs(const std::string& path, unsigned long flags, const std::string& options)
 {
-    if (::mount("tmpfs", path.c_str(), "tmpfs", flags, options.c_str()) != 0) {
-        LOGD("Mount failed for '" << path << "', options=" << options << ": " << getSystemErrorMessage());
-        return false;
+    try {
+        utils::mount("tmpfs", path.c_str(), "tmpfs", flags, options.c_str());
+        return 0;
+    } catch(const UtilsException & e) {
+        return e.mErrno;
     }
-    return true;
 }
 
 } // namespace
 
-bool mountRun(const std::string& path)
-{
-    return utils::mountTmpfs(path, RUN_MOUNT_POINT_FLAGS, RUN_MOUNT_POINT_OPTIONS)
-           || utils::mountTmpfs(path, RUN_MOUNT_POINT_FLAGS, RUN_MOUNT_POINT_OPTIONS_NO_SMACK);
-}
-
-bool mount(const std::string& source,
-           const std::string& target,
-           const std::string& filesystemtype,
-           unsigned long mountflags,
-           const std::string& data)
+void mountRun(const std::string& path)
 {
-    int ret = ::mount(source.c_str(),
-                      target.c_str(),
-                      filesystemtype.c_str(),
-                      mountflags,
-                      data.c_str());
-    if (ret < 0) {
-        LOGE("Mount operation failure: "
-             << "source path: "
-             << source
-             << ", target path: "
-             << target
-             << ", filesystemtype: "
-             << filesystemtype
-             << ", mountflags: "
-             << mountflags
-             << ", data: "
-             << data
-             << ", msg: "
-             << getSystemErrorMessage());
-        return false;
+    if (utils::mountTmpfs(path, RUN_MOUNT_POINT_FLAGS, RUN_MOUNT_POINT_OPTIONS)) {
+        int errno_ = utils::mountTmpfs(path, RUN_MOUNT_POINT_FLAGS, RUN_MOUNT_POINT_OPTIONS_NO_SMACK);
+        if (errno_) {
+            THROW_UTILS_EXCEPTION_ERRNO_E(path << ": mount failed", errno_);
+        }
     }
-    return true;
 }
 
-bool umount(const std::string& path)
+bool isMountPoint(const std::string& path)
 {
-    if (::umount(path.c_str()) != 0) {
-        LOGE("Umount failed for '" << path << "': " << getSystemErrorMessage());
-        return false;
-    }
-    return true;
+    std::string parentPath = dirName(path);
+    return ! hasSameMountPoint(path, parentPath);
 }
 
-bool isMountPoint(const std::string& path, bool& result)
+
+bool isMountPointShared(const std::string& path)
 {
-    std::string parentPath = dirName(path);
-    bool newResult;
-    if (!hasSameMountPoint(path, parentPath, newResult)) {
-        LOGE("Failed to check the files' mount points");
-        return false;
+    std::ifstream fileStream("/proc/self/mountinfo");
+    if (!fileStream.good()) {
+        THROW_UTILS_EXCEPTION_E(path << ": open failed");
     }
 
-    result = !newResult;
-    return true;
-}
+    // Find the line corresponding to the path
+    std::string line;
+    while (std::getline(fileStream, line).good()) {
+        std::istringstream iss(line);
+        auto it = std::istream_iterator<std::string>(iss);
+        std::advance(it, 4);
 
-bool hasSameMountPoint(const std::string& path1, const std::string& path2, bool& result)
-{
-    struct stat s1, s2;
-
-    if (::stat(path1.c_str(), &s1)) {
-        LOGD("Failed to get stat of " << path1 << ": " << getSystemErrorMessage());
-        return false;
-    }
+        if (it->compare(path)) {
+            // Wrong line, different path
+            continue;
+        }
 
-    if (::stat(path2.c_str(), &s2)) {
-        LOGD("Failed to get stat of " << path2 << ": " << getSystemErrorMessage());
-        return false;
+        // Right line, check if mount point shared
+        std::advance(it, 2);
+        return it->find("shared:") != std::string::npos;
     }
 
-    result = (s1.st_dev == s2.st_dev);
-    return true;
+    // Path not found
+    return false;
 }
 
-bool moveFile(const std::string& src, const std::string& dst)
+bool hasSameMountPoint(const std::string& path1, const std::string& path2)
 {
-    bool bResult;
-
-    boost::system::error_code error;
+    return utils::stat(path1).st_dev == utils::stat(path2).st_dev;
+}
 
+void moveFile(const std::string& src, const std::string& dst)
+{
     // The destination has to be a full path (including a file name)
     // so it doesn't exist yet, we need to check upper level dir instead.
-    if (!hasSameMountPoint(src, dirName(dst), bResult)) {
-        LOGE("Failed to check the files' mount points");
-        return false;
-    }
+    bool bResult = hasSameMountPoint(src, dirName(dst));
 
     if (bResult) {
+        boost::system::error_code error;
         fs::rename(src, dst, error);
         if (error) {
-            LOGE("Failed to rename the file: " << error);
-            return false;
+            THROW_UTILS_EXCEPTION_E(src << ": failed to rename to: " << dst << ", error: " << error.message());
         }
     } else {
-        fs::copy_file(src, dst, error);
-        if (error) {
-            LOGE("Failed to copy the file: " << error);
-            return false;
-        }
-        fs::remove(src, error);
-        if (error) {
-            LOGE("Failed to remove the file: " << error);
-            fs::remove(dst, error);
-            return false;
-        }
+        copyFile(src, dst);
+        utils::remove(src);
     }
-
-    return true;
 }
 
 namespace {
@@ -405,23 +484,21 @@ bool copyDirContentsRec(const boost::filesystem::path& src, const boost::filesys
             }
 
             // change owner
-            struct stat info;
-            ::stat(current.string().c_str(), &info);
+            struct stat info = utils::stat(current.string());
             if (fs::is_symlink(destination)) {
-                if (::lchown(destination.string().c_str(), info.st_uid, info.st_gid) < 0) {
-                    LOGW("Failed to change owner of symlink " << destination.string() << ": " << getSystemErrorMessage());
-                }
+                utils::lchown(destination.string(), info.st_uid, info.st_gid);
             } else {
-                if (::chown(destination.string().c_str(), info.st_uid, info.st_gid) < 0) {
-                    LOGW("Failed to change owner of file " << destination.string() << ": " << getSystemErrorMessage());
-                }
+                utils::chown(destination.string(), info.st_uid, info.st_gid);
             }
         }
-    } catch (fs::filesystem_error& e) {
+        return true;
+    } catch (const UtilsException& e) {
+        LOGW(e.what());
+    } catch (const fs::filesystem_error& e) {
         LOGW(e.what());
     }
 
-    return true;
+    return false;
 }
 
 boost::filesystem::perms getPerms(const mode_t& mode)
@@ -429,60 +506,47 @@ boost::filesystem::perms getPerms(const mode_t& mode)
     return static_cast<boost::filesystem::perms>(mode);
 }
 
-bool copySmackLabel(const std::string& /* src */, const std::string& /* dst */)
-{
-    //TODO: fill copySmackLabel function
-    return true;
-}
-
-
 } // namespace
 
-bool copyDirContents(const std::string& src, const std::string& dst)
+void copyDirContents(const std::string& src, const std::string& dst)
 {
-    return copyDirContentsRec(fs::path(src), fs::path(dst));
+    if (!copyDirContentsRec(fs::path(src), fs::path(dst))) {
+        THROW_UTILS_EXCEPTION_E(src << ": failed to copy contents to new location: " << dst);
+    }
 }
 
-bool createDir(const std::string& path, uid_t uid, uid_t gid, boost::filesystem::perms mode)
+void createDir(const std::string& path, uid_t uid, uid_t gid, boost::filesystem::perms mode)
 {
     fs::path dirPath(path);
     boost::system::error_code errorCode;
     bool runDirCreated = false;
     if (!fs::exists(dirPath)) {
         if (!fs::create_directory(dirPath, errorCode)) {
-            LOGE("Failed to create directory '" << path << "': "
-                 << errorCode.message());
-            return false;
+            THROW_UTILS_EXCEPTION_E(path << ": failed to create directory, error: " << errorCode.message());
         }
         runDirCreated = true;
     } else if (!fs::is_directory(dirPath)) {
-        LOGE("Path '" << path << " already exists");
-        return false;
+        THROW_UTILS_EXCEPTION_E(path << ": cannot create directory, already exists!");
     }
 
     // set permissions
     fs::permissions(dirPath, mode, errorCode);
     if (fs::status(dirPath).permissions() != mode) {
-        LOGE("Failed to set permissions to '" << path << "': "
-             << errorCode.message());
-        return false;
+        THROW_UTILS_EXCEPTION_E(path << ": failed to set permissions, error: " << errorCode.message());
     }
 
     // set owner
-    if (::chown(path.c_str(), uid, gid) != 0) {
-        int err = errno;
-        // remove the directory only if it hadn't existed before
+    try {
+        utils::chown(path, uid, gid);
+    } catch(...) {
         if (runDirCreated) {
             fs::remove(dirPath);
         }
-        LOGE("chown() failed for path '" << path << "': " << getSystemErrorMessage(err));
-        return false;
+        throw;
     }
-
-    return true;
 }
 
-bool createDirs(const std::string& path, mode_t mode)
+void createDirs(const std::string& path, mode_t mode)
 {
     const boost::filesystem::perms perms = getPerms(mode);
     std::vector<fs::path> dirsCreated;
@@ -491,11 +555,11 @@ bool createDirs(const std::string& path, mode_t mode)
     for (const auto& dirSegment : dirPath) {
         prefix /= dirSegment;
         if (!fs::exists(prefix)) {
-            bool created = createDir(prefix.string(), -1, -1, perms);
-            if (created) {
+            try {
+                createDir(prefix.string(), -1, -1, perms);
                 dirsCreated.push_back(prefix);
-            } else {
-                LOGE("Failed to create dir");
+            } catch(...) {
+                LOGE("Failed to create dir: " << prefix);
                 // undo
                 for (auto iter = dirsCreated.rbegin(); iter != dirsCreated.rend(); ++iter) {
                     boost::system::error_code errorCode;
@@ -505,14 +569,13 @@ bool createDirs(const std::string& path, mode_t mode)
                              << ", msg: " << errorCode.message());
                     }
                 }
-                return false;
+                throw;
             }
         }
     }
-    return true;
 }
 
-bool createEmptyDir(const std::string& path)
+void createEmptyDir(const std::string& path)
 {
     fs::path dirPath(path);
     boost::system::error_code ec;
@@ -520,113 +583,80 @@ bool createEmptyDir(const std::string& path)
 
     if (!fs::exists(dirPath)) {
         if (!fs::create_directory(dirPath, ec)) {
-            LOGE("Failed to create dir. Error: " << ec.message());
-            return false;
+            THROW_UTILS_EXCEPTION_E(dirPath.string() << ": failed to create dir, error: " << ec.message());
         }
         cleanDirCreated = true;
     } else if (!fs::is_directory(dirPath)) {
-        LOGE("Provided path already exists and is not a dir, cannot create.");
-        return false;
+        THROW_UTILS_EXCEPTION_E(dirPath.string() << ": already exists and is not a dir, cannot create.");
     }
 
     if (!cleanDirCreated) {
         // check if directory is empty if it was already created
         if (!fs::is_empty(dirPath)) {
-            LOGE("Directory has some data inside, cannot be used.");
-            return false;
+            THROW_UTILS_EXCEPTION_E(dirPath.string() << ": directory has some data inside, cannot be used.");
         }
     }
-
-    return true;
 }
 
-bool createFile(const std::string& path, int flags, mode_t mode)
+void createFile(const std::string& path, int flags, mode_t mode)
 {
-    int ret = ::open(path.c_str(), flags, mode);
-    if (ret < 0) {
-        LOGE("Failed to create file: path=host:"
-             << path
-             << ", msg: "
-             << getSystemErrorMessage());
-        return false;
-    }
-    close(ret);
-    return true;
+    utils::close(utils::open(path, O_CREAT | flags, mode));
 }
 
-bool createFifo(const std::string& path, mode_t mode)
+void createFifo(const std::string& path, mode_t mode)
 {
-    int ret = ::mkfifo(path.c_str(), mode);
-    if (ret < 0) {
-        LOGE("Failed to make fifo: path=host:" << path);
-        return false;
-    }
-    return true;
+    utils::mkfifo(path.c_str(), mode);
 }
 
-bool copyFile(const std::string& src, const std::string& dest)
+void copyFile(const std::string& src, const std::string& dest)
 {
     boost::system::error_code errorCode;
     fs::copy_file(src, dest, errorCode);
     if (errorCode) {
-        LOGE("Failed to copy file: msg: "
-             << errorCode.message()
-             << ", path=host:"
-             << src
-             << ", path=host:"
-             << dest);
-        return false;
+        THROW_UTILS_EXCEPTION_E("path=host:" << src << ": failed to copy file to path=host:"
+                                << dest << ", error: " << errorCode.message());
     }
-    bool retSmack = copySmackLabel(src, dest);
-    if (!retSmack) {
-        LOGE("Failed to copy file: msg: (can't copy smacklabel) "
-             << ", path=host:"
-             << src
-             << ", path=host:"
-             << dest);
+    try {
+        copySmackLabel(src, dest);
+    } catch(const UtilsException & e) {
+        std::string msg = "Failed to copy file: msg: (can't copy smacklabel), path=host:"
+             + src
+             + ", path=host:"
+             + dest + ".";
         fs::remove(src, errorCode);
         if (errorCode) {
-            LOGE("Failed to clean after copy failure: path=host:"
-                 << src
-                 << ", msg: "
-                 << errorCode.message());
+            msg += "\nFailed to clean after copy failure: path=host:"
+                 + src
+                 + ", msg: "
+                 + errorCode.message();
         }
-        return false;
+        THROW_UTILS_EXCEPTION_ERRNO_E(msg, e.mErrno);
     }
-    return true;
 }
 
-bool createLink(const std::string& src, const std::string& dest)
+void createLink(const std::string& src, const std::string& dest)
 {
-    int retLink = ::link(src.c_str(), dest.c_str());
-    if (retLink < 0) {
-        LOGE("Failed to hard link: path=host:"
-             << src
-             << ", path=host:"
-             << dest
-             << ", msg:"
-             << getSystemErrorMessage());
-        return false;
-    }
-    bool retSmack = copySmackLabel(src, dest);
-    if (!retSmack) {
-        LOGE("Failed to copy smack label: path=host:"
-             << src
-             << ", path=host:"
-             << dest);
+    utils::link(src, dest);
+    try {
+        copySmackLabel(src, dest, false);
+    } catch(const UtilsException & e) {
+        std::string msg = "Failed to copy smack label: path=host:"
+             + src
+             + ", path=host:"
+             + dest + ".";
         boost::system::error_code ec;
         fs::remove(dest, ec);
         if (!ec) {
-            LOGE("Failed to clean after hard link creation failure: path=host:"
-                 << src
-                 << ", to: "
-                 << dest
-                 << ", msg: "
-                 << ec.message());
+            msg += "\nFailed to clean after hard link creation failure: path=host:"
+                 + src
+                 + ", to: "
+                 + dest
+                 + ", msg: "
+                 + ec.message();
         }
-        return false;
+        THROW_UTILS_EXCEPTION_ERRNO_E(msg, e.mErrno);
     }
-    return true;
 }
 
+
 } // namespace utils
index 8a532dfad8190ea32ccb5f563914796c17807716..f08f3c8e4c56f30b38b8b6717e290833b3d3ec29 100644 (file)
 #define COMMON_UTILS_FS_HPP
 
 #include <string>
+#include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/vfs.h>
 #include <vector>
 #include <boost/filesystem.hpp>
 
 
 namespace utils {
 
+// syscall wrappers
+// Throw exception on error
+
+// remove file/dir (not recursive)
+// returns true if removed, false otherwise
+bool remove(const std::string& path);
+struct ::stat stat(const std::string& path);
+struct ::statfs statfs(const std::string& path);
+// true if can be accessed with given mode
+bool access(const std::string& path, int mode);
+void mount(const std::string& source,
+           const std::string& target,
+           const std::string& filesystemtype,
+           unsigned long mountflags,
+           const std::string& data);
+void umount(const std::string& path, int flags = 0);
+// returns descriptor to the newly created item
+void mkfifo(const std::string& path, mode_t mode);
+void chown(const std::string& path, uid_t uid, gid_t gid);
+void lchown(const std::string& path, uid_t uid, gid_t gid);
+void chown(const std::string& path, uid_t owner, gid_t group);
+void link(const std::string& src, const std::string& dst);
+void symlink(const std::string& target, const std::string& linkpath);
+void fchdir(int fd);
+void chdir(const std::string& path);
+// returns true if new dir created, false if dir was already present
+bool mkdir(const std::string& path, mode_t mode);
+// returns true if removed, false otherwise
+bool rmdir(const std::string& path);
+void mknod(const std::string& path, mode_t mode, dev_t dev);
+void chmod(const std::string& path, mode_t mode);
+void pivot_root(const std::string& new_root, const std::string& put_old);
+
+
 /**
  * Reads the content of file stream (no seek); Throws exception on error
  */
 std::string readFileStream(const std::string& path);
 
-/**
- * Reads the content of file stream (no seek)
- */
-bool readFileStream(const std::string& path, std::string& result);
-
 /**
  * Reads the content of a file (performs seek); Throws exception on error
  */
 std::string readFileContent(const std::string& path);
 
-/**
- * Reads the content of a file
- */
-bool readFileContent(const std::string& path, std::string& content);
-
 /**
  * Save the content to the file
  */
-bool saveFileContent(const std::string& path, const std::string& content);
+void saveFileContent(const std::string& path, const std::string& content);
 
 /**
  * Read a line from file
- * Its goal is to read a kernel config files (eg. from /proc, /sys/)
+ * Its goal is to read a kernel config files (eg. from /proc, /sys/).
+ * Throws exception on error
  */
-bool readFirstLineOfFile(const std::string& path, std::string& ret);
-
-/**
- * Remove file
- */
-bool removeFile(const std::string& path);
+void readFirstLineOfFile(const std::string& path, std::string& ret);
 
 /**
  * Checks if a path exists and points to an expected item type.
@@ -119,87 +141,93 @@ bool isAbsolute(const std::string& path);
 void assertIsAbsolute(const std::string& path);
 
 /**
- * List all (including '.' and '..' entries) dir entries
+ * Mounts run as a tmpfs on a given path.
+ * Throws exception on error
  */
-bool listDir(const std::string& path, std::vector<std::string>& files);
+void mountRun(const std::string& path);
 
 /**
- * Mounts run as a tmpfs on a given path
+ * Check if given path is a mount point.
+ * Throws exception on error.
+ * @return boolean result
  */
-bool mountRun(const std::string& path);
+bool isMountPoint(const std::string& path);
 
 /**
- * Creates mount point
- */
-bool mount(const std::string& source,
-           const std::string& target,
-           const std::string& filesystemtype,
-           unsigned long mountflags,
-           const std::string& data);
-
-/**
- * Umounts a filesystem
- */
-bool umount(const std::string& path);
-
-/**
- * Check if given path is a mount point
+ * Detect whether path is mounted as MS_SHARED.
+ * Parses /proc/self/mountinfo
+ * Throws exception on error.
+ *
+ * @param path mount point
+ * @return is the mount point shared
  */
-bool isMountPoint(const std::string& path, bool& result);
+bool isMountPointShared(const std::string& path);
 
 /**
- * Checks whether the given paths are under the same mount point
+ * Checks whether the given paths are under the same mount point.
+ * Throws exception on error.
+ * @return boolean result
  */
-bool hasSameMountPoint(const std::string& path1, const std::string& path2, bool& result);
+bool hasSameMountPoint(const std::string& path1, const std::string& path2);
 
 /**
  * Moves the file either by rename if under the same mount point
  * or by copy&delete if under a different one.
  * The destination has to be a full path including file name.
+ * Throws exception on error
  */
-bool moveFile(const std::string& src, const std::string& dst);
+void moveFile(const std::string& src, const std::string& dst);
 
 /**
  * Recursively copy contents of src dir to dst dir.
+ * Throws exception on error
  */
-bool copyDirContents(const std::string& src, const std::string& dst);
+void copyDirContents(const std::string& src, const std::string& dst);
 
 /**
  * Creates a directory with specific UID, GID and permissions set.
+ * Throws exception on error
  */
-bool createDir(const std::string& path, uid_t uid, uid_t gid, boost::filesystem::perms mode);
+void createDir(const std::string& path, uid_t uid, uid_t gid, boost::filesystem::perms mode);
 
 /**
  * Recursively creates a directory with specific permissions set.
+ * Throws exception on error
  */
-bool createDirs(const std::string& path, mode_t mode);
+void createDirs(const std::string& path, mode_t mode);
 
 /**
  * Creates an empty directory, ready to serve as mount point.
  * Succeeds either if path did not exist and was created successfully, or if already existing dir
  * under the same path is empty and is not a mount point.
+ * Throws exception on error
  */
-bool createEmptyDir(const std::string& path);
+void createEmptyDir(const std::string& path);
 
 /**
- * Creates an empty file
+ * Creates an empty file.
+ * Throws exception on error
  */
-bool createFile(const std::string& path, int flags, mode_t mode);
+void createFile(const std::string& path, int flags, mode_t mode);
 
 /**
- * Creates an FIFO special file
+ * Creates an FIFO special file.
+ * Throws exception on error
  */
-bool createFifo(const std::string& path, mode_t mode);
+void createFifo(const std::string& path, mode_t mode);
 
 /**
- * Copy an file
+ * Copy an file.
+ * Throws exception on error
  */
-bool copyFile(const std::string& src, const std::string& dest);
+void copyFile(const std::string& src, const std::string& dest);
 
 /**
  * Create hard link
+ * Throws exception on error.
  */
-bool createLink(const std::string& src, const std::string& dest);
+void createLink(const std::string& src, const std::string& dest);
+
 
 } // namespace utils
 
index d43805be263792f074ee4362ff5fe9651188c1f5..9a319a894be15357b2a0cd7e66c2ec40a73a8a71 100644 (file)
@@ -27,6 +27,7 @@
 #include "logger/logger.hpp"
 #include "utils/img.hpp"
 #include "utils/fs.hpp"
+#include "utils/fd-utils.hpp"
 #include "utils/paths.hpp"
 #include "utils/exception.hpp"
 
@@ -45,25 +46,32 @@ const unsigned long LOOP_MOUNT_POINT_FLAGS = MS_RDONLY;
 
 // Writes to ret if loop device (provided in loopdev arg) is free to use.
 // Returns true if check was successful, false if loop device FD was unavailable for some reason.
+// FIXME: function prone to races
 bool isLoopDevFree(const std::string& loopdev, bool& ret)
 {
+    int loopFD = -1;
     // initialize
     ret = false;
 
-    // open loop device FD
-    int loopFD = ::open(loopdev.c_str(), O_RDWR);
-    if (loopFD < 0) {
-        LOGD("Failed to open loop device descriptor: " << getSystemErrorMessage());
+    try
+    {
+        // open loop device FD
+        loopFD = utils::open(loopdev, O_RDWR);
+
+        // if ioctl with LOOP_GET_STATUS fails, device is not assigned and free to use
+        struct loop_info linfo;
+        try {
+            utils::ioctl(loopFD, LOOP_GET_STATUS, &linfo);
+        } catch(const UtilsException& e) {
+            ret = true;
+        }
+    } catch(const UtilsException& e) {
+        LOGE(loopdev << " error: " << e.what());
+        utils::close(loopFD);
         return false;
     }
 
-    // if ioctl with LOOP_GET_STATUS fails, device is not assigned and free to use
-    struct loop_info linfo;
-    if (::ioctl(loopFD, LOOP_GET_STATUS, &linfo)) {
-        ret = true;
-    }
-
-    ::close(loopFD);
+    utils::close(loopFD);
     return true;
 }
 
@@ -74,48 +82,40 @@ bool mountLoop(const std::string& img,
                unsigned long flags,
                const std::string& options)
 {
-    // to mount an image, we need to connect image FD with loop device FD
-    // get image file  FD
-    int fileFD = ::open(img.c_str(), O_RDWR);
-    if (fileFD < 0) {
-        LOGD("Failed to open image file descriptor: " << getSystemErrorMessage());
-        return false;
-    }
+    int fileFD = -1, loopFD = -1;
 
-    // get loop device FD
-    int loopFD = ::open(loopdev.c_str(), O_RDWR);
-    if (loopFD < 0) {
-        LOGD("Failed to open loop device descriptor: " << getSystemErrorMessage());
-        ::close(fileFD);
-        return false;
-    }
+    try
+    {
+        // to mount an image, we need to connect image FD with loop device FD
+        // get image file  FD
+        fileFD = utils::open(img, O_RDWR);
 
-    // set loop device
-    if (::ioctl(loopFD, LOOP_SET_FD, fileFD)) {
-        LOGD("Failed to assign loop device to image: " << getSystemErrorMessage());
-        ::close(fileFD);
-        ::close(loopFD);
-        return false;
-    }
+        // get loop device FD
+        loopFD = utils::open(loopdev, O_RDWR);
+
+        // set loop device
+        utils::ioctl(loopFD, LOOP_SET_FD, reinterpret_cast<void*>(fileFD));
 
-    // mount loop device to path
-    if (::mount(loopdev.c_str(), path.c_str(), type.c_str(), flags, options.c_str()) != 0) {
-        LOGD("Mount failed for '" << path << "', options=" << options << ": " << getSystemErrorMessage());
+        // mount loop device to path
+        utils::mount(loopdev, path, type, flags, options);
+
+        utils::close(fileFD);
+        utils::close(loopFD);
+        return true;
+    } catch(const utils::UtilsException& e) {
+        LOGE(path << " error: " << e.what());
         ::ioctl(loopFD, LOOP_CLR_FD, 0);
-        ::close(fileFD);
-        ::close(loopFD);
+        utils::close(fileFD);
+        utils::close(loopFD);
         return false;
     }
-
-    ::close(fileFD);
-    ::close(loopFD);
-    return true;
 }
 
 } // namespace
 
 // Finds first available loop device and returns its path through ret.
 // Returns false if an error occurs, or if all available loop devices are taken.
+// FIXME: function prone to races
 bool getFreeLoopDevice(std::string& ret)
 {
     for (unsigned int i = 0; i < 8; ++i) {
@@ -150,26 +150,22 @@ bool mountImage(const std::string& image, const std::string& path, const std::st
 
 bool umountImage(const std::string& path, const std::string& loopdev)
 {
-    if (::umount(path.c_str()) != 0) {
-        LOGD("Umount failed for '" << path << "': " << getSystemErrorMessage());
+    int loopFD = -1;
+
+    try
+    {
+        utils::umount(path);
+
+        // clear loop device
+        loopFD = utils::open(loopdev, O_RDWR);
+        utils::ioctl(loopFD, LOOP_CLR_FD, 0);
+        utils::close(loopFD);
+        return true;
+    } catch(const utils::UtilsException& e) {
+        LOGE(path << " error: " << e.what());
+        utils::close(loopFD);
         return false;
     }
-
-    // clear loop device
-    int loopFD = ::open(loopdev.c_str(), O_RDWR);
-    if (loopFD < 0) {
-        LOGD("Failed to open fd for loop device 0");
-        return false;
-    }
-
-    if (::ioctl(loopFD, LOOP_CLR_FD, 0) < 0) {
-        LOGD("Failed to clear loop device.");
-        close(loopFD);
-        return false;
-    }
-
-    close(loopFD);
-    return true;
 }
 
 bool copyImageContents(const std::string& img, const std::string& dst)
@@ -183,19 +179,21 @@ bool copyImageContents(const std::string& img, const std::string& dst)
         return false;
     }
 
-    const std::string mountPoint = createFilePath(dirName(img), "/mp/");
-    // create a mount point for copied image
-    if (!createEmptyDir(mountPoint)) {
-        LOGE("Cannot create mount point for copied image.");
-        return false;
-    }
+    std::string mountPoint;
+    try {
+        mountPoint = createFilePath(dirName(img), "/mp/");
+
+        // create a mount point for copied image
+        createEmptyDir(mountPoint);
 
-    // create dst directory
-    if (!createEmptyDir(dst)) {
-        LOGE("Cannot create directory for data.");
+        // create dst directory
+        createEmptyDir(dst);
+    } catch(const utils::UtilsException & e) {
+        LOGE("Cannot copy image: " << e.what());
         return false;
     }
 
+
     // find free loop device for image
     std::string loopdev;
     if (!utils::getFreeLoopDevice(loopdev)) {
@@ -212,8 +210,10 @@ bool copyImageContents(const std::string& img, const std::string& dst)
 
     // copy data
     LOGI("Beginning image copy");
-    if (!utils::copyDirContents(mountPoint, dst)) {
-        LOGE("Failed to copy image.");
+    try {
+        utils::copyDirContents(mountPoint, dst);
+    } catch(const utils::UtilsException & e) {
+        LOGE("Failed to copy image: " << e.what());
         utils::umountImage(mountPoint, loopdev);
         LOGD("Removing already copied data");
         fs::remove_all(fs::path(dst));
index 1c4f84d98480a0b9cb36ad4352d33e3045397ad6..5012e6cabde589949b50c29ae69c32933b0758ef 100644 (file)
@@ -45,9 +45,7 @@ Inotify::Inotify(cargo::ipc::epoll::EventPoll& eventPoll)
 {
     mFD = ::inotify_init1(IN_CLOEXEC);
     if (mFD == -1) {
-        const std::string msg = "Error in inotify_init1: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in inotify_init1()", errno);
     }
 
     mEventPoll.addFD(mFD, EPOLLIN, std::bind(&Inotify::handleInternal, this));
@@ -86,9 +84,7 @@ void Inotify::setHandler(const std::string& path,
 
     int watchID = ::inotify_add_watch(mFD, path.c_str(), eventMask);
     if (-1 == watchID) {
-        const std::string msg = "Error in inotify_add_watch: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in inotify_add_watch()", errno);
     }
 
     mHandlers.push_back({path, watchID, callback});
@@ -107,9 +103,7 @@ void Inotify::removeHandlerInternal(const std::string& path)
 
     // Unwatch the path
     if (-1 == ::inotify_rm_watch(mFD, it->watchID)) {
-        const std::string msg = "Error in inotify_rm_watch: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in inotify_rm_watch()", errno);
     }
 
     mHandlers.erase(it);
index 7bb3d23b4616e910d10ed7047e27e5243b5d5bd0..775fbb2603a8eef2394173a30007f7e93d3886ba 100644 (file)
 
 namespace utils {
 
-namespace {
+// ------------------- syscall wrappers -------------------
+void pthread_sigmask(int how, const ::sigset_t *set, ::sigset_t *get)
+{
+    int ret = ::pthread_sigmask(how, set, get);
+    if (ret != 0) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in pthread_sigmask()", ret);
+    }
+}
 
-void setSignalMask(int how, const ::sigset_t& set)
+void sigemptyset(::sigset_t *set)
 {
-    int ret = ::pthread_sigmask(how, &set, nullptr /*&oldSet*/);
-    if(ret != 0) {
-        const std::string msg = "Error in pthread_sigmask: " + getSystemErrorMessage(ret);
-        LOGE(msg);
-        throw UtilsException(msg);
+    if (::sigemptyset(set) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in sigemptyset()", errno);
     }
 }
 
-void changeSignal(int how, const int sigNum) {
-    ::sigset_t set;
-    if(-1 == ::sigemptyset(&set)) {
-        const std::string msg = "Error in sigemptyset: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+void sigfillset(::sigset_t *set)
+{
+    if(-1 == ::sigfillset(set)) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in sigfillset()", errno);
     }
+}
 
-    if(-1 ==::sigaddset(&set, sigNum)) {
-        const std::string msg = "Error in sigaddset: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+void sigaddset(::sigset_t *set, int signum)
+{
+    if (::sigaddset(set, signum) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in sigaddset()", errno);
     }
+}
+
+void sigpending(::sigset_t *set)
+{
+    if (::sigpending(set) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in sigpending()", errno);
+    }
+}
+
+bool sigismember(const ::sigset_t *set, int signum)
+{
+    int ret = ::sigismember(set, signum);
+    if (ret == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in sigismember()", errno);
+    }
+    return ret == 1;
+}
+
+int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout)
+{
+    int ret = ::sigtimedwait(set, info, timeout);
+    if (ret == -1) {
+        if (errno == EAGAIN) {
+            return 0;
+        }
+
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in sigtimedwait()", errno);
+    }
+    return ret;
+}
 
-    setSignalMask(how, set);
+void sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
+{
+    if(-1 == ::sigaction(signum, act, oldact)) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in sigaction()", errno);
+    }
 }
 
+namespace {
+void changeSignal(int how, const int sigNum) {
+    ::sigset_t set;
+    utils::sigemptyset(&set);
+    utils::sigaddset(&set, sigNum);
+    utils::pthread_sigmask(how, &set, nullptr);
+}
 }// namespace
 
+// ------------------- higher level functions -------------------
 ::sigset_t getSignalMask()
 {
     ::sigset_t set;
-    int ret = ::pthread_sigmask(0 /*ignored*/, nullptr /*get the oldset*/, &set);
-    if(ret != 0) {
-        const std::string msg = "Error in pthread_sigmask: " + getSystemErrorMessage(ret);
-        LOGE(msg);
-        throw UtilsException(msg);
-    }
+    utils::pthread_sigmask(0 /*ignored*/, nullptr /*get the oldset*/, &set);
     return set;
 }
 
 bool isSignalPending(const int sigNum)
 {
     ::sigset_t set;
-    if (::sigpending(&set) == -1) {
-        const std::string msg = "Error in sigpending: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
-    }
+    utils::sigpending(&set);
 
-    int ret = ::sigismember(&set, sigNum);
-    if (ret == -1) {
-        const std::string msg = "Error in sigismember: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
-    }
-
-    return ret;
+    return utils::sigismember(&set, sigNum);
 }
 
 bool waitForSignal(const int sigNum, int timeoutMs)
@@ -108,27 +137,12 @@ bool waitForSignal(const int sigNum, int timeoutMs)
     };
 
     ::sigset_t set;
-    if(-1 == ::sigemptyset(&set)) {
-        const std::string msg = "Error in sigemptyset: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
-    }
-
-    if(-1 ==::sigaddset(&set, sigNum)) {
-        const std::string msg = "Error in sigaddset: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
-    }
+    utils::sigemptyset(&set);
+    utils::sigaddset(&set, sigNum);
 
     ::siginfo_t info;
-    if (::sigtimedwait(&set, &info, &timeout) == -1) {
-        if (errno == EAGAIN) {
-            return false;
-        }
-
-        const std::string msg = "Error in sigtimedwait: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+    if(utils::sigtimedwait(&set, &info, &timeout) == 0) {
+        return false;
     }
 
     return true;
@@ -137,15 +151,7 @@ bool waitForSignal(const int sigNum, int timeoutMs)
 bool isSignalBlocked(const int sigNum)
 {
     ::sigset_t set = getSignalMask();
-
-    int ret = ::sigismember(&set, sigNum);
-    if(-1 == ret) {
-        const std::string msg = "Error in sigismember: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
-    }
-
-    return ret == 1;
+    return utils::sigismember(&set, sigNum);
 }
 
 void signalBlock(const int sigNum)
@@ -156,20 +162,11 @@ void signalBlock(const int sigNum)
 void signalBlockAllExcept(const std::initializer_list<int>& signals)
 {
     ::sigset_t set;
-    if(-1 == ::sigfillset(&set)) {
-        const std::string msg = "Error in sigfillset: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
-    }
-
+    utils::sigfillset(&set);
     for(const int s: signals) {
-        if(-1 == ::sigaddset(&set, s)) {
-            const std::string msg = "Error in sigaddset: " + getSystemErrorMessage();
-            LOGE(msg);
-            throw UtilsException(msg);
-        }
+        utils::sigaddset(&set, s);
     }
-    setSignalMask(SIG_BLOCK, set);
+    utils::pthread_sigmask(SIG_BLOCK, &set, nullptr);
 }
 
 void signalUnblock(const int sigNum)
@@ -185,11 +182,7 @@ std::vector<std::pair<int, struct ::sigaction>> signalIgnore(const std::initiali
     std::vector<std::pair<int, struct ::sigaction>> oldAct;
 
     for(const int s: signals) {
-        if(-1 == ::sigaction(s, &act, &old)) {
-            const std::string msg = "Error in sigaction: " + getSystemErrorMessage();
-            LOGE(msg);
-            throw UtilsException(msg);
-        }
+        utils::sigaction(s, &act, &old);
         oldAct.emplace_back(s, old);
     }
 
@@ -199,24 +192,15 @@ std::vector<std::pair<int, struct ::sigaction>> signalIgnore(const std::initiali
 struct ::sigaction signalSet(const int sigNum, const struct ::sigaction *sigAct)
 {
     struct ::sigaction old;
-
-    if(-1 == ::sigaction(sigNum, sigAct, &old)) {
-        const std::string msg = "Error in sigaction: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
-    }
-
+    utils::sigaction(sigNum, sigAct, &old);
     return old;
 }
 
 void sendSignal(const pid_t pid, const int sigNum)
 {
     if (-1 == ::kill(pid, sigNum)) {
-        const std::string msg = "Error during killing pid: " + std::to_string(pid) +
-                                " sigNum: " + std::to_string(sigNum) +
-                                ": "  + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error during killing pid: " << std::to_string(pid)
+                                      << " sigNum: " + std::to_string(sigNum), errno);
     }
 }
 
index cb644197cf8f60c2aaebf77f14c3833b0ea33d08..39217fa3c60bc0f5db978f75d66729ebcdb636a2 100644 (file)
 #include <csignal>
 #include <vector>
 
-
 namespace utils {
 
+// ------------------- syscall wrappers -------------------
+// Throw exception on error
+void pthread_sigmask(int how, const ::sigset_t *set, ::sigset_t *get);
+void sigemptyset(::sigset_t *set);
+void sigfillset(::sigset_t *set);
+void sigaddset(::sigset_t *set, int signum);
+void sigpending(::sigset_t *set);
+bool sigismember(const ::sigset_t *set, int signum);
+int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout);
+void sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
+
 
+// ------------------- higher level functions -------------------
 ::sigset_t getSignalMask();
 bool isSignalPending(const int sigNum);
 bool waitForSignal(const int sigNum, int timeoutMs);
index 6e4aa9645b8904da17672b33e0d2e94663cd6017..9dabf3e8bf6dd12059b8ba74b087d87236067e55 100644 (file)
 
 namespace utils {
 
-SignalFD::SignalFD(cargo::ipc::epoll::EventPoll& eventPoll)
-    :mEventPoll(eventPoll)
+// ------------------- syscall wrappers -------------------
+int signalfd(int fd, const sigset_t *mask, int flags)
 {
-    int error = ::sigemptyset(&mSet);
-    if (error == -1) {
-        const std::string msg = "Error in sigemptyset: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+    int ret = ::signalfd(fd, mask, flags);
+    if (ret == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in signalfd()", errno);
     }
+    return ret;
+}
 
-    mFD = ::signalfd(-1, &mSet, SFD_CLOEXEC);
-    if (mFD == -1) {
-        const std::string msg = "Error in signalfd: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
-    }
 
+// ------------------- higher level code -------------------
+SignalFD::SignalFD(cargo::ipc::epoll::EventPoll& eventPoll)
+    :mEventPoll(eventPoll)
+{
+    utils::sigemptyset(&mSet);
+
+    mFD = utils::signalfd(-1, &mSet, SFD_CLOEXEC);
     mEventPoll.addFD(mFD, EPOLLIN, std::bind(&SignalFD::handleInternal, this));
 }
 
@@ -89,26 +90,15 @@ void SignalFD::setHandler(const int sigNum, const Callback&& callback)
         mBlockedSignals.push_back(sigNum);
     }
 
-    int error = ::sigaddset(&mSet, sigNum);
-    if (error == -1) {
-        const std::string msg = getSystemErrorMessage();
-        LOGE("Error in signalfd: " << msg);
-        if(!isBlocked) {
-            signalUnblock(sigNum);
-            mBlockedSignals.pop_back();
-        }
-        throw UtilsException("Error in signalfd: " + msg);
-    }
-
-    error = ::signalfd(mFD, &mSet, SFD_CLOEXEC);
-    if (error != mFD) {
-        const std::string msg = getSystemErrorMessage();
-        LOGE("Error in signalfd: " << msg);
+    try {
+        utils::sigaddset(&mSet, sigNum);
+        utils::signalfd(mFD, &mSet, SFD_CLOEXEC);
+    } catch(...) {
         if(!isBlocked) {
             signalUnblock(sigNum);
             mBlockedSignals.pop_back();
         }
-        throw UtilsException("Error in signalfd: " + msg);
+        throw;
     }
 
     mCallbacks.insert({sigNum, callback});
index 8936b8df4d18562b6db036e86d9a3875e8cfc5a2..9b5f8c9c7a0b3bdd57ec2ea070f8d238695b8ae0 100644 (file)
 
 namespace utils {
 
+// ------------------- syscall wrappers -------------------
+// Throw exception on error
+int signalfd(int fd, const sigset_t *mask, int flags);
+
+// ------------------- higher level code -------------------
 /**
  * SignalFD takes control over handling signals
  * sent to the thread.
diff --git a/common/utils/smack.cpp b/common/utils/smack.cpp
new file mode 100644 (file)
index 0000000..c7c7514
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ *  Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/**
+ * @file
+ * @author  Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief   SMACK utils implementation
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "logger/logger.hpp"
+#include "utils/exception.hpp"
+#include "utils/smack.hpp"
+#include "utils/fs.hpp"
+
+#include <sys/vfs.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+
+
+namespace utils {
+// ------------------- syscall wrappers -------------------
+std::string getxattr(const std::string &path, const std::string &name)
+{
+    char value[SMACK_LABEL_MAX_LEN + 1];
+
+    int ret = ::getxattr(path.c_str(), name.c_str(), value, sizeof(value));
+    if (ret == -1) {
+        if (errno == ENODATA) {
+            return "";
+        }
+
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in getxattr(" << path << ")", errno);
+    }
+
+    value[ret] = '\0';
+    return value;
+}
+
+std::string lgetxattr(const std::string &path, const std::string &name)
+{
+    char value[SMACK_LABEL_MAX_LEN + 1];
+
+    int ret = ::lgetxattr(path.c_str(), name.c_str(), value, sizeof(value));
+    if (ret == -1) {
+        if (errno == ENODATA) {
+            return "";
+        }
+
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in lgetxattr(" << path << ")", errno);
+    }
+
+    value[ret] = '\0';
+    return value;
+}
+
+void removexattr(const std::string &path, const std::string &name)
+{
+    if (::removexattr(path.c_str(), name.c_str()) == -1) {
+        if (errno == ENODATA) {
+            return;
+        }
+
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in removexattr(" << path << ")", errno);
+    }
+}
+
+void lremovexattr(const std::string &path, const std::string &name)
+{
+    if (::lremovexattr(path.c_str(), name.c_str()) == -1) {
+        if (errno == ENODATA) {
+            return;
+        }
+
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in lremovexattr(" << path << ")", errno);
+    }
+}
+
+void setxattr(const std::string &path, const std::string &name,
+              const std::string &value, int flags)
+{
+    if (::setxattr(path.c_str(), name.c_str(), value.c_str(), value.size(), flags) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in setxattr(" << path << ")", errno);
+    }
+}
+
+void lsetxattr(const std::string &path, const std::string &name,
+               const std::string &value, int flags)
+{
+    if (::lsetxattr(path.c_str(), name.c_str(), value.c_str(), value.size(), flags) == -1) {
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in setxattr(" << path << ")", errno);
+    }
+}
+
+
+// ------------------- higher level functions -------------------
+bool isSmackActive()
+{
+    try {
+        struct statfs sfbuf = utils::statfs(SMACK_MOUNT_PATH);
+        if ((uint32_t)sfbuf.f_type == (uint32_t)SMACK_MAGIC) {
+            return true;
+        }
+    } catch(const UtilsException & e) {}
+
+    return false;
+}
+
+bool isSmackNamespaceActive()
+{
+    return utils::exists("/proc/self/attr/label_map");
+}
+
+std::string smackXattrName(SmackLabelType type)
+{
+    switch (type) {
+    case SmackLabelType::SMACK_LABEL_ACCESS:
+        return "security.SMACK64";
+    case SmackLabelType::SMACK_LABEL_EXEC:
+        return "security.SMACK64EXEC";
+    case SmackLabelType::SMACK_LABEL_MMAP:
+        return "security.SMACK64MMAP";
+    case SmackLabelType::SMACK_LABEL_TRANSMUTE:
+        return "security.SMACK64TRANSMUTE";
+    case SmackLabelType::SMACK_LABEL_IPIN:
+        return "security.SMACK64IPIN";
+    case SmackLabelType::SMACK_LABEL_IPOUT:
+        return "security.SMACK64IPOUT";
+    default:
+        THROW_UTILS_EXCEPTION_E("Wrong SMACK label type passed");
+    }
+}
+
+std::string smackGetSelfLabel()
+{
+    return utils::readFileStream("/proc/self/attr/current");
+}
+
+std::string smackGetFileLabel(const std::string &path,
+                              SmackLabelType labelType,
+                              bool followLinks)
+{
+    const std::string xattrName = smackXattrName(labelType);
+
+    if (followLinks) {
+        return utils::getxattr(path, xattrName);
+    } else {
+        return utils::lgetxattr(path, xattrName);
+    }
+}
+
+void smackSetFileLabel(const std::string &path,
+                       const std::string &label,
+                       SmackLabelType labelType,
+                       bool followLinks)
+{
+    const std::string xattrName = smackXattrName(labelType);
+
+    if (label.size() > SMACK_LABEL_MAX_LEN) {
+        THROW_UTILS_EXCEPTION_E("SMACK label too long");
+    }
+
+    if (label.empty()) {
+        if (followLinks) {
+            utils::removexattr(path, xattrName);
+        } else {
+            utils::lremovexattr(path, xattrName);
+        }
+    } else {
+        if (followLinks) {
+            utils::setxattr(path, xattrName, label, 0);
+        } else {
+            utils::lsetxattr(path, xattrName, label, 0);
+        }
+    }
+}
+
+void copySmackLabel(const std::string& src, const std::string& dst, bool resolveLink)
+{
+    smackSetFileLabel(dst, smackGetFileLabel(src, SmackLabelType::SMACK_LABEL_ACCESS, resolveLink),
+                                                  SmackLabelType::SMACK_LABEL_ACCESS, resolveLink);
+    smackSetFileLabel(dst, smackGetFileLabel(src, SmackLabelType::SMACK_LABEL_EXEC, resolveLink),
+                                                  SmackLabelType::SMACK_LABEL_EXEC, resolveLink);
+    smackSetFileLabel(dst, smackGetFileLabel(src, SmackLabelType::SMACK_LABEL_MMAP, resolveLink),
+                                                  SmackLabelType::SMACK_LABEL_MMAP, resolveLink);
+    smackSetFileLabel(dst, smackGetFileLabel(src, SmackLabelType::SMACK_LABEL_TRANSMUTE, resolveLink),
+                                                  SmackLabelType::SMACK_LABEL_TRANSMUTE, resolveLink);
+}
+
+} // namespace lxcpp
diff --git a/common/utils/smack.hpp b/common/utils/smack.hpp
new file mode 100644 (file)
index 0000000..dbd8505
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *  Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/**
+ * @file
+ * @author  Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief   SMACK utils headers
+ */
+
+#ifndef COMMON_UTILS_SMACK_HPP
+#define COMMON_UTILS_SMACK_HPP
+
+#include <string>
+
+#define SMACK_MOUNT_PATH "/sys/fs/smackfs"
+#define SMACK_LABEL_MAX_LEN 255
+
+#ifndef SMACK_MAGIC
+#define SMACK_MAGIC 0x43415d53 // "SMAC"
+#endif
+
+namespace utils {
+
+// ------------------- syscall wrappers -------------------
+// Throw exception on error
+std::string getxattr(const std::string &path, const std::string &name);
+std::string lgetxattr(const std::string &path, const std::string &name);
+void removexattr(const std::string &path, const std::string &name);
+void lremovexattr(const std::string &path, const std::string &name);
+void setxattr(const std::string &path, const std::string &name,
+              const std::string &value, int flags);
+void lsetxattr(const std::string &path, const std::string &name,
+               const std::string &value, int flags);
+
+// ------------------- higher level functions -------------------
+enum class SmackLabelType : int {
+    SMACK_LABEL_ACCESS = 0,
+    SMACK_LABEL_EXEC,
+    SMACK_LABEL_MMAP,
+    SMACK_LABEL_TRANSMUTE,
+    SMACK_LABEL_IPIN,
+    SMACK_LABEL_IPOUT,
+
+    // ---
+    SMACK_LABEL_TERMINATOR
+};
+
+bool isSmackActive();
+bool isSmackNamespaceActive();
+std::string smackXattrName(SmackLabelType type);
+std::string smackGetSelfLabel();
+std::string smackGetFileLabel(const std::string &path,
+                              SmackLabelType labelType,
+                              bool followLinks);
+void smackSetFileLabel(const std::string &path,
+                       const std::string &label,
+                       SmackLabelType labelType,
+                       bool followLinks);
+void copySmackLabel(const std::string &src, const std::string &dst, bool resolveLink = true);
+
+} // namespace utils
+
+#endif // COMMON_UTILS_SMACK_HPP
index 74fc738d5737c3526d561463da86136dba5888fd..b59c4e0a3316a7d5be4421d0d99141719b91bbdc 100644 (file)
@@ -77,7 +77,7 @@ void ValueLatch<T>::set(const T& value)
 {
     std::unique_lock<std::mutex> lock(mMutex);
     if (mValue) {
-        throw UtilsException("Cannot set value multiple times");
+        THROW_UTILS_EXCEPTION_E("Cannot set value multiple times");
     }
     mValue.reset(new T(value));
     mCondition.notify_one();
@@ -88,7 +88,7 @@ void ValueLatch<T>::set(T&& value)
 {
     std::unique_lock<std::mutex> lock(mMutex);
     if (mValue) {
-        throw UtilsException("Cannot set value multiple times");
+        THROW_UTILS_EXCEPTION_E("Cannot set value multiple times");
     }
     mValue.reset(new T(std::move(value)));
     mCondition.notify_one();
@@ -115,7 +115,7 @@ T ValueLatch<T>::get(const unsigned int timeoutMs)
         std::unique_ptr<T> retValue(std::move(mValue));
         return T(std::move(*retValue));
     } else {
-        throw UtilsException("Timeout occured");
+        THROW_UTILS_EXCEPTION_E("Timeout occured");
     }
 }
 
index c5b726c303df65405d4fc59e278c70090030a7f8..c3119cab26b1be7535bc995d701539d98c16b596 100644 (file)
@@ -27,6 +27,7 @@
 #include "utils/vt.hpp"
 #include "logger/logger.hpp"
 #include "utils/exception.hpp"
+#include "utils/fd-utils.hpp"
 
 #include <fcntl.h>
 #include <sys/ioctl.h>
@@ -45,42 +46,33 @@ namespace utils {
 
 bool activateVT(const int& vt)
 {
-    int consoleFD = ::open(TTY_DEV.c_str(), O_WRONLY);
-    if (consoleFD < 0) {
-        LOGE("console open failed: " << errno << " (" << getSystemErrorMessage() << ")");
-        return false;
-    }
+    int consoleFD = -1;
 
-    struct vt_stat vtstat;
-    vtstat.v_active = 0;
-    if (::ioctl(consoleFD, VT_GETSTATE, &vtstat)) {
-        LOGE("Failed to get vt state: " << errno << " (" << getSystemErrorMessage() << ")");
-        ::close(consoleFD);
-        return false;
-    }
+    try {
+        consoleFD = utils::open(TTY_DEV, O_WRONLY);
 
-    if (vtstat.v_active == vt) {
-        LOGW("vt" << vt << " is already active.");
-        ::close(consoleFD);
-        return true;
-    }
+        struct vt_stat vtstat;
+        vtstat.v_active = 0;
+        utils::ioctl(consoleFD, VT_GETSTATE, &vtstat);
 
-    // activate vt
-    if (::ioctl(consoleFD, VT_ACTIVATE, vt)) {
-        LOGE("Failed to activate vt" << vt << ": " << errno << " (" << getSystemErrorMessage() << ")");
-        ::close(consoleFD);
-        return false;
-    }
+        if (vtstat.v_active == vt) {
+            LOGW("vt" << vt << " is already active.");
+        }
+        else {
+            // activate vt
+            utils::ioctl(consoleFD, VT_ACTIVATE, reinterpret_cast<void*>(vt));
+
+            // wait until activation is finished
+            utils::ioctl(consoleFD, VT_WAITACTIVE, reinterpret_cast<void*>(vt));
+        }
 
-    // wait until activation is finished
-    if (::ioctl(consoleFD, VT_WAITACTIVE, vt)) {
-        LOGE("Failed to wait for vt" << vt << " activation: " << errno << " (" << getSystemErrorMessage() << ")");
-        ::close(consoleFD);
+        utils::close(consoleFD);
+        return true;
+    } catch(const UtilsException & e) {
+        LOGE("Failed to activate vt" << vt << ": " << e.what() << " (" << getSystemErrorMessage(e.mErrno) << ")");
+        utils::close(consoleFD);
         return false;
     }
-
-    ::close(consoleFD);
-    return true;
 }
 
 } // namespace utils
index 565a558c26e434b16e8df13dd5f948653d7575e2..d1466b04df6b6f242a33b3151ee69c1ccaa23d9a 100644 (file)
@@ -44,9 +44,7 @@ EventPoll::EventPoll()
     : mPollFD(::epoll_create1(EPOLL_CLOEXEC))
 {
     if (mPollFD == -1) {
-        const std::string msg = "Failed to create epoll: " + getSystemErrorMessage();
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_ERRNO_E("Error in epoll_create1()", errno);
     }
 }
 
@@ -72,15 +70,11 @@ void EventPoll::addFD(const int fd, const Events events, Callback&& callback)
     std::lock_guard<Mutex> lock(mMutex);
 
     if (mCallbacks.find(fd) != mCallbacks.end()) {
-        const std::string msg = "fd " + std::to_string(fd) + " already added";
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_E("fd " << std::to_string(fd) << " already added");
     }
 
     if (!addFDInternal(fd, events)) {
-        const std::string msg = "Could not add fd";
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_E("Could not add fd");
     }
 
     mCallbacks.insert({fd, std::make_shared<Callback>(std::move(callback))});
@@ -91,9 +85,7 @@ void EventPoll::modifyFD(const int fd, const Events events)
 {
     // No need to lock as modify doesn't touch the mCallbacks map
     if (!modifyFDInternal(fd, events)) {
-        const std::string msg = "Could not modify fd: " + std::to_string(fd);
-        LOGE(msg);
-        throw UtilsException(msg);
+        THROW_UTILS_EXCEPTION_E("Could not modify fd: " << std::to_string(fd));
     }
 }
 
@@ -123,9 +115,7 @@ bool EventPoll::dispatchIteration(const int timeoutMs)
             if (errno == EINTR) {
                 continue;
             }
-            const std::string msg = "Failed to wait on epoll: " + getSystemErrorMessage();
-            LOGE(msg);
-            throw UtilsException(msg);
+            THROW_UTILS_EXCEPTION_ERRNO_E("Error in epoll_wait()", errno);
         }
 
         // callback could be removed in the meantime, so be careful, find it inside lock
index e79316cefa59ce2c7bda87bad2a1f4660e6686c8..01bee1ef369a4bb263babdba01900f1c8db508fe 100644 (file)
@@ -22,27 +22,20 @@ PROJECT(cargo-json)
 MESSAGE(STATUS "")
 MESSAGE(STATUS "Generating makefile for the lib${PROJECT_NAME}...")
 
-FILE(GLOB SRCS internals/*.cpp)
+FILE(GLOB HEADERS           *.hpp)
+FILE(GLOB HEADERS_INTERNALS internals/*.hpp)
 
 SET(_LIB_VERSION_ "${VERSION}")
 SET(_LIB_SOVERSION_ "0")
 SET(PC_FILE "lib${PROJECT_NAME}.pc")
 
 ## Setup target ################################################################
-ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
-SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
-    SOVERSION   ${_LIB_SOVERSION_}
-    VERSION     ${_LIB_VERSION_}
-)
-
-ADD_DEPENDENCIES(${PROJECT_NAME} cargo-utils)
 
 ## Link libraries ##############################################################
 PKG_SEARCH_MODULE(JSON_C REQUIRED json json-c)
 
 INCLUDE_DIRECTORIES(${COMMON_FOLDER} ${LIBS_FOLDER})
 INCLUDE_DIRECTORIES(SYSTEM ${JSON_C_INCLUDE_DIRS})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${JSON_C_LIBRARIES})
 
 ## Generate the pc file ########################################################
 CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY)
@@ -51,10 +44,6 @@ CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY)
 INSTALL(FILES       ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE}
         DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
 
-INSTALL(TARGETS     ${PROJECT_NAME}
-        DESTINATION ${LIB_INSTALL_DIR}
-        COMPONENT   RuntimeLibraries)
-
 INSTALL(DIRECTORY . DESTINATION ${INCLUDE_INSTALL_DIR}/${PROJECT_NAME}
         FILES_MATCHING PATTERN "*.hpp"
                        PATTERN "CMakeFiles" EXCLUDE)
index f0d69b68217dcadff474fd4c0b521c8a4b49d863..4a2dc8cd55027deb52c9e0124e59a19e613eb72f 100644 (file)
@@ -26,9 +26,9 @@
 #ifndef CARGO_JSON_CARGO_JSON_HPP
 #define CARGO_JSON_CARGO_JSON_HPP
 
+#include "utils/fs.hpp"
 #include "cargo-json/internals/to-json-visitor.hpp"
 #include "cargo-json/internals/from-json-visitor.hpp"
-#include "cargo-json/internals/fs-utils.hpp"
 
 namespace cargo {
 
@@ -73,11 +73,7 @@ std::string saveToJsonString(const Cargo& visitable)
 template <class Cargo>
 void loadFromJsonFile(const std::string& filename, Cargo& visitable)
 {
-    std::string content;
-    if (!internals::fsutils::readFileContent(filename, content)) {
-        const std::string& msg = "Could not load " + filename;
-        throw CargoException(msg);
-    }
+    const std::string content = utils::readFileContent(filename);
     try {
         loadFromJsonString(content, visitable);
     } catch (CargoException& e) {
@@ -96,9 +92,7 @@ template <class Cargo>
 void saveToJsonFile(const std::string& filename, const Cargo& visitable)
 {
     const std::string content = saveToJsonString(visitable);
-    if (!internals::fsutils::saveFileContent(filename, content)) {
-        throw CargoException("Could not save " + filename);
-    }
+    utils::saveFileContent(filename, content);
 }
 
 } // namespace cargo
diff --git a/libs/cargo-json/internals/fs-utils.cpp b/libs/cargo-json/internals/fs-utils.cpp
deleted file mode 100644 (file)
index c0ad6d1..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License
- */
-
-/**
- * @file
- * @author  Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
- * @brief   Filesystem helper functions
- */
-
-#include "config.hpp"
-
-#include "cargo-json/internals/fs-utils.hpp"
-
-#include <fstream>
-#include <streambuf>
-
-
-namespace cargo {
-namespace internals {
-namespace fsutils {
-
-bool readFileContent(const std::string& path, std::string& result)
-{
-    std::ifstream file(path);
-
-    if (!file) {
-        return false;
-    }
-
-    file.seekg(0, std::ios::end);
-    std::streampos length = file.tellg();
-    if (length < 0) {
-        return false;
-    }
-    result.resize(static_cast<size_t>(length));
-    file.seekg(0, std::ios::beg);
-
-    file.read(&result[0], length);
-    if (!file) {
-        result.clear();
-        return false;
-    }
-
-    return true;
-}
-
-bool saveFileContent(const std::string& path, const std::string& content)
-{
-    std::ofstream file(path);
-    if (!file) {
-        return false;
-    }
-    file.write(content.data(), static_cast<std::streamsize>(content.size()));
-    if (!file) {
-        return false;
-    }
-    return true;
-}
-
-} // namespace fsutils
-} // namespace internals
-} // namespace cargo
diff --git a/libs/cargo-json/internals/fs-utils.hpp b/libs/cargo-json/internals/fs-utils.hpp
deleted file mode 100644 (file)
index 2d2ba9b..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License
- */
-
-/**
- * @file
- * @author  Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
- * @brief   src/cargo/manager.hpp
- */
-
-#ifndef CARGO_JSON_INTERNALS_FS_UTILS_HPP
-#define CARGO_JSON_INTERNALS_FS_UTILS_HPP
-
-#include <string>
-
-namespace cargo {
-namespace internals {
-namespace fsutils {
-
-bool readFileContent(const std::string& path, std::string& result);
-bool saveFileContent(const std::string& path, const std::string& content);
-
-inline std::string readFileContent(const std::string& path) {
-    std::string content;
-    return readFileContent(path, content) ? content : std::string();
-}
-} // namespace fsutils
-} // namespace internals
-} // namespace cargo
-
-#endif // CARGO_JSON_INTERNALS_FS_UTILS_HPP
index 18690b5b4a7108e146e0a59c15d5a2c281e643aa..dcdea91ff52044205bda9a4f269e5fcd948e83b5 100644 (file)
@@ -8,5 +8,5 @@ includedir=@INCLUDE_INSTALL_DIR@
 Name: lib@PROJECT_NAME@
 Description: cargo Json library
 Version: @_LIB_VERSION_@
-Libs: -L${libdir} -l@PROJECT_NAME@ -l@JSON_C_LIBRARIES@
+Libs: -L${libdir} -l@JSON_C_LIBRARIES@
 Cflags: -I${includedir} -I${includedir}/@PROJECT_NAME@ -I@JSON_C_INCLUDE_DIRS@
index 06125b5b672ccfcd3d395cc368b36856f243b833..6eeb1e5ae712d07bc6d3a2b1960c82c03ca2f6b8 100644 (file)
 #ifndef CARGO_SQLITE_JSON_CARGO_SQLITE_JSON_HPP
 #define CARGO_SQLITE_JSON_CARGO_SQLITE_JSON_HPP
 
+#include "utils/fs.hpp"
 #include "cargo-json/internals/to-json-visitor.hpp"
 #include "cargo-sqlite/internals/to-kvstore-visitor.hpp"
 #include "cargo-json/internals/from-json-visitor.hpp"
 #include "cargo-sqlite/internals/from-kvstore-visitor.hpp"
 #include "cargo-sqlite/internals/from-kvstore-ignoring-visitor.hpp"
-#include "cargo-json/internals/fs-utils.hpp"
 // TODO: remove dependencies to other libraries internals
 
 namespace cargo {
@@ -77,10 +77,7 @@ void loadFromKVStoreWithJsonFile(const std::string& kvfile,
                                  Cargo& visitable,
                                  const std::string& kvVisitableName)
 {
-    std::string content;
-    if (!internals::fsutils::readFileContent(jsonfile, content)) {
-        throw CargoException("Could not load " + jsonfile);
-    }
+    const std::string content = utils::readFileContent(jsonfile);
     try {
         loadFromKVStoreWithJson(kvfile, content, visitable, kvVisitableName);
     } catch (CargoException& e) {
index adb1527821eba411c4e352806dfb059a846462f4..046873ea87ca2c089dfecab9d35c37a68b0f3d05 100644 (file)
@@ -130,42 +130,18 @@ The package provides libcargo GVariant development module.
 %{_libdir}/pkgconfig/libcargo-gvariant.pc
 
 ## libcargo-json Package ######################################################
-%package -n libcargo-json
-Summary:            Cargo Json module
-Group:              Security/Other
-%if %{platform_type} == "TIZEN"
-BuildRequires:      libjson-devel >= 0.10
-Requires:           libjson >= 0.10
-%else
-BuildRequires:      json-c-devel
-Requires:           json-c
-%endif
-Requires(post):     /sbin/ldconfig
-Requires(postun):   /sbin/ldconfig
-
-%description -n libcargo-json
-The package provides libcargo Json module.
-
-%post -n libcargo-json -p /sbin/ldconfig
-
-%postun -n libcargo-json -p /sbin/ldconfig
-
-%files -n libcargo-json
-%defattr(644,root,root,755)
-%{_libdir}/libcargo-json.so.0
-%attr(755,root,root) %{_libdir}/libcargo-json.so.%{version}
-
 %package -n libcargo-json-devel
 Summary:        Development cargo Json module
 Group:          Development/Libraries
 Requires:       libcargo-devel = %{epoch}:%{version}-%{release}
-Requires:       libcargo-json = %{epoch}:%{version}-%{release}
 Requires:       boost-devel
 Requires:       pkgconfig(libLogger)
 %if %{platform_type} == "TIZEN"
 Requires:       libjson-devel >= 0.10
+BuildRequires:  libjson-devel >= 0.10
 %else
 Requires:       json-c-devel
+BuildRequires:  json-c-devel
 %endif
 
 %description -n libcargo-json-devel
@@ -173,7 +149,6 @@ The package provides libcargo Json development module.
 
 %files -n libcargo-json-devel
 %defattr(644,root,root,755)
-%{_libdir}/libcargo-json.so
 %{_includedir}/cargo-json
 %{_libdir}/pkgconfig/libcargo-json.pc
 
index b647c7dc5605ceb8c3b00a935a4b1146d3771270..c157111b2c4587f180ed1740cc314134ead71ca0 100644 (file)
@@ -49,7 +49,7 @@ SET_TARGET_PROPERTIES(${UT_SERVER_CODENAME} PROPERTIES
 )
 
 TARGET_LINK_LIBRARIES(${UT_SERVER_CODENAME} ${Boost_LIBRARIES}
-                      Logger cargo-json cargo-sqlite cargo-fd cargo-ipc cargo-validator)
+                      Logger ${JSON_C_LIBRARIES} cargo-sqlite cargo-fd cargo-ipc cargo-validator)
 
 IF(NOT WITHOUT_SYSTEMD)
 SET_TARGET_PROPERTIES(${SOCKET_TEST_CODENAME} PROPERTIES
index 90c9affc5ddcb6d79859c5cfbcad704760f6444d..807f3b4f6d4ff2760b253df2130c09ae9216376b 100644 (file)
@@ -36,6 +36,7 @@
 #include "cargo-ipc/epoll/glib-dispatcher.hpp"
 #include "utils/channel.hpp"
 #include "utils/glib-loop.hpp"
+#include "utils/fs.hpp"
 #include "utils/latch.hpp"
 #include "utils/value-latch.hpp"
 #include "utils/scoped-dir.hpp"
@@ -774,7 +775,7 @@ MULTI_FIXTURE_TEST_CASE(FDSendReceive, F, ThreadedFixture, GlibFixture)
     const char DATA[] = "Content of the file";
     {
         // Fill the file
-        fs::remove(TEST_FILE);
+        utils::remove(TEST_FILE);
         std::ofstream file(TEST_FILE);
         file << DATA;
         file.close();
index 3b6862d0e4be9ed87e4095b68a5bb404aac83a83..819bed57010cef0833aaf1a4fef33a4ede6cfc8f 100644 (file)
@@ -27,6 +27,8 @@
 
 #include "ut.hpp"
 #include "testconfig-example.hpp"
+#include "utils/fs.hpp"
+#include "utils/fd-utils.hpp"
 #include "cargo-gvariant/cargo-gvariant.hpp"
 #include "cargo-fd/cargo-fd.hpp"
 #include "cargo-sqlite/cargo-sqlite.hpp"
@@ -335,7 +337,7 @@ BOOST_AUTO_TEST_CASE(FromToFD)
     loadFromJsonString(jsonTestString, config);
     // Setup fd
     std::string fifoPath = UT_PATH + "fdstore";
-    BOOST_CHECK(::mkfifo(fifoPath.c_str(), S_IWUSR | S_IRUSR) >= 0);
+    BOOST_CHECK_NO_THROW(utils::mkfifo(fifoPath, S_IWUSR | S_IRUSR));
     int fd = ::open(fifoPath.c_str(), O_RDWR);
     BOOST_REQUIRE(fd >= 0);
 
@@ -356,8 +358,9 @@ BOOST_AUTO_TEST_CASE(FromToInternetFD)
     loadFromJsonString(jsonTestString, config);
     // Setup fd
     std::string fifoPath = UT_PATH + "fdstore";
-    BOOST_CHECK(::mkfifo(fifoPath.c_str(), S_IWUSR | S_IRUSR) >= 0);
-    int fd = ::open(fifoPath.c_str(), O_RDWR);
+    BOOST_CHECK_NO_THROW(utils::mkfifo(fifoPath, S_IWUSR | S_IRUSR));
+    BOOST_REQUIRE(utils::access(fifoPath, O_RDWR));
+    int fd = utils::open(fifoPath.c_str(), O_RDWR);
     BOOST_REQUIRE(fd >= 0);
 
     // The test
@@ -368,7 +371,7 @@ BOOST_AUTO_TEST_CASE(FromToInternetFD)
     BOOST_CHECK_EQUAL(out, jsonTestString);
 
     // Cleanup
-    BOOST_CHECK(::close(fd) >= 0);
+    BOOST_CHECK_NO_THROW(utils::close(fd));
 }
 
 BOOST_AUTO_TEST_CASE(FromKVWithDefaults)
index d6b50ff0899541b24f15707f8fa52fe773b2f20e..5e69ab178700c8c3d149b23477bbc08ec949a419 100644 (file)
@@ -77,77 +77,71 @@ BOOST_AUTO_TEST_CASE(ReadFileContent)
     BOOST_CHECK_EQUAL(REFERENCE_FILE_CONTENT, readFileContent(REFERENCE_FILE_PATH));
     BOOST_CHECK_EXCEPTION(readFileContent(BUGGY_FILE_PATH),
                           UtilsException,
-                          WhatEquals("Read failed"));
+                          WhatEquals(BUGGY_FILE_PATH + ": could not open for reading"));
 }
 
 BOOST_AUTO_TEST_CASE(SaveFileContent)
 {
-    BOOST_REQUIRE(saveFileContent(FILE_PATH, REFERENCE_FILE_CONTENT));
+    BOOST_REQUIRE_NO_THROW(saveFileContent(FILE_PATH, REFERENCE_FILE_CONTENT));
     BOOST_CHECK_EQUAL(REFERENCE_FILE_CONTENT, readFileContent(FILE_PATH));
 }
 
 BOOST_AUTO_TEST_CASE(RemoveFile)
 {
-    BOOST_REQUIRE(saveFileContent(FILE_PATH, REFERENCE_FILE_CONTENT));
-    BOOST_REQUIRE(removeFile(FILE_PATH));
+    BOOST_REQUIRE_NO_THROW(saveFileContent(FILE_PATH, REFERENCE_FILE_CONTENT));
+    BOOST_REQUIRE_EQUAL(remove(FILE_PATH), true);
     BOOST_REQUIRE(!boost::filesystem::exists(FILE_PATH));
 }
 
 BOOST_AUTO_TEST_CASE(MountPoint)
 {
-    bool result;
     namespace fs = boost::filesystem;
     boost::system::error_code ec;
 
     BOOST_REQUIRE(fs::create_directory(MOUNT_POINT_1, ec));
-    BOOST_REQUIRE(isMountPoint(MOUNT_POINT_1, result));
-    BOOST_CHECK_EQUAL(result, false);
-    BOOST_REQUIRE(hasSameMountPoint(TEST_PATH, MOUNT_POINT_1, result));
-    BOOST_CHECK_EQUAL(result, true);
-
-    BOOST_REQUIRE(mountRun(MOUNT_POINT_1));
-    BOOST_REQUIRE(isMountPoint(MOUNT_POINT_1, result));
-    BOOST_CHECK_EQUAL(result, true);
-    BOOST_REQUIRE(hasSameMountPoint(TEST_PATH, MOUNT_POINT_1, result));
-    BOOST_CHECK_EQUAL(result, false);
-
-    BOOST_REQUIRE(umount(MOUNT_POINT_1));
+    BOOST_REQUIRE_EQUAL(false, isMountPoint(MOUNT_POINT_1));
+    BOOST_REQUIRE_EQUAL(true, hasSameMountPoint(TEST_PATH, MOUNT_POINT_1));
+
+    BOOST_REQUIRE_NO_THROW(mountRun(MOUNT_POINT_1));
+    BOOST_REQUIRE_EQUAL(true, isMountPoint(MOUNT_POINT_1));
+    BOOST_REQUIRE_EQUAL(false, hasSameMountPoint(TEST_PATH, MOUNT_POINT_1));
+
+    BOOST_REQUIRE_NO_THROW(utils::umount(MOUNT_POINT_1));
     BOOST_REQUIRE(fs::remove(MOUNT_POINT_1, ec));
 }
 
 BOOST_AUTO_TEST_CASE(MoveFile)
 {
-    namespace fs = boost::filesystem;
-    boost::system::error_code ec;
+    //namespace fs = boost::filesystem;
     std::string src, dst;
 
     // same mount point
     src = TEST_PATH + "/" + FILE_NAME_1;
     dst = TEST_PATH + "/" + FILE_NAME_2;
 
-    BOOST_REQUIRE(saveFileContent(src, REFERENCE_FILE_CONTENT));
+    BOOST_REQUIRE_NO_THROW(saveFileContent(src, REFERENCE_FILE_CONTENT));
 
-    BOOST_CHECK(moveFile(src, dst));
-    BOOST_CHECK(!fs::exists(src));
+    BOOST_CHECK_NO_THROW(moveFile(src, dst));
+    BOOST_CHECK(!utils::exists(src));
     BOOST_CHECK_EQUAL(readFileContent(dst), REFERENCE_FILE_CONTENT);
 
-    BOOST_REQUIRE(fs::remove(dst));
+    BOOST_REQUIRE(utils::remove(dst));
 
     // different mount point
     src = TEST_PATH + "/" + FILE_NAME_1;
     dst = MOUNT_POINT_2 + "/" + FILE_NAME_2;
 
-    BOOST_REQUIRE(fs::create_directory(MOUNT_POINT_2, ec));
-    BOOST_REQUIRE(mountRun(MOUNT_POINT_2));
-    BOOST_REQUIRE(saveFileContent(src, REFERENCE_FILE_CONTENT));
+    BOOST_REQUIRE_NO_THROW(utils::createEmptyDir(MOUNT_POINT_2));
+    BOOST_REQUIRE_NO_THROW(mountRun(MOUNT_POINT_2));
+    BOOST_REQUIRE_NO_THROW(saveFileContent(src, REFERENCE_FILE_CONTENT));
 
-    BOOST_CHECK(moveFile(src, dst));
-    BOOST_CHECK(!fs::exists(src));
+    BOOST_CHECK_NO_THROW(moveFile(src, dst));
+    BOOST_CHECK(!utils::exists(src));
     BOOST_CHECK_EQUAL(readFileContent(dst), REFERENCE_FILE_CONTENT);
 
-    BOOST_REQUIRE(fs::remove(dst));
-    BOOST_REQUIRE(umount(MOUNT_POINT_2));
-    BOOST_REQUIRE(fs::remove(MOUNT_POINT_2, ec));
+    BOOST_REQUIRE(utils::remove(dst));
+    BOOST_REQUIRE_NO_THROW(utils::umount(MOUNT_POINT_2));
+    BOOST_REQUIRE_NO_THROW(utils::rmdir(MOUNT_POINT_2));
 }
 
 BOOST_AUTO_TEST_CASE(CopyDirContents)
@@ -183,11 +177,11 @@ BOOST_AUTO_TEST_CASE(CopyDirContents)
     BOOST_REQUIRE(fs::create_directory(src_inner2, ec));
     BOOST_REQUIRE(ec.value() == 0);
 
-    BOOST_REQUIRE(saveFileContent(src + "/" + FILE_NAME_1, REFERENCE_FILE_CONTENT));
-    BOOST_REQUIRE(saveFileContent(src + "/" + FILE_NAME_2, FILE_CONTENT_2));
-    BOOST_REQUIRE(saveFileContent(src_inner + "/" + FILE_NAME_1, FILE_CONTENT_3));
-    BOOST_REQUIRE(saveFileContent(src_inner2 + "/" + FILE_NAME_1, FILE_CONTENT_3));
-    BOOST_REQUIRE(saveFileContent(src_inner2 + "/" + FILE_NAME_2, FILE_CONTENT_2));
+    BOOST_REQUIRE_NO_THROW(saveFileContent(src + "/" + FILE_NAME_1, REFERENCE_FILE_CONTENT));
+    BOOST_REQUIRE_NO_THROW(saveFileContent(src + "/" + FILE_NAME_2, FILE_CONTENT_2));
+    BOOST_REQUIRE_NO_THROW(saveFileContent(src_inner + "/" + FILE_NAME_1, FILE_CONTENT_3));
+    BOOST_REQUIRE_NO_THROW(saveFileContent(src_inner2 + "/" + FILE_NAME_1, FILE_CONTENT_3));
+    BOOST_REQUIRE_NO_THROW(saveFileContent(src_inner2 + "/" + FILE_NAME_2, FILE_CONTENT_2));
 
     // change permissions of src_inner2 directory
     fs::permissions(src_inner2, fs::owner_read, ec);
@@ -198,7 +192,7 @@ BOOST_AUTO_TEST_CASE(CopyDirContents)
     BOOST_REQUIRE(ec.value() == 0);
 
     // copy data
-    BOOST_CHECK(copyDirContents(src, dst));
+    BOOST_CHECK_NO_THROW(copyDirContents(src, dst));
 
     // check if copy is successful
     BOOST_CHECK(fs::exists(dst + "/" + FILE_NAME_1));
index ce840ee41b3eb5420f2d185c5245a0f0ce15a8f9..fbc61dc1101ac71ebdc7858c9a94199d641905da 100644 (file)
@@ -89,7 +89,7 @@ BOOST_AUTO_TEST_CASE(CreateDeleteFileHandler)
     i.setHandler(TEST_DIR, IN_DELETE, [&](const std::string& name, uint32_t) {
         deleteResult.set(name);
     });
-    fs::remove(FILE_PATH);
+    utils::remove(FILE_PATH);
     BOOST_REQUIRE_EQUAL(deleteResult.get(), FILE_NAME);
 }
 
@@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(NoFalseEventHandler)
     i.setHandler(TEST_DIR, IN_CREATE, [&](const std::string& name, uint32_t) {
         createResult.set(name);
     });
-    fs::remove(FILE_PATH);
+    utils::remove(FILE_PATH);
     BOOST_REQUIRE_THROW(createResult.get(10), UtilsException);
 }
 
@@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE(RemoveHandler)
     });
     i.removeHandler(TEST_DIR);
     utils::createFile(FILE_PATH, O_WRONLY | O_CREAT, 0666);
-    fs::remove(FILE_PATH);
+    utils::remove(FILE_PATH);
     BOOST_REQUIRE_THROW(createResult.get(10), UtilsException);
 }