Skip to content

Commit

Permalink
Updated installer maker
Browse files Browse the repository at this point in the history
Fixed issue #3.
Further Safetied the installer-maker.
Added options to run the installer maker with command-line options, falling back on defaults that allows it to source from the directory it is running in.
Removed responsibility of archiver writing and updating the installer file - its only goal should be to retrieve, merge, and prepare a buffer for all files to-be-archived (and the reverse), but nothing related to the installer files.
  • Loading branch information
Yattabyte committed Mar 14, 2019
1 parent 9bf5e44 commit ee55225
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 53 deletions.
30 changes: 7 additions & 23 deletions src/Archiver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <vector>


bool Archiver::Pack(const std::string & directory, size_t & fileCount, size_t & byteCount)
bool Archiver::Pack(const std::string & directory, size_t & fileCount, size_t & byteCount, char ** archBuffer)
{
// Variables
fileCount = 0ull;
Expand Down Expand Up @@ -48,6 +48,7 @@ bool Archiver::Pack(const std::string & directory, size_t & fileCount, size_t &
archiveSize += unitSize;
files.push_back({ entry.path().string(), path, entry.file_size(), unitSize, entry.last_write_time() });
}
fileCount = files.size();

// Create buffer for final file data
char * filebuffer = new char[archiveSize];
Expand Down Expand Up @@ -91,30 +92,10 @@ bool Archiver::Pack(const std::string & directory, size_t & fileCount, size_t &
threader.shutdown();

// Compress the archive
char * compressedBuffer(nullptr);
size_t compressedSize(0ull);
bool returnResult = false;
if (BFT::CompressBuffer(filebuffer, archiveSize, &compressedBuffer, compressedSize)) {
// Update variables
fileCount = files.size();
byteCount = compressedSize;

// Write installer to disk
Resource installer(IDR_INSTALLER, "INSTALLER");
std::ofstream file(directory + "\\installer.exe", std::ios::binary | std::ios::out);
if (file.is_open())
file.write(reinterpret_cast<char*>(installer.getPtr()), (std::streamsize)installer.getSize());
file.close();

// Update installer's resource
auto handle = BeginUpdateResource("installer.exe", true);
returnResult = (bool)UpdateResource(handle, "ARCHIVE", MAKEINTRESOURCE(IDR_ARCHIVE), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), compressedBuffer, (DWORD)byteCount);
EndUpdateResource(handle, FALSE);
}

bool returnResult = BFT::CompressBuffer(filebuffer, archiveSize, archBuffer, byteCount);

// Clean up
delete[] filebuffer;
delete[] compressedBuffer;
return returnResult;
}

Expand All @@ -125,6 +106,9 @@ bool Archiver::Unpack(const std::string & directory, size_t & fileCount, size_t
byteCount = 0ull;
Threader threader;
Resource archive(IDR_ARCHIVE, "ARCHIVE");
if (!archive.exists())
return false;

char * decompressedBuffer(nullptr);
size_t decompressedSize(0ull);
const bool result = BFT::DecompressBuffer(reinterpret_cast<char*>(archive.getPtr()), archive.getSize(), &decompressedBuffer, decompressedSize);
Expand Down
3 changes: 2 additions & 1 deletion src/Archiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ class Archiver {
@param directory the directory to compress / create an installer in.
@param fileCount reference updated with the number of files packaged.
@param byteCount reference updated with the number of bytes packaged.
@param archBuffer pointer to the archive buffer.
@return true if packing success, false otherwise. */
static bool Pack(const std::string & directory, size_t & fileCount, size_t & byteCount);
static bool Pack(const std::string & directory, size_t & fileCount, size_t & byteCount, char ** archBuffer);
/** Unpacks the installer's contents into a directory.
@param directory the directory to decompress into.
@param fileCount reference updated with the number of files unpackaged.
Expand Down
9 changes: 9 additions & 0 deletions src/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ inline static void * PTR_ADD(void *const ptr, const size_t & offset)
return static_cast<std::byte*>(ptr) + offset;
};

/** Cleans up a target string representing a file path, removing leading and trailing quotes*/
inline static void sanitize_path(std::string & path)
{
if (path.front() == '"' || path.front() == '\'')
path.erase(0ull, 1ull);
if (path.back() == '"' || path.back() == '\'')
path.erase(path.size() - 1ull);
}

/** Return file-info for all files within the directory specified.
@param directory the directory to retrieve file-info from.
@return a vector of file information, including file names, sizes, meta-data, etc. */
Expand Down
115 changes: 94 additions & 21 deletions src/InstallerMaker/installerMaker.cpp
Original file line number Diff line number Diff line change
@@ -1,37 +1,110 @@
#include "Archiver.h"
#include "Common.h"
#include "Resource.h"
#include <chrono>
#include <fstream>
#include <iostream>


/** Specify a message to print to the terminal before closing the program.
@param message the message to write-out.*/
inline static void exit_program(const char * message)
{
std::cout << message;
system("pause");
exit(EXIT_FAILURE);
}

/** Displays help information about this program, then terminates it. */
inline static void display_help_and_exit()
{
exit_program(
"Usage:\n\n"
" * if run without any arguments : uses application directory\n"
" * use command -ovrd to skip user-ready prompt.\n"
" * use command -src=[path] to specify the directory to package into an installer.\n"
" * use command -dst=[path] to specify the directory to write the installer.\n"
);
}

/** Entry point. */
int main()
int main(int argc, char *argv[])
{
const auto directory = get_current_directory();

// Check if user is ready to compress
std::cout << "Compress the current directory: \"" + directory + "\"\nInput (Y/N): ";
char input('N');
std::cin >> input;
input = (char)toupper((int)input);
if (input == 'Y') {
// Package to an output file
const auto start = std::chrono::system_clock::now();
std::cout << "...working..." << std::endl;
size_t fileCount(0ull), byteCount(0ull);
if (Archiver::Pack(directory, fileCount, byteCount)) {
// Check command line arguments
bool skipPrompt = false;
std::string srcDirectory(""), dstDirectory("");
for (int x = 1; x < argc; ++x) {
std::string command(argv[x], 5);
std::transform(command.begin(), command.end(), command.begin(), ::tolower);
if (command == "-ovrd")
skipPrompt = true;
else if (command == "-src=")
srcDirectory = std::string(&argv[x][5]);
else if (command == "-dst=")
dstDirectory = std::string(&argv[x][5]);
else
display_help_and_exit();
}

// If no (usable) arguments, use current running directory
if (srcDirectory == "" || argc == 1)
srcDirectory = get_current_directory();
sanitize_path(srcDirectory);

// Allow null destination directory, will just make it the source directory
if (dstDirectory == "")
dstDirectory = srcDirectory;
dstDirectory += "\\installer.exe";
sanitize_path(dstDirectory);

// Report an overview of supplied procedure
std::cout
<< "Packaging:\t\"" << srcDirectory << "\"\n"
<< "Into:\t\t\"" << dstDirectory << "\"\n\n";

// See if we should skip the user-ready prompt
if (!skipPrompt) {
std::cout << "Ready?\n";
system("pause");
std::cout << std::endl;
}

// Package to an output file
const auto start = std::chrono::system_clock::now();
size_t fileCount(0ull), byteCount(0ull);
char * archiveBuffer(nullptr);
if (!Archiver::Pack(srcDirectory, fileCount, byteCount, &archiveBuffer))
exit_program("Packaging failed, aborting...");
else {
// Write installer to disk
Resource installer(IDR_INSTALLER, "INSTALLER");
if (!installer.exists())
exit_program("Cannot access installer resource, aborting...");
else {
std::ofstream file(dstDirectory, std::ios::binary | std::ios::out);
if (!file.is_open())
exit_program("Cannot write installer to disk, aborting...");
file.write(reinterpret_cast<char*>(installer.getPtr()), (std::streamsize)installer.getSize());
file.close();

// Update installer's resource
auto handle = BeginUpdateResource(dstDirectory.c_str(), true);
if (!(bool)UpdateResource(handle, "ARCHIVE", MAKEINTRESOURCE(IDR_ARCHIVE), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), archiveBuffer, (DWORD)byteCount))
exit_program("Cannot write archive contents to the installer, aborting...");
EndUpdateResource(handle, FALSE);
delete[] archiveBuffer;

// Success, report results
const auto end = std::chrono::system_clock::now();
const std::chrono::duration<double> elapsed_seconds = end - start;
std::cout
<< "Compression into \"" << directory << "\" complete.\n"
<< "Files packaged: " << fileCount << "\n"
<< "Bytes packaged: " << byteCount << "\n"
<< "Elapsed time: " << elapsed_seconds.count() << " seconds\n";
}
}
<< "Total duration: " << elapsed_seconds.count() << " seconds\n\n";

// Exit
system("pause");
exit(1);
// Exit
system("pause");
exit(EXIT_SUCCESS);
}
}
}
4 changes: 1 addition & 3 deletions src/PatchMaker/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ add_executable(${Module} ${ROOT}
${CORE_DIR}/Instructions.h
${CORE_DIR}/Instructions.cpp
${CORE_DIR}/BufferTools.h
${CORE_DIR}/BufferTools.cpp
${CORE_DIR}/Archiver.h
${CORE_DIR}/Archiver.cpp )
${CORE_DIR}/BufferTools.cpp )
# Set working directory to the project directory
set_target_properties(${Module} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}
LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}
Expand Down
1 change: 0 additions & 1 deletion src/PatchMaker/patchMaker.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#include "Archiver.h"
#include "BufferTools.h"
#include "Common.h"
#include <chrono>
Expand Down
4 changes: 1 addition & 3 deletions src/Patcher/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ add_executable(${Module} ${ROOT}
${CORE_DIR}/Instructions.h
${CORE_DIR}/Instructions.cpp
${CORE_DIR}/BufferTools.h
${CORE_DIR}/BufferTools.cpp
${CORE_DIR}/Archiver.h
${CORE_DIR}/Archiver.cpp )
${CORE_DIR}/BufferTools.cpp)
# Set working directory to the project directory
set_target_properties(${Module} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}
LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}
Expand Down
1 change: 0 additions & 1 deletion src/Patcher/patcher.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#include "Archiver.h"
#include "BufferTools.h"
#include "Common.h"
#include <chrono>
Expand Down
5 changes: 5 additions & 0 deletions src/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ class Resource {
inline size_t getSize() const {
return m_size;
}
/** Check if this resource has successfully completed initialization and has at least 1 byte of data.
@return true if this resource exists, false otherwise. */
inline bool exists() const {
return (m_hResource && m_hMemory && m_ptr) && (m_size > 0ull);
}


private:
Expand Down

0 comments on commit ee55225

Please sign in to comment.