Merge "Changing the return value description of IsBitSet(), IsProbablePrimeNumber...
[platform/framework/native/appfw.git] / src / io / FIo_FileUtil.cpp
index 7fc3c56..0edf5d5 100644 (file)
@@ -1,5 +1,4 @@
 //
-// Open Service Platform
 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
 //
 // Licensed under the Apache License, Version 2.0 (the License);
@@ -55,7 +54,6 @@ namespace Tizen { namespace Io
 
 static const int _BASE_YEAR = 1900;
 static const int _MAX_COPY_BYTES = 4096;
-static const int _MAX_OPENMODE_LENGTH = 3;
 
 //Holds app path prefixes
 static const char* filePathAppPrefix[] =
@@ -104,7 +102,7 @@ _FileUtil::Remove(const String& filePath)
 
        if (_FileUtil::IsFileExist(pFilePath.get()) == false)
        {
-               SysLog(NID_IO, "[E_FILE_NOT_FOUND] File(%s) does not exist.", pFilePath.get());
+               SysSecureLogException(NID_IO, E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] File (%s) does not exist.", pFilePath.get());
                return E_FILE_NOT_FOUND;
        }
 
@@ -163,7 +161,7 @@ result
 _FileUtil::Move(const String& oldFilePath, const String& newFilePath)
 {
        result r = E_SUCCESS;
-       struct stat statBuf;
+       struct stat64 statBuf;
 
        unique_ptr<char[]> pOldPath(_StringConverter::CopyToCharArrayN(oldFilePath));
        SysTryReturn(NID_IO, pOldPath != null, GetLastResult(), GetLastResult(),
@@ -179,33 +177,31 @@ _FileUtil::Move(const String& oldFilePath, const String& newFilePath)
        SysTryReturnResult(NID_IO, _FileUtil::IsFileExist(oldFilePath) == true, E_FILE_NOT_FOUND,
                           "Old filepath not found.");
 
-       if (stat(pOldPath.get(), &statBuf) < 0)
+       if (stat64(pOldPath.get(), &statBuf) < 0)
        {
                r = __ConvertNativeErrorToResult(errno);
-               SysLogException(NID_IO, r, "[%s] stat() failed, path: %s, errno: %d (%s)", GetErrorMessage(r), pOldPath.get(), errno, strerror(errno));
+               SysLogException(NID_IO, r, "[%s] stat64() failed, path: %s, errno: %d (%s)",
+                               GetErrorMessage(r), pOldPath.get(), errno, strerror(errno));
                return r;
        }
        SysTryReturnResult(NID_IO, S_ISDIR(statBuf.st_mode) == false, E_INVALID_ARG,
                           "The old path is a directory.");
 
-       // TODO: Use rename() for move operation in same mount point
-       // and need API versioning.
-#if 0
        int ret = rename(pOldPath.get(), pNewPath.get());
-       if (ret != 0)
+       if (ret != 0 && errno != EXDEV)
        {
                r = __ConvertNativeErrorToResult(errno);
-               SysLog(NID_IO, "[%s] rename() failed, errno: %d, strerror: %s", errno, strerror(errno));
+               SysLog(NID_IO, "[%s] rename() failed, errno: %d (%s)", GetErrorMessage(r), errno, strerror(errno));
                return r;
        }
-#else
-       // To work across different mount points
-       r = File::Copy(oldFilePath, newFilePath, true);
-       SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
+       else if (errno == EXDEV)
+       {
+               r = File::Copy(oldFilePath, newFilePath, true);
+               SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to caller...", GetErrorMessage(r));
 
-       r = File::Remove(oldFilePath);
-       SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
-#endif
+               r = File::Remove(oldFilePath);
+               SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to caller...", GetErrorMessage(r));
+       }
 
        return E_SUCCESS;
 }
@@ -213,13 +209,14 @@ _FileUtil::Move(const String& oldFilePath, const String& newFilePath)
 result
 _FileUtil::Copy(const String& srcFilePath, const String& destFilePath, bool failIfExist)
 {
-       result r = E_SUCCESS;
        int srcFd = -1;
        int dstFd = -1;
-       int size = 0;
-       void* pSrcMap = MAP_FAILED;
-       void* pDstMap = MAP_FAILED;
-       unique_ptr<char[]> pBuffer(null);
+       ssize_t readBytes = -1;
+       ssize_t writtenBytes = -1;
+       ssize_t remainingBytes = -1;
+       char* pBuffer = null;
+       char* pCopyBuf = null;
+       result r = E_SUCCESS;
 
        unique_ptr<char[]> pSrcpath(_StringConverter::CopyToCharArrayN(srcFilePath));
        SysTryReturn(NID_IO, pSrcpath != null, GetLastResult(), GetLastResult(),
@@ -239,84 +236,79 @@ _FileUtil::Copy(const String& srcFilePath, const String& destFilePath, bool fail
                return r;
        }
 
-       // try linux way to optimally use mmap.
-       srcFd = open(pSrcpath.get(), O_RDONLY);
-       r = __ConvertNativeErrorToResult(errno);
-       SysTryReturn(NID_IO, (srcFd != -1), r, r, "[%s] Failed to open file (%s).", __ConvertNativeErrorToMessage(errno), pSrcpath.get());
-
-       dstFd = open(pDstpath.get(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
-       r = __ConvertNativeErrorToResult(errno);
-       SysTryCatch(NID_IO, (dstFd != -1), , r, "[%s] Failed to open file (%s), errno: %d (%s)",
-                          __ConvertNativeErrorToMessage(errno), pDstpath.get(), errno, strerror(errno));
-
-       // First try the mmap method
-       size = lseek(srcFd, 0, SEEK_END);
-       r = __ConvertNativeErrorToResult(errno);
-       SysTryCatch(NID_IO, (size != -1), , r, "[%s] Failed to reach the end of file (%s).", __ConvertNativeErrorToMessage(
-                                  errno), pDstpath.get());
-
-       pSrcMap = mmap(0, size, PROT_READ, MAP_SHARED, srcFd, 0);
-       pDstMap = mmap(0, size, PROT_WRITE, MAP_SHARED, dstFd, 0);
-
-       if ((pSrcMap != MAP_FAILED) && (pDstMap != MAP_FAILED))
+       srcFd = open64(pSrcpath.get(), O_RDONLY);
+       if (srcFd == -1)
        {
-               // do the copy and commit
-               memcpy(pDstMap, pSrcMap, size);
-               msync(pDstMap, size, MS_SYNC);
+               r = __ConvertNativeErrorToResult(errno);
+               SysLogException(NID_IO, r, "[%s] Failed to open file (%s).", GetErrorMessage(r), pSrcpath.get());
+               return r;
        }
-       else    // mmap method filed due to memory limitations.. try regular copy
+       dstFd = open64(pDstpath.get(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
+       if (dstFd == -1)
        {
-               off_t start = lseek(srcFd, 0, SEEK_SET);
                r = __ConvertNativeErrorToResult(errno);
-               SysTryCatch(NID_IO, (start != -1), , r, "[%s] Failed to reach the end of file (%s).", __ConvertNativeErrorToMessage(
-                                          errno), pDstpath.get());
+               SysLogException(NID_IO, r, "[%s] Failed to open file (%s), errno: %d (%s)",
+                                  GetErrorMessage(r), pDstpath.get(), errno, strerror(errno));
+               goto CATCH;
+       }
 
-               pBuffer = unique_ptr<char[]> (new (std::nothrow) char[_MAX_COPY_BYTES]);
-               SysTryCatch(NID_IO, (pBuffer != null), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
+       pBuffer = new (std::nothrow) char[_MAX_COPY_BYTES];
+       SysTryCatch(NID_IO, pBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
 
-               ssize_t bytesRead = -1;
-               ssize_t bytesWritten = -1;
+       pCopyBuf = pBuffer;
+       do
+       {
                do
                {
-                       bytesRead = read(srcFd, pBuffer.get(), _MAX_COPY_BYTES);
+                       readBytes = read(srcFd, pCopyBuf, _MAX_COPY_BYTES);
+               }
+               while (readBytes < 0 && errno == EINTR);
+               if (readBytes < 0)
+               {
                        r = __ConvertNativeErrorToResult(errno);
-                       SysTryCatch(NID_IO, bytesRead != -1, , r, "[%s] Failed to read from file (%s), errno: %d",
-                                          __ConvertNativeErrorToMessage(errno), pSrcpath.get(), errno);
-
-                       bytesWritten = write(dstFd, pBuffer.get(), bytesRead);
+                       SysLogException(NID_IO, r, "[%s] Failed to read from source file (%s), errno: %d (%s)",
+                                       GetErrorMessage(r), pSrcpath.get(), errno, strerror(errno));
+                       goto CATCH;
+               }
+               else if (readBytes == 0)
+               {
+                       break;
+               }
+               remainingBytes = readBytes;
+RETRY:
+               do
+               {
+                       writtenBytes = write(dstFd, pCopyBuf, remainingBytes);
+               }
+               while (writtenBytes < 0 && errno == EINTR);
+               if (writtenBytes < 0)
+               {
                        r = __ConvertNativeErrorToResult(errno);
-                       SysTryCatch(NID_IO, bytesWritten != -1, , r, "[%s] Failed to write to file (%s), errno: %d",
-                                          __ConvertNativeErrorToMessage(
-                                                  errno), pDstpath.get(), errno);
+                       SysLogException(NID_IO, r, "[%s] Failed to write to destination file (%s), errno: %d (%s)",
+                                       GetErrorMessage(r), pDstpath.get(), errno, strerror(errno));
+                       goto CATCH;
+               }
+               else if (writtenBytes < remainingBytes)
+               {
+                       remainingBytes = remainingBytes - writtenBytes;
+                       pCopyBuf = const_cast< char* >(pCopyBuf) + writtenBytes;
+                       goto RETRY;
                }
-               while (bytesRead);
        }
+       while (readBytes);
 
-       r = E_SUCCESS;
-
-       // fall thru
+       // fall through
 CATCH:
-
        if (srcFd != -1)
        {
                close(srcFd);
        }
-
        if (dstFd != -1)
        {
                fsync(dstFd);
                close(dstFd);
        }
-
-       if (pSrcMap != MAP_FAILED && size != -1)
-       {
-               munmap(pSrcMap, size);
-       }
-
-       if (pDstMap != MAP_FAILED && size != -1)
-       {
-               munmap(pDstMap, size);
-       }
+       delete[] pBuffer;
 
        return r;
 }
@@ -326,10 +318,9 @@ _FileUtil::GetAttributes(const String& filePath, FileAttributes& attribute)
 {
        DateTime dateTime;
        DateTime modifiedTime;
-       long long fileSize = 0;
+       off64_t fileSize = 0;
        unsigned long attr = 0;
        result r = E_SUCCESS;
-       struct tm* pTm = null;
        String fileName = L"";
        bool hidden = false;
 
@@ -337,11 +328,12 @@ _FileUtil::GetAttributes(const String& filePath, FileAttributes& attribute)
        SysTryReturn(NID_IO, (pFilePath != null), GetLastResult(), GetLastResult(), "[%s] Invalid source file path.",
                           GetErrorMessage(GetLastResult()));
 
-       struct stat statbuf;
-       if (int ret = stat(pFilePath.get(), &statbuf) == -1)
+       struct stat64 statbuf;
+       if (stat64(pFilePath.get(), &statbuf) == -1)
        {
                r = __ConvertNativeErrorToResult(errno);
-               SysLogException(NID_IO, r, "[%s] Failed to get file (%s) status.", GetErrorMessage(r), pFilePath.get());
+               SysSecureLogException(NID_IO, r, "[%s] Failed to get file (%s) status. errno: %d (%s)",
+                               GetErrorMessage(r), pFilePath.get(), errno, strerror(errno));
                return r;
        }
 
@@ -351,15 +343,13 @@ _FileUtil::GetAttributes(const String& filePath, FileAttributes& attribute)
        // attributes
        attr = statbuf.st_mode;
 
-       //  time of last status change
-       pTm = localtime(&statbuf.st_ctime);
-       SysTryReturnResult(NID_IO, pTm != null, E_SYSTEM, "Failed to call localtime() (%s).", strerror(errno));
+       struct tm resultTm;
+       struct tm* pTm = localtime_r(&statbuf.st_mtime, &resultTm);
+       SysTryReturnResult(NID_IO, pTm != null, E_SYSTEM, "Failed to get local time (%s).", strerror(errno));
+
        r = dateTime.SetValue(_BASE_YEAR + pTm->tm_year, 1 + pTm->tm_mon, pTm->tm_mday, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
        SysTryReturn(NID_IO, (!IsFailed(r)), r, r, "[%s] Failed to set DateTime.", GetErrorMessage(r));
 
-       // time of last modification
-       pTm = localtime(&statbuf.st_mtime);
-       SysTryReturnResult(NID_IO, pTm != null, E_SYSTEM, "Failed to call localtime() (%s).", strerror(errno));
        r = modifiedTime.SetValue(_BASE_YEAR + pTm->tm_year, 1 + pTm->tm_mon, pTm->tm_mday, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
        SysTryReturn(NID_IO, (!IsFailed(r)), r, r, "[%s] Failed to set DateTime.", GetErrorMessage(r));
 
@@ -381,7 +371,8 @@ _FileUtil::GetFileName(const String& filePath)
        int pos = -1;
 
        result r = filePath.LastIndexOf(L'/', filePath.GetLength() - 1, pos);
-       SysTryReturn(NID_IO, !IsFailed(r), fileName, E_INVALID_ARG, "[E_INVALID_ARG] The file path is invalid.");
+       SysTryReturn(NID_IO, r == E_SUCCESS || r == E_OBJ_NOT_FOUND, fileName, E_INVALID_ARG,
+                       "[E_INVALID_ARG] The file path is invalid.");
 
        r = filePath.SubString(pos + 1, fileName);
        SysTryReturn(NID_IO, !IsFailed(r), fileName, E_INVALID_ARG, "[E_INVALID_ARG] The file path is invalid.");
@@ -399,7 +390,8 @@ _FileUtil::GetFileExtension(const String& filePath)
        int pos = -1;
 
        result r = filePath.LastIndexOf(L'/', filePath.GetLength() - 1, pos);
-       SysTryReturn(NID_IO, !IsFailed(r), extName, E_INVALID_ARG, "[E_INVALID_ARG] The file path is invalid.");
+       SysTryReturn(NID_IO, r == E_SUCCESS || r == E_OBJ_NOT_FOUND, extName, E_INVALID_ARG,
+                       "[E_INVALID_ARG] The file path is invalid.");
 
        String fileName;
        r = filePath.SubString(pos + 1, fileName);