Reduce number of error logs in ckm.
[platform/core/security/key-manager.git] / src / manager / service / file-system.cpp
index f714a89..376d78d 100644 (file)
@@ -20,6 +20,7 @@
  * @brief       Sample service implementation.
  */
 #include <string.h>
+#include <stdio.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <string>
 #include <sstream>
 #include <fstream>
+#include <memory>
+#include <stdexcept>
 
+#include <dpl/errno_string.h>
+#include <dpl/fstream_accessors.h>
 #include <dpl/log/log.h>
 
+#include <exception.h>
 #include <file-system.h>
 
 namespace {
 
-static const std::string CKM_DATA_PATH = "/opt/data/ckm/";
-static const std::string CKM_KEY_PREFIX = "key-";
-static const std::string CKM_DB_KEY_PREFIX = "db-key-";
-static const std::string CKM_DB_PREFIX = "db-";
-static const std::string CKM_REMOVED_APP_PREFIX = "removed-app-";
+const std::string CKM_DATA_PATH = "/opt/data/ckm/";
+const std::string CKM_KEY_PREFIX = "key-";
+const std::string CKM_DB_KEY_PREFIX = "db-key-";
+const std::string CKM_DB_PREFIX = "db-";
+const std::string CKM_REMOVED_APP_PREFIX = "removed-app-";
+const std::string CKM_LOCK_FILE = "/var/run/key-manager.pid";
 
 } // namespace anonymous
 
