From fa7834b5d650549f1125dc653fc2b732f4c9e3d0 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Sat, 27 Aug 2011 14:50:52 +0200 Subject: [PATCH] Added a mkinitrd program that creates initrds for Sortix. --- mkinitrd/Makefile | 13 ++ mkinitrd/catinitrd.cpp | 223 ++++++++++++++++++++++++++++++++++ mkinitrd/lsinitrd.cpp | 155 ++++++++++++++++++++++++ mkinitrd/mkinitrd.cpp | 263 +++++++++++++++++++++++++++++++++++++++++ sortix/initrd.h | 54 +++++++++ 5 files changed, 708 insertions(+) create mode 100644 mkinitrd/Makefile create mode 100644 mkinitrd/catinitrd.cpp create mode 100644 mkinitrd/lsinitrd.cpp create mode 100644 mkinitrd/mkinitrd.cpp create mode 100644 sortix/initrd.h diff --git a/mkinitrd/Makefile b/mkinitrd/Makefile new file mode 100644 index 00000000..b849e402 --- /dev/null +++ b/mkinitrd/Makefile @@ -0,0 +1,13 @@ +CPPFLAGS=-I.. +CXXFLAGS=-Wall + +BINARIES=mkinitrd lsinitrd catinitrd + +all: $(BINARIES) + +%: %.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $< -o $@ + +clean: + rm -f $(BINARIES) + diff --git a/mkinitrd/catinitrd.cpp b/mkinitrd/catinitrd.cpp new file mode 100644 index 00000000..ed9c1005 --- /dev/null +++ b/mkinitrd/catinitrd.cpp @@ -0,0 +1,223 @@ +/****************************************************************************** + + COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along + with Sortix. If not, see . + + catinitrd.cpp + Output files in a Sortix ramdisk. + +******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool writeall(int fd, const void* p, size_t size) +{ + const uint8_t* buffer = (const uint8_t*) p; + + size_t bytesWritten = 0; + + while ( bytesWritten < size ) + { + ssize_t written = write(fd, buffer + bytesWritten, size - bytesWritten); + if ( written < 0 ) { return false; } + bytesWritten += written; + } + + return true; +} + +bool readall(int fd, void* p, size_t size) +{ + uint8_t* buffer = (uint8_t*) p; + + size_t bytesread = 0; + + while ( bytesread < size ) + { + ssize_t justread = read(fd, buffer + bytesread, size - bytesread); + if ( justread <= 0 ) { return false; } + bytesread += justread; + } + + return true; +} + +void usage(int argc, char* argv[]) +{ + printf("usage: %s [OPTIONS] [files]\n", argv[0]); + printf("Options:\n"); + printf(" -q Surpress normal output\n"); + printf(" -v Be verbose\n"); + printf(" --usage Display this screen\n"); + printf(" --help Display this screen\n"); + printf(" --version Display version information\n"); +} + +void version() +{ + printf("catinitrd 0.1\n"); + printf("Copyright (C) 2011 Jonas 'Sortie' Termansen\n"); + printf("This is free software; see the source for copying conditions. There is NO\n"); + printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); + printf("website: http://www.maxsi.org/software/sortix/\n"); +} + +bool verbose = false; + +int main(int argc, char* argv[]) +{ + if ( argc < 2 ) { usage(argc, argv); return 0; } + + const char* src = NULL; + + for ( int i = 1; i < argc; i++ ) + { + if ( strcmp(argv[i], "-q") == 0 ) + { + verbose = false; + argv[i] = NULL; + } + else if ( strcmp(argv[i], "-v") == 0 ) + { + verbose = true; + argv[i] = NULL; + } + else if ( strcmp(argv[i], "--usage") == 0 ) + { + usage(argc, argv); + return 0; + } + else if ( strcmp(argv[i], "--help") == 0 ) + { + usage(argc, argv); + return 0; + } + else if ( strcmp(argv[i], "--version") == 0 ) + { + version(); + return 0; + } + else if ( src == NULL ) + { + src = argv[i]; + argv[i] = NULL; + } + } + + int fd = open(src, O_RDONLY); + if ( fd < 0 ) { error(0, errno, "%s", src); return 1; } + + Sortix::InitRD::Header header; + if ( !readall(fd, &header, sizeof(header)) ) + { + error(0, errno, "read: %s", src); + close(fd); + return 1; + } + + if ( strcmp(header.magic, "sortix-initrd-1") != 0 ) + { + error(0, 0, "not a sortix ramdisk: %s", src); + close(fd); + return 1; + } + + int result = 0; + + for ( int i = 1; i < argc; i++ ) + { + if ( argv[i] == NULL ) { continue; } + + bool found = false; + + for ( uint32_t n = 0; n < header.numfiles; n++ ) + { + off_t fileheaderpos = sizeof(header) + n * sizeof(Sortix::InitRD::FileHeader); + if ( lseek(fd, fileheaderpos, SEEK_SET ) < 0 ) + { + error(0, errno, "seek: %s", src); + close(fd); + return 1; + } + + Sortix::InitRD::FileHeader fileheader; + if ( !readall(fd, &fileheader, sizeof(fileheader)) ) + { + error(0, errno, "read: %s", src); + close(fd); + return 1; + } + + if ( strcmp(argv[i], fileheader.name) != 0 ) { continue; } + + found = true; + + if ( lseek(fd, fileheader.offset, SEEK_SET ) < 0 ) + { + error(0, errno, "seek: %s", src); + close(fd); + return 1; + } + + const size_t BUFFER_SIZE = 16384UL; + uint8_t buffer[BUFFER_SIZE]; + + uint32_t filesize = fileheader.size; + uint32_t readsofar = 0; + while ( readsofar < filesize ) + { + uint32_t left = filesize-readsofar; + size_t toread = (left < BUFFER_SIZE) ? left : BUFFER_SIZE; + ssize_t bytesread = read(fd, buffer, toread); + if ( bytesread <= 0 ) + { + error(0, errno, "read: %s", src); + close(fd); + return 1; + } + + if ( !writeall(1, buffer, bytesread) ) + { + error(0, errno, "write: "); + close(fd); + return 1; + } + + readsofar += bytesread; + } + } + + if ( !found ) + { + result |= 1; + error(0, ENOENT, "%s", argv[i]); + } + } + + close(fd); + + return result; +} diff --git a/mkinitrd/lsinitrd.cpp b/mkinitrd/lsinitrd.cpp new file mode 100644 index 00000000..3c523bce --- /dev/null +++ b/mkinitrd/lsinitrd.cpp @@ -0,0 +1,155 @@ +/****************************************************************************** + + COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along + with Sortix. If not, see . + + lsinitrd.cpp + Lists the files in a Sortix ramdisk. + +******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool readall(int fd, void* p, size_t size) +{ + uint8_t* buffer = (uint8_t*) p; + + size_t bytesread = 0; + + while ( bytesread < size ) + { + ssize_t justread = read(fd, buffer + bytesread, size - bytesread); + if ( justread <= 0 ) { return false; } + bytesread += justread; + } + + return true; +} + +void usage(int argc, char* argv[]) +{ + printf("usage: %s [OPTIONS] \n", argv[0]); + printf("Options:\n"); + printf(" -q Surpress normal output\n"); + printf(" -v Be verbose\n"); + printf(" --usage Display this screen\n"); + printf(" --help Display this screen\n"); + printf(" --version Display version information\n"); +} + +void version() +{ + printf("lsinitrd 0.1\n"); + printf("Copyright (C) 2011 Jonas 'Sortie' Termansen\n"); + printf("This is free software; see the source for copying conditions. There is NO\n"); + printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); + printf("website: http://www.maxsi.org/software/sortix/\n"); +} + +bool verbose = false; + +int listfiles(const char* filepath) +{ + int fd = open(filepath, O_RDONLY); + if ( fd < 0 ) { error(0, errno, "%s", filepath); return 1; } + + Sortix::InitRD::Header header; + if ( !readall(fd, &header, sizeof(header)) ) + { + error(0, errno, "read: %s", filepath); + close(fd); + return 1; + } + + if ( strcmp(header.magic, "sortix-initrd-1") != 0 ) + { + error(0, 0, "not a sortix ramdisk: %s", filepath); + close(fd); + return 1; + } + + for ( uint32_t i = 0; i < header.numfiles; i++ ) + { + Sortix::InitRD::FileHeader fileheader; + if ( !readall(fd, &fileheader, sizeof(fileheader)) ) + { + error(0, errno, "read: %s", filepath); + close(fd); + return 1; + } + + printf("%s\n", fileheader.name); + } + + close(fd); + + return 0; +} + +int main(int argc, char* argv[]) +{ + if ( argc < 2 ) { usage(argc, argv); return 0; } + + for ( int i = 1; i < argc; i++ ) + { + if ( strcmp(argv[i], "-q") == 0 ) + { + verbose = false; + argv[i] = NULL; + } + else if ( strcmp(argv[i], "-v") == 0 ) + { + verbose = true; + argv[i] = NULL; + } + else if ( strcmp(argv[i], "--usage") == 0 ) + { + usage(argc, argv); + return 0; + } + else if ( strcmp(argv[i], "--help") == 0 ) + { + usage(argc, argv); + return 0; + } + else if ( strcmp(argv[i], "--version") == 0 ) + { + version(); + return 0; + } + } + + int result = 0; + + for ( int i = 1; i < argc; i++ ) + { + if ( argv[i] == NULL ) { continue; } + + result |= listfiles(argv[i]); + } + + return result; +} diff --git a/mkinitrd/mkinitrd.cpp b/mkinitrd/mkinitrd.cpp new file mode 100644 index 00000000..fba94a78 --- /dev/null +++ b/mkinitrd/mkinitrd.cpp @@ -0,0 +1,263 @@ +/****************************************************************************** + + COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along + with Sortix. If not, see . + + mkinitrd.cpp + Produces a simple ramdisk meant for bootstrapping the Sortix kernel. + +******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool writeall(int fd, const void* p, size_t size) +{ + const uint8_t* buffer = (const uint8_t*) p; + + size_t bytesWritten = 0; + + while ( bytesWritten < size ) + { + ssize_t written = write(fd, buffer + bytesWritten, size - bytesWritten); + if ( written < 0 ) { return false; } + bytesWritten += written; + } + + return true; +} + +void usage(int argc, char* argv[]) +{ + printf("usage: %s [OPTIONS] \n", argv[0]); + printf("Options:\n"); + printf(" -o Write the ramdisk to this file\n"); + printf(" -q Surpress normal output\n"); + printf(" -v Be verbose\n"); + printf(" --usage Display this screen\n"); + printf(" --help Display this screen\n"); + printf(" --version Display version information\n"); +} + +void version() +{ + printf("mkinitrd 0.1\n"); + printf("Copyright (C) 2011 Jonas 'Sortie' Termansen\n"); + printf("This is free software; see the source for copying conditions. There is NO\n"); + printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); + printf("website: http://www.maxsi.org/software/sortix/\n"); +} + +bool verbose = false; + +int main(int argc, char* argv[]) +{ + const char* dest = NULL; + + if ( argc < 2 ) { usage(argc, argv); return 0; } + + uint32_t numfiles = 0; + + for ( int i = 1; i < argc; i++ ) + { + if ( strcmp(argv[i], "-o") == 0 ) + { + if ( i + 1 < argc ) + { + dest = argv[i+1]; + argv[i+1] = NULL; + } + argv[i] = NULL; + i++; + } + else if ( strcmp(argv[i], "-q") == 0 ) + { + verbose = false; + argv[i] = NULL; + } + else if ( strcmp(argv[i], "-v") == 0 ) + { + verbose = true; + argv[i] = NULL; + } + else if ( strcmp(argv[i], "--usage") == 0 ) + { + usage(argc, argv); + return 0; + } + else if ( strcmp(argv[i], "--help") == 0 ) + { + usage(argc, argv); + return 0; + } + else if ( strcmp(argv[i], "--version") == 0 ) + { + version(); + return 0; + } + else + { + numfiles++; + } + } + + if ( dest == NULL ) + { + fprintf(stderr, "%s: no output file specified\n", argv[0]); + return 0; + } + + int fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + if ( fd < 0 ) + { + error(0, errno, "%s", dest); + return 1; + } + + // Write the initrd headers. + Sortix::InitRD::Header header; + memset(&header, 0, sizeof(header)); + strcpy(header.magic, "sortix-initrd-1"); + header.numfiles = numfiles; + if ( !writeall(fd, &header, sizeof(header)) ) + { + error(0, errno, "write: %s", dest); + close(fd); + unlink(dest); + return 1; + } + + uint32_t fileoffset = sizeof(header) + numfiles * sizeof(Sortix::InitRD::FileHeader); + + uint32_t filenum = 0; + for ( int i = 1; i < argc; i++ ) + { + const char* file = argv[i]; + + if ( file == NULL ) { continue; } + + Sortix::InitRD::FileHeader fileheader; + memset(&fileheader, 0, sizeof(fileheader)); + + if ( sizeof(fileheader.name) - 1 < strlen(file) ) + { + fprintf(stderr, "%s: file name is too long: %s\n", argv[0], file); + close(fd); + unlink(dest); + return 1; + } + + int filefd = open(file, O_RDONLY); + if ( filefd < 0 ) + { + error(0, errno, "%s", file); + close(fd); + unlink(dest); + return 1; + } + + if ( verbose ) + { + fprintf(stderr, "%s\n", file); + } + + struct stat st; + if ( fstat(filefd, &st) != 0 ) + { + error(0, errno, "stat: %s", file); + close(fd); + unlink(dest); + return 1; + } + + uint32_t filesize = st.st_size; + fileheader.permissions = 0755; + fileheader.size = filesize; + fileheader.owner = 1; + fileheader.group = 1; + fileheader.offset = fileoffset; + strcpy(fileheader.name, file); + + off_t fileheaderpos = sizeof(header) + filenum * sizeof(Sortix::InitRD::FileHeader); + if ( lseek(fd, fileheaderpos, SEEK_SET ) < 0 ) + { + error(0, errno, "seek: %s", dest); + close(fd); + unlink(dest); + return 1; + } + + if ( !writeall(fd, &fileheader, sizeof(fileheader)) ) + { + error(0, errno, "write: %s", dest); + close(fd); + unlink(dest); + return 1; + } + + if ( lseek(fd, fileoffset, SEEK_SET ) < 0 ) + { + error(0, errno, "seek: %s", dest); + close(fd); + unlink(dest); + return 1; + } + + const size_t BUFFER_SIZE = 16384UL; + uint8_t buffer[BUFFER_SIZE]; + + uint32_t readsofar = 0; + while ( readsofar < filesize ) + { + uint32_t left = filesize-readsofar; + size_t toread = (left < BUFFER_SIZE) ? left : BUFFER_SIZE; + ssize_t bytesread = read(filefd, buffer, toread); + if ( bytesread <= 0 ) + { + error(0, errno, "read: %s", file); + close(fd); + unlink(dest); + return 1; + } + + if ( !writeall(fd, buffer, bytesread) ) + { + error(0, errno, "write: %s", dest); + close(fd); + unlink(dest); + return 1; + } + + readsofar += bytesread; + } + + fileoffset += filesize; + filenum++; + + close(filefd); + } + + return 0; +} diff --git a/sortix/initrd.h b/sortix/initrd.h new file mode 100644 index 00000000..39171156 --- /dev/null +++ b/sortix/initrd.h @@ -0,0 +1,54 @@ +/****************************************************************************** + + COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along + with Sortix. If not, see . + + initrd.h + Declares the structure of the Sortix ramdisk. + +******************************************************************************/ + +#ifndef SORTIX_INITRD_H +#define SORTIX_INITRD_H + +namespace Sortix +{ + namespace InitRD + { + struct Header; + struct FileHeader; + + struct Header + { + char magic[16]; // Contains "sortix-initrd-1" + uint32_t numfiles; + // FileHeader[numfiles]; + }; + + struct FileHeader + { + mode_t permissions; + uid_t owner; + gid_t group; + uint32_t size; + uint32_t offset; // where the physical data is located. + char name[128]; + }; + } +} + +#endif