sync with master
[platform/framework/native/appfw.git] / src / io / FIo_FileUtil.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_FileUtil.cpp
20  * @brief       This is the implementation file for _FileUtil 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
36 #include <FIoFile.h>
37 #include <FIoDirectory.h>
38 #include <FBaseResult.h>
39 #include <FBaseSysLog.h>
40
41 #include <FBase_StringConverter.h>
42 #include <FBase_NativeError.h>
43 #include <FApp_AppInfo.h>
44 #include <FIo_FileAttributesImpl.h>
45 #include <FIo_SecureIoUtil.h>
46 #include <FIo_FileImpl.h>
47 #include <FIo_FileUtil.h>
48
49 using namespace std;
50 using namespace Tizen::Base;
51 using namespace Tizen::App;
52
53 namespace Tizen { namespace Io
54 {
55
56 static const int _BASE_YEAR = 1900;
57 static const int _MAX_COPY_BYTES = 4096;
58 static const int _MAX_OPENMODE_LENGTH = 3;
59
60 //Holds app path prefixes
61 static const char* filePathAppPrefix[] =
62 {
63         "/Home",
64         "/Res",
65         "/Share",
66         "/Share2",
67         "/HomeExt",
68         "/ShareExt",
69         "/Share2Ext",
70         "/Clipboard",
71         "/NPKI",
72         "/Storagecard/NPKI",
73         "/system/Document",
74         "/system/Data/FWeb",
75         "/Storagecard/DownloadedAppPackages",
76         "/system/Media",
77         "/system/Ringtones",
78         "/system/Wallpapers",
79         "/EmailBox",
80         "/MmsBox"
81 };
82
83 //Holds Media path prefixes
84 static const char* filePathMediaPrefix[] =
85 {
86         "/Media",
87         "/Storagecard/Media"
88 };
89
90 //Holds system path prefixes
91 static const char* filePathSystemPrefix[] =
92 {
93         "/system/configuration",
94         "/SystemRw"
95 };
96
97 result
98 _FileUtil::Remove(const String& filePath)
99 {
100         result r = E_SUCCESS;
101         unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
102         SysTryReturn(NID_IO, (pFilePath != null), GetLastResult(), GetLastResult(), ("[%s] Invalid file path."),
103                                 GetErrorMessage(GetLastResult()));
104
105         if (_FileUtil::IsFileExist(pFilePath.get()) == false)
106         {
107                 SysLog(NID_IO, "[E_FILE_NOT_FOUND] File(%s) does not exist.", pFilePath.get());
108                 return E_FILE_NOT_FOUND;
109         }
110
111         char resolvedPath[PATH_MAX] = {0,};
112         if (realpath(pFilePath.get(), resolvedPath) == null)
113         {
114                 switch (errno)
115                 {
116                 case EACCES:
117                         r = E_ILLEGAL_ACCESS;
118                         break;
119                 case EINVAL:
120                         // fall through
121                 case ELOOP:
122                         // fall through
123                 case ENAMETOOLONG:
124                         // fall through
125                 case ENOTDIR:
126                         r = E_INVALID_ARG;
127                         break;
128                 case EIO:
129                         r = E_IO;
130                         break;
131                 case ENOENT:
132                         r = E_FILE_NOT_FOUND;
133                         break;
134                 default:
135                         r = E_SYSTEM;
136                         break;
137                 }
138
139                 SysLog(NID_IO, "[%s] Failed to produce canonical absolute path (%ls). errno: %d (%s)",
140                                 GetErrorMessage(r), filePath.GetPointer(), errno, strerror(errno));
141
142                 return r;
143         }
144
145         int ret = unlink(resolvedPath);
146         if (ret != 0)
147         {
148                 if (errno == EISDIR)
149                 {
150                         r = E_INVALID_ARG;
151                 }
152                 else
153                 {
154                         r = __ConvertNativeErrorToResult(errno);
155                         SysLog(NID_IO, "[%s] Failed to unlink(), errno: %d (%s)", GetErrorMessage(r), errno, strerror(errno));
156                 }
157         }
158
159         return r;
160 }
161
162 result
163 _FileUtil::Move(const String& oldFilePath, const String& newFilePath)
164 {
165         result r = E_SUCCESS;
166         struct stat statBuf;
167
168         unique_ptr<char[]> pOldPath(_StringConverter::CopyToCharArrayN(oldFilePath));
169         SysTryReturn(NID_IO, pOldPath != null, GetLastResult(), GetLastResult(),
170                            "[%s] Invalid old file path.", GetErrorMessage(GetLastResult()));
171
172         unique_ptr<char[]> pNewPath(_StringConverter::CopyToCharArrayN(newFilePath));
173         SysTryReturn(NID_IO, pNewPath != null, GetLastResult(), GetLastResult(),
174                            "[%s] Invalid new file path.", GetErrorMessage(GetLastResult()));
175
176         SysTryReturnResult(NID_IO, _FileUtil::IsFileExist(newFilePath) == false, E_FILE_ALREADY_EXIST,
177                            "New file already exists.");
178
179         SysTryReturnResult(NID_IO, _FileUtil::IsFileExist(oldFilePath) == true, E_FILE_NOT_FOUND,
180                            "Old filepath not found.");
181
182         if (stat(pOldPath.get(), &statBuf) < 0)
183         {
184                 r = __ConvertNativeErrorToResult(errno);
185                 SysLogException(NID_IO, r, "[%s] stat() failed, path: %s, errno: %d (%s)", GetErrorMessage(r), pOldPath.get(), errno, strerror(errno));
186                 return r;
187         }
188         SysTryReturnResult(NID_IO, S_ISDIR(statBuf.st_mode) == false, E_INVALID_ARG,
189                            "The old path is a directory.");
190
191         int ret = rename(pOldPath.get(), pNewPath.get());
192         if (ret != 0 && errno != EXDEV)
193         {
194                 r = __ConvertNativeErrorToResult(errno);
195                 SysLog(NID_IO, "[%s] rename() failed, errno: %d (%s)", GetErrorMessage(r), errno, strerror(errno));
196                 return r;
197         }
198         else if (errno == EXDEV)
199         {
200                 r = File::Copy(oldFilePath, newFilePath, true);
201                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to caller...", GetErrorMessage(r));
202
203                 r = File::Remove(oldFilePath);
204                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to caller...", GetErrorMessage(r));
205         }
206
207         return E_SUCCESS;
208 }
209
210 result
211 _FileUtil::Copy(const String& srcFilePath, const String& destFilePath, bool failIfExist)
212 {
213         int srcFd = -1;
214         int dstFd = -1;
215         ssize_t readBytes = -1;
216         ssize_t writtenBytes = -1;
217         ssize_t remainingBytes = -1;
218         char* pBuffer = null;
219         result r = E_SUCCESS;
220
221         unique_ptr<char[]> pSrcpath(_StringConverter::CopyToCharArrayN(srcFilePath));
222         SysTryReturn(NID_IO, pSrcpath != null, GetLastResult(), GetLastResult(),
223                            "[%s] Invalid source file path.", GetErrorMessage(GetLastResult()));
224
225         unique_ptr<char[]> pDstpath(_StringConverter::CopyToCharArrayN(destFilePath));
226         SysTryReturn(NID_IO, pDstpath != null, GetLastResult(), GetLastResult(),
227                            "[%s] Invalid destination file path.", GetErrorMessage(GetLastResult()));
228
229         SysTryReturnResult(NID_IO, _FileUtil::IsFileExist(srcFilePath) == true, E_FILE_NOT_FOUND,
230                            "Source file(%s) does not exist.", pSrcpath.get());
231
232         if ((_FileUtil::IsFileExist(destFilePath) == true) && (failIfExist == true))
233         {
234                 r = E_FILE_ALREADY_EXIST;
235                 SysLog(NID_IO, "[E_FILE_ALREADY_EXIST] Destination file already exists.");
236                 return r;
237         }
238
239         srcFd = open(pSrcpath.get(), O_RDONLY);
240         if (srcFd == -1)
241         {
242                 r = __ConvertNativeErrorToResult(errno);
243                 SysLogException(NID_IO, r, "[%s] Failed to open file (%s).", GetErrorMessage(r), pSrcpath.get());
244                 return r;
245         }
246         dstFd = open(pDstpath.get(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
247         if (dstFd == -1)
248         {
249                 r = __ConvertNativeErrorToResult(errno);
250                 SysLogException(NID_IO, r, "[%s] Failed to open file (%s), errno: %d (%s)",
251                                    GetErrorMessage(r), pDstpath.get(), errno, strerror(errno));
252                 goto CATCH;
253         }
254
255         pBuffer = new (std::nothrow) char[_MAX_COPY_BYTES];
256         SysTryCatch(NID_IO, pBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
257
258         do
259         {
260                 do
261                 {
262                         readBytes = read(srcFd, pBuffer, _MAX_COPY_BYTES);
263                 }
264                 while (readBytes < 0 && errno == EINTR);
265                 if (readBytes < 0)
266                 {
267                         r = __ConvertNativeErrorToResult(errno);
268                         SysLogException(NID_IO, r, "[%s] Failed to read from source file (%s), errno: %d (%s)",
269                                         GetErrorMessage(r), pSrcpath.get(), errno, strerror(errno));
270                         goto CATCH;
271                 }
272                 else if (readBytes == 0)
273                 {
274                         break;
275                 }
276                 remainingBytes = readBytes;
277 RETRY:
278                 do
279                 {
280                         writtenBytes = write(dstFd, pBuffer, remainingBytes);
281                 }
282                 while (writtenBytes < 0 && errno == EINTR);
283                 if (writtenBytes < 0)
284                 {
285                         r = __ConvertNativeErrorToResult(errno);
286                         SysLogException(NID_IO, r, "[%s] Failed to write to destination file (%s), errno: %d (%s)",
287                                         GetErrorMessage(r), pDstpath.get(), errno, strerror(errno));
288                         goto CATCH;
289                 }
290                 else if (writtenBytes < remainingBytes)
291                 {
292                         remainingBytes = remainingBytes - writtenBytes;
293                         pBuffer = const_cast< char* >(pBuffer) + writtenBytes;
294                         goto RETRY;
295                 }
296         }
297         while (readBytes);
298
299         // fall through
300 CATCH:
301         if (srcFd != -1)
302         {
303                 close(srcFd);
304         }
305         if (dstFd != -1)
306         {
307                 fsync(dstFd);
308                 close(dstFd);
309         }
310         delete pBuffer;
311
312         return r;
313 }
314
315 result
316 _FileUtil::GetAttributes(const String& filePath, FileAttributes& attribute)
317 {
318         DateTime dateTime;
319         DateTime modifiedTime;
320         long long fileSize = 0;
321         unsigned long attr = 0;
322         result r = E_SUCCESS;
323         struct tm* pTm = null;
324         String fileName = L"";
325         bool hidden = false;
326
327         unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
328         SysTryReturn(NID_IO, (pFilePath != null), GetLastResult(), GetLastResult(), "[%s] Invalid source file path.",
329                            GetErrorMessage(GetLastResult()));
330
331         struct stat statbuf;
332         if (int ret = stat(pFilePath.get(), &statbuf) == -1)
333         {
334                 r = __ConvertNativeErrorToResult(errno);
335                 SysLogException(NID_IO, r, "[%s] Failed to get file (%s) status.", GetErrorMessage(r), pFilePath.get());
336                 return r;
337         }
338
339         // size
340         fileSize = statbuf.st_size;
341
342         // attributes
343         attr = statbuf.st_mode;
344
345         //  time of last status change
346         pTm = localtime(&statbuf.st_ctime);
347         SysTryReturnResult(NID_IO, pTm != null, E_SYSTEM, "Failed to call localtime() (%s).", strerror(errno));
348         r = dateTime.SetValue(_BASE_YEAR + pTm->tm_year, 1 + pTm->tm_mon, pTm->tm_mday, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
349         SysTryReturn(NID_IO, (!IsFailed(r)), r, r, "[%s] Failed to set DateTime.", GetErrorMessage(r));
350
351         // time of last modification
352         pTm = localtime(&statbuf.st_mtime);
353         SysTryReturnResult(NID_IO, pTm != null, E_SYSTEM, "Failed to call localtime() (%s).", strerror(errno));
354         r = modifiedTime.SetValue(_BASE_YEAR + pTm->tm_year, 1 + pTm->tm_mon, pTm->tm_mday, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
355         SysTryReturn(NID_IO, (!IsFailed(r)), r, r, "[%s] Failed to set DateTime.", GetErrorMessage(r));
356
357         fileName = _FileUtil::GetFileName(filePath);
358         if (fileName.StartsWith(L".", 0)) // including . and ..
359         {
360                 hidden = true;
361         }
362
363         _FileAttributesImpl::GetInstance(attribute)->Set(dateTime, modifiedTime, fileSize, attr, hidden);
364
365         return E_SUCCESS;
366 }
367
368 String
369 _FileUtil::GetFileName(const String& filePath)
370 {
371         String fileName;
372         int pos = -1;
373
374         result r = filePath.LastIndexOf(L'/', filePath.GetLength() - 1, pos);
375         SysTryReturn(NID_IO, !IsFailed(r), fileName, E_INVALID_ARG, "[E_INVALID_ARG] The file path is invalid.");
376
377         r = filePath.SubString(pos + 1, fileName);
378         SysTryReturn(NID_IO, !IsFailed(r), fileName, E_INVALID_ARG, "[E_INVALID_ARG] The file path is invalid.");
379         SysTryReturn(NID_IO, fileName.GetLength() > 0 && fileName.GetLength() <= NAME_MAX, fileName, E_INVALID_ARG,
380                         "[E_INVALID_ARG] The length of file name is zero or exceeds system limitations.");
381
382         SetLastResult(E_SUCCESS);
383         return fileName;
384 }
385
386 String
387 _FileUtil::GetFileExtension(const String& filePath)
388 {
389         String extName;
390         int pos = -1;
391
392         result r = filePath.LastIndexOf(L'/', filePath.GetLength() - 1, pos);
393         SysTryReturn(NID_IO, !IsFailed(r), extName, E_INVALID_ARG, "[E_INVALID_ARG] The file path is invalid.");
394
395         String fileName;
396         r = filePath.SubString(pos + 1, fileName);
397         SysTryReturn(NID_IO, !IsFailed(r), extName, E_INVALID_ARG, "[E_INVALID_ARG] The file path is invalid.");
398         SysTryReturn(NID_IO, fileName.GetLength() > 0 && fileName.GetLength() <= NAME_MAX, extName, E_INVALID_ARG,
399                         "[E_INVALID_ARG] The length of file name is zero or exceeds system limitations.");
400
401         r = fileName.LastIndexOf(L'.', fileName.GetLength() - 1, pos);
402         SysTryReturn(NID_IO, !IsFailed(r), extName, E_INVALID_ARG, "[E_INVALID_ARG] The file path is invalid.");
403
404         r = fileName.SubString(pos + 1, extName);
405         SysTryReturn(NID_IO, !IsFailed(r), extName, E_INVALID_ARG, "[E_INVALID_ARG] The file path is invalid.");
406
407         SetLastResult(E_SUCCESS);
408         return extName;
409 }
410
411 bool
412 _FileUtil::IsFileExist(const String& filePath)
413 {
414         int ret = 0;
415         result r = E_SUCCESS;
416
417         unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
418         SysTryReturn(NID_IO, (pFilePath != null), false, GetLastResult(), ("[%s] Invalid file path."),
419                            GetErrorMessage(GetLastResult()));
420
421         ret = access(pFilePath.get(), F_OK);
422         if (ret != 0)
423         {
424                 switch (errno)
425                 {
426                 case ENAMETOOLONG:
427                         r = E_INVALID_ARG;
428                         break;
429                 case ENOENT:
430                         r = E_SUCCESS;
431                         break;
432                 default:
433                         r = __ConvertNativeErrorToResult(errno);
434                         break;
435                 }
436         }
437
438         SetLastResult(r);
439         return (ret == 0) ? true : false;
440 }
441
442 #if 0
443 bool
444 _FileUtil::IsEncrypted(const String& filePath)
445 {
446         result  r = E_SUCCESS;
447         // TODO: int    pathKind;
448         int     readItems = 0;
449         int     fileLength = 0;
450         bool    encrypted = false;
451         // TODO: bool   checkPrivilege = false;
452         byte    secureHeader[SECURE_FILE_HEADER_SIZE_V1 + SECURE_IO_LOF_SIZE];
453         byte    reservedValue[SECURE_IO_STATIC_BIN_LEN] = {0xCA, 0xFE, 0xBE, 0xBE, 0xDA, 0xEF, 0xEB, 0xEB};
454         char    magicNum1[SECURE_IO_MAGIC_NUMBER_SIZE] = {0xCA, 0xFE, 0xBE, 0xBE};
455         char    magicNum2[SECURE_IO_MAGIC_NUMBER_SIZE] = {0xDA, 0xEF, 0xEF, 0xEB};
456         FILE*   pFile = null;
457
458         unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
459         SysTryReturn(NID_IO, pFilePath != null, false, E_INVALID_ARG, "[E_INVALID_ARG] CopyToCharArrayN failed!");
460
461         fileLength = strlen(pFilePath.get());
462         SysTryReturn(NID_IO, fileLength > 0, false, E_INVALID_ARG, "[E_INVALID_ARG] CopyToCharArrayN failed!");
463
464         if (pFilePath[fileLength - 1] == ('/'))
465         {
466                 pFilePath[fileLength - 1] = ('\0'); // remove last '/' character if exists.
467         }
468
469 //      // TODO: check accessibility to path
470 //      r = CheckAccessibilityToPath(pFilePath, &pathKind, 0);
471 //      if(IsFailed(r))
472 //              goto CATCH;
473 //
474 //      if(pathKind == __PATH_KIND_AUTHORIZED_MMC)
475 //      {
476 //              __CheckPrivilege(PRV_INSTALLATION, checkPrivilege);
477 //              if(!checkPrivilege)
478 //              {
479 //                      r = E_ILLEGAL_ACCESS;
480 //                      goto CATCH;
481 //              }
482 //      }
483 //      else if(pathKind == __PATH_KIND_AUTHORIZED_LINK || pathKind == __PATH_KIND_AUTHORIZED_NPKI ||
484 //                      pathKind == __PATH_KIND_AUTHORIZED_PRELOADED_MEDIA)
485 //      {
486 //              __CheckPrivilege(PRV_PRIVILEGED_IO, checkPrivilege);
487 //              if(!checkPrivilege)
488 //              {
489 //                      r = E_ILLEGAL_ACCESS;
490 //                      goto CATCH;
491 //              }
492 //      }
493 //      else if (pathKind == __PATH_KIND_APP_DENY)
494 //      {
495 //              r = E_ILLEGAL_ACCESS;
496 //              goto CATCH;
497 //      }
498
499         pFile = fopen(pFilePath.get(), "r");
500         if (pFile == null)
501         {
502                 r = __ConvertNativeErrorToResult(errno);
503                 SysLog(NID_IO, "[%s] Failed to open file (%s) in openMode (%s), (errno: %d).", GetErrorMessage(r), pFilePath.get(), "r", errno);
504                 goto CATCH;
505         }
506
507         readItems = fread(secureHeader, 1, SECURE_FILE_HEADER_SIZE_V1 + SECURE_IO_LOF_SIZE, pFile);
508
509         if (readItems < (SECURE_FILE_HEADER_SIZE_V1 + SECURE_IO_LOF_SIZE))
510         {
511                 int eof = feof((FILE*)pFile);
512                 if (eof)
513                 {
514                         //No error;
515                         encrypted = false;
516                         goto CATCH;
517                 }
518
519                 r = __ConvertNativeErrorToResult(errno);
520                 SysLog(NID_IO, "[%s] Failed to open file (%s) in openMode (%s), (errno: %d).", GetErrorMessage(r), pFilePath.get(), "r", errno);
521                 goto CATCH;
522         }
523
524         if (memcmp(secureHeader, SECURE_FILE_HEADER_STRING, SECURE_FILE_HEADER_STRING_SIZE) == 0 && \
525                 memcmp(secureHeader + SECURE_FILE_HEADER_STRING_SIZE, reservedValue, SECURE_IO_STATIC_BIN_LEN) == 0)
526         {
527                 encrypted = true;
528         }
529         else if (memcmp(secureHeader, SECURE_REG_HEADER_STRING, SECURE_REG_HEADER_STRING_SIZE) == 0 && \
530                 memcmp(secureHeader + SECURE_REG_HEADER_STRING_SIZE, reservedValue, SECURE_IO_STATIC_BIN_LEN) == 0)
531         {
532                 encrypted = true;
533         }
534         else if ((memcmp(secureHeader, magicNum1, SECURE_IO_MAGIC_NUMBER_SIZE) == 0) &&
535                         (memcmp(secureHeader + SECURE_IO_STATIC_BIN_LEN, magicNum2, SECURE_IO_MAGIC_NUMBER_SIZE) == 0))
536
537         {
538                 encrypted = true;
539         }
540         else
541         {
542                 encrypted = false;
543         }
544
545         // fall thru
546 CATCH:
547
548         if (pFile)
549         {
550                 fclose(pFile);
551         }
552
553         SetLastResult(r);
554         return encrypted;
555 }
556 #endif
557
558 bool
559 _FileUtil::IsAppPath(const String& filePath)
560 {
561         result r = E_SUCCESS;
562
563         if (VerifyFilePath(filePath, FILEPATH_TYPE_APP))
564         {
565                 SetLastResult(E_SUCCESS);
566                 return true;
567         }
568         r = GetLastResult();
569
570         SetLastResult(r);
571         return false;
572 }
573
574 bool
575 _FileUtil::IsMediaPath(const String& filePath)
576 {
577         result r = E_SUCCESS;
578
579         if (VerifyFilePath(filePath, FILEPATH_TYPE_MEDIA))
580         {
581                 SetLastResult(E_SUCCESS);
582                 return true;
583         }
584         r = GetLastResult();
585
586         SetLastResult(r);
587         return false;
588 }
589
590 bool
591 _FileUtil::IsSystemPath(const String& filePath)
592 {
593         result r = E_SUCCESS;
594
595         if (VerifyFilePath(filePath, FILEPATH_TYPE_SYSTEM))
596         {
597                 SetLastResult(E_SUCCESS);
598                 return true;
599         }
600         r = GetLastResult();
601
602         SetLastResult(r);
603         return false;
604 }
605
606 bool
607 _FileUtil::VerifyFilePath(const String& filePath, _FilePathType pathType)
608 {
609         result r = E_SUCCESS;
610         String tmpStr("");
611         String absolutePath("");
612         int i = 0;
613         int index = 0;
614         int pathCount = 0;
615         char** ppPathList = null;
616         bool candidateFound = false;
617         wchar_t ch = L'\0';
618
619         //TODO Apply realpath after data caging.
620         //
621         //char resolved_path[1024];
622         //char* pFilePath = _StringConverter::CopyToCharArrayN(filePath);
623         //
624         //r = GetLastResult();
625         //
626         //SysTryCatch(NID_IO, pFilePath != null,
627         //        r, r, "[%s] Failed to get file path", GetErrorMessage(r));
628
629
630         //SysLog(NID_IO, "convert: %s", pFilePath);
631         //if (realpath(pFilePath, resolved_path) !=0)
632         //{
633         //      r = __ConvertNativeErrorToResult(errno);
634         //      SysLog(NID_IO, "convert Error!!! [%s] %s", resolved_path, GetErrorMessage(r));
635         //      delete[] pFilePath;
636         //      return false;
637         //      }
638         //
639         //SysLog(NID_IO, "convert result: %s", resolved_path);
640         //absolutePath.Append(resolved_path);
641         //delete[] pFilePath;
642
643         absolutePath.Append(filePath);
644         // This code does not handle paths without prefix '/' ex: "Home/myfile"
645         // since it depends on cwd.
646         switch (pathType)
647         {
648         case FILEPATH_TYPE_APP:
649                 pathCount = MAX_FILEPATH_APP;
650                 ppPathList = const_cast <char**>(filePathAppPrefix);
651                 break;
652
653         case FILEPATH_TYPE_MEDIA:
654                 pathCount = MAX_FILEPATH_MEDIA;
655                 ppPathList = const_cast <char**>(filePathMediaPrefix);
656                 break;
657
658         case FILEPATH_TYPE_SYSTEM:
659                 pathCount = MAX_FILEPATH_SYSTEM;
660                 ppPathList = const_cast <char**>(filePathSystemPrefix);
661                 break;
662
663         default:
664                 r = E_INVALID_ARG;
665                 goto CATCH;
666         }
667
668         absolutePath.GetCharAt(absolutePath.GetLength() - 1, ch);
669         if (ch != L'/') // if last char of absolutePath is not '/' then append it to make path parsing easier
670         {
671                 absolutePath.Append(L'/');
672         }
673
674         for (i = 0; i < pathCount; i++)
675         {
676                 tmpStr.Clear();
677                 tmpStr.Append(ppPathList[i]);
678
679                 if (absolutePath.IndexOf(tmpStr, 0, index) == E_SUCCESS)
680                 {
681                         if (index == 0)
682                         {
683                                 ch = L'\0';
684                                 if (absolutePath.GetCharAt(tmpStr.GetLength(), ch) == E_SUCCESS)
685                                 {
686                                         if (ch == L'/') // validate exact path. paths like /Home123/file.txt is not supported.
687                                         {
688                                                 candidateFound = true;
689                                                 break;
690                                         }
691                                 }
692                         }
693                 }
694         }
695
696         if (candidateFound == true)
697         {
698                 r = E_SUCCESS;
699         }
700         else
701         {
702                 r = E_INVALID_ARG;
703         }
704
705         // fall thru
706 CATCH:
707         SetLastResult(r);
708
709         if (r == E_SUCCESS)
710         {
711                 return true;
712         }
713
714         return false;
715 }
716
717 result
718 _FileUtil::ConvertToSecureFile(const String& plainFilePath, const String& secureFilePath, const ByteBuffer* pKey)
719 {
720         SysTryReturnResult(NID_IO, plainFilePath.GetLength() > 0 && plainFilePath.GetLength() <= PATH_MAX, E_INVALID_ARG,
721                            "Invalid argument was passed. Given file name length is not correct!");
722         SysTryReturnResult(NID_IO, plainFilePath.EndsWith(L"/") == false, E_INVALID_ARG,
723                            "Invalid argument was passed. Given file name is not correct! - ends with '/'");
724
725         SysTryReturnResult(NID_IO, secureFilePath.GetLength() > 0 && secureFilePath.GetLength() <= PATH_MAX, E_INVALID_ARG,
726                            "Invalid argument was passed. Given file name length is not correct!");
727         SysTryReturnResult(NID_IO, secureFilePath.EndsWith(L"/") == false, E_INVALID_ARG,
728                            "Invalid argument was passed. Given file name is not correct! - ends with '/'");
729
730         int     fileSize = 0;
731         int     readSize = 0;
732         int lastBlockSize = 0;
733         int bufferSize = 0;
734         int blockCount = 0;
735         int count = 0;
736         unique_ptr<byte[]> pBuffer(null);
737         result  r = E_SUCCESS;
738
739         if (File::IsFileExist(secureFilePath))
740         {
741                 r = GetLastResult();
742                 if (!IsFailed(r))
743                 {
744                         r = E_FILE_ALREADY_EXIST;
745                         SysLog(NID_IO, "[E_FILE_ALREADY_EXIST] The secure file already exist.");
746                 }
747                 else
748                 {
749                         SysLog(NID_IO, "[%s] Propagated.", GetErrorMessage(r));
750                 }
751                 return r;
752         }
753
754         unique_ptr<File> pFile(new (std::nothrow) File());
755         SysTryReturnResult(NID_IO, pFile != null, E_OUT_OF_MEMORY, "Unable to create Io::File");
756
757         r = pFile->Construct(plainFilePath, L"r", false);
758         if (IsFailed(r))
759         {
760                 if (r == E_MAX_EXCEEDED)
761                 {
762                         r = E_IO;
763                 }
764                 SysLog(NID_IO, "[%s] Propagated.", GetErrorMessage(r));
765                 return r;
766         }
767
768         r = pFile->Seek(FILESEEKPOSITION_END, 0);
769         SysTryReturn(NID_IO, r == E_SUCCESS , r, r, "[%s] Propagated", GetErrorMessage(r));
770
771         fileSize = pFile->Tell();
772
773         r = pFile->Seek(FILESEEKPOSITION_BEGIN, 0);
774         SysTryReturn(NID_IO, r == E_SUCCESS , r, r, "[%s] Propagated", GetErrorMessage(r));
775
776         unique_ptr<File> pSecureFile(new (std::nothrow) File());
777         SysTryReturnResult(NID_IO, pSecureFile != null, E_OUT_OF_MEMORY,
778                         "Unable to create Io::File");
779
780         r = pSecureFile->Construct(secureFilePath, "w", *pKey);
781         SysTryReturn(NID_IO, r == E_SUCCESS , r, r, "[%s] Propagated", GetErrorMessage(r));
782
783         if (fileSize == 0)
784         {
785                 return r;
786         }
787
788         lastBlockSize = fileSize % CIPHER_BLOCK_SIZE;
789         if (lastBlockSize == 0)
790         {
791                 blockCount = fileSize / CIPHER_BLOCK_SIZE;
792                 lastBlockSize = CIPHER_BLOCK_SIZE;
793         }
794         else
795         {
796                 blockCount = fileSize / CIPHER_BLOCK_SIZE + 1;
797         }
798
799         for(count = 0; count < blockCount; count++)
800         {
801                 if (pBuffer != null)
802                 {
803                         memset(pBuffer.get(), 0, CIPHER_BLOCK_SIZE);
804                 }
805
806                 if ((count + 1) == blockCount && pBuffer == null)
807                 {
808                         pBuffer.reset(new (std::nothrow) byte[lastBlockSize]);
809                         SysTryReturnResult(NID_IO, pBuffer != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
810                         memset(pBuffer.get(), 0, lastBlockSize);
811                         bufferSize = lastBlockSize;
812                 }
813
814                 else if ((count + 1) != blockCount && pBuffer == null)
815                 {
816                         pBuffer.reset(new (std::nothrow) byte[CIPHER_BLOCK_SIZE]);
817                         SysTryReturnResult(NID_IO, pBuffer != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
818                         memset(pBuffer.get(), 0, CIPHER_BLOCK_SIZE);
819                         bufferSize = CIPHER_BLOCK_SIZE;
820                 }
821
822                 readSize = pFile->Read(pBuffer.get(), bufferSize);
823                 r = GetLastResult();
824                 if (IsFailed(r))
825                 {
826                         if (r == E_END_OF_FILE)
827                         {
828                                 r = E_IO;
829                         }
830                         SysLog(NID_IO, "[%s] Propagated.", GetErrorMessage(r));
831                         return r;
832                 }
833
834                 r = pSecureFile->Write(pBuffer.get(), readSize);
835                 SysTryReturn(NID_IO, r == E_SUCCESS , r, r, "[%s] Propagated", GetErrorMessage(r));
836         }
837
838         return E_SUCCESS;
839 }
840
841 }} // Tizen::Io
842