aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile.in26
-rwxr-xr-xbootstrap22
-rw-r--r--builddeps/limine.conf2
-rw-r--r--configure.ac11
-rw-r--r--lib/libc/Makefile3
-rw-r--r--lib/libc/src/arch/amd64/crti.S (renamed from lib/libc/src/arch/amd64/crt0.S)4
-rw-r--r--share/man/man1/omar.155
-rw-r--r--sys/fs/initramfs.c108
-rw-r--r--tools/omar/Makefile12
-rw-r--r--tools/omar/README9
-rw-r--r--tools/omar/omar.c447
-rw-r--r--usr.bin/osh/Makefile4
-rw-r--r--usr.sbin/init/Makefile2
14 files changed, 629 insertions, 77 deletions
diff --git a/.gitignore b/.gitignore
index 001bc03..c93d8a9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,5 +12,6 @@
/base
/sys/include/machine
/lib/libc/include/machine/
+/tools/omar/bin/
/share/misc/hwdoc
autom4te.cache
diff --git a/Makefile.in b/Makefile.in
index 35595b1..457173e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -4,16 +4,22 @@ override PROMPT := printf "%s\t\t%s\n"
###############################
# CFLAGS, QEMU flags + misc
###############################
+override PROJECT_ROOT = @PROJECT_ROOT@
override BOOT_FW = @BOOT_FW@
override ARCH = @ARCH@
override HYRA_VERSION = @PACKAGE_VERSION@
override PROMPT := printf "%s\t\t%s\n"
override KERNEL_CFLAGS = @KERNEL_CFLAGS@ $(KERNEL_DEFINES)
-override KERNEL_LDFLAGS = -nostdlib -znoexecstack -zmax-page-size=0x1000 -static -Tsys/arch/$(ARCH)/conf/link.ld
+override KERNEL_LDFLAGS = -no-pie -nostdlib -znoexecstack -zmax-page-size=0x1000 -static -Tsys/arch/$(ARCH)/conf/link.ld
override QEMU_FLAGS = @QEMU_FLAGS@
override KERNEL_DEFINES = $ -DHYRA_VERSION="\"$(HYRA_VERSION)\""\
-DHYRA_BUILDDATE="\"@HYRA_BUILDDATE@\""\
-DHYRA_ARCH="\"@ARCH@\"" $(shell cat sys/arch/$(ARCH)/conf/GENERIC | tools/kconf/kconf)
+######################
+# Initramfs config
+######################
+override RAMFS_TOOL = @RAMFS_TOOL@
+override RAMFS_LOC = ramfs.omar
######################
# Toolchain
@@ -72,20 +78,19 @@ all: base libc sbin bin base/boot/hyra-kernel ramfs iso
.PHONY: sbin
sbin: $(SBIN_MAKEDIRS)
$(MAKE) -C $^ -I$(shell pwd)/builddeps \
- LDSCRIPT=$(shell pwd)/usr.sbin/link.ld USRDIR=$(USRDIR)
- find $^ -type f -executable -exec mv {} base/usr/sbin/ \;
+ LDSCRIPT=$(shell pwd)/usr.sbin/link.ld USRDIR=$(USRDIR)\
+ ROOT=$(PROJECT_ROOT)
.PHONY: bin
bin: $(BIN_MAKEDIRS)
$(MAKE) -C $^ -I$(shell pwd)/builddeps \
- LDSCRIPT=$(shell pwd)/usr.bin/link.ld USRDIR=$(USRDIR)
- find $^ -type f -executable -exec mv {} base/usr/bin/ \;
+ LDSCRIPT=$(shell pwd)/usr.bin/link.ld USRDIR=$(USRDIR) \
+ ROOT=$(PROJECT_ROOT)
.PHONY: libc
libc:
$(MAKE) -C lib/libc/ -I$(shell pwd)/builddeps \
- USRDIR=$(USRDIR) ARCH=$(ARCH)
- cp lib/libc/build/libc.a base/usr/lib/
+ USRDIR=$(USRDIR) ARCH=$(ARCH) ROOT=$(PROJECT_ROOT)
.PHONY: base
base:
@@ -106,9 +111,8 @@ run:
.PHONY: ramfs
ramfs:
- cd base/; find . -name "*" | cpio --create --format=odc \
- --no-absolute-filenames > ../ramfs.cpio
- $(PROMPT) " RAMFS " $(shell pwd)/ramfs.cpio
+ $(RAMFS_TOOL) -i base/ -o ramfs.omar
+ $(PROMPT) " RAMFS " $(shell pwd)/ramfs.omar
.PHONY: clean
clean:
@@ -120,7 +124,7 @@ iso:
mkdir -p iso_root/boot/
mkdir -p iso_root/EFI/BOOT/
cp stand/limine/$(BOOT_FW) iso_root/EFI/BOOT/
- mv ramfs.cpio iso_root/boot/
+ mv $(RAMFS_LOC) iso_root/boot/
cp builddeps/limine.conf stand/limine/limine-bios.sys \
stand/limine/limine-bios-cd.bin stand/limine/limine-uefi-cd.bin iso_root/
cp base/boot/* iso_root/boot/
diff --git a/bootstrap b/bootstrap
index f9370ab..511d49b 100755
--- a/bootstrap
+++ b/bootstrap
@@ -3,6 +3,19 @@ set -e
mkdir -p lib/
+SYSTEM_NAME="$(uname -s)"
+MAKE="make"
+GIT="git"
+GCC="gcc"
+CLANG="clang"
+
+
+if [ "$SYSTEM_NAME" = "OpenBSD" ]
+then
+ MAKE="$(which gmake)"
+fi
+
+
# arg0: Output path.
# arg1: Command for downloading
try_fetch() {
@@ -27,16 +40,21 @@ fetch() {
}
build_limine() {
- make -C stand/limine/
+ $MAKE -C stand/limine/
}
build_kconf() {
- make -C tools/kconf/
+ $MAKE -C tools/kconf/
+}
+
+build_omar() {
+ $MAKE -C tools/omar/
}
build() {
build_limine
build_kconf
+ build_omar
}
echo "----------------------------------"
diff --git a/builddeps/limine.conf b/builddeps/limine.conf
index f1907ea..308ad26 100644
--- a/builddeps/limine.conf
+++ b/builddeps/limine.conf
@@ -9,5 +9,5 @@ resolution: 1280x720
/Hyra
protocol: limine
kernel_path: boot():/boot/hyra-kernel
- module_path: boot():/boot/ramfs.cpio
+ module_path: boot():/boot/ramfs.omar
diff --git a/configure.ac b/configure.ac
index 3729adb..a07647e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,7 @@
AC_INIT([Hyra], [1.6], [ian@osmora.org])
TARGET="amd64"
+PROJECT_ROOT=`pwd`
BOOT_FW="BOOTX64.EFI"
AC_ARG_ENABLE([aarch64],
[AS_HELP_STRING([--enable-aarch64], [Enable AARCH64 Support])],
@@ -13,10 +14,10 @@ KERN_CFLAGS_AMD64="-fexceptions --std=gnu11 -ffreestanding -fno-stack-protector
-Werror=implicit-int -Werror=int-conversion \\
-Werror=missing-prototypes \\
-Werror=incompatible-pointer-types -Werror=int-to-pointer-cast \\
- -Werror=return-type -Wunused -mabi=sysv -mno-80387 -mno-mmx -mno-3dnow \\
- -mno-sse -mno-sse2 -mno-red-zone -mcmodel=kernel -pedantic \\
+ -Werror=return-type -Wunused -mno-80387 -mno-mmx -mno-3dnow \\
+ -mno-sse -mno-sse2 -mno-red-zone -mcmodel=kernel -pedantic \\
-I sys/include/ -I sys/include/lib/ -D_KERNEL -Wno-pointer-sign -MMD \\
- -Wno-gnu-zero-variadic-macro-arguments -Wno-language-extension-token -Wno-tautological-constant-out-of-range-compare -Wno-c23-extensions"
+ -Wno-gnu-zero-variadic-macro-arguments -Wno-c2x-extensions -Wno-language-extension-token -Wno-tautological-constant-out-of-range-compare"
KERN_CFLAGS_AARCH64="-fexceptions --std=gnu11 -ffreestanding -fno-stack-protector -fno-pic \\
@@ -26,7 +27,7 @@ KERN_CFLAGS_AARCH64="-fexceptions --std=gnu11 -ffreestanding -fno-stack-protecto
-Werror=incompatible-pointer-types -Werror=int-to-pointer-cast \\
-Werror=return-type -Wunused -pedantic \\
-I sys/include/ -I sys/include/lib/ -D_KERNEL -Wno-pointer-sign -MMD \\
- -Wno-gnu-zero-variadic-macro-arguments -Wno-language-extension-token -Wno-tautological-constant-out-of-range-compare -Wno-c23-extensions"
+ -Wno-gnu-zero-variadic-macro-arguments -Wno-c2x-extensions -Wno-language-extension-token -Wno-tautological-constant-out-of-range-compare"
QEMU_FLAGS_AMD64="--enable-kvm -monitor stdio \\
@@ -53,6 +54,8 @@ AC_SUBST(QEMU_FLAGS, [$QEMU_FLAGS_AMD64])
AC_SUBST(QEMU, [qemu-system-x86_64])
AC_SUBST(BOOT_FW, [$BOOT_FW])
AC_SUBST(ARCH, [$TARGET])
+AC_SUBST(PROJECT_ROOT, [$PROJECT_ROOT])
AC_SUBST(TOOLCHAIN, [clang])
+AC_SUBST(RAMFS_TOOL, [tools/omar/bin/omar])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
index 43c823e..49e7329 100644
--- a/lib/libc/Makefile
+++ b/lib/libc/Makefile
@@ -9,6 +9,9 @@ all: sys/include/machine headers $(LIBC_ASMOBJ) $(LIBC_OBJ) build/libc.a
build/libc.a: build/
ar rcs build/libc.a $(LIBC_OBJ) $(LIBC_ASMOBJ)
+ mv $(LIBC_ASMOBJ) build/ # For initial bootstrapping
+ mv build/crti.S.o build/crti.o
+ mv build/*.o build/*.a $(ROOT)/base/usr/lib/
%.o: %.c
$(CC) $(CFLAGS) -Iinclude/ $< -o $@
diff --git a/lib/libc/src/arch/amd64/crt0.S b/lib/libc/src/arch/amd64/crti.S
index 1a5b466..582fea4 100644
--- a/lib/libc/src/arch/amd64/crt0.S
+++ b/lib/libc/src/arch/amd64/crti.S
@@ -29,8 +29,8 @@
#include <sys/syscall.h>
-.text
-.globl _start
+ .section .init
+ .globl _start
_start:
// Mark end of callstack
xor %rbp, %rbp
diff --git a/share/man/man1/omar.1 b/share/man/man1/omar.1
new file mode 100644
index 0000000..611b6da
--- /dev/null
+++ b/share/man/man1/omar.1
@@ -0,0 +1,55 @@
+.\" Copyright (c) 2025 Ian Marco Moffett and the Osmora Team.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright notice,
+.\" this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of Hyra nor the names of its
+.\" contributors may be used to endorse or promote products derived from
+.\" this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.Dd May 2 2025
+.Dt OMAR 1
+.Os HYRA
+.Sh NAME
+.Nm omar - OSMORA Archive Format
+.Sh SYNOPSIS
+omar -i [input] -o [output]
+
+.Sh DESCRIPTION
+Prepare files for use in an initramfs
+
+.Ft -i
+ input path directory
+
+.Ft -o
+ output path
+
+Upon creation of the archive image, OMAR will
+produce pathnames through stdout with the following
+types in square brackets ([])
+
+.Ft [f]
+ Regular file
+
+.Ft [d]
+ Directory
+
+.Sh AUTHORS
+.An Ian Moffett Aq Mt ian@osmora.org
diff --git a/sys/fs/initramfs.c b/sys/fs/initramfs.c
index fd746ef..b12a64b 100644
--- a/sys/fs/initramfs.c
+++ b/sys/fs/initramfs.c
@@ -33,12 +33,16 @@
#include <sys/errno.h>
#include <sys/limine.h>
#include <sys/panic.h>
+#include <sys/param.h>
#include <sys/vnode.h>
#include <fs/initramfs.h>
#include <vm/dynalloc.h>
#include <string.h>
-#define CPIO_TRAILER "TRAILER!!!"
+#define OMAR_EOF "RAMO"
+#define OMAR_REG 0
+#define OMAR_DIR 1
+#define BLOCK_SIZE 512
/*
* File or directory.
@@ -51,20 +55,18 @@ struct initramfs_node {
};
/*
- * ODC CPIO header
+ * The OMAR file header, describes the basics
+ * of a file.
+ *
+ * @magic: Header magic ("OMAR")
+ * @len: Length of the file
+ * @namelen: Length of the filename
*/
-struct cpio_hdr {
- char c_magic[6];
- char c_dev[6];
- char c_ino[6];
- char c_mode[6];
- char c_uid[6];
- char c_gid[6];
- char c_nlink[6];
- char c_rdev[6];
- char c_mtime[11];
- char c_namesize[6];
- char c_filesize[11];
+struct __packed omar_hdr {
+ char magic[4];
+ uint8_t type;
+ uint8_t namelen;
+ uint32_t len;
};
static volatile struct limine_module_request mod_req = {
@@ -92,21 +94,6 @@ get_module(const char *path, uint64_t *size) {
}
/*
- * Convert octal to base 10
- */
-static uint32_t
-oct2dec(const char *in, size_t sz)
-{
- size_t val = 0;
-
- for (size_t i = 0; i < sz; ++i) {
- val = val * 8 + (in[i] - '0');
- }
-
- return val;
-}
-
-/*
* Get a file from initramfs
*
* @path: Path of file to get.
@@ -115,41 +102,54 @@ oct2dec(const char *in, size_t sz)
static int
initramfs_get_file(const char *path, struct initramfs_node *res)
{
- const struct cpio_hdr *hdr;
struct initramfs_node node;
- uintptr_t addr;
- size_t namesize, filesize;
- mode_t mode;
+ const struct omar_hdr *hdr;
+ const char *p, *name;
+ char namebuf[256];
+ off_t off;
- addr = (uintptr_t)initramfs;
+ p = initramfs;
for (;;) {
- hdr = (void *)addr;
- namesize = oct2dec(hdr->c_namesize, sizeof(hdr->c_namesize));
- filesize = oct2dec(hdr->c_filesize, sizeof(hdr->c_filesize));
- mode = oct2dec(hdr->c_mode, sizeof(hdr->c_mode));
+ hdr = (struct omar_hdr *)p;
+ if (strncmp(hdr->magic, OMAR_EOF, sizeof(OMAR_EOF)) == 0) {
+ break;
+ }
- /* Make sure the magic is correct */
- if (strncmp(hdr->c_magic, "070707", 6) != 0) {
+ /* Ensure the file is valid */
+ if (strncmp(hdr->magic, "OMAR", 4) != 0) {
+ /* Bad magic */
+ return -EINVAL;
+ }
+ if (hdr->namelen > sizeof(namebuf) - 1) {
return -EINVAL;
}
- addr += sizeof(struct cpio_hdr);
- node.path = (const char *)addr;
+ name = (char *)p + sizeof(struct omar_hdr);
+ memcpy(namebuf, name, hdr->namelen);
+ namebuf[hdr->namelen] = '\0';
- /* Is this the requested file? */
- if (strcmp(node.path, path) == 0) {
- node.data = (void *)(addr + namesize);
- node.size = filesize;
- node.mode = mode;
+ /* Compute offset to next block */
+ if (hdr->type == OMAR_DIR) {
+ off = 512;
+ } else {
+ off = ALIGN_UP(sizeof(*hdr) + hdr->namelen + hdr->len, BLOCK_SIZE);
+ }
+
+ /* Skip header and name, right to the data */
+ p = (char *)hdr + sizeof(struct omar_hdr);
+ p += hdr->namelen;
+
+ if (strcmp(namebuf, path) == 0) {
+ node.mode = 0700;
+ node.size = hdr->len;
+ node.data = (void *)p;
*res = node;
return 0;
}
- /* Get next header and see if we are at the end */
- addr += (namesize + filesize);
- if (strcmp(node.path, CPIO_TRAILER) == 0) {
- break;
- }
+ hdr = (struct omar_hdr *)((char *)hdr + off);
+ p = (char *)hdr;
+ memset(namebuf, 0, sizeof(namebuf));
}
return -ENOENT;
@@ -256,9 +256,9 @@ initramfs_init(struct fs_info *fip)
struct mount *mp;
int status;
- initramfs = get_module("/boot/ramfs.cpio", &initramfs_size);
+ initramfs = get_module("/boot/ramfs.omar", &initramfs_size);
if (initramfs == NULL) {
- panic("failed to open initramfs cpio image\n");
+ panic("failed to open initramfs OMAR image\n");
}
status = vfs_alloc_vnode(&g_root_vnode, VDIR);
diff --git a/tools/omar/Makefile b/tools/omar/Makefile
new file mode 100644
index 0000000..ee30260
--- /dev/null
+++ b/tools/omar/Makefile
@@ -0,0 +1,12 @@
+CFILES = $(shell find . -name "*.c")
+CFLAGS = -pedantic
+CC = gcc
+
+.PHONY: all
+all:
+ mkdir -p bin/
+ $(CC) $(CFLAGS) $(CFILES) -o bin/omar
+
+.PHONY: clean
+clean:
+ rm -rf bin/
diff --git a/tools/omar/README b/tools/omar/README
new file mode 100644
index 0000000..3c74d78
--- /dev/null
+++ b/tools/omar/README
@@ -0,0 +1,9 @@
+------------------------------
+OMAR - OSMORA Archive Format
+------------------------------
+
+OMAR is a minimal, bullshit free archive format aimed to replace
+the old and outdated CPIO (copy in/out) format.
+
+OMAR is designed for readonly in-memory filesystems (such as initramfs),
+with simplicity, clarity and "getting it done" in mind.
diff --git a/tools/omar/omar.c b/tools/omar/omar.c
new file mode 100644
index 0000000..129303e
--- /dev/null
+++ b/tools/omar/omar.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <assert.h>
+#include <dirent.h>
+#include <string.h>
+#include <libgen.h>
+
+/* OMAR magic constants */
+#define OMAR_MAGIC "OMAR"
+#define OMAR_EOF "RAMO"
+
+/* OMAR type constants */
+#define OMAR_REG 0
+#define OMAR_DIR 1
+
+/* OMAR modes */
+#define OMAR_ARCHIVE 0
+#define OMAR_EXTRACT 1
+
+#define ALIGN_UP(value, align) (((value) + (align)-1) & ~((align)-1))
+#define BLOCK_SIZE 512
+
+static int mode = OMAR_ARCHIVE;
+static int outfd;
+static const char *inpath = NULL;
+static const char *outpath = NULL;
+
+/*
+ * The OMAR file header, describes the basics
+ * of a file.
+ *
+ * @magic: Header magic ("OMAR")
+ * @len: Length of the file
+ * @namelen: Length of the filename
+ */
+struct omar_hdr {
+ char magic[4];
+ uint8_t type;
+ uint8_t namelen;
+ uint32_t len;
+} __attribute__((packed));
+
+static inline void
+help(void)
+{
+ printf("--------------------------------------\n");
+ printf("The OSMORA archive format\n");
+ printf("Usage: omar -i [input_dir] -o [output]\n");
+ printf("-h Show this help screen\n");
+ printf("-x Extract an OMAR archive\n");
+ printf("--------------------------------------\n");
+}
+
+/*
+ * Strip out root dir
+ *
+ * XXX: This is added code to work with Hyra
+ * initramfs.
+ */
+static const char *
+strip_root(const char *path)
+{
+ const char *p;
+
+ for (p = path; *p != '\0'; ++p) {
+ if (*p == '/') {
+ ++p;
+ return p;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Recursive mkdir
+ */
+static void
+mkpath(const char *path)
+{
+ size_t len;
+ char buf[256];
+ char cwd[256];
+ char *p = NULL;
+
+ len = snprintf(buf, sizeof(buf), "%s", path);
+ if (buf[len - 1] == '/') {
+ buf[len - 1] = '\0';
+ }
+ for (p = (char *)buf + 1; *p != '\0'; ++p) {
+ if (*p == '/') {
+ *p = '\0';
+ mkdir(buf, 0700);
+ *p = '/';
+ }
+ }
+
+ mkdir(buf, 0700);
+}
+
+/*
+ * Push a file into the archive output
+ *
+ * @pathname: Full path name of file (NULL if EOF)
+ * @name: Name of file (for EOF, set to "EOF")
+ */
+static int
+file_push(const char *pathname, const char *name)
+{
+ struct omar_hdr hdr;
+ struct stat sb;
+ int infd, rem, error;
+ int pad_len;
+ size_t len;
+ char *buf;
+
+ hdr.type = OMAR_REG;
+
+ /* Attempt to open the input file if not EOF */
+ if (pathname != NULL) {
+ if ((infd = open(pathname, O_RDONLY)) < 0) {
+ perror("open");
+ return infd;
+ }
+
+ if ((error = fstat(infd, &sb)) < 0) {
+ return error;
+ }
+
+ if (S_ISDIR(sb.st_mode)) {
+ hdr.type = OMAR_DIR;
+ }
+ }
+
+ hdr.len = (pathname == NULL) ? 0 : sb.st_size;
+ hdr.namelen = strlen(name);
+
+ /*
+ * If we are at the end of the file, use the OMAR_EOF
+ * magic constant instant of the usual OMAR_MAGIC.
+ */
+ if (pathname == NULL) {
+ memcpy(hdr.magic, OMAR_EOF, sizeof(hdr.magic));
+ } else {
+ memcpy(hdr.magic, OMAR_MAGIC, sizeof(hdr.magic));
+ }
+
+ write(outfd, &hdr, sizeof(hdr));
+ write(outfd, name, hdr.namelen);
+
+ /* If we are at the end of file, we are done */
+ if (pathname == NULL) {
+ close(infd);
+ return 0;
+ }
+
+ /* Pad directories to zero */
+ if (hdr.type == OMAR_DIR) {
+ len = sizeof(hdr) + hdr.namelen;
+ rem = len & (BLOCK_SIZE - 1);
+ pad_len = BLOCK_SIZE - rem;
+
+ buf = malloc(pad_len);
+ memset(buf, 0, pad_len);
+ write(outfd, buf, pad_len);
+ free(buf);
+ return 0;
+ }
+
+ /* We need the file data now */
+ buf = malloc(hdr.len);
+ if (buf == NULL) {
+ printf("out of memory\n");
+ close(infd);
+ return -ENOMEM;
+ }
+ if (read(infd, buf, hdr.len) <= 0) {
+ perror("read");
+ close(infd);
+ return -EIO;
+ }
+
+ /*
+ * Write the actual file contents, if the file length is not
+ * a multiple of the block size, we'll need to pad out the rest
+ * to zero.
+ */
+ write(outfd, buf, hdr.len);
+ len = sizeof(hdr) + (hdr.namelen + hdr.len);
+ rem = len & (BLOCK_SIZE - 1);
+ if (rem != 0) {
+ /* Compute the padding length */
+ pad_len = BLOCK_SIZE - rem;
+
+ buf = realloc(buf, pad_len);
+ memset(buf, 0, pad_len);
+ write(outfd, buf, pad_len);
+ }
+ close(infd);
+ free(buf);
+ return 0;
+}
+
+/*
+ * Start creating an archive from the
+ * basepath of a directory.
+ */
+static int
+archive_create(const char *base, const char *dirname)
+{
+ DIR *dp;
+ struct dirent *ent;
+ struct omar_hdr hdr;
+ const char *p = NULL, *p1;
+ char pathbuf[256];
+ char namebuf[256];
+
+ dp = opendir(base);
+ if (dp == NULL) {
+ perror("opendir");
+ return -ENOENT;
+ }
+
+ while ((ent = readdir(dp)) != NULL) {
+ if (ent->d_name[0] == '.') {
+ continue;
+ }
+
+ snprintf(pathbuf, sizeof(pathbuf), "%s/%s", base, ent->d_name);
+ snprintf(namebuf, sizeof(namebuf), "%s/%s", dirname, ent->d_name);
+ p1 = strip_root(namebuf);
+
+ if (ent->d_type == DT_DIR) {
+ printf("%s [d]\n", p1);
+ file_push(pathbuf, p1);
+ archive_create(pathbuf, namebuf);
+ } else if (ent->d_type == DT_REG) {
+ printf("%s [f]\n", p1);
+ file_push(pathbuf, p1);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Extract a single file
+ *
+ * @data: Data to extract
+ * @len: Length of data
+ * @path: Path to output file
+ */
+static int
+extract_single(char *data, size_t len, const char *path)
+{
+ int fd;
+
+ if ((fd = open(path, O_WRONLY | O_CREAT, 0700)) < 0) {
+ return fd;
+ }
+
+ return write(fd, data, len) > 0 ? 0 : -1;
+}
+
+/*
+ * Extract an OMAR archive.
+ *
+ * XXX: The input file [-i] will be the OMAR archive to
+ * be extracted, the output directory [-o] will be
+ * where the files get extracted.
+ */
+static int
+archive_extract(void)
+{
+ char *buf, *name, *p;
+ struct stat sb;
+ struct omar_hdr *hdr;
+ int fd, error;
+ off_t off;
+ char namebuf[256];
+
+ if ((fd = open(inpath, O_RDONLY)) < 0) {
+ perror("open");
+ return fd;
+ }
+
+ if ((error = fstat(fd, &sb)) != 0) {
+ perror("fstat");
+ close(fd);
+ return error;
+ }
+
+ buf = malloc(sb.st_size);
+ if (buf == NULL) {
+ fprintf(stderr, "out of memory\n");
+ close(fd);
+ return -ENOMEM;
+ }
+
+ if (read(fd, buf, sb.st_size) <= 0) {
+ fprintf(stderr, "omar: no data read\n");
+ close(fd);
+ return -EIO;
+ }
+
+ hdr = (struct omar_hdr *)buf;
+ for (;;) {
+ if (memcmp(hdr->magic, OMAR_EOF, sizeof(OMAR_EOF)) == 0) {
+ printf("EOF!\n");
+ return 0;
+ }
+
+ /* Ensure the header is valid */
+ if (memcmp(hdr->magic, "OMAR", 4) != 0) {
+ fprintf(stderr, "bad magic\n");
+ break;
+ }
+
+ name = (char *)hdr + sizeof(struct omar_hdr);
+ memcpy(namebuf, name, hdr->namelen);
+ namebuf[hdr->namelen] = '\0';
+ printf("unpacking %s\n", namebuf);
+
+ if (hdr->type == OMAR_DIR) {
+ off = 512;
+ mkpath(namebuf);
+ } else {
+ off = ALIGN_UP(sizeof(hdr) + hdr->namelen + hdr->len, BLOCK_SIZE);
+ p = (char *)hdr + sizeof(struct omar_hdr);
+ p += hdr->namelen;
+ extract_single(p, hdr->len, namebuf);
+ }
+
+ hdr = (struct omar_hdr *)((char *)hdr + off);
+ memset(namebuf, 0, sizeof(namebuf));
+ }
+
+ free(buf);
+}
+
+int
+main(int argc, char **argv)
+{
+ int optc, retval;
+ int error, flags;
+
+ if (argc < 2) {
+ help();
+ return -1;
+ }
+
+ while ((optc = getopt(argc, argv, "xhi:o:")) != -1) {
+ switch (optc) {
+ case 'x':
+ mode = OMAR_EXTRACT;
+ break;
+ case 'i':
+ inpath = optarg;
+ break;
+ case 'o':
+ outpath = optarg;
+ break;
+ case 'h':
+ help();
+ return 0;
+ default:
+ help();
+ return -1;
+ }
+ }
+
+ if (inpath == NULL) {
+ fprintf(stderr, "omar: no input path\n");
+ help();
+ return -1;
+ }
+ if (outpath == NULL) {
+ fprintf(stderr, "omar: no output path\n");
+ help();
+ return -1;
+ }
+
+ /*
+ * Do our specific job based on the mode
+ * OMAR is set to be in.
+ */
+ switch (mode) {
+ case OMAR_ARCHIVE:
+ /* Begin archiving the file */
+ outfd = open(outpath, O_WRONLY | O_CREAT, 0700);
+ if (outfd < 0) {
+ printf("omar: failed to open output file\n");
+ return outfd;
+ }
+
+ retval = archive_create(inpath, basename((char *)inpath));
+ file_push(NULL, "EOF");
+ break;
+ case OMAR_EXTRACT:
+ /* Begin extracting the file */
+ if ((error = mkdir(outpath, 0700) != 0)) {
+ perror("mkdir");
+ return error;
+ }
+
+ retval = archive_extract();
+ break;
+ }
+ close(outfd);
+ return retval;
+}
diff --git a/usr.bin/osh/Makefile b/usr.bin/osh/Makefile
index 28981fe..1505412 100644
--- a/usr.bin/osh/Makefile
+++ b/usr.bin/osh/Makefile
@@ -2,5 +2,5 @@ include user.mk
CFILES = $(shell find . -name "*.c")
-osh:
- $(CC) $(CFILES) -o $@ $(INTERNAL_CFLAGS)
+$(ROOT)/base/usr/bin/osh:
+ gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS)
diff --git a/usr.sbin/init/Makefile b/usr.sbin/init/Makefile
index bee9f3a..5f95379 100644
--- a/usr.sbin/init/Makefile
+++ b/usr.sbin/init/Makefile
@@ -2,5 +2,5 @@ include user.mk
CFILES = $(shell find . -name "*.c")
-init:
+$(ROOT)/base/usr/sbin/init:
gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS)