2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @File : FBaseUtil_FileUnzipperImpl.cpp
19 * @brief : Implementation for _FileUnzipperImpl Class
27 #include <sys/types.h>
29 #include <FBaseResult.h>
30 #include <FBaseSysLog.h>
31 #include <FBaseUtilStringUtil.h>
32 #include <FBase_NativeError.h>
34 #include "FBaseUtil_ZipEntryInfo.h"
35 #include "FBaseUtil_FileUnzipperImpl.h"
37 using namespace Tizen::Io;
39 namespace Tizen {namespace Base {namespace Utility
43 #define UNZ_COMP_CASE_SENSITIVE 1
44 #define UNZ_COMP_NO_CASE_SENSITIVE 2
46 #define UNZ_WRITE_BUF_LEN 4096 \
47 // _BADA_SLP_FIXME : TODO - Select an optimal value for this.
51 void operator ()(void* p)
62 void operator ()(FILE* p)
72 _FileUnzipperImpl::CreateDirectories(char* pFilePath)
77 char* pPos = pFilePath;
78 while ((pPos = strchr(pPos + 1, '/')) != null)
81 if (access(pFilePath, F_OK) != 0)
83 ret = mkdir(pFilePath, S_IRUSR | S_IWUSR | S_IXUSR);
86 r = _NativeError::ConvertNativeErrorToResult(errno, true);
87 SysSecureTryReturnResult(NID_BASE_UTIL,
88 (r == E_SUCCESS) || (r == E_FILE_ALREADY_EXIST), r, "Unable to create directory [%s]", pFilePath);
98 _FileUnzipperImpl::IsFileExistsInZip(const char pArchiveName[], const char* pFilePathForZip)
100 std::unique_ptr< void, CloseUnzipFile > pUnzipFile(unzOpen(pArchiveName));
101 if (pUnzipFile != null)
103 return unzLocateFile(pUnzipFile.get(), pFilePathForZip, UNZ_COMP_CASE_SENSITIVE) != UNZ_END_OF_LIST_OF_FILE;
109 _FileUnzipperImpl::_FileUnzipperImpl(void)
110 : __pArchiveName(null)
117 _FileUnzipperImpl::~_FileUnzipperImpl(void)
123 _FileUnzipperImpl::Construct(const String& filePath)
125 SysAssertf(__pArchiveName == null, "Already constructed! "
126 "Calling Construct() twice or more on a same instance is not allowed for this class");
128 std::unique_ptr< ByteBuffer > pFilePathBuff(StringUtil::StringToUtf8N(filePath));
129 SysTryReturnResult(NID_BASE_UTIL, pFilePathBuff != null, E_INVALID_ARG, "Invalid file path.");
131 const char* pFilePath = reinterpret_cast<const char*> (pFilePathBuff->GetPointer());
132 SysSecureTryReturnResult(NID_BASE_UTIL, access(pFilePath, F_OK) == 0, E_FILE_NOT_FOUND, "Invalid file path [%s].", pFilePath);
134 std::unique_ptr< void, CloseUnzipFile > pUnzipFile(unzOpen(pFilePath));
135 SysSecureTryReturnResult(NID_BASE_UTIL, pUnzipFile != null, E_IO, "Failed to open [%s].", pFilePath);
140 FilePath unzFileEntryName = {0};
141 unz_global_info gunzfileInfo = {0};
142 unz_file_info unzfileInfo = {0};
144 int err = unzGetGlobalInfo(pUnzipFile.get(), &gunzfileInfo);
145 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to open the zip entry.");
147 err = unzGoToFirstFile(pUnzipFile.get());
148 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to get the first file entry in the zip file.");
152 err = unzGetCurrentFileInfo(pUnzipFile.get(), &unzfileInfo, unzFileEntryName, PATH_MAX, null, 0, null, 0);
153 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to get file entry info from the zip file.");
155 (unzFileEntryName[strlen(unzFileEntryName) - 1] == '/')? dirCount++ : fileCount++;
157 err = unzGoToNextFile(pUnzipFile.get());
158 SysTryReturnResult(NID_BASE_UTIL,
159 (err == UNZ_OK) || (err == UNZ_END_OF_LIST_OF_FILE), E_IO, "Failed to get the next entry in the zip file.");
161 } while (UNZ_END_OF_LIST_OF_FILE != err);
163 int len = strlen(pFilePath);
164 std::unique_ptr< char[] > pArchiveName(new (std::nothrow) char[len + 1]);
165 SysTryReturnResult(NID_BASE_UTIL, pArchiveName != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
167 strncpy(pArchiveName.get(), pFilePath, len);
168 pArchiveName[len] = 0;
170 __pArchiveName = std::move(pArchiveName);
171 __entryCount = gunzfileInfo.number_entry;
172 __dirCount = dirCount;
173 __fileCount = fileCount;
180 _FileUnzipperImpl::UnzipCurrentFileTo(void* pUnZipFile, FilePath outPath, int usedBytes) const
182 unz_file_info unzfileInfo = {0};
183 int err = unzGetCurrentFileInfo(pUnZipFile, &unzfileInfo, &(outPath[usedBytes]), PATH_MAX - usedBytes, null, 0, null, 0);
184 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to get file entry info from the zip file.");
186 result r = _FileUnzipperImpl::CreateDirectories(outPath);
187 SysSecureTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to create Directory [%s]", outPath);
189 if(outPath[strlen(outPath) - 1] != '/')
191 std::unique_ptr< FILE, CloseFile > pFile(fopen(outPath, "w"));
192 r = __ConvertNativeErrorToResult(errno);
193 SysSecureTryReturnResult(NID_BASE_UTIL, pFile != null, r, "Failed to open file [name: %s, errorno: %d].", outPath, errno);
195 err = unzOpenCurrentFile(pUnZipFile);
196 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to open current zip file.");
200 char writeBuf[UNZ_WRITE_BUF_LEN] = {0};
203 readLen = unzReadCurrentFile(pUnZipFile, writeBuf, sizeof(writeBuf));
204 r = (readLen < 0) ? E_IO : E_SUCCESS;
205 SysTryCatch(NID_BASE_UTIL, r == E_SUCCESS, unzCloseCurrentFile(pUnZipFile), r,
206 "[%s] Failed to read from zip file.", GetErrorMessage(E_IO));
210 writeCnt = fwrite(writeBuf, 1, readLen, pFile.get());
211 if (writeCnt < readLen)
213 int ret = ferror(pFile.get());
214 r = __ConvertNativeErrorToResult(ret);
215 SysTryCatch(NID_BASE_UTIL, ret != 0, unzCloseCurrentFile(pUnZipFile), r,
216 "[%s] Failed to perform write operation.", GetErrorMessage(r));
221 unzCloseCurrentFile(pUnZipFile);
229 _FileUnzipperImpl::UnzipTo(const String& dirPath) const
231 SysAssertf(__pArchiveName != null, "Not yet constructed! Construct() should be called before use");
233 String dirPathStr(dirPath);
234 dirPathStr.Replace(L"\\", L"/");
235 if (dirPathStr.EndsWith(L"/") == false)
237 dirPathStr.Append(L"/");
240 std::unique_ptr< ByteBuffer > pDirBuff(StringUtil::StringToUtf8N(dirPathStr));
241 SysTryReturnResult(NID_BASE_UTIL, pDirBuff != null, E_INVALID_ARG, "Invalid file path.");
243 FilePath outPath = {0};
244 int dirPathLength = pDirBuff->GetCapacity() - 1;
245 strncat(outPath, reinterpret_cast<const char*> (pDirBuff->GetPointer()), dirPathLength);
247 std::unique_ptr< void, CloseUnzipFile > pUnzipFile(unzOpen(__pArchiveName.get()));
248 SysSecureTryReturnResult(NID_BASE_UTIL, pUnzipFile != null, E_IO, "Failed to open [%s].", __pArchiveName.get());
250 int err = unzGoToFirstFile(pUnzipFile.get());
251 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to get the first file entry in the zip file.");
253 result r = E_SUCCESS;
254 int entryCount = __entryCount;
257 r = UnzipCurrentFileTo(pUnzipFile.get(), outPath, dirPathLength);
258 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to unzip current file");
262 err = unzGoToNextFile(pUnzipFile.get());
263 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to fetch the next file entry in the zip file.");
271 _FileUnzipperImpl::UnzipTo(const String& dirPath, const String& zipEntryName) const
273 SysAssertf(__pArchiveName != null, "Not yet constructed! Construct() should be called before use");
275 String dirPathStr = dirPath;
276 dirPathStr.Replace(L"\\", L"/");
277 if (dirPathStr.EndsWith(L"/") == false)
279 dirPathStr.Append(L"/");
282 std::unique_ptr< ByteBuffer > pDirBuff(StringUtil::StringToUtf8N(dirPathStr));
283 SysTryReturnResult(NID_BASE_UTIL, pDirBuff != null, E_INVALID_ARG, "Invalid file path.");
285 FilePath outPath = {0};
286 int dirPathLength = pDirBuff->GetCapacity() - 1;
287 strncat(outPath, reinterpret_cast<const char*> (pDirBuff->GetPointer()), dirPathLength);
289 std::unique_ptr< ByteBuffer > pZipEntryBuff(StringUtil::StringToUtf8N(zipEntryName));
290 SysTryReturnResult(NID_BASE_UTIL, pZipEntryBuff != null, E_INVALID_ARG, "[%s] Invalid zip Entry Name.", GetErrorMessage(E_INVALID_ARG));
292 const char* pZipEntryName = reinterpret_cast<const char*> (pZipEntryBuff->GetPointer());
294 std::unique_ptr< void, CloseUnzipFile > pUnzipFile(unzOpen(__pArchiveName.get()));
295 SysSecureTryReturnResult(NID_BASE_UTIL, pUnzipFile != null, E_IO, "Failed to open [%s].", __pArchiveName.get());
297 int err = unzLocateFile(pUnzipFile.get(), pZipEntryName, UNZ_COMP_CASE_SENSITIVE);
298 SysSecureTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_FILE_NOT_FOUND, "Failed to locate file entry (%s).", pZipEntryName);
300 return UnzipCurrentFileTo(pUnzipFile.get(), outPath, dirPathLength);
304 _FileUnzipperImpl::GetEntryCount(void) const
306 SysAssertf(__pArchiveName != null, "Not yet constructed! Construct() should be called before use");
311 _FileUnzipperImpl::GetFileCount(void) const
313 SysAssertf(__pArchiveName != null, "Not yet constructed! Construct() should be called before use");
319 _FileUnzipperImpl::GetDirectoryCount(void) const
321 SysAssertf(__pArchiveName != null, "Not yet constructed! Construct() should be called before use");
326 _FileUnzipperImpl::GetCurrentFileInfo(void* pUnZipFile, ZipEntry& entry) const
328 unz_file_info unzFileInfo = {0};
329 char unzFileEntryName[PATH_MAX + 1];
331 // after locate, the current file is the entry, fetch its info
332 int err = unzGetCurrentFileInfo(pUnZipFile, &unzFileInfo, unzFileEntryName, PATH_MAX, null, 0, null, 0);
333 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to fetch information of current file in the zip entry.");
335 String fileEntryName;
336 result r = StringUtil::Utf8ToString(unzFileEntryName, fileEntryName);
337 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, E_IO, "Invalid file path in Zip file.");
340 r = StringUtil::Utf8ToString(__pArchiveName.get(), archieveName);
341 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, E_IO, "Invalid file path in Zip file.");
344 int level = DEFAULT_COMPRESSION;
346 err = unzOpenCurrentFile2(pUnZipFile, &method, &level, 1);
347 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to open the current entry in the zip file.");
349 err = unzCloseCurrentFile(pUnZipFile);
350 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to close the zip entry.");
352 _ZipEntryInfo* pZipEntryInfo = null;
353 if (entry.__unzFile == null)
355 pZipEntryInfo = new (std::nothrow) _ZipEntryInfo;
356 SysTryReturnResult(NID_BASE_UTIL, pZipEntryInfo != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
360 pZipEntryInfo = static_cast <_ZipEntryInfo*>(entry.__unzFile);
363 // pZipEntryInfo->__unzFile = __pUzFile;
364 pZipEntryInfo->__name = fileEntryName;
365 if (level == Z_BEST_SPEED)
367 pZipEntryInfo->__compressionLevel = BEST_SPEED;
369 else if (level == Z_BEST_COMPRESSION)
371 pZipEntryInfo->__compressionLevel = BEST_COMPRESSION;
375 pZipEntryInfo->__compressionLevel = DEFAULT_COMPRESSION;
378 const int length = (pZipEntryInfo->__name).GetLength();
379 pZipEntryInfo->__isDirectory = ((pZipEntryInfo->__name)[length - 1] == '/') ? true : false;
380 pZipEntryInfo->__compressedSize = unzFileInfo.compressed_size;
381 pZipEntryInfo->__uncompressedSize = unzFileInfo.uncompressed_size;
382 pZipEntryInfo->__archiveName = archieveName;
383 pZipEntryInfo->__method = method;
385 // set the entry information
386 entry.Set(pZipEntryInfo);
392 _FileUnzipperImpl::GetEntry(const String& zipEntryName, ZipEntry& entry) const
394 SysAssertf(__pArchiveName != null, "Not yet constructed! Construct() should be called before use");
396 std::unique_ptr< ByteBuffer > pZipEntryBuff(StringUtil::StringToUtf8N(zipEntryName));
397 SysTryReturnResult(NID_BASE_UTIL, pZipEntryBuff != null, E_INVALID_ARG, "Invalid file path.");
399 const char* pZipEntryName = reinterpret_cast<const char*> (pZipEntryBuff->GetPointer());
401 std::unique_ptr< void, CloseUnzipFile > pZipFile(unzOpen(__pArchiveName.get()));
402 SysSecureTryReturnResult(NID_BASE_UTIL, pZipFile != null, E_IO, "Failed to open [%s].", __pArchiveName.get());
404 int err = unzLocateFile(pZipFile.get(), pZipEntryName, UNZ_COMP_CASE_SENSITIVE);
405 SysSecureTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_FILE_NOT_FOUND, "Failed to locate file entry (%s).", pZipEntryName);
407 return GetCurrentFileInfo(pZipFile.get(), entry);
412 _FileUnzipperImpl::GetEntry(int index, ZipEntry& entry) const
414 SysAssertf(__pArchiveName != null, "Not yet constructed! Construct() should be called before use");
416 std::unique_ptr< void, CloseUnzipFile > pZipFile(unzOpen(__pArchiveName.get()));
417 SysSecureTryReturnResult(NID_BASE_UTIL, pZipFile != null, E_IO, "Failed to open [%s].", __pArchiveName.get());
419 // goto the first file in the archive
420 int err = unzGoToFirstFile(pZipFile.get());
421 SysTryReturnResult(NID_BASE_UTIL, (err == UNZ_OK), E_IO, "Failed to get the first file entry in the zip file.");
425 err = unzGoToNextFile(pZipFile.get());
426 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to move to the next entry in zip file.");
429 return GetCurrentFileInfo(pZipFile.get(), entry);
432 } } } // Tizen::Base::Utility