Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / platform / Tizen / CHIPLinuxStorage.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    All rights reserved.
5  *
6  *    Licensed under the Apache License, Version 2.0 (the "License");
7  *    you may not use this file except in compliance with the License.
8  *    You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *    Unless required by applicable law or agreed to in writing, software
13  *    distributed under the License is distributed on an "AS IS" BASIS,
14  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *    See the License for the specific language governing permissions and
16  *    limitations under the License.
17  */
18
19 /**
20  *    @file
21  *         This file implements a class for managing client application
22  *         user-editable settings on Linux platform.
23  *
24  */
25
26 #include <errno.h>
27 #include <fstream>
28 #include <inttypes.h>
29 #include <libgen.h>
30 #include <string>
31 #include <unistd.h>
32
33 #include <platform/Linux/CHIPLinuxStorage.h>
34 #include <platform/internal/CHIPDeviceLayerInternal.h>
35 #include <support/Base64.h>
36 #include <support/CHIPMem.h>
37 #include <support/CodeUtils.h>
38 #include <support/ScopedBuffer.h>
39 #include <support/logging/CHIPLogging.h>
40
41 namespace chip {
42 namespace DeviceLayer {
43 namespace Internal {
44
45 ChipLinuxStorage::ChipLinuxStorage()
46 {
47     mDirty = false;
48 }
49
50 ChipLinuxStorage::~ChipLinuxStorage() {}
51
52 CHIP_ERROR ChipLinuxStorage::Init(const char * configFile)
53 {
54     CHIP_ERROR retval = CHIP_NO_ERROR;
55
56     mConfigPath.assign(configFile);
57     retval = ChipLinuxStorageIni::Init();
58
59     if (retval == CHIP_NO_ERROR)
60     {
61         std::ifstream ifs;
62
63         ifs.open(configFile, std::ifstream::in);
64
65         // Create default setting file if not exist.
66         if (!ifs.good())
67         {
68             mDirty = true;
69             retval = Commit();
70             mDirty = false;
71         }
72     }
73
74     if (retval == CHIP_NO_ERROR)
75     {
76         retval = ChipLinuxStorageIni::AddConfig(mConfigPath);
77     }
78
79     return retval;
80 }
81
82 CHIP_ERROR ChipLinuxStorage::ReadValue(const char * key, bool & val)
83 {
84     CHIP_ERROR retval = CHIP_NO_ERROR;
85     uint32_t result;
86
87     mLock.lock();
88
89     retval = ChipLinuxStorageIni::GetUIntValue(key, result);
90     val    = (result != 0);
91
92     mLock.unlock();
93
94     return retval;
95 }
96
97 CHIP_ERROR ChipLinuxStorage::ReadValue(const char * key, uint32_t & val)
98 {
99     CHIP_ERROR retval = CHIP_NO_ERROR;
100
101     mLock.lock();
102
103     retval = ChipLinuxStorageIni::GetUIntValue(key, val);
104
105     mLock.unlock();
106
107     return retval;
108 }
109
110 CHIP_ERROR ChipLinuxStorage::ReadValue(const char * key, uint64_t & val)
111 {
112     CHIP_ERROR retval = CHIP_NO_ERROR;
113
114     mLock.lock();
115
116     retval = ChipLinuxStorageIni::GetUInt64Value(key, val);
117
118     mLock.unlock();
119
120     return retval;
121 }
122
123 CHIP_ERROR ChipLinuxStorage::ReadValueStr(const char * key, char * buf, size_t bufSize, size_t & outLen)
124 {
125     CHIP_ERROR retval = CHIP_NO_ERROR;
126
127     mLock.lock();
128
129     retval = ChipLinuxStorageIni::GetStringValue(key, buf, bufSize, outLen);
130
131     mLock.unlock();
132
133     return retval;
134 }
135
136 CHIP_ERROR ChipLinuxStorage::ReadValueBin(const char * key, uint8_t * buf, size_t bufSize, size_t & outLen)
137 {
138     CHIP_ERROR retval = CHIP_NO_ERROR;
139
140     mLock.lock();
141
142     retval = ChipLinuxStorageIni::GetBinaryBlobValue(key, buf, bufSize, outLen);
143
144     mLock.unlock();
145
146     return retval;
147 }
148
149 CHIP_ERROR ChipLinuxStorage::WriteValue(const char * key, bool val)
150 {
151     CHIP_ERROR retval = CHIP_NO_ERROR;
152
153     if (val)
154     {
155         retval = WriteValue(key, static_cast<uint32_t>(1));
156     }
157     else
158     {
159         retval = WriteValue(key, static_cast<uint32_t>(0));
160     }
161
162     return retval;
163 }
164
165 CHIP_ERROR ChipLinuxStorage::WriteValue(const char * key, uint32_t val)
166 {
167     char buf[32];
168
169     snprintf(buf, sizeof(buf), "%d", val);
170
171     return WriteValueStr(key, buf);
172 }
173
174 CHIP_ERROR ChipLinuxStorage::WriteValue(const char * key, uint64_t val)
175 {
176     char buf[64];
177
178     snprintf(buf, sizeof(buf), "%" PRIu64, val);
179
180     return WriteValueStr(key, buf);
181 }
182
183 CHIP_ERROR ChipLinuxStorage::WriteValueStr(const char * key, const char * val)
184 {
185     CHIP_ERROR retval = CHIP_NO_ERROR;
186
187     mLock.lock();
188
189     retval = ChipLinuxStorageIni::AddEntry(key, val);
190
191     mDirty = true;
192
193     mLock.unlock();
194
195     return retval;
196 }
197
198 CHIP_ERROR ChipLinuxStorage::WriteValueBin(const char * key, const uint8_t * data, size_t dataLen)
199 {
200     static const size_t kMaxBlobSize = 5 * 1024;
201
202     CHIP_ERROR retval = CHIP_NO_ERROR;
203     chip::Platform::ScopedMemoryBuffer<char> encodedData;
204     size_t encodedDataLen     = 0;
205     size_t expectedEncodedLen = ((dataLen + 3) * 4) / 3;
206
207     // We only support encoding blobs up to 5kb
208     if (dataLen > kMaxBlobSize)
209     {
210         retval = CHIP_ERROR_INVALID_ARGUMENT;
211     }
212
213     // Compute our expectedEncodedLen
214     // Allocate just enough space for the encoded data, and the NULL terminator
215     if (retval == CHIP_NO_ERROR)
216     {
217         if (!encodedData.Alloc(expectedEncodedLen + 1))
218         {
219             retval = CHIP_ERROR_NO_MEMORY;
220         }
221     }
222
223     // Encode it
224     if (retval == CHIP_NO_ERROR)
225     {
226         // We tested above that dataLen is no more than kMaxBlobSize.
227         static_assert(kMaxBlobSize < UINT16_MAX, "dataLen won't fit");
228         encodedDataLen              = Base64Encode(data, static_cast<uint16_t>(dataLen), encodedData.Get());
229         encodedData[encodedDataLen] = 0;
230     }
231
232     // Store it
233     if (retval == CHIP_NO_ERROR)
234     {
235         WriteValueStr(key, encodedData.Get());
236     }
237
238     return retval;
239 }
240
241 CHIP_ERROR ChipLinuxStorage::ClearValue(const char * key)
242 {
243     CHIP_ERROR retval = CHIP_NO_ERROR;
244
245     mLock.lock();
246
247     retval = ChipLinuxStorageIni::RemoveEntry(key);
248
249     if (retval == CHIP_NO_ERROR)
250     {
251         mDirty = true;
252     }
253     else
254     {
255         retval = CHIP_ERROR_KEY_NOT_FOUND;
256     }
257
258     mLock.unlock();
259
260     return retval;
261 }
262
263 CHIP_ERROR ChipLinuxStorage::ClearAll()
264 {
265     CHIP_ERROR retval = CHIP_NO_ERROR;
266
267     mLock.lock();
268
269     retval = ChipLinuxStorageIni::RemoveAll();
270
271     mLock.unlock();
272
273     if (retval == CHIP_NO_ERROR)
274     {
275         mDirty = true;
276         retval = Commit();
277     }
278     else
279     {
280         retval = CHIP_ERROR_WRITE_FAILED;
281     }
282
283     return retval;
284 }
285
286 bool ChipLinuxStorage::HasValue(const char * key)
287 {
288     bool retval;
289
290     mLock.lock();
291
292     retval = ChipLinuxStorageIni::HasValue(key);
293
294     mLock.unlock();
295
296     return retval;
297 }
298
299 CHIP_ERROR ChipLinuxStorage::Commit()
300 {
301     CHIP_ERROR retval = CHIP_NO_ERROR;
302
303     if (mDirty && !mConfigPath.empty())
304     {
305         mLock.lock();
306
307         retval = ChipLinuxStorageIni::CommitConfig(mConfigPath);
308
309         mLock.unlock();
310     }
311     else
312     {
313         retval = CHIP_ERROR_WRITE_FAILED;
314     }
315
316     return retval;
317 }
318
319 } // namespace Internal
320 } // namespace DeviceLayer
321 } // namespace chip