Revert "fixed PLM issue. Assert occured when an application was closed using back...
[platform/framework/native/appfw.git] / src / io / FIo_NormalFile.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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 /**
18  * @file        FIo_NormalFile.cpp
19  * @brief       This is the implementation file for _NormalFile class.
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/mman.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <time.h>
30 #include <limits.h>
31 #include <errno.h>
32 #include <new>
33 #include <unique_ptr.h>
34
35 #include <FIoFile.h>
36 #include <FIoDirectory.h>
37 #include <FBaseResult.h>
38 #include <FBaseSysLog.h>
39
40 #include <FBase_StringConverter.h>
41 #include <FBase_NativeError.h>
42 #include <FIo_FileAttributesImpl.h>
43 #include <FIo_NormalFile.h>
44
45 using namespace std;
46 using namespace Tizen::Base;
47
48 namespace Tizen { namespace Io
49 {
50
51 static const int _MAX_LINE_LENGTH = 4096;
52
53 _NormalFile::_NormalFile(void)
54         : __pFile(NULL)
55 {
56 }
57
58 _NormalFile::~_NormalFile(void)
59 {
60         result r = E_SUCCESS;
61
62         if (__pFile)
63         {
64                 if (fclose(__pFile) != 0)
65                 {
66                         r = __ConvertNativeErrorToResult(errno);
67                         SysLog(NID_IO, "[%s] Failed to close the file.", GetErrorMessage(r));
68                 }
69                 __pFile = NULL;
70         }
71 }
72
73 result
74 _NormalFile::Construct(const String& filePath, const char* pOpenMode)
75 {
76         SysAssertf(__pFile == NULL, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
77
78         int fd = -1;
79         result r = E_SUCCESS;
80
81         unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
82         SysTryReturn(NID_IO, (pFilePath != null), GetLastResult(), GetLastResult(), ("[%s] Invalid file path."),
83                                 GetErrorMessage(GetLastResult()));
84
85         FILE* pFile = fopen(pFilePath.get(), pOpenMode);
86         if (pFile == null)
87         {
88                 r = __ConvertNativeErrorToResult(errno);
89                 SysSecureLogException(NID_IO, r, "[%s] Failed to open file (%s) in openMode (%s), errno: %d (%s).",
90                                 GetErrorMessage(r), pFilePath.get(), pOpenMode, errno, strerror(errno));
91                 return r;
92         }
93
94         fd = fileno(pFile);
95
96         __pFile = pFile;
97         __filePath = filePath;
98
99         return E_SUCCESS;
100 }
101
102 result
103 _NormalFile::ReadN(char** buffer, int& length)
104 {
105         SysAssertf(__pFile != NULL, "Not yet constructed. Construct() should be called before use.\n");
106         result r = E_SUCCESS;
107
108         int ret = fseek(__pFile, 0, SEEK_END);
109         SysTryReturnResult(NID_IO, ret >= 0, E_SYSTEM, "The system I/O error occurred.");
110
111         long fileSize = ftell(__pFile);
112         SysTryReturnResult(NID_IO, fileSize >= 0, E_SYSTEM, "The system I/O error occurred.");
113
114         SysSecureLog(NID_IO, "The length of registry file (%ls) is %ld.", __filePath.GetPointer(), fileSize);
115         if (fileSize == 0)
116         {
117                 return E_SUCCESS;
118         }
119
120         ret = fseek(__pFile, 0, SEEK_SET); // moves file offset to zero because of a+ open mode.
121         SysTryReturnResult(NID_IO, ret >= 0, E_SYSTEM, "The system I/O error occurred.");
122
123         unique_ptr<char[]> pBuffer(new (std::nothrow) char[fileSize + 1]);
124         SysTryReturnResult(NID_IO, pBuffer != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
125         memset(pBuffer.get(), 0x00, fileSize + 1);
126
127         int readBytes = fread((void*)pBuffer.get(), 1, (size_t)fileSize, __pFile);
128         SysTryCatch(NID_IO, readBytes > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to read registry file (%d, %s).",
129                         errno, strerror(errno));
130
131         length = readBytes + 1;
132         *buffer = pBuffer.release();
133
134         // fall through
135 CATCH:
136         if (IsFailed(r))
137         {
138                 *buffer = null;
139                 length = 0;
140         }
141
142         return r;
143 }
144
145 result
146 _NormalFile::Read(ByteBuffer& buffer)
147 {
148         SysAssertf(__pFile != NULL, "Not yet constructed. Construct() should be called before use.\n");
149
150         result r = E_SUCCESS;
151
152         int length = buffer.GetRemaining();
153         if (length == 0)
154         {
155                 return E_INVALID_ARG;
156         }
157
158         int curPos = buffer.GetPosition();
159         int bytesRead = fread((void*) (buffer.GetPointer() + curPos), 1, length, __pFile);
160         if (bytesRead < length)
161         {
162                 SysTryReturnResult(NID_IO, !(bytesRead == 0 && feof(__pFile)), E_END_OF_FILE, "end of file");
163
164                 if (ferror(__pFile))
165                 {
166                         r = __ConvertNativeErrorToResult(errno);
167                         SysTryReturnResult(NID_IO, !(r == E_INVALID_OPERATION), E_ILLEGAL_ACCESS, "File was not opened for reading!");
168                         SysLogException(NID_IO, r, "[%s] Failed to read data from file, (errno: %d)", GetErrorMessage(r), errno);
169                         return r;
170                 }
171         }
172
173         buffer.SetPosition(curPos + bytesRead);
174
175         return E_SUCCESS;
176 }
177
178 int
179 _NormalFile::Read(void* buffer, int length)
180 {
181         SysAssertf(__pFile != NULL, "Not yet constructed. Construct() should be called before use.\n");
182
183         result r = E_SUCCESS;
184
185         int readBytes = fread(buffer, 1, length, __pFile);
186         if (readBytes < length)
187         {
188                 //SysTryReturn(NID_IO, !(readBytes == 0 && feof(__pFile)), 0, E_END_OF_FILE, "[E_END_OF_FILE] end of file");
189                 if (readBytes == 0 && feof(__pFile))
190                 {
191                         SysLog(NID_IO, "[E_END_OF_FILE] end of file");
192                         SetLastResult(E_END_OF_FILE);
193                         return 0;
194                 }
195
196                 if (ferror(__pFile))
197                 {
198                         r = __ConvertNativeErrorToResult(errno);
199                         SysTryReturn(NID_IO, !(r == E_INVALID_OPERATION), 0, E_ILLEGAL_ACCESS,
200                                         "[E_ILLEGAL_ACCESS] File was not opened for reading!");
201                         SysLogException(NID_IO, r, "[%s] Failed to read data from file", GetErrorMessage(r));
202                         return 0;
203                 }
204         }
205
206         SetLastResult(E_SUCCESS);
207         return readBytes;
208 }
209
210 result
211 _NormalFile::Read(String& buffer)
212 {
213         SysAssertf(__pFile != NULL, "Not yet constructed. Construct() should be called before use.\n");
214
215         char line[_MAX_LINE_LENGTH] = {0, };
216         result r = E_SUCCESS;
217
218         buffer.Clear();
219         if (fgets(line, _MAX_LINE_LENGTH - 1, __pFile) == null)
220         {
221                 SysTryReturnResult(NID_IO, !feof(__pFile), E_END_OF_FILE, "end of file");
222
223                 if (ferror(__pFile))
224                 {
225                         r = __ConvertNativeErrorToResult(errno);
226                         SysTryReturnResult(NID_IO, !(r == E_INVALID_OPERATION), E_ILLEGAL_ACCESS, " File was not opened for reading!");
227                         SysLogException(NID_IO, r, "[%s] Failed to read data from file", GetErrorMessage(r));
228                 }
229         }
230         else
231         {
232                 buffer = String(line);
233         }
234
235         return r;
236 }
237
238 result
239 _NormalFile::Write(const ByteBuffer& buffer)
240 {
241         SysAssertf(__pFile != NULL, "Not yet constructed. Construct() should be called before use.\n");
242
243         result r = E_SUCCESS;
244
245         int length = buffer.GetLimit();
246         if (length == 0)
247         {
248                 return E_INVALID_ARG;
249         }
250
251         int bytesWritten = fwrite(buffer.GetPointer(), 1, length, __pFile);
252         if (bytesWritten < length)
253         {
254                 if (ferror(__pFile))
255                 {
256                         r = __ConvertNativeErrorToResult(errno);
257                         SysTryReturnResult(NID_IO, !(r == E_INVALID_OPERATION), E_ILLEGAL_ACCESS, "File was not opened for writing!");
258                         SysLogException(NID_IO, r, "[%s] Failed to write data to file, (errno: %d).", GetErrorMessage(r), errno);
259                 }
260         }
261
262         return r;
263 }
264
265 result
266 _NormalFile::Write(const void* buffer, int length)
267 {
268         SysAssertf(__pFile != NULL, "Not yet constructed. Construct() should be called before use.\n");
269         SysTryReturnResult(NID_IO, length > 0, E_INVALID_ARG, "length cannot be 0!");
270
271         result r = E_SUCCESS;
272
273         if ((size_t) length > fwrite(buffer, 1, length, __pFile))
274         {
275                 if (ferror(__pFile))
276                 {
277                         r = __ConvertNativeErrorToResult(errno);
278                         SysTryReturnResult(NID_IO, !(r == E_INVALID_OPERATION), E_ILLEGAL_ACCESS, "File was not opened for writing!");
279                         SysLogException(NID_IO, r, "[%s] Failed to write data to file, (errno: %d).", GetErrorMessage(r), errno);
280                 }
281         }
282
283         return r;
284 }
285
286 result
287 _NormalFile::Write(const String& buffer)
288 {
289         result r = E_SUCCESS;
290
291         SysAssertf(__pFile != NULL, "Not yet constructed. Construct() should be called before use.\n");
292         SysTryReturnResult(NID_IO, buffer.GetLength() > 0, E_INVALID_ARG, "Buffer length cannot be 0!");
293
294         unique_ptr<char[]> pData(_StringConverter::CopyToCharArrayN(buffer));
295         SysTryReturn(NID_IO, (pData != null), GetLastResult(), GetLastResult(), ("[%s] Invalid file path."),
296                                 GetErrorMessage(GetLastResult()));
297
298         if (fputs(pData.get(), __pFile) <= 0)
299         {
300                 if (ferror(__pFile))
301                 {
302                         r = __ConvertNativeErrorToResult(errno);
303                         SysTryReturnResult(NID_IO, !(r == E_INVALID_OPERATION), E_ILLEGAL_ACCESS, "File was not opened for writing!");
304                         SysLogException(NID_IO, r, "[%s] Failed to write data to file, (errno: %d).", GetErrorMessage(r), errno);
305                 }
306         }
307
308         return r;
309 }
310
311 result
312 _NormalFile::Flush(void)
313 {
314         result r = E_SUCCESS;
315
316         SysAssertf(__pFile != NULL, "Not yet constructed. Construct() should be called before use.\n");
317
318         // fflush() returns '0' even if file was opened in read only mode!
319         if (fflush(__pFile) != 0)
320         {
321                 r = __ConvertNativeErrorToResult(errno);
322                 SysLogException(NID_IO, r, "[%s] Failed to flush data to file. errno(%d)", GetErrorMessage(r), errno);
323         }
324
325         return r;
326 }
327
328 int
329 _NormalFile::Tell(void) const
330 {
331         SysAssertf(__pFile != NULL, "Not yet constructed. Construct() should be called before use.\n");
332         result r = E_SUCCESS;
333
334         int ret = ftell(__pFile);
335         if (ret == -1)
336         {
337                 r = __ConvertNativeErrorToResult(errno);
338                 SysLogException(NID_IO, r, "[%s] Failed to flush data to file", GetErrorMessage(r));
339         }
340
341         SetLastResult(r);
342         return ret;
343 }
344
345 result
346 _NormalFile::Seek(FileSeekPosition position, long offset)
347 {
348         SysAssertf(__pFile != NULL, "Not yet constructed. Construct() should be called before use.\n");
349
350         result r = E_SUCCESS;
351
352         int whence = FILESEEKPOSITION_CURRENT;
353         switch (position)
354         {
355         case FILESEEKPOSITION_BEGIN:
356                 whence = SEEK_SET;
357                 break;
358
359         case FILESEEKPOSITION_CURRENT:
360                 whence = SEEK_CUR;
361                 break;
362
363         case FILESEEKPOSITION_END:
364                 whence = SEEK_END;
365                 break;
366         default:
367                 SysTryReturnResult(NID_IO, false, E_INVALID_ARG, "Seek position is invalid.");
368         }
369
370         int ret = fseek(__pFile, offset, whence);
371         if (ret != 0)
372         {
373                 r = __ConvertNativeErrorToResult(errno);
374                 SysLogException(NID_IO, r, "[%s] Failed to seek in file", GetErrorMessage(r));
375         }
376
377         return r;
378 }
379
380 result
381 _NormalFile::Truncate(int length)
382 {
383         SysAssertf(__pFile != NULL, "Not yet constructed. Construct() should be called before use.\n");
384         result r = E_SUCCESS;
385
386         int ret = ftruncate(fileno(__pFile), (off_t)length);
387         if (ret != 0)
388         {
389                 r = __ConvertNativeErrorToResult(errno);
390                 SysLogException(NID_IO, r, "[%s] Failed to truncate file. errno(%d)", GetErrorMessage(r), errno);
391         }
392
393         return r;
394 }
395
396 String
397 _NormalFile::GetName(void)
398 {
399         SysAssertf(__pFile != NULL, "Not yet constructed. Construct() should be called before use.\n");
400
401         SetLastResult(E_SUCCESS); // for OSP 2.0 compatibility
402         return __filePath;
403 }
404
405 }} // Tizen::Io
406