Merge "Fix SerialPort" into tizen_2.1
[platform/framework/native/appfw.git] / src / io / FIo_SecureFile.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        FIo_SecureFile.cpp
20  * @brief       This is the implementation file for _SecureFile class.
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <sys/mman.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <time.h>
31 #include <limits.h>
32 #include <errno.h>
33 #include <new>
34 #include <unique_ptr.h>
35 #include <FBaseResult.h>
36 #include <FIoFile.h>
37 #include <FBase_StringConverter.h>
38 #include <FBase_NativeError.h>
39 #include <FBaseSysLog.h>
40 #include <FIo_FileImpl.h>
41 #include <FIo_NormalFile.h>
42 #include <FIo_SecureFile.h>
43 #include <FIo_SecureIoUtil.h>
44
45 using namespace std;
46 using namespace Tizen::Base;
47
48 namespace Tizen { namespace Io
49 {
50
51 _SecureFile::_SecureFile(void)
52         : __pNormalFile(null)
53         , __virtualFilePointer(0)
54         , __pKey(null)
55 {
56 }
57
58 _SecureFile::_SecureFile(bool read, bool write, bool truncate, bool append)
59         : __pNormalFile(null)
60         , __virtualFilePointer(0)
61         , __pKey(null)
62 {
63         _read = read;
64         _write = write;
65         _truncate = truncate;
66         _append = append;
67 }
68
69 _SecureFile::~_SecureFile(void)
70 {
71         delete __pNormalFile;
72         delete __pKey;
73 }
74
75 result
76 _SecureFile::Construct(const String& filePath, const char* pOpenMode, const ByteBuffer* pKeyBuffer)
77 {
78         SysAssertf(__pNormalFile == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
79
80         result r = E_SUCCESS;
81
82         SysTryReturnResult(NID_IO, !(pKeyBuffer && pKeyBuffer->GetRemaining() <= 0), E_INVALID_ARG,
83                                            "Invalid Key parameter");
84
85         unique_ptr< Tizen::Base::ByteBuffer > pKey(_SecureIoUtil::GetSecureKeyN(pKeyBuffer));
86         SysTryReturnResult(NID_IO, !(pKey == null || (pKey != null && pKey->GetRemaining() < ONE_BLOCK_SIZE)), E_INVALID_ARG, "Unable to generate key!");
87
88         unique_ptr< _NormalFile > pNormalFile(new (std::nothrow) _NormalFile());
89         SysTryReturnResult(NID_IO, pNormalFile != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
90
91         if (!_read)
92         {
93                 unique_ptr< char[] > pMode(new char[strlen(pOpenMode) + 2]);
94                 strcpy(pMode.get(), pOpenMode);
95                 strcat(pMode.get(), "+\0");
96                 r = pNormalFile->Construct(filePath, pMode.get());
97         }
98         else
99         {
100                 r = pNormalFile->Construct(filePath, pOpenMode);
101         }
102         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to open file (%ls) in openmode (%s).",
103                                  GetErrorMessage(r), filePath.GetPointer(), pOpenMode);
104
105         if (_append)
106         {
107                 r = _SecureIoUtil::GetDataLengh(pNormalFile.get(), &__virtualFilePointer);
108                 if (IsFailed(r))
109                 {
110                         if (r == E_END_OF_FILE)
111                         {
112                                 r = E_IO; //for security error
113                         }
114                         return r;
115                 }
116         }
117
118         if (!(_SecureIoUtil::IsEmpty(filePath)))
119         {
120                 Tizen::Io::_FlagState flag;
121
122                 r = _SecureIoUtil::CheckFlag(pNormalFile.get(), &flag);
123                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to check flags in file header.", GetErrorMessage(r));
124
125                 if (flag == FLAG_STATE_CVF_CTF)
126                 {
127                         r = _SecureIoUtil::DeleteBlockReplica(pNormalFile.get(), filePath);
128                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to delete block replica of file.", GetErrorMessage(r));
129
130                         r = _SecureIoUtil::SetFlag(pNormalFile.get(), FLAG_STATE_CVF);
131                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to set flags in file header.", GetErrorMessage(r));
132                 }
133                 else if (flag == FLAG_STATE_CTF)
134                 {
135                         r = _SecureIoUtil::RestoreCorruptBlock(pNormalFile.get(), filePath);
136                         SysTryReturnResult(NID_IO, !IsFailed(r), E_IO, "Failed to set flags in file header.");
137
138                         r = _SecureIoUtil::DeleteBlockReplica(pNormalFile.get(), filePath);
139                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to delete block replica of file.", GetErrorMessage(r));
140
141                         r = _SecureIoUtil::SetFlag(pNormalFile.get(), FLAG_STATE_CVF);
142                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to set flags in file header.", GetErrorMessage(r));
143                 }
144                 else if (flag == FLAG_STATE_CVF)
145                 {
146                         //Do Nothing
147                 }
148                 else
149                 {
150                         int readItems = 0;
151                         int dataLen = 0;
152                         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_10_BYTES);
153                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek file (%ls) in openMode (%s).",
154                                                  GetErrorMessage(r), filePath.GetPointer(), pOpenMode);
155
156                         readItems = pNormalFile->Read(&dataLen, SECURE_IO_LOF_SIZE);  // read LoF
157                         if (readItems < SECURE_IO_LOF_SIZE)
158                         {
159                                 if (_SecureIoUtil::IsEndOfFile(pNormalFile.get()) && readItems == 0)
160                                 {
161                                         r = E_END_OF_FILE;
162                                 }
163                                 else
164                                 {
165                                         r = __ConvertNativeErrorToResult(errno);
166                                 }
167
168                                 SysLog(NID_IO, "[%s] Failed to fread file (%ls) in openMode (%s), (errno: %d).",
169                                            GetErrorMessage(r), filePath.GetPointer(), pOpenMode, errno);
170                                 return r;
171                         }
172
173                         if (dataLen > SECURE_FILE_HEADER_SIZE_V1)
174                         {
175                                 r = pNormalFile->Truncate(dataLen);
176                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to truncate file (%ls) in openMode (%ls).", GetErrorMessage(r));
177
178                                 r = pNormalFile->Flush();
179                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to flush data to file", GetErrorMessage(r));
180
181                                 r = _SecureIoUtil::SetFlag(pNormalFile.get(), FLAG_STATE_CVF);
182                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to set flags in file header.", GetErrorMessage(r));
183                         }
184                         else
185                         {
186                                 r = pNormalFile->Truncate(0);
187                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to truncate file (%ls) in openMode (%s).",
188                                                          GetErrorMessage(r), filePath.GetPointer(), pOpenMode);
189
190                                 r = pNormalFile->Flush();
191                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to flush data to file", GetErrorMessage(r));
192
193                         }
194                 }
195         }
196
197         __filePath = filePath;
198         __pNormalFile = pNormalFile.release();
199         __pKey = pKey.release();
200
201         return E_SUCCESS;
202 }
203
204 result
205 _SecureFile::Read(ByteBuffer& buffer)
206 {
207         result r = E_SUCCESS;
208         int dataPos = 0;
209         int length = buffer.GetRemaining();
210         int curPos = buffer.GetPosition();
211         int readBytes = 0;
212         const byte* pTempBuffer = null;
213
214         ClearLastResult();
215         SysAssertf(__pNormalFile != null, "Not yet constructed. Construct() should be called before use.\n");
216
217         SysTryReturnResult(NID_IO, length > 0, E_INVALID_ARG, "Invalid argument passed.");
218         SysAssert(curPos >= 0);
219
220         r = _SecureIoUtil::SelectCipherBlock(__pNormalFile, __virtualFilePointer, &dataPos);
221         if (IsFailed(r))
222         {
223                 if (r == E_STORAGE_FULL)
224                 {
225                         r = E_IO;
226                 }
227                 return r;
228         }
229         pTempBuffer = buffer.GetPointer();
230         r = _SecureIoUtil::ReadDataFromCipherBlock(__pNormalFile, dataPos, length, (const_cast< byte* >(pTempBuffer) + curPos), DATA_FORMAT_BYTE, &readBytes, *__pKey);
231         if (IsFailed(r))
232         {
233                 SysTryReturnResult(NID_IO, !(r == E_INVALID_OPERATION), E_ILLEGAL_ACCESS, "File is not opened for reading!");
234                 SysLog(NID_IO, "[%s] Failed to read data from file", GetErrorMessage(r));
235                 return r;
236         }
237
238         SysTryReturnResult(NID_IO, readBytes >= 0, E_IO, "Read bytes value is invalid");
239
240         r = buffer.SetPosition(curPos + readBytes);
241         SysAssert(!IsFailed(r));
242         __virtualFilePointer = __virtualFilePointer + readBytes;
243
244         return r;
245 }
246
247 int
248 _SecureFile::Read(void* pBuffer, int length)
249 {
250         SysAssertf(__pNormalFile != null, "Not yet constructed. Construct() should be called before use.\n");
251         SysTryReturn(NID_IO, !(pBuffer == null || length <= 0), 0, E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument passed.");
252
253         int readBytes = 0;
254         int dataPos = 0;
255         result r = E_SUCCESS;
256
257         r = _SecureIoUtil::SelectCipherBlock(__pNormalFile, __virtualFilePointer, &dataPos);
258         if (IsFailed(r))
259         {
260                 if (r == E_STORAGE_FULL)
261                 {
262                         r = E_IO; //for security error
263                 }
264                 SysPropagate(NID_IO, r);
265                 return 0;
266         }
267
268         r = _SecureIoUtil::ReadDataFromCipherBlock(__pNormalFile, dataPos, length, reinterpret_cast< byte* >(pBuffer), DATA_FORMAT_BYTE, &readBytes, *__pKey);
269         if (IsFailed(r))
270         {
271                 SysTryReturn(NID_IO, !(r == E_INVALID_OPERATION), 0, E_ILLEGAL_ACCESS, "[E_ILLEGAL_ACCESS]File is not opended for reading!");
272                 SysLog(NID_IO, "[%s] Failed to read data from file", GetErrorMessage(r));
273                 SysPropagate(NID_IO, r);
274                 return 0;
275         }
276
277         SysTryReturn(NID_IO, readBytes >= 0, 0, E_IO, "[E_IO] Failed to read specified bytes from file.");
278
279         __virtualFilePointer = __virtualFilePointer + readBytes;
280
281         SetLastResult(r);
282         return readBytes;
283 }
284
285 result
286 _SecureFile::Read(String& buffer)
287 {
288         result r = E_SUCCESS;
289         int dataPos = 0;
290         int readItems = 0;
291         char bstrBuf[FIO_LEN_4K] = {0, };
292
293         ClearLastResult();
294         SysAssertf(__pNormalFile != null, "Not yet constructed. Construct() should be called before use.\n");
295
296         buffer.Clear();
297
298         r = _SecureIoUtil::SelectCipherBlock(__pNormalFile, __virtualFilePointer, &dataPos);
299         if (IsFailed(r))
300         {
301                 if (r == E_STORAGE_FULL)
302                 {
303                         r = E_IO; //for security error
304                 }
305                 return r;
306         }
307
308         r = _SecureIoUtil::ReadDataFromCipherBlock(__pNormalFile, dataPos, sizeof(bstrBuf), reinterpret_cast< byte* >(bstrBuf), DATA_FORMAT_STRING, &readItems, *__pKey);
309         if (IsFailed(r))
310         {
311                 SysTryReturnResult(NID_IO, !(r == E_INVALID_OPERATION), E_ILLEGAL_ACCESS, "File is not opened for reading!");
312                 SysLog(NID_IO, "[%s] Failed to read data from file", GetErrorMessage(r));
313                 return r;
314         }
315         SysAssert(readItems > 0);
316         __virtualFilePointer = __virtualFilePointer + readItems;
317
318         {
319                 String tmp(bstrBuf);
320                 buffer = tmp;
321         }
322
323         return r;
324 }
325
326 result
327 _SecureFile::Write(const ByteBuffer& buffer)
328 {
329         return Write(buffer.GetPointer(), buffer.GetLimit());
330 }
331
332 result
333 _SecureFile::Write(const void* pBuffer, int length)
334 {
335         result r = E_SUCCESS;
336         int dataPos = 0;
337         bool eofSet = false;
338         bool replica = false;
339
340         ClearLastResult();
341         SysAssertf(__pNormalFile != null, "Not yet constructed. Construct() should be called before use.\n");
342
343         SysTryReturnResult(NID_IO, !(!pBuffer || length <= 0), E_INVALID_ARG, "Invalid argument passed.");
344
345         r = _SecureIoUtil::InsertSecureFileHeader(__pNormalFile);
346         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write file headers.", GetErrorMessage(r));
347
348         r = _SecureIoUtil::SaveLengthOfFile(__pNormalFile);
349         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to set length in file header.", GetErrorMessage(r));
350
351         r = _SecureIoUtil::SelectCipherBlock(__pNormalFile, __virtualFilePointer, &dataPos);
352         if (IsFailed(r))
353         {
354                 if (r == E_END_OF_FILE)
355                 {
356                         r = E_IO; //for security error
357                 }
358                 goto CATCH;
359         }
360
361         if (dataPos == 0)
362         {
363                 eofSet = _SecureIoUtil::IsEndOfFile(__pNormalFile);
364
365                 if (eofSet)
366                 {
367                         r = _SecureIoUtil::SetFlag(__pNormalFile, FLAG_STATE_NONE);
368                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to set flags in file header.", GetErrorMessage(r));
369
370                         replica = false;
371                 }
372                 else
373                 {
374                         r = _SecureIoUtil::MakeCipherBlockReplica(__pNormalFile, __filePath, dataPos, length);
375                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to make cipher block replica of file.", GetErrorMessage(r));
376
377                         r = _SecureIoUtil::SetFlag(__pNormalFile, FLAG_STATE_CTF);
378                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to set flags in file header.", GetErrorMessage(r));
379
380                         replica = true;
381                 }
382
383         }
384         else
385         {
386                 r = _SecureIoUtil::MakeCipherBlockReplica(__pNormalFile, __filePath, dataPos, length);
387                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to make cipher block replica of file.", GetErrorMessage(r));
388
389                 r = _SecureIoUtil::SetFlag(__pNormalFile, FLAG_STATE_CTF);
390                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to set flags in file header.", GetErrorMessage(r));
391
392                 replica = true;
393         }
394
395         r = _SecureIoUtil::WriteDataInCipherBlock(__pNormalFile, dataPos, eofSet, length, const_cast< byte* >(static_cast< const byte* >(pBuffer)), *__pKey);
396         if (IsFailed(r))
397         {
398                 if (r == E_END_OF_FILE)
399                 {
400                         r = E_IO; //for security error
401                 }
402                 goto CATCH;
403         }
404
405         if (replica)
406         {
407                 r = _SecureIoUtil::SetFlag(__pNormalFile, FLAG_STATE_CVF_CTF);
408                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to set flags in file header.", GetErrorMessage(r));
409                 r = _SecureIoUtil::DeleteBlockReplica(__pNormalFile, __filePath);
410                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failedt to delete block replica of file.", GetErrorMessage(r));
411         }
412
413         r = _SecureIoUtil::SetFlag(__pNormalFile, FLAG_STATE_CVF);
414         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to set flags in file header.", GetErrorMessage(r));
415
416         __virtualFilePointer = __virtualFilePointer + length;
417
418 CATCH:
419
420         SysTryReturnResult(NID_IO, !(r == E_INVALID_OPERATION), E_ILLEGAL_ACCESS, "File is not opened for writing!");
421
422         return r;
423 }
424
425 result
426 _SecureFile::Write(const String& buffer)
427 {
428         unique_ptr< char[] > pData(_StringConverter::CopyToCharArrayN(buffer));
429
430         SysTryReturn(NID_IO, pData != null, GetLastResult(), GetLastResult(), "[%s] Propagated.", GetErrorMessage(GetLastResult()));
431
432         return Write(pData.get(), buffer.GetLength());
433 }
434
435 result
436 _SecureFile::Flush(void)
437 {
438         result r = E_SUCCESS;
439         ClearLastResult();
440
441         SysAssertf(__pNormalFile != null, "Not yet constructed. Construct() should be called before use.\n");
442         r = __pNormalFile->Flush();
443         return r;
444 }
445
446 int
447 _SecureFile::Tell(void) const
448 {
449         SysAssertf(__pNormalFile != null, "Not yet constructed. Construct() should be called before use.\n");
450
451         long dataLen = 0;
452         result r = E_SUCCESS;
453         int ret = 0;
454
455         r = _SecureIoUtil::GetDataLengh(__pNormalFile, &dataLen);
456         if (IsFailed(r))
457         {
458                 if (r == E_ILLEGAL_ACCESS || r == E_STORAGE_FULL || r == E_END_OF_FILE)
459                 {
460                         r = E_IO; //for security error
461                 }
462                 goto CATCH;
463         }
464
465         SysTryCatch(NID_IO, (dataLen >= __virtualFilePointer), r = E_IO, E_IO, "[E_IO] Failed to tell in file.");
466
467         ret = __virtualFilePointer;
468
469         // fall through
470 CATCH:
471         return ret;
472 }
473
474 result
475 _SecureFile::Seek(FileSeekPosition position, long offset)
476 {
477         result r = E_SUCCESS;
478         long fileEndPos = 0;
479         long tempFilePointer = 0;
480
481         ClearLastResult();
482         SysAssertf(__pNormalFile != null, "Not yet constructed. Construct() should be called before use.\n");
483
484         r = _SecureIoUtil::GetDataLengh(__pNormalFile, &fileEndPos);
485         if (IsFailed(r))
486         {
487                 if (r == E_ILLEGAL_ACCESS || r == E_END_OF_FILE)
488                 {
489                         r = E_IO; //for security error
490                 }
491                 return r;
492         }
493
494         switch (position)
495         {
496         case FILESEEKPOSITION_BEGIN:
497                 tempFilePointer = 0;
498                 break;
499
500         case FILESEEKPOSITION_CURRENT:
501                 tempFilePointer = __virtualFilePointer;
502                 break;
503
504         case FILESEEKPOSITION_END:
505                 tempFilePointer = fileEndPos;
506                 break;
507
508         default:
509                 SysAssert(false);
510                 break;
511         }
512
513         if (tempFilePointer + offset > fileEndPos)
514         {
515                 //In  Linux , Seek () will set  file position beyond end of file also even if file is opened in READONLY.
516                 if (_write == false)
517                 {
518                         return E_ILLEGAL_ACCESS;
519                 }
520                 else
521                 {
522                         unique_ptr< byte[] > pTempBuffer(new (std::nothrow) byte[tempFilePointer + offset - fileEndPos]);
523                         SysTryReturnResult(NID_IO, pTempBuffer != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
524
525                         memset(pTempBuffer.get(), 0, tempFilePointer + offset - fileEndPos);
526                         __virtualFilePointer = fileEndPos;
527
528                         r = this->Write(pTempBuffer.get(), tempFilePointer + offset - fileEndPos);
529
530                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write data in to the file.", GetErrorMessage(r));
531
532                 }
533         }
534         else if (tempFilePointer + offset == fileEndPos)
535         {
536                 __virtualFilePointer = fileEndPos;
537         }
538         else if (tempFilePointer + offset < 0)
539         {
540                 return E_INVALID_ARG;
541         }
542         else if (tempFilePointer + offset == 0)
543         {
544                 __virtualFilePointer = 0;
545         }
546         else
547         {
548                 __virtualFilePointer = tempFilePointer + offset;
549         }
550
551         return r;
552 }
553
554 result
555 _SecureFile::Truncate(int length)
556 {
557         result r = E_SUCCESS;
558         long fileEndPos = 0;
559         int readItems = 0;
560         int dataPos = 0;
561
562         ClearLastResult();
563         SysAssertf(__pNormalFile != null, "Not yet constructed. Construct() should be called before use.\n");
564         SysTryReturnResult(NID_IO, length >= 0, E_INVALID_ARG, "Invalid argument is passed (length < 0)");
565
566         if (length == 0)
567         {
568                 r = __pNormalFile->Truncate(length);
569                 if (r != E_SUCCESS)
570                 {
571                         SysLog(NID_IO, "[%s] Failed to truncate data to file", GetErrorMessage(r));
572                 }
573                 __virtualFilePointer = 0;
574
575                 goto CATCH;
576         }
577
578         r = _SecureIoUtil::GetDataLengh(__pNormalFile, &fileEndPos);
579         if (IsFailed(r))
580         {
581                 if (r == E_END_OF_FILE)
582                 {
583                         r = E_IO; //for security error
584                 }
585                 goto CATCH;
586         }
587
588         if (length >= fileEndPos)
589         {
590                 if (length == fileEndPos)
591                 {
592                         this->Seek(FILESEEKPOSITION_END, 0);
593                         goto CATCH;
594                 }
595                 else
596                 {
597                         unique_ptr< byte[] > pTempBuffer(new (std::nothrow) byte[length - fileEndPos]);
598                         SysTryCatch(NID_IO, pTempBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
599
600
601                         memset(pTempBuffer.get(), 0, length - fileEndPos);
602                         r = this->Seek(FILESEEKPOSITION_END, 0);
603                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to seek in file.", GetErrorMessage(r));
604
605                         r = this->Write(pTempBuffer.get(), length - fileEndPos);
606                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to write data in file.", GetErrorMessage(r));
607                 }
608         }
609         else
610         {
611                 unique_ptr< byte[] > pTempBuffer(null);
612
613                 __virtualFilePointer = length;
614                 r = _SecureIoUtil::SelectCipherBlock(__pNormalFile, __virtualFilePointer, &dataPos);
615                 if (IsFailed(r))
616                 {
617                         if (r == E_END_OF_FILE)
618                         {
619                                 r = E_IO; //for security error
620                         }
621                         goto CATCH;
622                 }
623
624                 if (dataPos != 0)
625                 {
626                         pTempBuffer = unique_ptr< byte[] >(new (std::nothrow) byte[dataPos]);
627                         SysTryCatch(NID_IO, pTempBuffer, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
628
629                         r = _SecureIoUtil::ReadDataFromCipherBlock(__pNormalFile, 0, dataPos, pTempBuffer.get(), DATA_FORMAT_BYTE, &readItems, *__pKey);
630                         if (IsFailed(r))
631                         {
632                                 if (r == E_END_OF_FILE)
633                                 {
634                                         r = E_IO; //for security error
635                                 }
636                                 goto CATCH;
637                         }
638
639                         SysAssert(readItems == dataPos);
640                         r = _SecureIoUtil::SelectCipherBlock(__pNormalFile, __virtualFilePointer, &dataPos);
641                         if (IsFailed(r))
642                         {
643                                 if (r == E_END_OF_FILE)
644                                 {
645                                         r = E_IO; //for security error
646                                 }
647                                 goto CATCH;
648                         }
649                 }
650
651                 length = __pNormalFile->Tell();
652                 SysTryCatch(NID_IO, length != -1, r = __ConvertNativeErrorToResult(errno), r, "[%s] Failed to tell in file", GetErrorMessage(r));
653
654                 r = __pNormalFile->Truncate(length);
655                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to truncate data to file", GetErrorMessage(r));
656
657
658                 r = __pNormalFile->Flush();
659                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to flush data to file", GetErrorMessage(r));
660
661
662                 r = _SecureIoUtil::GetDataLengh(__pNormalFile, &__virtualFilePointer);
663                 if (IsFailed(r))
664                 {
665                         if (r == E_END_OF_FILE)
666                         {
667                                 r = E_IO; //for security error
668                         }
669                         goto CATCH;
670                 }
671
672                 if (pTempBuffer != null)
673                 {
674                         r = this->Write(static_cast< void* >(pTempBuffer.get()), dataPos);
675                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to write data in file.", GetErrorMessage(r));
676                 }
677         }
678         r = _SecureIoUtil::GetDataLengh(__pNormalFile, &__virtualFilePointer);
679         if (IsFailed(r))
680         {
681                 if (r == E_END_OF_FILE)
682                 {
683                         r = E_IO; //for security error
684                 }
685                 goto CATCH;
686         }
687
688 CATCH:
689
690         __pNormalFile->Flush();
691         return r;
692 }
693
694 String
695 _SecureFile::GetName(void)
696 {
697         SysAssertf(__pNormalFile != null, "Not yet constructed. Construct() should be called before use.\n");
698
699         SetLastResult(E_SUCCESS); // for OSP 2.0 compatibility
700         return __filePath;
701 }
702
703 }} // Tizen::Io