Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open file from memory buffer using minizip

Tags:

c++

c

zlib

I am searching how to open archive from memory buffer using minizip.

I found ioapi_mem_c.zip from their page http://www.winimage.com/zLibDll/minizip.html.

I can't understand how to use it. Can some one give me an example?

like image 545
DenSumy Avatar asked Apr 29 '13 08:04

DenSumy


2 Answers

I solved my problem for unziping: I added this function to unzip.c

extern unzFile ZEXPORT unzOpenBuffer (const  void* buffer, uLong size)
{
    char path[16] = {0};
    zlib_filefunc64_32_def memory_file;
    uLong base = (uLong)buffer;

    sprintf(path, "%x+%x", base, size);

    fill_memory_filefunc64_32(&memory_file);
    return unzOpenInternal(path, &memory_file, 0);
}

And made some changes in ioapi_mem.c:

void fill_memory_filefunc64_32 (pzlib_filefunc_def)
    zlib_filefunc64_32_def* pzlib_filefunc_def;
{
    pzlib_filefunc_def->zopen32_file = fopen_mem_func;
    pzlib_filefunc_def->zfile_func64.zopen64_file = fopen_mem_func;
    pzlib_filefunc_def->zfile_func64.zread_file = fread_mem_func;
    pzlib_filefunc_def->zfile_func64.zwrite_file = fwrite_mem_func;
    pzlib_filefunc_def->ztell32_file = ftell_mem_func;
    pzlib_filefunc_def->zseek32_file = fseek_mem_func;
    pzlib_filefunc_def->zfile_func64.zseek64_file = NULL;
    pzlib_filefunc_def->zfile_func64.zclose_file = fclose_mem_func;
    pzlib_filefunc_def->zfile_func64.zerror_file = ferror_mem_func;
    pzlib_filefunc_def->zfile_func64.opaque = NULL;
}

I hope this will help someone who will have the same problem.

