Skip to content

Commit

Permalink
dropped libarchive dependency and added internal tar extraction class…
Browse files Browse the repository at this point in the history
… + libzip for zip decompression
  • Loading branch information
Paolo committed Mar 16, 2021
1 parent e877c63 commit d94a628
Show file tree
Hide file tree
Showing 10 changed files with 361 additions and 31 deletions.
31 changes: 21 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
project (Unlocker)

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/modules)

SET(UNLOCKER_STATIC_LIBS_WIN ON CACHE BOOL "Links statically") # Set to OFF for dynamic linking

IF (MSVC)
Expand All @@ -26,13 +28,21 @@ endif()

include_directories(${CURL_INCLUDE_DIRS})

find_package(LibArchive REQUIRED)
#find_package(LibArchive REQUIRED)

if(LibArchive_FOUND)
message (STATUS "LibArchive found, version ${LibArchive_VERSION}")
endif()
#if(LibArchive_FOUND)
# message (STATUS "LibArchive found, version ${LibArchive_VERSION}")
#endif()

#include_directories(${LibArchive_INCLUDE_DIRS})

include_directories(${LibArchive_INCLUDE_DIRS})
find_package(LibZip REQUIRED)

include_directories(${LIBZIP_INCLUDE_DIRS})

if(LIBZIP_FOUND)
message (STATUS "LibZip found")
endif()

# main include files
include_directories ("${PROJECT_SOURCE_DIR}/include")
Expand All @@ -47,18 +57,18 @@ set (SOURCE_FILES src/unlocker.cpp /
src/installinfoutils.cpp /
src/servicestoputils.cpp /
src/patchutils.cpp /
)
src/tar.cpp )

IF (MSVC)
IF (UNLOCKER_STATIC_LIBS_WIN)
# Preprocessor definitions needed to avoid name mangling when statically importing libs on MSVC compiler
# Name mangling is needed if libraries are built dynamically with MSVC
# Should not be an issue with other compilers
add_compile_definitions( "CURL_STATICLIB" "LIBARCHIVE_STATIC")
add_compile_definitions( "CURL_STATICLIB" )
ENDIF()
ENDIF (MSVC)

add_executable(Unlocker ${SOURCE_FILES})
add_executable(Unlocker ${SOURCE_FILES} )

set_target_properties(Unlocker PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS ON)

Expand All @@ -68,7 +78,8 @@ endif()

target_link_libraries (Unlocker ${ZLIB_LIBRARIES})
target_link_libraries (Unlocker ${CURL_LIBRARIES})
target_link_libraries (Unlocker ${LibArchive_LIBRARIES})
#target_link_libraries (Unlocker ${LibArchive_LIBRARIES})
target_link_libraries (Unlocker ${LIBZIP_LIBRARY})

if(WIN32)
target_link_libraries (Unlocker ws2_32 Wldap32)
Expand All @@ -91,7 +102,7 @@ ENDIF(MSVC)
set (TEST_SOURCES tests/test_patch.cpp /
src/debugutils.cpp /
src/patchutils.cpp /
)
src/tar.cpp )

add_executable( TestPatch ${TEST_SOURCES} )

Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ I created the C++ version of this tool to avoid issues between different Python

* ```--install``` *(Default behavior when called with no arguments)* Installs the patch.
* ```--uninstall``` Uninstalls the patch. Works only if the patch was previously installed and the *backup* folder is intact
* ```--download-tools``` Only downloads the tools in the `tools` folder
* ```--help``` Shows a list of the available options

**I tested the program on Windows with VMware Player 15.0.** I plan to test it on Linux soon, though as of now I don't know if it works there, or with other VMware versions.
Expand All @@ -41,9 +42,9 @@ The program can be compiled on Windows with CMake, provided you get or compile t
The program needs the following libraries:

* libcurl
* zlib
* libarchive
* libzip

The tar extraction is handled internally, while the zip decompression needs the `libzip` library. `libcurl` is used for downloading the tools.

**Windows:**
Run *CMake* on the source folder to generate a Visual Studio Project. The CMakeList is set up to compile with static libraries, if you have shared ones change *CMakeLists.txt* file accordingly (**UNLOCKER_STATIC_LIBS_WIN** variable). Point the CMake utility to the proper library/headers paths when prompted or add them to your PATH.
Expand Down
17 changes: 13 additions & 4 deletions include/archiveutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,30 @@
#define ARCHIVEUTILS_H