@@ -78,9 +85,15 @@ std::string FileSystem::getRemovedAppsPath() const {
 RawBuffer FileSystem::loadFile(const std::string &path) const {
     std::ifstream is(path);
 
-    if (is.fail())
+    if (is.fail() && ENOENT == errno)
         return RawBuffer();
 
+    if (is.fail()) {
+        auto description = GetErrnoString(errno);
+        ThrowErr(Exc::FileSystemFailed,
+                 "Error opening file: ", path, " Reason: ", description);
+    }
+
     std::istreambuf_iterator<char> begin(is),end;
     std::vector<char> buff(begin,end); // This trick does not work with boost vector
 
@@ -99,27 +112,38 @@ RawBuffer FileSystem::getDBDEK() const
     return loadFile(getDBDEKPath());
 }
 
-bool FileSystem::saveFile(const std::string &path, const RawBuffer &buffer) const {
-    std::ofstream os(path, std::ios::out | std::ofstream::binary);
+void FileSystem::saveFile(const std::string &path, const RawBuffer &buffer) const {
+    std::ofstream os(path, std::ios::out | std::ofstream::binary | std::ofstream::trunc);
     std::copy(buffer.begin(), buffer.end(), std::ostreambuf_iterator<char>(os));
-    return !os.fail();
+
+    // Prevent desynchronization in batter remove test.
+    os.flush();
+    fsync(FstreamAccessors<std::ofstream>::GetFd(os)); // flush kernel space buffer
+    os.close();
+
+    if (os.fail())
+        ThrowErr(Exc::FileSystemFailed, "Failed to save file: ", path);
 }
 
-bool FileSystem::saveDKEK(const RawBuffer &buffer) const {
-    return saveFile(getDKEKPath(), buffer);
+void FileSystem::saveDKEK(const RawBuffer &buffer) const {
+    saveFile(getDKEKPath(), buffer);
 }
 
-bool FileSystem::saveDBDEK(const RawBuffer &buffer) const {
-    return saveFile(getDBDEKPath(), buffer);
+void FileSystem::saveDBDEK(const RawBuffer &buffer) const {
+    saveFile(getDBDEKPath(), buffer);
 }
 
-bool FileSystem::addRemovedApp(const std::string &smackLabel) const
+void FileSystem::addRemovedApp(const std::string &smackLabel) const
 {
     std::ofstream outfile;
     outfile.open(getRemovedAppsPath(), std::ios_base::app);
     outfile << smackLabel << std::endl;
     outfile.close();
-    return !outfile.fail();
+    if (outfile.fail()) {
+        auto desc = GetErrnoString(errno);
+        ThrowErr(Exc::FileSystemFailed,
+                 "Could not update file: ", getRemovedAppsPath(), " Reason: ", desc);
+    }
 }
 
 AppLabelVector FileSystem::clearRemovedsApps() const
@@ -147,8 +171,7 @@ int FileSystem::init() {
     errno = 0;
     if ((mkdir(CKM_DATA_PATH.c_str(), 0700)) && (errno != EEXIST)) {
         int err = errno;
-        LogError("Error in mkdir. Data directory could not be created. Errno: "
-            << err << " (" << strerror(err) << ")");
+        LogError("Error in mkdir " << CKM_DATA_PATH << ". Reason: " << GetErrnoString(err));
         return -1; // TODO set up some error code
     }
     return 0;
@@ -156,21 +179,27 @@ int FileSystem::init() {
 
 UidVector FileSystem::getUIDsFromDBFile() {
     UidVector uids;
-    DIR *dirp = NULL;
-    errno = 0;
+    std::unique_ptr<DIR, std::function<int(DIR*)>>
+        dirp(::opendir(CKM_DATA_PATH.c_str()), ::closedir);
 
-    if((dirp = opendir(CKM_DATA_PATH.c_str())) == NULL) {
+    if (!dirp.get()) {
         int err = errno;
-        LogError("Error in opendir. Data directory could not be read. Errno: "
-                << err << " (" << strerror(err) << ")");
+        LogError("Error in opendir. Data directory could not be read. Error: " << GetErrnoString(err));
         return UidVector();
     }
 
-    struct dirent pPrevDirEntry;
-    struct dirent* pDirEntry = NULL;
+    size_t len = offsetof(struct dirent, d_name) + pathconf(CKM_DATA_PATH.c_str(), _PC_NAME_MAX) + 1;
+    std::unique_ptr<struct dirent, std::function<void(void*)>>
+        pEntry(static_cast<struct dirent*>(::malloc(len)), ::free);
 
-    while ((!readdir_r(dirp, &pPrevDirEntry, &pDirEntry)) && pDirEntry && (pDirEntry->d_name)) {
+    if (!pEntry.get()) {
+        LogError("Memory allocation failed.");
+        return UidVector();
+    }
+
+    struct dirent* pDirEntry = NULL;
 
+    while ( (!readdir_r(dirp.get(), pEntry.get(), &pDirEntry)) && pDirEntry ) {
         // Ignore files with diffrent prefix
         if (strncmp(pDirEntry->d_name, CKM_KEY_PREFIX.c_str(), CKM_KEY_PREFIX.size())) {
             continue;
@@ -180,15 +209,14 @@ UidVector FileSystem::getUIDsFromDBFile() {
         try {
             uids.push_back(static_cast<uid_t>(std::stoi((pDirEntry->d_name)+CKM_KEY_PREFIX.size())));
         } catch (const std::invalid_argument) {
-            LogError("Error in extracting uid from db file. Error=std::invalid_argument."
+            LogDebug("Error in extracting uid from db file. Error=std::invalid_argument."
                 "This will be ignored.File=" << pDirEntry->d_name << "");
         } catch(const std::out_of_range) {
-            LogError("Error in extracting uid from db file. Error=std::out_of_range."
+            LogDebug("Error in extracting uid from db file. Error=std::out_of_range."
                 "This will be ignored. File="<< pDirEntry->d_name << "");
         }
     }
 
-    closedir(dirp);
     return uids;
 }
 
@@ -198,33 +226,39 @@ int FileSystem::removeUserData() const {
     if (unlink(getDBPath().c_str())) {
         retCode = -1;
         err = errno;
-        LogError("Error in unlink user database: " << getDBPath()
-            << "Errno: " << errno << " " << strerror(err));
+        LogDebug("Error in unlink user database: " << getDBPath()
+            << "Errno: " << errno << " " << GetErrnoString(err));
     }
 
     if (unlink(getDKEKPath().c_str())) {
         retCode = -1;
         err = errno;
-        LogError("Error in unlink user DKEK: " << getDKEKPath()
-            << "Errno: " << errno << " " << strerror(err));
+        LogDebug("Error in unlink user DKEK: " << getDKEKPath()
+            << "Errno: " << errno << " " << GetErrnoString(err));
     }
 
     if (unlink(getDBDEKPath().c_str())) {
         retCode = -1;
         err = errno;
-        LogError("Error in unlink user DBDEK: " << getDBDEKPath()
-            << "Errno: " << errno << " " << strerror(err));
+        LogDebug("Error in unlink user DBDEK: " << getDBDEKPath()
+            << "Errno: " << errno << " " << GetErrnoString(err));
     }
 
     if (unlink(getRemovedAppsPath().c_str())) {
         retCode = -1;
         err = errno;
-        LogError("Error in unlink user's Removed Apps File: " << getRemovedAppsPath()
-            << "Errno: " << errno << " " << strerror(err));
+        LogDebug("Error in unlink user's Removed Apps File: " << getRemovedAppsPath()
+            << "Errno: " << errno << " " << GetErrnoString(err));
     }
 
     return retCode;
 }
 
+FileLock FileSystem::lock()
+{
+    FileLock fl(CKM_LOCK_FILE.c_str());
+    return fl;
+}
+
 } // namespace CKM