And Here is simple class implementation how to use it:

 void ZipArchiveImpl::OpenArchive()
        {
            ASSERT(!mInited, "Already opened.");


            if ((mFileMode == FM_READ))
            {
                if (mArchiveName.size() == 0)
                {


                    u32 sz = mFile->GetFileSize();
                    mUnzBlock.Resize(sz);
                    mFile->SetPosition(0);
                    mFile->Read(mUnzBlock.Data(), mUnzBlock.GetSizeInBytes());

                    mUnzHandle = unzOpenBuffer(mUnzBlock.Data(), mUnzBlock.GetSizeInBytes());

                }
                else
                {
                    mUnzHandle = unzOpen(mArchiveName.c_str());
                }

                if (!mUnzHandle) return;
                FillMap();
            }

            else if (mFileMode == FM_WRITE)
            {
                ASSERT0(mArchiveName.size());
                mZipHandle = zipOpen(mArchiveName.c_str(), 0);

                if (!mZipHandle) return;
            }



            mInited = true;
        }

        IFile* ZipArchiveImpl::OpenRead(const std::string& name)
        {
            if (IsExist(name))
            {

                ZipFileInfo info = mFileMap.find(name)->second;

                MemoryBlock block(1);
                block.Resize(info.uncompressedSize);

                int res = unzGoToFilePos(mUnzHandle, &info.filePosInfo);
                if (UNZ_OK != res)
                {
                    return false;
                }

                // open the current file with optional password
                if (mArchivePassword != "")
                {
                    res = unzOpenCurrentFilePassword(info.zipFileHandle, mArchivePassword.c_str());
                }
                else
                {
                    res = unzOpenCurrentFile(info.zipFileHandle);
                }
                if (UNZ_OK != res)
                {
                    return false;
                }

                // read uncompressed data
                int readResult = unzReadCurrentFile(info.zipFileHandle, block.Data(), info.uncompressedSize);

                // close the file
                res = unzCloseCurrentFile(info.zipFileHandle);
                if (UNZ_OK != res)
                {
                    return false;
                }

                if (info.uncompressedSize == readResult)
                {
                    return ROBE_NEW MemoryFile(block.Data(), info.uncompressedSize);
                }
                else
                {
                    return NULL;
                }
            }
            else
            {
                return NULL;
            }
        }

        IFile* ZipArchiveImpl::OpenRead(u32 id)
        {
            ASSERT0(mFileNames.size() > id);
            if (IsExist(mFileNames[id]))
            {
                return OpenRead(mFileNames[id]);
            }
            else
            {
                return NULL;
            }
        }

        void ZipArchiveImpl::FillMap()
        {
            s32 walkRes = unzGoToFirstFile(mUnzHandle);
            unz_file_info info;
            while (UNZ_OK == walkRes)
            {

                // get info about current file
                char currentFileName[512];
                s32 fileInfoRes = unzGetCurrentFileInfo(mUnzHandle, &info, currentFileName, sizeof(currentFileName), 0, 0, 0, 0);

                std::string name = std::string(currentFileName);
                mFileNames.push_back(name);
                InitInfo(name, &info);
                walkRes = unzGoToNextFile(mUnzHandle);

            }
            OpenRead(0);

            if (UNZ_END_OF_LIST_OF_FILE != walkRes)
            {

            }
        }

        void ZipArchiveImpl::InitInfo(const std::string& name, unz_file_info* info)
        {
            ZipFileInfo zfi;
            mFileMap.insert(std::pair<std::string, ZipFileInfo>(name, zfi));
            mFileMap[name].zipFileHandle = mUnzHandle;
            int res = unzGetFilePos(mFileMap[name].zipFileHandle, &mFileMap[name].filePosInfo);

            mFileMap[name].uncompressedSize = info->uncompressed_size;

            char lastsymbol = name[name.size() - 1];
            if (lastsymbol == '/' || lastsymbol == '\\')
            {
                mFileMap[name].type = ZFT_DIR;
            }
            else
            {
                mFileMap[name].type = ZFT_FILE;
            }
        }


        ZipArchiveImpl::~ZipArchiveImpl()
        {
            if (mInited)
            {
                if (mUnzHandle) unzClose(mUnzHandle);
                if (mZipHandle) zipClose(mZipHandle, 0);
            }
        }

        bool ZipArchiveImpl::IsExist(const std::string& name)
        {
            return (mFileMap.find(name) != mFileMap.end());
        }

        void ZipArchiveImpl::SaveFileToZip(const std::string& path, IFile* file)
        {
            const u32 DefaultFileAttribute = 32;


            MemoryBlock block(1);
            block.Resize(file->GetFileSize());
            file->Read(block.Data(), block.GetSizeInBytes());

            zip_fileinfo zinfo;

            memset(&zinfo, 0, sizeof(zinfo));

            zinfo.internal_fa = 0;
            zinfo.external_fa = DefaultFileAttribute;

            ::boost::posix_time::ptime pt = ::boost::posix_time::from_time_t(time(0));
            std::tm ptm             = ::boost::posix_time::to_tm(pt);

            zinfo.dosDate           = 0;
            zinfo.tmz_date.tm_year  = ptm.tm_year;
            zinfo.tmz_date.tm_mon   = ptm.tm_mon;
            zinfo.tmz_date.tm_mday  = ptm.tm_mday;
            zinfo.tmz_date.tm_hour  = ptm.tm_hour;
            zinfo.tmz_date.tm_min   = ptm.tm_min;
            zinfo.tmz_date.tm_sec   = ptm.tm_sec;

            zipOpenNewFileInZip(mZipHandle, path.c_str(), &zinfo, 0, 0, 0, 0, 0, Z_DEFLATED, Z_BEST_SPEED);
            zipWriteInFileInZip(mZipHandle, block.Data(), block.GetSizeInBytes());
            zipCloseFileInZip(mZipHandle);
        }

        unsigned long ZipArchiveImpl::GetFileAttributes(const std::string& filePath)
        {
            unsigned long attrib = 0;
            #ifdef WIN32
            attrib = ::GetFileAttributes(filePath.c_str());
            #else
            struct stat path_stat;
            if (::stat(filePath.c_str(), &path_stat) == 0)
            {
                attrib = path_stat.st_mode;
            }
            #endif
            return attrib;
        }
like image 180
DenSumy Avatar answered Nov 10 '22 01:11

DenSumy


added this function to unzip.c

extern unzFile ZEXPORT unzOpenBuffer(const  void* buffer, uLong size)
{
    zlib_filefunc_def filefunc32 = { 0 };
    ourmemory_t *punzmem = (ourmemory_t*)malloc(sizeof(ourmemory_t));
    punzmem->size = size;
    punzmem->base = (char *)malloc(punzmem->size);
    memcpy(punzmem->base, buffer, punzmem->size);
    punzmem->grow = 0;
    punzmem->cur_offset = 0;
    punzmem->limit = 0;
    fill_memory_filefunc(&filefunc32, punzmem);
    return unzOpen2(NULL, &filefunc32);
}
like image 1
Curry30 Avatar answered Nov 10 '22 02:11

Curry30