#include "filesystem.hpp"

/*
#include <archive.h>
#include <archive_entry.h>

*/
#ifdef __linux__
#include <cstring>
#endif

#define LIBZIP_STATIC

#include "zipconf.h"
#include "zip.h"
#include "tar.h"
#include "debugutils.h"

#define AR_BUFFER_SIZE 4096

namespace Archive
{
int copy_data(struct archive* ar, struct archive* aw);
/*int copy_data(struct archive* ar, struct archive* aw);
bool extract(const char* from, const char* filename, const char* to);
bool extract_s(fs::path from, std::string filename, fs::path to);
bool extract_s(fs::path from, std::string filename, fs::path to);*/
bool extract_zip(fs::path from, std::string filename, fs::path to);
bool extract_tar(fs::path from, std::string filename, fs::path to);
}

#endif // ARCHIVEUTILS_H
4 changes: 3 additions & 1 deletion include/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
*/

// Program options
#define PROG_VERSION "v1.1.2"
#define PROG_VERSION "v1.1.3"

// Install - Default option
#define INSTALL_OPTION "--install"
// Uninstall
#define UNINSTALL_OPTION "--uninstall"
// Only download tools
#define DOWNLOADONLY_OPTION "--download-tools"
// Show help message
#define HELP_OPTION "--help"

Expand Down
78 changes: 78 additions & 0 deletions include/tar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#ifndef TAR_H
#define TAR_H

#include <string>
#include <vector>
#include <stdexcept>
#include <cmath>


enum tar_type_flag {
REGTYPE = '0', /* regular file */
AREGTYPE = '\0', /* regular file */
LNKTYPE = '1', /* link */
SYMTYPE = '2', /* reserved */
CHRTYPE = '3', /* character special */
BLKTYPE = '4', /* block special */
DIRTYPE = '5', /* directory */
FIFOTYPE = '6', /* FIFO special */
CONTTYPE = '7', /* reserved */
XHDTYPE = 'x', /* Extended header referring to the next file in the archive */
XGLTYPE = 'g' /* Global extended header */
};

struct tar_posix_header
{ /* byte offset */
char name[100]; /* 0 */
char mode[8]; /* 100 */
char uid[8]; /* 108 */
char gid[8]; /* 116 */
char size[12]; /* 124 */
char mtime[12]; /* 136 */
char chksum[8]; /* 148 */
char typeflag; /* 156 */
char linkname[100]; /* 157 */
char magic[6]; /* 257 */
char version[2]; /* 263 */
char uname[32]; /* 265 */
char gname[32]; /* 297 */
char devmajor[8]; /* 329 */
char devminor[8]; /* 337 */
char prefix[155]; /* 345 */
char pad[12]; /* 500 */
/* 512 */
};

class Tar
{
public:

struct File
{
std::string name;
int mode;
int ownerId;
int groupId;
int size;
int lastModified;
tar_type_flag typeflag;
std::string linkedName;
size_t position;
};

Tar(std::string filename);
~Tar();
void extract(const File& file, std::string to);
bool extract(std::string fileName, std::string to);
const std::vector<File>& getFileList() const;
private:
FILE* tarfile = NULL;
std::vector<File> fileList;

int oct_to_int(char* oct);
int oct_to_sz(char* oct);

static constexpr int EXTRACT_BUFFER_SZ = 1024 * 16;
};

#endif // TAR_H
34 changes: 34 additions & 0 deletions modules/FindLibZip.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
FIND_PATH(LIBZIP_INCLUDE_DIR
zip.h
"$ENV{LIB_DIR}/include"
"$ENV{INCLUDE}"
/usr/local/include
/usr/include
)

FIND_PATH(LIBZIP_CONF_INCLUDE_DIR
zipconf.h
"$ENV{LIB_DIR}/include"
"$ENV{LIB_DIR}/lib/libzip/include"
"$ENV{LIB}/lib/libzip/include"
/usr/local/lib/libzip/include
/usr/lib/libzip/include
/usr/local/include
/usr/include
"$ENV{INCLUDE}"
)

FIND_LIBRARY(LIBZIP_LIBRARY NAMES zip PATHS "$ENV{LIB_DIR}/lib" "$ENV{LIB}" /usr/local/lib /usr/lib )

INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibZip DEFAULT_MSG
LIBZIP_LIBRARY LIBZIP_INCLUDE_DIR LIBZIP_CONF_INCLUDE_DIR)

SET(LIBZIP_INCLUDE_DIRS ${LIBZIP_INCLUDE_DIR} ${LIBZIP_CONF_INCLUDE_DIR})
MARK_AS_ADVANCED(LIBZIP_LIBRARY LIBZIP_INCLUDE_DIR LIBZIP_CONF_INCLUDE_DIR LIBZIP_INCLUDE_DIRS)

IF (LIBZIP_FOUND)
MESSAGE(STATUS "Found libzip: ${LIBZIP_LIBRARY}")
ELSE (LIPZIP_FOUND)
MESSAGE(FATAL_ERROR "Could not find libzip")
ENDIF (LIBZIP_FOUND)
68 changes: 62 additions & 6 deletions src/archiveutils.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#include "archiveutils.h"
#include <errno.h>

/**
Helper function to extract a file using filesystem::path and std::string
*/
bool Archive::extract_s(fs::path from, std::string filename, fs::path to)
/*bool Archive::extract_s(fs::path from, std::string filename, fs::path to)
{
std::string from_s = from.string();
std::string to_s = to.string();
Expand Down Expand Up @@ -32,20 +33,20 @@ int Archive::copy_data(struct archive* ar, struct archive* aw)
return (r);
}
}
}
}*/

/**
Extract from archive "from", the file "filename" into path "to" (filename has to be included here too)
*/
bool Archive::extract(const char* from, const char* filename, const char* to)
/*bool Archive::extract(const char* from, const char* filename, const char* to)
{
struct archive* a;
struct archive* ext;
struct archive_entry* entry;
int flags;
int r;
/* Select which attributes we want to restore. */
// Select which attributes we want to restore.
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
Expand All @@ -57,7 +58,7 @@ bool Archive::extract(const char* from, const char* filename, const char* to)
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
if ((r = archive_read_open_filename(a, from, 10240)))
if ((r = archive_read_open_filename(a, from, 10240)) != ARCHIVE_OK)
return false;
for (;;) {
r = archive_read_next_header(a, &entry);
Expand All @@ -81,7 +82,7 @@ bool Archive::extract(const char* from, const char* filename, const char* to)
else if (archive_entry_size(entry) > 0) {
r = copy_data(a, ext);
if (r < ARCHIVE_OK)
logerr(archive_error_string(ext));
return false;
if (r < ARCHIVE_WARN)
return false;
}
Expand All @@ -99,4 +100,59 @@ bool Archive::extract(const char* from, const char* filename, const char* to)
archive_write_close(ext);
archive_write_free(ext);
return true;
}*/

bool Archive::extract_tar(fs::path from, std::string filename, fs::path to)
{
std::string from_s = from.string(), to_s = to.string();

try
{
Tar tarfile(from_s);
if (!tarfile.extract(filename, to_s)) {
fprintf(stderr, "Error while extracting %s. Not in the archive\n", filename.c_str());
return false;
}
return true;
}
catch (const std::exception& exc)
{
fprintf(stderr, "%s\n", exc.what());
return false;
}
}

bool Archive::extract_zip(fs::path from, std::string filename, fs::path to)
{
std::string from_s = from.string(), to_s = to.string();
const char* from_c = from_s.c_str(), * to_c = to_s.c_str();
int zerr = ZIP_ER_OK;
zip_t* in_archive = zip_open(from_c, ZIP_RDONLY, &zerr);

if (zerr != ZIP_ER_OK) {
fprintf(stderr, "Error while opening %s\n", from_c);
return false;
}

zip_file_t* target_file = zip_fopen(in_archive, filename.c_str(), 0);

if (target_file == NULL) {
fprintf(stderr, "Error while opening %s in %s. %s\n", filename.c_str(), from_c, zip_strerror(in_archive));
zip_close(in_archive);
return false;
}

FILE* out_f = fopen(to_c, "wb");

char buffer[AR_BUFFER_SIZE];
int sz = 0;
while ((sz = zip_fread(target_file, buffer, AR_BUFFER_SIZE)) > 0) {
fwrite(buffer, sizeof(char), sz, out_f);
}

fclose(out_f);

zip_fclose(target_file);
zip_close(in_archive);
return true;
}
Loading

0 comments on commit d94a628

Please sign in to comment.