Remove unneeded return statement
[platform/core/security/cynara.git] / src / service / storage / InMemoryStorageBackend.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        InMemoryStorageBackend.cpp
18  * @author      Aleksander Zdyb <a.zdyb@partner.samsung.com>
19  * @version     1.0
20  * @brief       Implementation of InMemoryStorageBackend
21  */
22
23 #include <errno.h>
24 #include <fstream>
25 #include <functional>
26 #include <memory>
27 #include <string>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <unordered_map>
31 #include <vector>
32
33 #include <log/log.h>
34 #include <exceptions/BucketNotExistsException.h>
35 #include <exceptions/CannotCreateFileException.h>
36 #include <exceptions/FileNotFoundException.h>
37 #include <exceptions/UnexpectedErrorException.h>
38 #include <types/PolicyBucket.h>
39 #include <types/PolicyResult.h>
40 #include <types/PolicyType.h>
41
42 #include <storage/BucketDeserializer.h>
43 #include <storage/StorageDeserializer.h>
44 #include <storage/StorageSerializer.h>
45
46 #include "InMemoryStorageBackend.h"
47
48 namespace Cynara {
49
50 void InMemoryStorageBackend::load(void) {
51     std::string indexFilename = m_dbPath + m_indexFileName;
52
53     try {
54         std::shared_ptr<std::ifstream> indexStream = std::make_shared<std::ifstream>();
55         openFileStream(indexStream, indexFilename);
56
57         StorageDeserializer storageDeserializer(indexStream,
58             std::bind(&InMemoryStorageBackend::bucketStreamOpener, this, std::placeholders::_1));
59
60         storageDeserializer.initBuckets(buckets());
61         storageDeserializer.loadBuckets(buckets());
62     } catch (const FileNotFoundException &) {
63         LOGE("Reading cynara database failed.");
64     }
65
66     if (!hasBucket(defaultPolicyBucketId)) {
67             LOGN("Creating defaultBucket.");
68             this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() });
69     }
70 }
71
72 void InMemoryStorageBackend::save(void) {
73
74     //create directory
75     int ret = mkdir(m_dbPath.c_str(), S_IRWXU);
76     if (ret < 0) {
77         int err = errno;
78         if (err != EEXIST) {
79             LOGE("Cannot create directory <%s>. Error [%d] : <%s>.",
80                  m_dbPath.c_str(), err, strerror(err));
81             throw UnexpectedErrorException(err, strerror(err));
82         }
83     }
84
85     std::shared_ptr<std::ofstream> indexStream = std::make_shared<std::ofstream>();
86     openDumpFileStream(indexStream, m_dbPath + m_indexFileName);
87
88     StorageSerializer storageSerializer(indexStream);
89     storageSerializer.dump(buckets(), std::bind(&InMemoryStorageBackend::bucketDumpStreamOpener,
90                            this, std::placeholders::_1));
91 }
92
93 PolicyBucket InMemoryStorageBackend::searchDefaultBucket(const PolicyKey &key) {
94     return searchBucket(defaultPolicyBucketId, key);
95 }
96
97 PolicyBucket InMemoryStorageBackend::searchBucket(const PolicyBucketId &bucketId,
98                                                   const PolicyKey &key) {
99     try {
100         const auto &bucket = this->buckets().at(bucketId);
101         return bucket.filtered(key);
102     } catch (const std::out_of_range &) {
103         throw BucketNotExistsException(bucketId);
104     }
105 }
106
107 void InMemoryStorageBackend::insertPolicy(const PolicyBucketId &bucketId, PolicyPtr policy) {
108     try {
109         auto &bucket = buckets().at(bucketId);
110         auto &policies = bucket.policyCollection();
111         policies.push_back(policy);
112     } catch (const std::out_of_range &) {
113         throw BucketNotExistsException(bucketId);
114     }
115 }
116
117 void InMemoryStorageBackend::createBucket(const PolicyBucketId &bucketId,
118                                           const PolicyResult &defaultPolicy) {
119     PolicyBucket newBucket;
120     newBucket.setDefaultPolicy(defaultPolicy);
121     buckets().insert({ bucketId, newBucket });
122 }
123
124 void InMemoryStorageBackend::updateBucket(const PolicyBucketId &bucketId,
125                                           const PolicyResult &defaultPolicy) {
126     try {
127         auto &bucket = buckets().at(bucketId);
128         bucket.setDefaultPolicy(defaultPolicy);
129     } catch (const std::out_of_range &) {
130         throw BucketNotExistsException(bucketId);
131     }
132 }
133
134 void InMemoryStorageBackend::deleteBucket(const PolicyBucketId &bucketId) {
135     auto bucketErased = buckets().erase(bucketId);
136     if (bucketErased == 0) {
137         throw BucketNotExistsException(bucketId);
138     }
139 }
140
141 bool InMemoryStorageBackend::hasBucket(const PolicyBucketId &bucketId) {
142     return buckets().find(bucketId) != buckets().end();
143 }
144
145 void InMemoryStorageBackend::deletePolicy(const PolicyBucketId &bucketId, const PolicyKey &key) {
146     try {
147         // TODO: Move the erase code to PolicyCollection maybe?
148         auto &bucket = buckets().at(bucketId);
149         auto &policies = bucket.policyCollection();
150         policies.erase(remove_if(policies.begin(), policies.end(),
151                 [key](PolicyPtr policy) -> bool {
152                     return policy->key() == key;
153             }), policies.end());
154     } catch (const std::out_of_range &) {
155         throw BucketNotExistsException(bucketId);
156     }
157 }
158
159 void InMemoryStorageBackend::deleteLinking(const PolicyBucketId &bucketId) {
160     auto bucketIdMatches = [&bucketId] (PolicyPtr policy) -> bool {
161         auto policyResult = policy->result();
162
163         // Check bucket id only if policy is a bucket policy
164         // TODO: Maybe move the test to PolicyResult
165         if (policyResult.policyType() == PredefinedPolicyType::BUCKET) {
166             return policyResult.metadata() == bucketId;
167         }
168         return false;
169     };
170
171     for (auto &bucketIter : buckets()) {
172         // TODO: Move the erase code to PolicyCollection maybe?
173         auto &bucket = bucketIter.second;
174         auto &policies = bucket.policyCollection();
175         policies.erase(remove_if(policies.begin(), policies.end(), bucketIdMatches),
176                 policies.end());
177     }
178 }
179
180 void InMemoryStorageBackend::openFileStream(std::shared_ptr<std::ifstream> stream,
181                                             const std::string &filename) {
182     // TODO: Consider adding exceptions to streams and handling them:
183     // stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
184     stream->open(filename);
185
186     if (!stream->is_open())
187         throw FileNotFoundException(filename);
188 }
189
190 void InMemoryStorageBackend::openDumpFileStream(std::shared_ptr<std::ofstream> stream,
191                                                 const std::string &filename) {
192     stream->open(filename, std::ofstream::out | std::ofstream::trunc);
193
194     if (!stream->is_open()) {
195         throw CannotCreateFileException(filename);
196     }
197 }
198
199 std::shared_ptr<BucketDeserializer> InMemoryStorageBackend::bucketStreamOpener(
200         const PolicyBucketId &bucketId) {
201     std::string bucketFilename = m_dbPath + "_" + bucketId;
202     std::shared_ptr<std::ifstream> bucketStream = std::make_shared<std::ifstream>();
203     try {
204         openFileStream(bucketStream, bucketFilename);
205         return std::make_shared<BucketDeserializer>(bucketStream);
206     } catch (const FileNotFoundException &) {
207         return nullptr;
208     }
209 }
210
211 std::shared_ptr<StorageSerializer> InMemoryStorageBackend::bucketDumpStreamOpener(
212         const PolicyBucketId &bucketId) {
213     std::string bucketFilename = m_dbPath + "_" + bucketId;
214     std::shared_ptr<std::ofstream> bucketStream = std::make_shared<std::ofstream>();
215
216     openDumpFileStream(bucketStream, bucketFilename);
217     return std::make_shared<StorageSerializer>(bucketStream);
218 }
219
220 } /* namespace Cynara */