2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @File : FBaseUtil_FileUnzipperImpl.cpp
20 * @brief : Implementation for _FileUnzipperImpl Class
28 #include <sys/types.h>
30 #include <FBaseResult.h>
31 #include <FBaseSysLog.h>
32 #include <FBaseUtilStringUtil.h>
33 #include <FBase_NativeError.h>
35 #include "FBaseUtil_ZipEntryInfo.h"
36 #include "FBaseUtil_FileUnzipperImpl.h"
38 using namespace Tizen::Io;
40 namespace Tizen {namespace Base {namespace Utility
44 #define UNZ_COMP_CASE_SENSITIVE 1
45 #define UNZ_COMP_NO_CASE_SENSITIVE 2
47 #define UNZ_WRITE_BUF_LEN 4096 \
48 // _BADA_SLP_FIXME : TODO - Select an optimal value for this.
52 void operator ()(void* p)
63 void operator ()(FILE* p)
73 _FileUnzipperImpl::CreateDirectories(char* pFilePath)
78 char* pPos = pFilePath;
79 while ((pPos = strchr(pPos + 1, '/')) != null)
82 if (access(pFilePath, F_OK) != 0)
84 ret = mkdir(pFilePath, S_IRUSR | S_IWUSR | S_IXUSR);
87 r = _NativeError::ConvertNativeErrorToResult(errno, true);
88 SysTryReturnResult(NID_BASE_UTIL,
89 (r == E_SUCCESS) || (r == E_FILE_ALREADY_EXIST), r, "Unable to create directory [%s]", pFilePath);
99 _FileUnzipperImpl::IsFileExistsInZip(const char pArchiveName[], const char* pFilePathForZip)
101 std::unique_ptr< void, CloseUnzipFile > pUnzipFile(unzOpen(pArchiveName));
102 if (pUnzipFile != null)
104 return unzLocateFile(pUnzipFile.get(), pFilePathForZip, UNZ_COMP_CASE_SENSITIVE) != UNZ_END_OF_LIST_OF_FILE;
110 _FileUnzipperImpl::_FileUnzipperImpl(void)
111 : __pArchiveName(null)
118 _FileUnzipperImpl::~_FileUnzipperImpl(void)
124 _FileUnzipperImpl::Construct(const String& filePath)
126 SysAssertf(__pArchiveName == null, "Already constructed! "
127 "Calling Construct() twice or more on a same instance is not allowed for this class");
129 std::unique_ptr< ByteBuffer > pFilePathBuff(StringUtil::StringToUtf8N(filePath));
130 SysTryReturnResult(NID_BASE_UTIL, pFilePathBuff != null, E_INVALID_ARG, "Invalid file path.");
132 const char* pFilePath = reinterpret_cast<const char*> (pFilePathBuff->GetPointer());
133 SysTryReturnResult(NID_BASE_UTIL, access(pFilePath, F_OK) == 0, E_FILE_NOT_FOUND, "Invalid file path [%s].", pFilePath);
135 std::unique_ptr< void, CloseUnzipFile > pUnzipFile(unzOpen(pFilePath));
136 SysTryReturnResult(NID_BASE_UTIL, pUnzipFile != null, E_IO, "Failed to open [%s].", pFilePath);
141 FilePath unzFileEntryName = {0};
142 unz_global_info gunzfileInfo = {0};
143 unz_file_info unzfileInfo = {0};
145 int err = unzGetGlobalInfo(pUnzipFile.get(), &gunzfileInfo);
146 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to open the zip entry.");
148 err = unzGoToFirstFile(pUnzipFile.get());
149 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to get the first file entry in the zip file.");
153 err = unzGetCurrentFileInfo(pUnzipFile.get(), &unzfileInfo, unzFileEntryName, PATH_MAX, null, 0, null, 0);
154 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to get file entry info from the zip file.");
156 (unzFileEntryName[strlen(unzFileEntryName) - 1] == '/')? dirCount++ : fileCount++;
158 err = unzGoToNextFile(pUnzipFile.get());
159 SysTryReturnResult(NID_BASE_UTIL,
160 (err == UNZ_OK) || (err == UNZ_END_OF_LIST_OF_FILE), E_IO, "Failed to get the next entry in the zip file.");
162 } while (UNZ_END_OF_LIST_OF_FILE != err);
164 int len = strlen(pFilePath);
165 std::unique_ptr< char[] > pArchiveName(new (std::nothrow) char[len + 1]);
166 SysTryReturnResult(NID_BASE_UTIL, pArchiveName != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
168 strncpy(pArchiveName.get(), pFilePath, len);
169 pArchiveName[len] = 0;
171 __pArchiveName = std::move(pArchiveName);
172 __entryCount = gunzfileInfo.number_entry;
173 __dirCount = dirCount;
174 __fileCount = fileCount;
181 _FileUnzipperImpl::UnzipCurrentFileTo(void* pUnZipFile, FilePath outPath, int usedBytes) const
183 unz_file_info unzfileInfo = {0};
184 int err = unzGetCurrentFileInfo(pUnZipFile, &unzfileInfo, &(outPath[usedBytes]), PATH_MAX - usedBytes, null, 0, null, 0);
185 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to get file entry info from the zip file.");
187 result r = _FileUnzipperImpl::CreateDirectories(outPath);
188 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to create Directory [%s]", outPath);
190 if(outPath[strlen(outPath) - 1] != '/')
192 std::unique_ptr< FILE, CloseFile > pFile(fopen(outPath, "w"));
193 r = __ConvertNativeErrorToResult(errno);
194 SysTryReturnResult(NID_BASE_UTIL, pFile != null, r, "Failed to open file [name: %s, errorno: %d].", outPath, errno);
196 err = unzOpenCurrentFile(pUnZipFile);
197 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to open current zip file.");
201 char writeBuf[UNZ_WRITE_BUF_LEN] = {0};
204 readLen = unzReadCurrentFile(pUnZipFile, writeBuf, sizeof(writeBuf));
205 r = (readLen < 0) ? E_IO : E_SUCCESS;
206 SysTryCatch(NID_BASE_UTIL, r == E_SUCCESS, unzCloseCurrentFile(pUnZipFile), r,
207 "[%s] Failed to read from zip file (%s).", GetErrorMessage(E_IO), outPath);
211 writeCnt = fwrite(writeBuf, 1, readLen, pFile.get());
212 if (writeCnt < readLen)
214 int ret = ferror(pFile.get());
215 r = __ConvertNativeErrorToResult(ret);
216 SysTryCatch(NID_BASE_UTIL, ret != 0, unzCloseCurrentFile(pUnZipFile), r,
217 "[%s] Failed to perform write operation.", GetErrorMessage(r));
222 unzCloseCurrentFile(pUnZipFile);
230 _FileUnzipperImpl::UnzipTo(const String& dirPath) const
232 SysAssertf(__pArchiveName != null, "Not yet constructed! Construct() should be called before use");
234 String dirPathStr(dirPath);
235 dirPathStr.Replace(L"\\", L"/");
236 if (dirPathStr.EndsWith(L"/") == false)
238 dirPathStr.Append(L"/");
241 std::unique_ptr< ByteBuffer > pDirBuff(StringUtil::StringToUtf8N(dirPathStr));
242 SysTryReturnResult(NID_BASE_UTIL, pDirBuff != null, E_INVALID_ARG, "Invalid file path.");
244 FilePath outPath = {0};
245 int dirPathLength = pDirBuff->GetCapacity() - 1;
246 strncat(outPath, reinterpret_cast<const char*> (pDirBuff->GetPointer()), dirPathLength);
248 std::unique_ptr< void, CloseUnzipFile > pUnzipFile(unzOpen(__pArchiveName.get()));
249 SysTryReturnResult(NID_BASE_UTIL, pUnzipFile != null, E_IO, "Failed to open [%s].", __pArchiveName.get());
251 int err = unzGoToFirstFile(pUnzipFile.get());
252 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to get the first file entry in the zip file.");
254 result r = E_SUCCESS;
255 int entryCount = __entryCount;
258 r = UnzipCurrentFileTo(pUnzipFile.get(), outPath, dirPathLength);
259 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, r, "Failed to unzip current file");
263 err = unzGoToNextFile(pUnzipFile.get());
264 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to fetch the next file entry in the zip file.");
272 _FileUnzipperImpl::UnzipTo(const String& dirPath, const String& zipEntryName) const
274 SysAssertf(__pArchiveName != null, "Not yet constructed! Construct() should be called before use");
276 String dirPathStr = dirPath;
277 dirPathStr.Replace(L"\\", L"/");
278 if (dirPathStr.EndsWith(L"/") == false)
280 dirPathStr.Append(L"/");
283 std::unique_ptr< ByteBuffer > pDirBuff(StringUtil::StringToUtf8N(dirPathStr));
284 SysTryReturnResult(NID_BASE_UTIL, pDirBuff != null, E_INVALID_ARG, "Invalid file path.");
286 FilePath outPath = {0};
287 int dirPathLength = pDirBuff->GetCapacity() - 1;
288 strncat(outPath, reinterpret_cast<const char*> (pDirBuff->GetPointer()), dirPathLength);
290 std::unique_ptr< ByteBuffer > pZipEntryBuff(StringUtil::StringToUtf8N(zipEntryName));
291 SysTryReturnResult(NID_BASE_UTIL, pZipEntryBuff != null, E_INVALID_ARG, "[%s] Invalid zip Entry Name.", GetErrorMessage(E_INVALID_ARG));
293 const char* pZipEntryName = reinterpret_cast<const char*> (pZipEntryBuff->GetPointer());
295 std::unique_ptr< void, CloseUnzipFile > pUnzipFile(unzOpen(__pArchiveName.get()));
296 SysTryReturnResult(NID_BASE_UTIL, pUnzipFile != null, E_IO, "Failed to open [%s].", __pArchiveName.get());
298 int err = unzLocateFile(pUnzipFile.get(), pZipEntryName, UNZ_COMP_CASE_SENSITIVE);
299 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_FILE_NOT_FOUND, "Failed to locate file entry (%s).", pZipEntryName);
301 return UnzipCurrentFileTo(pUnzipFile.get(), outPath, dirPathLength);
305 _FileUnzipperImpl::GetEntryCount(void) const
307 SysAssertf(__pArchiveName != null, "Not yet constructed! Construct() should be called before use");
312 _FileUnzipperImpl::GetFileCount(void) const
314 SysAssertf(__pArchiveName != null, "Not yet constructed! Construct() should be called before use");
320 _FileUnzipperImpl::GetDirectoryCount(void) const
322 SysAssertf(__pArchiveName != null, "Not yet constructed! Construct() should be called before use");
327 _FileUnzipperImpl::GetCurrentFileInfo(void* pUnZipFile, ZipEntry& entry) const
329 unz_file_info unzFileInfo = {0};
330 char unzFileEntryName[PATH_MAX + 1];
332 // after locate, the current file is the entry, fetch its info
333 int err = unzGetCurrentFileInfo(pUnZipFile, &unzFileInfo, unzFileEntryName, PATH_MAX, null, 0, null, 0);
334 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to fetch information of current file in the zip entry.");
336 String fileEntryName;
337 result r = StringUtil::Utf8ToString(unzFileEntryName, fileEntryName);
338 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, E_IO, "Invalid file path in Zip file.");
341 r = StringUtil::Utf8ToString(__pArchiveName.get(), archieveName);
342 SysTryReturnResult(NID_BASE_UTIL, r == E_SUCCESS, E_IO, "Invalid file path in Zip file.");
345 int level = DEFAULT_COMPRESSION;
347 err = unzOpenCurrentFile2(pUnZipFile, &method, &level, 1);
348 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to open the current entry in the zip file.");
350 err = unzCloseCurrentFile(pUnZipFile);
351 SysTryReturnResult(NID_BASE_UTIL, err == UNZ_OK, E_IO, "Failed to close the zip entry.");
353 _ZipEntryInfo* pZipEntryInfo = null;
354 if (entry.__unzFile == null)
356 pZipEntryInfo = new (std::nothrow) _ZipEntryInfo;
357 SysTryReturnResult(NID_BASE_UTIL, pZipEntryInfo != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
361 pZipEntryInfo = static_cast <_ZipEntryInfo*>(entry.__unzFile);
364 // pZipEntryInfo->__unzFile = __pUzFile;
365 pZipEntryInfo->__name = fileEntryName;
366 if (level == Z_BEST_SPEED)
368 pZipEntryInfo->__compressionLevel = BEST_SPEED;
370 else if (level == Z_BEST_COMPRESSION)
372 pZipEntryInfo->__compressionLevel = BEST_COMPRESSION;
376 pZipEntryInfo->__compressionLevel = DEFAULT_COMPRESSION;
379 pZipEntryInfo->__isDirectory = (unzFileInfo.external_fa == 16) ? 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 SysTryReturnResult(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 SysTryReturnResult(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 SysTryReturnResult(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