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