aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore13
-rw-r--r--LICENSE20
-rw-r--r--Makefile43
-rw-r--r--README56
-rw-r--r--bie.1.in70
-rw-r--r--bie.c134
6 files changed, 336 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54eb42b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+*.o
+bie
+
+*.d
+
+tags
+TAGS
+
+config.mk
+
+eprintf.h
+eprintf.c
+bie.1
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1a71eb5
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright 2018 Tomasz Kramkowski <tk@the-tk.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..982352c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,43 @@
+# Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>
+# SPDX-License-Identifier: MIT
+-include config.mk
+
+PROG := bie
+MANPAGE := $(PROG).1
+VERSION != git describe --tags 2>/dev/null || echo "v0.1"
+
+EPRINTF_PATH ?= ../eprintf
+PKG_CONFIG ?= pkg-config
+LN ?= ln -sf
+
+CPPFLAGS += -DVERSION=\"$(VERSION)\"
+CFLAGS += -std=c11 -MMD -MP
+
+OBJ := bie.o eprintf.o
+DEP := $(OBJ:.o=.d)
+
+prefix ?= /usr/local
+exec_prefix ?= $(prefix)
+bindir = $(exec_prefix)/bin
+datarootdir = $(prefix)/share
+mandir = $(datarootdir)/man
+man1dir = $(mandir)/man1
+
+all: $(PROG) $(MANPAGE)
+$(PROG): $(OBJ)
+bie.o: eprintf.h
+$(MANPAGE): $(MANPAGE).in
+ m4 -DVERSION=$(VERSION) $^ >$@
+
+install: $(PROG) $(MANPAGE)
+ install -Dm755 -s $(PROG) -t $(DESTDIR)$(bindir)
+ install -Dm644 $(MANPAGE) -t $(DESTDIR)$(man1dir)
+
+clean:
+ $(RM) $(OBJ) $(DEP) $(PROG) $(MANPAGE)
+
+include $(EPRINTF_PATH)/module.mk
+
+-include $(DEP)
+
+.PHONY: all install clean
diff --git a/README b/README
new file mode 100644
index 0000000..9135648
--- /dev/null
+++ b/README
@@ -0,0 +1,56 @@
+ _ _
+ | | (_)
+ | |__ _ ___
+ | '_ \| |/ _ \
+ | |_) | | __/
+ |_.__/|_|\___|
+
+---------------------------------------------------------------------
+
+bie is a tool for generating a simple indexed flat archive.
+
+Example:
+========
+
+$ echo "foo" >a
+$ dd if=/dev/urandom of=b bs=30 count=1
+$ zlib-flate -compress <bie.c >c
+$ bie archive.bie archive.idx a b c
+$ hexdump -C archive.bie
+00000000 66 6f 6f 0a 00 00 00 00 00 00 00 00 00 00 00 00 |foo.............|
+00000010 1b c9 01 82 4f df 1a ec 01 2a dc 0e 3e f1 e7 52 |....O....*..>..R|
+00000020 ed e3 99 3e 70 b0 eb 6f f8 20 49 ba b9 8d 00 00 |...>p..o. I.....|
+00000030 78 9c 95 54 6d 6f d3 30 10 fe 9c fc 8a a3 a8 6b |x..Tmo.0.......k|
+00000040 d2 76 5d 37 10 42 7d 19 2f a5 43 15 65 a0 ad 93 |.v]7.B}./.C.e...|
+00000050 40 6c 1a 21 71 5a ab 89 1d c5 4e c7 c6 fa df b9 |@l.!qZ....N.....|
+... SNIP ...
+$ cat archive.idx
+BIE_ENTRY(a, 0, 4)
+BIE_ENTRY(b, 16, 30)
+BIE_ENTRY(c, 48, 750)
+
+Use:
+====
+
+Create an archive and index from a list of files you wish to access
+from your program.
+
+Use the CPP or another macro processor to expand BIE_ENTRY to some
+code which stores this information in your program.
+
+Read the archive into memory (or link it in) and use the offset and
+size data from the index to read from the archive.
+
+Dependencies:
+=============
+
+eprintf - https://the-tk.com/cgit/eprintf/
+Place in a directory adjacent to the location of the bie sources or
+override EPRINTF_PATH in config.mk
+
+Compilation and Installation:
+=============================
+
+$ echo prefix=/usr >config.mk
+$ make
+# make install
diff --git a/bie.1.in b/bie.1.in
new file mode 100644
index 0000000..3dc9eef
--- /dev/null
+++ b/bie.1.in
@@ -0,0 +1,70 @@
+.\" Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>
+.\" SPDX-License-Identifier: MIT
+.TH "BIE" "1" "2018-03-27" "bie VERSION" "bie Manual"
+
+.SH "NAME"
+bie \- a tool for generating an indexed flat archive
+
+.SH "SYNOPSIS"
+.B bie
+.RB [ -hv ]
+.RB [ -- ]
+.I output index input...
+
+.SH "DESCRIPTION"
+.I output
+is the destination of the flat archive.
+.I index
+is the destination of the index file.
+.I input
+is the list of files to archive.
+.P
+The output is a concatenation of the contents of all the input files
+with each file aligned to as 16 byte boundary. The format of the index
+file is a list of macro calls to BIE_ENTRY with the parameters being
+the name, the offset and the size of each input file.
+.P
+An appropriate definition of BIE_ENTRY should be provided to make use
+of this information.
+.P
+The name of each input file will be slugified to remove any characters
+which are not valid inside a C identifier (leading digits are
+removed). The slugification process leaves alphanumeric characters
+alone, replaces punctuation and spaces with underscores and removes
+any other characters. Any resulting leading underscores are dropped.
+.P
+.B bie
+does not attempt to fix name collisions.
+
+.SH "OPTIONS"
+.B -h
+.RS
+Show help.
+.RE
+
+.B -v
+.RS
+Show version and license information.
+.RE
+
+.SH "EXAMPLES"
+bie assets.bie assets.idx a b c
+.RS
+This will instruct
+.B bie
+to read the contents of the files named a, b and c and to generate an
+assets.bie which is a concatenation of the aligned file contents of a,
+b and c and to generate an assets.idx which might look like this:
+
+.nf
+BIE_ENTRY(a, 0, 10)
+BIE_ENTRY(b, 16, 30)
+BIE_ENTRY(c, 48, 100)
+.fi
+.RE
+
+.SH "SEE ALSO"
+.BR ld (1),
+.BR zlib-flate (1)
+.SH AUTHOR
+Tomasz Kramkowski <tk@the-tk.com>
diff --git a/bie.c b/bie.c
new file mode 100644
index 0000000..66c97c9
--- /dev/null
+++ b/bie.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>
+ * SPDX-License-Identifier: MIT
+ */
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "eprintf.h"
+
+#ifndef VERSION
+#define VERSION "v0.1"
+#endif
+
+enum {
+ ALIGN = 16,
+};
+
+static const char *usage = "[-hv] [--] output map input...";
+
+static void help(void)
+{
+ fprintf(stderr,
+ "Options:\n"
+ " -h Show this help.\n"
+ " -v Show version and license information.\n"
+ "\n"
+ "Please check the bie(1) man page for more information.\n");
+}
+
+static void version(void)
+{
+ fprintf(stderr,
+ "bie %s\n"
+ "Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>\n"
+ "Licensed under the MIT license <https://opensource.org/licenses/MIT>\n"
+ "There is NO WARRANTY, to the extent permitted by law.\n",
+ VERSION);
+}
+
+static void slug(FILE *f, const char *text)
+{
+ bool leading = true;
+ int c;
+
+ while (c = *text++, c != '\0') {
+ if (isalpha(c)) {
+ leading = false;
+ fputc(c, f);
+ continue;
+ }
+ if (leading) continue;
+ if (isdigit(c))
+ fputc(c, f);
+ else if (ispunct(c) || isspace(c))
+ fputc('_', f);
+ }
+}
+
+static void mapentry(FILE *map, const char *name, size_t pos, size_t size)
+{
+ fprintf(map, "BIE_ENTRY(");
+ slug(map, name);
+ fprintf(map, ", %zu, %zu)\n", pos, size);
+}
+
+static size_t dumpfile(FILE *dest, FILE *src)
+{
+ size_t size = 0;
+ int c;
+
+ while (c = fgetc(src), c != EOF) {
+ size++;
+ fputc(c, dest);
+ }
+
+ return size;
+}
+
+int main(int argc, char **argv)
+{
+ const char *argv0 = argv[0] != NULL ? argv[0] : "bie";
+ FILE *dest, *map;
+ size_t pos = 0;
+
+ setprogname(argv0);
+
+ for (argv++, argc--; argv[0] != NULL && argv[0][0] == '-' &&
+ argv[0][1] != '-' && argv[0][2] == '\0'; argv++, argc--) {
+ switch (argv[0][1]) {
+ case 'h':
+ fprintf(stderr, "Usage: %s %s\n", argv0, usage);
+ help();
+ return EXIT_SUCCESS;
+ case 'v':
+ version();
+ return EXIT_SUCCESS;
+ }
+ }
+
+ if (argc < 3)
+ eprintf("Invalid argument count\nUsage: %s %s", argv0, usage);
+
+ dest = fopen(argv[0], "wb");
+ if (dest == NULL)
+ eprintf("Could not open `%s':", argv[0]);
+
+ map = fopen(argv[1], "w");
+ if (map == NULL)
+ eprintf("Could not open `%s':", argv[1]);
+
+ for (int i = 2; i < argc; i++) {
+ size_t size;
+ FILE *src;
+
+ src = fopen(argv[i], "rb");
+ if (src == NULL)
+ eprintf("Could not open `%s':", argv[i]);
+ size = dumpfile(dest, src);
+ fclose(src);
+ mapentry(map, argv[i], pos, size);
+ pos += size;
+ if (pos % ALIGN) {
+ size_t pad = ALIGN - pos % ALIGN;
+ for (size_t i = 0; i < pad; i++)
+ fputc(0, dest);
+ pos += pad;
+ }
+ }
+
+ fclose(map);
+ fclose(dest);
+}