Compare commits

...

15 Commits
0.0.1 ... main

Author SHA1 Message Date
7642a79c02 Added Makefile, fixed default install permissions including for executables, made metadata lines ignored when installing for now (they were just added recently and aren't properly handled yet) 2025-06-08 18:09:03 +10:00
99a5a7693e Added Makefile, fixed default install permissions including for executables, made metadata lines ignored when installing for now (they were just added recently and aren't properly handled yet) 2025-06-08 18:07:21 +10:00
5f4c96bb0a Update README.md 2025-06-08 06:54:41 +00:00
7bc5733dea Update README.md 2025-06-08 06:18:51 +00:00
7cd36a43c1 Add slabpkg.pkb 2025-06-08 06:16:35 +00:00
b562e0921e Update dist/README.md 2025-06-08 06:12:32 +00:00
019c24509f Add dist/README.md 2025-06-08 06:11:33 +00:00
a32f402bea Update README.md 2025-06-08 06:01:01 +00:00
e148e8fe18 Update README.md 2025-06-08 05:56:26 +00:00
bfe4ff3bce Update slabpkg.c 2025-06-08 05:52:59 +00:00
fad4cd8c44 Rename to slabpkg 2025-06-08 05:51:07 +00:00
0bf88712b3 Name change 2025-06-08 05:46:36 +00:00
df3313798e Update Formats.md 2025-06-08 05:36:36 +00:00
5874a9e92c Bumped version number, fixed instructions slightly 2025-06-08 05:24:18 +00:00
8b68f3a3ce Add Formats.md 2025-06-08 05:20:42 +00:00
7 changed files with 118 additions and 14 deletions

27
Formats.md Normal file
View File

@ -0,0 +1,27 @@
# Formats
The `slpkg` tool uses custom formats rather than zip/tar/gz and so on.
## Why New Formats?
The reasoning behind this is very simple: zip and tar are complex formats with different extensions & cross-platform concerns, whereas the package manager just needs to do the basic job of packaging & installing software files (NOT modifying archives one file at a time, NOT backwards compatibility with old archives etc.).
So it's much easier to implement formats for that purpose than using legacy zip or tar formats then having to add modern extensions as well as packaging metadata on top, but this also allows tight control over things like data integrity so hopefully the package manager also gives better feedback when things do break.
## .pkb files
These are human-edited text files listing package contents and other metadata needed to build a package file.
## .pkg files
These are binary files consisting of an archive header, a number of (file-like or metadata) entry headers, a string section and then a series of file contents.
Each part of a `.pkg` file is checksummed individually, allowing archivers years down the track to monitor any bitrot in old packages in a fine-grained way.
## .pkh files
These are the same format as their corresponding `.pkg` except only need to contain the headers & strings to index installed data.
## .cv1 files
These are compressed files in an early version compression format.

14
Makefile Normal file
View File

@ -0,0 +1,14 @@
all: slabpkg.pkg
dist/slabpkg: slabpkg.c
$(CC) -o $@ $^
slabpkg.pkg: slabpkg.pkb dist/slabpkg
dist/slabpkg build slabpkg.pkb
testroot/slabpkg: dist/slabpkg slabpkg.pkg testroot/README.md
dist/slabpkg --root ./testroot install slabpkg.pkg
test: dist/slabpkg testroot/slabpkg
dist/slabpkg sum $^
testroot/slabpkg sum $^

View File

@ -1,14 +1,22 @@
# slpkg
# slabpkg
SecureLang™ Package Manager
SecureLang™ Application Binary Package Manager
## Features
* build/install/remove software packages
* keeps a simple database of installed packages/files
* compress/decompress individual files
* custom formats (no zip/tar)
* simple & portable codebase
* Builds/installs/removes software packages
* Keeps a simple database of installed packages/files
* Compresses/decompresses individual files
* Uses custom formats (no zip/tar)
* Built-in integrity checking
* Very simple & portable codebase, plain C
## Limitations
* Doesn't handle advanced features or system integration yet, only "lowest common denominator" feature set
* No timestamps, minimal handling of permissions
* Not OS-aware, doesn't check system compatibility or have a way of organising packages for different targets yet
* Early version, so small changes to the format are to be expected
## TODO

5
dist/README.md vendored Normal file
View File

@ -0,0 +1,5 @@
# The dist Directory
This directory is used within a project source directory to collect files for packaging with `slabpkg`. This generally means the compiled program files and any other installable program data are placed in a `dist` directory.
This file isn't packaged but exists in the source distribution for the purposes of documentation and so that the `dist` subdirectory isn't deleted when there are no built files.

View File

@ -6,6 +6,9 @@
#ifndef PKG_MKDIR_SIMPLE
#define PKG_MKDIR_LINUX
#endif
#ifndef PKG_CHMOD_SIMPLE
#define PKG_CHMOD_LINUX
#endif
// For reliable integer sizing
#include <stdint.h>
@ -25,6 +28,15 @@ int mkdir(const char* dirname);
#error Either (-D) PKG_MKDIR_LINUX or PKG_MKDIR_SIMPLE must be defined
#endif
#endif
// For chmod
#ifdef PKG_CHMOD_LINUX
#include <sys/stat.h>
#else
#ifdef PKG_CHMOD_NONE
#else
#error Either (-D) PKG_CHMOD_LINUX or PKG_CHMOD_SIMPLE must be defined
#endif
#endif
// The compressed buffer needs to be a bit over twice size the regular
// buffer to account for worst case scenario.
@ -38,6 +50,7 @@ int mkdir(const char* dirname);
#define PKG_JOBTYPE_COMPRESS 5
#define PKG_JOBTYPE_DECOMPRESS 6
#define PKG_FLAGS_TYPEMASK 0xF00
#define PKG_FLAGS_DIRECTORY 0x100
#define PKG_FLAGS_EXECUTABLE 0x200
#define PKG_FLAGS_PROVIDES 0x300
@ -110,7 +123,7 @@ char pkg_comprbuffer[PKG_COMPRBUFSIZE];
int pkg_mkdir(const char* path) {
#ifdef PKG_MKDIR_LINUX
return mkdir(path, 0775);
return mkdir(path, 0755); // NOTE: Was previously using 0775, figured more secure by default is better?
#endif
#ifdef PKG_MKDIR_SIMPLE
return mkdir(path);
@ -121,6 +134,23 @@ int pkg_remove(const char* path, int isdir) {
return unlink(path);
}
int pkg_chmod_default(const char* path) {
#ifdef PKG_CHMOD_LINUX
return chmod(path, 0644);
#else
return 0;
#endif
}
int pkg_chmod_executable(const char* path) {
#ifdef PKG_CHMOD_LINUX
return chmod(path, 0755);
#else
fprintf(stderr, "NOTE: Ignoring executable bit for '%s'\n", path);
return 0;
#endif
}
int pkg_versionmeta_alldigits(pkg_versionmeta_t* m) {
const char* s = m->value;
while (*s) {
@ -516,6 +546,7 @@ int pkg_sum_init(pkg_sum_t* sum, char* filename, int dupfilename) {
if (sum == NULL) {
return -1;
}
sum->flags = 0;
sum->cmprsize = 0;
sum->extrsize = 0;
sum->checksum64 = 0x811C9DC5BADC0DE5ULL;
@ -846,10 +877,14 @@ int pkg_archive_extractcontents(pkg_archive_t* archive, FILE* input, const char*
while (filehdr != NULL) {
char* outputname = pkg_ezstrcat(installroot, filehdr->name); // Note, this assumes one or the other includes a path separator
if (filehdr->flags & PKG_FLAGS_DIRECTORY) {
int t = filehdr->flags & PKG_FLAGS_TYPEMASK;
if (t == PKG_FLAGS_DIRECTORY) {
fprintf(stderr, "Creating directory '%s'...\n", outputname);
int mkdirresult = pkg_mkdir(outputname);
fprintf(stderr, "mkdir of '%s' returned %d\n", outputname, mkdirresult);
} else if (t == PKG_FLAGS_PROVIDES || t == PKG_FLAGS_REQUIRES || t == PKG_FLAGS_SUGGESTS || t == PKG_FLAGS_CONFLICTS) {
fprintf(stderr, "Ignoring metadata line '%s'...\n", filehdr->name);
} else {
fprintf(stderr, "Creating file '%s'...\n", outputname);
FILE* f = fopen(outputname, "w");
@ -892,6 +927,12 @@ int pkg_archive_extractcontents(pkg_archive_t* archive, FILE* input, const char*
fprintf(stderr, "VERIFICATION ERROR: File data checksums for '%s' don't match. Recorded checksum 0x%X, calculated checksum 0x%X!\n", filehdr->name, filehdr->checksum32, datasum.checksum32);
return -1;
}
if (t == PKG_FLAGS_EXECUTABLE) {
pkg_chmod_executable(outputname);
} else {
pkg_chmod_default(outputname);
}
}
filehdr = filehdr->next;
@ -1054,7 +1095,7 @@ int pkg_job_build(pkg_job_t* job, char* name) {
outname[strlen(outname)-1] = 'g'; // "*.pkb"-> "*.pkg"
char* shortname = strndup(name + sepi, n - (sepi + 4)); // Trim directory path and filename extension
printf("TODO build '%s' source dirname '%s' dist dirname '%s' output name '%s' shortname '%s'...\n", name, srcd, distd, outname, shortname);
//printf("TODO build '%s' source dirname '%s' dist dirname '%s' output name '%s' shortname '%s'...\n", name, srcd, distd, outname, shortname);
FILE* buildf = fopen(name, "rb");
@ -1720,7 +1761,7 @@ int usage(int argc, char** argv, int argi, char* error) {
formatinfo(out);
fprintf(out, "DEMO INSTRUCTIONS:\n\n");
fprintf(out, " 1. compile pkg.c\n 2. place the executable in a subdirectory named `dist`\n 3. create a file `pkg.pkb` with a line `/pkg` (executable path within `dist`)\n 4. run `./dist/pkg build pkg.pkb`\n 5. work out how to install it (try --root ... install)\n\n");
fprintf(out, " 1. compile slabpkg.c\n 2. place the executable in a subdirectory named `dist`\n 3. create a file `slabpkg.pkb` with a line `/slabpkg` (executable path within `dist`)\n 4. run `./dist/slabpkg build slabpkg.pkb`\n 5. work out how to install it (try --root ... install)\n\n");
if (error) {
fprintf(out, "ERROR:\n %s\n", error);
@ -1733,7 +1774,7 @@ int usage(int argc, char** argv, int argi, char* error) {
int main(int argc, char** argv) {
pkg_job_t job;
int argi = 1;
printf("SecureLang Package Manager 0.0.1\nThis currently doesn't include proper versioning or dependencies.\n");
printf("SecureLang Application Binary Package Manager 0.0.2\nThis currently doesn't include proper versioning or dependencies.\n");
if (argc < 2) {
return usage(argc, argv, argi, "Expected command (build, install, ...)");
@ -1754,7 +1795,11 @@ int main(int argc, char** argv) {
if (argi >= argc) {
return usage(argc, argv, argi, "Expected a directory name following the --root option.");
}
job.installroot = strdup(argv[argi]);
if (strlen(argv[argi]) == 0 || (argv[argi][strlen(argv[argi])-1] != '/' && argv[argi][strlen(argv[argi])-1] != '\\')) {
job.installroot = pkg_ezstrcat(argv[argi], "/");
} else {
job.installroot = strdup(argv[argi]);
}
argi++;
} else if (!strcmp(argv[argi], "--dbroot")) {
argi++;
@ -1840,4 +1885,4 @@ int main(int argc, char** argv) {
} else {
return usage(argc, argv, argi, "Unrecognised command");
}
}
}

2
slabpkg.pkb Normal file
View File

@ -0,0 +1,2 @@
provides slabpkg 0.0.2
executable /slabpkg

3
testroot/README.md Normal file
View File

@ -0,0 +1,3 @@
# The testroot Directory
This directory only exists for testing `slabpkg` installing itself, and this file only exists so that the directory isn't deleted from the source directory.