initial commit

This commit is contained in:
2024-11-02 11:17:36 +00:00
commit f68ac974d8
14 changed files with 831 additions and 0 deletions

145
.gitignore vendored Normal file
View File

@@ -0,0 +1,145 @@
# Created by https://www.toptal.com/developers/gitignore/api/linux,vim,c,cmake,macos
# Edit at https://www.toptal.com/developers/gitignore?templates=linux,vim,c,cmake,macos
### C ###
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
### CMake ###
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
### CMake Patch ###
# External projects
*-prefix/
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### macOS Patch ###
# iCloud generated files
*.icloud
### Vim ###
# Swap
[._]*.s[a-v][a-z]
!*.svg # comment out if you don't need vector files
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Session
Session.vim
Sessionx.vim
# Temporary
.netrwhist
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~
# End of https://www.toptal.com/developers/gitignore/api/linux,vim,c,cmake,macos
build/

20
CMakeLists.txt Normal file
View File

@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.18)
project(ec3)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
find_package(Bluelib REQUIRED)
find_package(LibLZMA REQUIRED)
file(GLOB ec3_sources
src/*.c
src/*.h)
add_executable(ec3 ${ec3_sources})
target_link_libraries(ec3
Bluelib::Core
Bluelib::Object
Bluelib::Term
Bluelib::Cmd
LibLZMA::LibLZMA)

153
cmake/FindBluelib.cmake Normal file
View File

@@ -0,0 +1,153 @@
#[=======================================================================[.rst:
FindBluelib
------------
Find the Bluelib library and header directories
Imported Targets
^^^^^^^^^^^^^^^^
This module defines the following :prop_tgt:`IMPORTED` target:
``Bluelib::Bluelib``
The Bluelib library, if found
Result Variables
^^^^^^^^^^^^^^^^
This module will set the following variables in your project:
``Bluelib_FOUND``
true if the Bluelib C headers and libraries were found
``Bluelib_INCLUDE_DIR``
directories containing the Bluelib C headers.
``Bluelib_LIBRARY``
the C library to link against
Hints
^^^^^
The user may set the environment variable ``Bluelib_PREFIX`` to the root
directory of a Bluelib library installation.
#]=======================================================================]
set (Bluelib_SEARCH_PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr/local/share
/usr
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
${Bluelib_PREFIX}
$ENV{Bluelib_PREFIX})
if (Bluelib_STATIC)
set(_lib_suffix "-s")
endif ()
set(supported_components Core Object Term Cmd)
set(components ${Bluelib_FIND_COMPONENTS})
string(REPLACE ";" ", " supported_components_string_list "${supported_components}")
if (NOT components)
set(components ${supported_components})
endif ()
set(required_vars)
foreach (component ${components})
if (NOT "${component}" IN_LIST supported_components)
message(FATAL_ERROR "'${component}' is not a valid Bluelib module.\nSupported modules: ${supported_components_string_list}")
endif ()
string(TOLOWER ${component} header_name)
set(lib_name ${header_name}${_lib_suffix})
if (NOT Bluelib_${component}_INCLUDE_DIR)
find_path(Bluelib_${component}_INCLUDE_DIR
NAMES blue/${header_name}.h ${Bluelib_FIND_ARGS}
PATH_SUFFIXES include
PATHS ${Bluelib_SEARCH_PATHS})
endif ()
if (NOT Bluelib_${component}_LIBRARY)
find_library(Bluelib_${component}_LIBRARY
NAMES blue-${lib_name} ${Bluelib_FIND_ARGS}
PATH_SUFFIXES lib
PATHS ${Bluelib_SEARCH_PATHS})
else ()
# on Windows, ensure paths are in canonical format (forward slahes):
file(TO_CMAKE_PATH "${Bluelib_${component}_LIBRARY}" Bluelib_${component}_LIBRARY)
endif()
list(APPEND required_vars Bluelib_${component}_INCLUDE_DIR Bluelib_${component}_LIBRARY)
endforeach (component)
unset(Bluelib_FIND_ARGS)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Bluelib
REQUIRED_VARS ${required_vars})
if (Bluelib_FOUND)
set(created_targets)
foreach (component ${components})
string(TOLOWER ${component} header_name)
set(lib_name ${header_name}${_lib_suffix})
if(NOT TARGET Bluelib::${component})
add_library(Bluelib::${component} UNKNOWN IMPORTED)
set_target_properties(Bluelib::${component} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Bluelib_${component}_INCLUDE_DIR}")
target_compile_definitions(Bluelib::${component} INTERFACE _CRT_SECURE_NO_WARNINGS=1)
set_target_properties(Bluelib::${component} PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${Bluelib_${component}_LIBRARY}")
set(created_targets ${created_targets} ${component})
endif ()
endforeach (component)
foreach (component ${created_targets})
if ("${component}" STREQUAL "Object")
if (NOT TARGET Bluelib::Core)
message(FATAL_ERROR "Bluelib: Module 'Object' depends on 'Core', which was not specified in find_package()")
endif ()
target_link_libraries(Bluelib::Object INTERFACE Bluelib::Core)
endif ()
if ("${component}" STREQUAL "Term")
if (NOT TARGET Bluelib::Core)
message(FATAL_ERROR "Bluelib: Module 'Term' depends on 'Core', which was not specified in find_package()")
endif ()
if (NOT TARGET Bluelib::Object)
message(FATAL_ERROR "Bluelib: Module 'Term' depends on 'Object', which was not specified in find_package()")
endif ()
target_link_libraries(Bluelib::Term INTERFACE Bluelib::Core Bluelib::Object)
endif ()
if ("${component}" STREQUAL "Cmd")
if (NOT TARGET Bluelib::Core)
message(FATAL_ERROR "Bluelib: Module 'Cmd' depends on 'Core', which was not specified in find_package()")
endif ()
if (NOT TARGET Bluelib::Object)
message(FATAL_ERROR "Bluelib: Module 'Cmd' depends on 'Object', which was not specified in find_package()")
endif ()
if (NOT TARGET Bluelib::Term)
message(FATAL_ERROR "Bluelib: Module 'Cmd' depends on 'Term', which was not specified in find_package()")
endif ()
target_link_libraries(Bluelib::Cmd INTERFACE Bluelib::Core Bluelib::Object Bluelib::Term)
endif ()
endforeach (component)
endif()

115
src/capture.c Normal file
View File

@@ -0,0 +1,115 @@
#include "commands.h"
#include <blue/cmd.h>
#define BUFFER_SIZE 65536
enum {
OPT_OUTPATH,
OPT_OUTPATH_PATH,
ARG_DIRECTORY,
OPT_TAGGED_DIRECTORY,
OPT_TAGGED_DIRECTORY_TAG,
OPT_TAGGED_DIRECTORY_PATH,
OPT_VERBOSE,
};
static int capture(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_CAPTURE, CMD_ROOT)
{
B_COMMAND_NAME("capture");
B_COMMAND_SHORT_NAME('Z');
B_COMMAND_DESC(
"capture one or more directories into an ec3 container. each "
"directory specified will be stored in a separate volume "
"within "
"the created container.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(capture);
B_COMMAND_HELP_OPTION();
B_COMMAND_OPTION(OPT_OUTPATH)
{
B_OPTION_SHORT_NAME('o');
B_OPTION_LONG_NAME("out");
B_OPTION_DESC("the path to save the new file to.");
B_OPTION_ARG(OPT_OUTPATH_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_ARG(ARG_DIRECTORY)
{
B_ARG_NAME("directory");
B_ARG_DESC(
"a directory to add to the container. a volume "
"will be created "
"within the container to store the specified "
"directory.");
B_ARG_NR_VALUES(B_ARG_1_OR_MORE_VALUES);
}
B_COMMAND_OPTION(OPT_TAGGED_DIRECTORY)
{
B_OPTION_SHORT_NAME('D');
B_OPTION_LONG_NAME("tagged-directory");
B_OPTION_DESC(
"a file to add to the container, with an associated "
"tag. a disk "
"image will be created within the container to store "
"the specified "
"directory. the tag must be either: (a) a 64-bit "
"hexadecimal "
"number; or (b) a string of no more than 8 "
"characters.");
B_OPTION_ARG(OPT_TAGGED_DIRECTORY_TAG)
{
B_ARG_NAME("tag");
B_ARG_NR_VALUES(1);
}
B_OPTION_ARG(OPT_TAGGED_DIRECTORY_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_OPTION(OPT_VERBOSE)
{
B_OPTION_SHORT_NAME('v');
B_OPTION_LONG_NAME("verbose");
B_OPTION_DESC(
"show detailed output logs. this option can be "
"specified multiple "
"times to increase the level of output.");
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_OPT(OPT_OUTPATH);
B_COMMAND_USAGE_ARG(ARG_DIRECTORY);
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_OPT(OPT_OUTPATH);
B_COMMAND_USAGE_OPT(OPT_TAGGED_DIRECTORY);
}
}

33
src/check-sig.c Normal file
View File

@@ -0,0 +1,33 @@
#include "commands.h"
#include <blue/cmd.h>
enum {
ARG_FILE,
};
static int check_sig(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_CHECK_SIG, CMD_ROOT)
{
B_COMMAND_NAME("check-sig");
B_COMMAND_SHORT_NAME('Y');
B_COMMAND_DESC("validate the digital signature of an ec3 file");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(check_sig);
B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_FILE)
{
B_ARG_NAME("file");
B_ARG_NR_VALUES(B_ARG_1_OR_MORE_VALUES);
B_ARG_DESC("the file(s) to validate");
}
}

17
src/commands.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef COMMANDS_H_
#define COMMANDS_H_
enum command_id {
CMD_ROOT = 0,
CMD_CREATE,
CMD_WRAP,
CMD_CAPTURE,
CMD_SHELL,
CMD_EXTRACT,
CMD_GET_MANIFEST,
CMD_CHECK_SIG,
CMD_EXPLORE,
CMD_QUERY,
};
#endif

40
src/create.c Normal file
View File

@@ -0,0 +1,40 @@
#include "commands.h"
#include <blue/cmd.h>
enum {
OPT_OUTPATH,
OPT_OUTPATH_PATH,
};
static int create(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_CREATE, CMD_ROOT)
{
B_COMMAND_NAME("create");
B_COMMAND_SHORT_NAME('C');
B_COMMAND_DESC("create an ec3 file");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(create);
B_COMMAND_HELP_OPTION();
B_COMMAND_OPTION(OPT_OUTPATH)
{
B_OPTION_SHORT_NAME('o');
B_OPTION_LONG_NAME("out");
B_OPTION_DESC("the path to save the new file to");
B_OPTION_ARG(OPT_OUTPATH_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
}

34
src/explore.c Normal file
View File

@@ -0,0 +1,34 @@
#include "commands.h"
#include <blue/cmd.h>
enum {
ARG_FILE,
};
static int explore(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_EXPLORE, CMD_ROOT)
{
B_COMMAND_NAME("explore");
B_COMMAND_SHORT_NAME('E');
B_COMMAND_DESC(
"start a basic shell to browse the contents of an ec3 file");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(explore);
B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_FILE)
{
B_ARG_NAME("file");
B_ARG_NR_VALUES(1);
B_ARG_DESC("the file to explore");
}
}

33
src/extract.c Normal file
View File

@@ -0,0 +1,33 @@
#include "commands.h"
#include <blue/cmd.h>
enum {
ARG_FILE,
};
static int extract(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_EXTRACT, CMD_ROOT)
{
B_COMMAND_NAME("extract");
B_COMMAND_SHORT_NAME('X');
B_COMMAND_DESC("extract the contents of an ec3 file");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(extract);
B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_FILE)
{
B_ARG_NAME("file");
B_ARG_NR_VALUES(B_ARG_1_OR_MORE_VALUES);
B_ARG_DESC("the file to extract");
}
}

33
src/get-manifest.c Normal file
View File

@@ -0,0 +1,33 @@
#include "commands.h"
#include <blue/cmd.h>
enum {
ARG_FILE,
};
static int get_manifest(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_GET_MANIFEST, CMD_ROOT)
{
B_COMMAND_NAME("get-manifest");
B_COMMAND_SHORT_NAME('M');
B_COMMAND_DESC("retrieve and print the manifest of an ec3 file");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(get_manifest);
B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_FILE)
{
B_ARG_NAME("file");
B_ARG_NR_VALUES(1);
B_ARG_DESC("the file to query");
}
}

19
src/main.c Normal file
View File

@@ -0,0 +1,19 @@
#include "commands.h"
#include <blue/cmd.h>
#include <blue/term.h>
B_COMMAND(CMD_ROOT, B_COMMAND_INVALID_ID)
{
B_COMMAND_NAME("ec3");
B_COMMAND_DESC(
"Elastic, Compressed, Content-Addressed Container image "
"manipulation tool");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_HELP_OPTION();
}
int main(int argc, const char **argv)
{
return b_command_dispatch(CMD_ROOT, argc, argv);
}

39
src/query.c Normal file
View File

@@ -0,0 +1,39 @@
#include "commands.h"
#include <blue/cmd.h>
enum {
ARG_CONTAINER,
OPT_VERBOSE,
};
static int query(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_QUERY, CMD_ROOT)
{
B_COMMAND_NAME("query");
B_COMMAND_SHORT_NAME('Q');
B_COMMAND_DESC("query information about a container.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(query);
B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_CONTAINER)
{
B_ARG_NAME("container");
B_ARG_DESC("the container to query.");
B_ARG_NR_VALUES(1);
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_ARG(ARG_CONTAINER);
}
}

54
src/shell.c Normal file
View File

@@ -0,0 +1,54 @@
#include "commands.h"
#include <blue/cmd.h>
enum {
ARG_CONTAINER,
OPT_VERBOSE,
};
static int shell(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_SHELL, CMD_ROOT)
{
B_COMMAND_NAME("shell");
B_COMMAND_SHORT_NAME('S');
B_COMMAND_DESC(
"start a basic shell to explore the volumes within a "
"container.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(shell);
B_COMMAND_HELP_OPTION();
B_COMMAND_OPTION(OPT_VERBOSE)
{
B_OPTION_SHORT_NAME('v');
B_OPTION_LONG_NAME("verbose");
B_OPTION_DESC(
"show detailed output logs. this option can be "
"specified multiple "
"times to increase the level of output.");
}
B_COMMAND_ARG(ARG_CONTAINER)
{
B_ARG_NAME("container");
B_ARG_DESC(
"the container to explore. the container must contain "
"at least one "
"volume.");
B_ARG_NR_VALUES(1);
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_ARG(ARG_CONTAINER);
}
}

96
src/wrap.c Normal file
View File

@@ -0,0 +1,96 @@
#include "commands.h"
#include <blue/cmd.h>
#include <stdlib.h>
enum {
OPT_OUTPATH,
OPT_OUTPATH_PATH,
ARG_FILE,
ARG_FILE_PATH,
OPT_TAGGED_FILE,
OPT_TAGGED_FILE_TAG,
OPT_TAGGED_FILE_PATH,
};
static int wrap(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_WRAP, CMD_ROOT)
{
B_COMMAND_NAME("wrap");
B_COMMAND_SHORT_NAME('W');
B_COMMAND_DESC(
"wrap one or more files into an ec3 container. each file will "
"be "
"stored in a separate blob tag within the created container.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(wrap);
B_COMMAND_HELP_OPTION();
B_COMMAND_OPTION(OPT_OUTPATH)
{
B_OPTION_SHORT_NAME('o');
B_OPTION_LONG_NAME("out");
B_OPTION_DESC("the path to save the new file to");
B_OPTION_ARG(OPT_OUTPATH_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_ARG(ARG_FILE)
{
B_ARG_NAME("file");
B_ARG_DESC("a file to add to the container");
B_ARG_NR_VALUES(B_ARG_1_OR_MORE_VALUES);
}
B_COMMAND_OPTION(OPT_TAGGED_FILE)
{
B_OPTION_SHORT_NAME('I');
B_OPTION_LONG_NAME("tagged-file");
B_OPTION_DESC(
"a file to add to the container, with an associated "
"tag. "
"the tag must be either: (a) a 64-bit hexadecimal "
"number; "
"or (b) a string of no more than 8 characters.");
B_OPTION_ARG(OPT_TAGGED_FILE_TAG)
{
B_ARG_NAME("tag");
B_ARG_DESC("the tag!");
B_ARG_NR_VALUES(1);
}
B_OPTION_ARG(OPT_TAGGED_FILE_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_OPT(OPT_OUTPATH);
B_COMMAND_USAGE_ARG(ARG_FILE);
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_OPT(OPT_OUTPATH);
B_COMMAND_USAGE_OPT(OPT_TAGGED_FILE);
}
}