diff --git a/Makefile b/Makefile
index efd51392..604473c6 100644
--- a/Makefile
+++ b/Makefile
@@ -69,7 +69,7 @@ everything-all-archs:
# Initializing RamDisk
$(INITRD): suball
- (cd $(INITRDDIR) && ../mkinitrd/mkinitrd * -o ../$(INITRD))
+ mkinitrd/mkinitrd initrd -o $(INITRD)
# Statistics
linecount:
diff --git a/mkinitrd/.gitignore b/mkinitrd/.gitignore
index f5631bac..deee3b80 100644
--- a/mkinitrd/.gitignore
+++ b/mkinitrd/.gitignore
@@ -1,3 +1,2 @@
mkinitrd
-lsinitrd
-catinitrd
+initrdfs
diff --git a/mkinitrd/Makefile b/mkinitrd/Makefile
index 7cf1b6e5..fc7e53ac 100644
--- a/mkinitrd/Makefile
+++ b/mkinitrd/Makefile
@@ -1,12 +1,15 @@
+SORTIXKERNEL=../sortix
+LIBMAXSI=../libmaxsi
+
CPPFLAGS=-I../sortix/include
CXXFLAGS=-Wall
-BINARIES=mkinitrd lsinitrd catinitrd
+BINARIES=mkinitrd initrdfs
all: $(BINARIES)
-%: %.cpp
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+%: %.cpp crc32.cpp $(LIBMAXSI)/ioleast.cpp
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $< crc32.cpp $(LIBMAXSI)/ioleast.cpp -o $@
clean:
rm -f $(BINARIES)
diff --git a/mkinitrd/catinitrd.cpp b/mkinitrd/catinitrd.cpp
deleted file mode 100644
index b0df228b..00000000
--- a/mkinitrd/catinitrd.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-/******************************************************************************
-
- 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/crc32.cpp b/mkinitrd/crc32.cpp
new file mode 100644
index 00000000..6898c7e4
--- /dev/null
+++ b/mkinitrd/crc32.cpp
@@ -0,0 +1,94 @@
+/*******************************************************************************
+
+ COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2012.
+ COPYRIGHT(C) KRZYSZTOF DABROWSKI 1999, 2000.
+ COPYRIGHT(C) ElysiuM deeZine 1999, 2000.
+ Based on implementation by Finn Yannick Jacobs.
+
+ 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 .
+
+ crc32.cpp
+ Calculates a CRC32 Checksum on binary data.
+
+*******************************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+#include "crc32.h"
+
+void GenerateCRC32Table(uint32_t tabel[256])
+{
+ uint32_t poly = 0xEDB88320U;
+ for ( uint32_t i = 0; i < 256; i++ )
+ {
+ uint32_t crc = i;
+ for ( uint32_t j = 8; 0 < j; j-- )
+ {
+ if ( crc & 1 ) { crc = (crc >> 1) ^ poly; }
+ else { crc >>= 1; }
+ }
+ tabel[i] = crc;
+ }
+}
+
+uint32_t ContinueCRC32(uint32_t tabel[256], uint32_t crc, uint8_t* block,
+ size_t size)
+{
+ for ( size_t i = 0; i < size; i++ )
+ {
+ crc = ((crc >> 8) & 0x00FFFFFF) ^ tabel[(crc ^ *block++) & 0xFF];
+ }
+ return crc;
+}
+
+uint32_t FinishCRC32(uint32_t crc)
+{
+ return crc ^ 0xFFFFFFFF;
+}
+
+uint32_t CRC32(uint8_t* block, size_t size)
+{
+ uint32_t tabel[256];
+ GenerateCRC32Table(tabel);
+ return FinishCRC32(ContinueCRC32(tabel, CRC32_START_SEED, block, size));
+}
+
+bool CRC32File(uint32_t* result, const char* name, int fd, off_t offset,
+ off_t length)
+{
+ uint32_t tabel[256];
+ GenerateCRC32Table(tabel);
+ uint32_t crc = CRC32_START_SEED;
+ const size_t BUFFER_SIZE = 16UL * 1024UL;
+ uint8_t buffer[BUFFER_SIZE];
+ off_t sofar = 0;
+ ssize_t amount;
+ while ( sofar < length &&
+ 0 < (amount = pread(fd, buffer, BUFFER_SIZE, offset + sofar)) )
+ {
+ if ( length - sofar < amount ) { amount = length - sofar; }
+ crc = ContinueCRC32(tabel, crc, buffer, amount);
+ sofar += amount;
+ }
+ if ( amount < 0 ) { error(0, errno, "read: %s", name); return false; }
+ if ( sofar < length ) { error(0, EIO, "read: %s", name); return false; }
+ crc = FinishCRC32(crc);
+ *result = crc;
+ return true;
+}
diff --git a/mkinitrd/crc32.h b/mkinitrd/crc32.h
new file mode 100644
index 00000000..34018606
--- /dev/null
+++ b/mkinitrd/crc32.h
@@ -0,0 +1,40 @@
+/*******************************************************************************
+
+ COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2012.
+ COPYRIGHT(C) KRZYSZTOF DABROWSKI 1999, 2000.
+ COPYRIGHT(C) ElysiuM deeZine 1999, 2000.
+ Based on implementation by Finn Yannick Jacobs.
+
+ 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 .
+
+ crc32.h
+ Calculates a CRC32 Checksum on binary data.
+
+*******************************************************************************/
+
+#ifndef CRC32_H
+#define CRC32_H
+
+const uint32_t CRC32_START_SEED = 0xFFFFFFFF;
+void GenerateCRC32Table(uint32_t tabel[256]);
+uint32_t ContinueCRC32(uint32_t tabel[256], uint32_t crc, uint8_t* block,
+ size_t size);
+uint32_t FinishCRC32(uint32_t crc);
+uint32_t CRC32(uint8_t* block, size_t size);
+bool CRC32File(uint32_t* result, const char* name, int fd, off_t offset,
+ off_t length);
+
+#endif
diff --git a/mkinitrd/initrdfs.cpp b/mkinitrd/initrdfs.cpp
new file mode 100644
index 00000000..38cc50a6
--- /dev/null
+++ b/mkinitrd/initrdfs.cpp
@@ -0,0 +1,349 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
+
+ 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 .
+
+ initrdfs.cpp
+ Provides access to filesystems in the Sortix kernel initrd format.
+
+*******************************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "crc32.h"
+
+#if !defined(sortix)
+__BEGIN_DECLS
+size_t preadall(int fd, void* buf, size_t count, off_t off);
+size_t preadleast(int fd, void* buf, size_t least, size_t max, off_t off);
+size_t pwriteall(int fd, const void* buf, size_t count, off_t off);
+size_t pwriteleast(int fd, const void* buf, size_t least, size_t max, off_t off);
+size_t readall(int fd, void* buf, size_t count);
+size_t readleast(int fd, void* buf, size_t least, size_t max);
+size_t writeall(int fd, const void* buf, size_t count);
+size_t writeleast(int fd, const void* buf, size_t least, size_t max);
+__END_DECLS
+#endif
+
+char* Substring(const char* str, size_t start, size_t length)
+{
+ char* result = (char*) malloc(length+1);
+ strncpy(result, str + start, length);
+ result[length] = 0;
+ return result;
+}
+
+bool ReadSuperBlock(int fd, initrd_superblock_t* dest)
+{
+ return preadall(fd, dest, sizeof(*dest), 0) == sizeof(*dest);
+}
+
+initrd_superblock_t* GetSuperBlock(int fd)
+{
+ size_t sbsize = sizeof(initrd_superblock_t);
+ initrd_superblock_t* sb = (initrd_superblock_t*) malloc(sbsize);
+ if ( !sb ) { return NULL; }
+ if ( !ReadSuperBlock(fd, sb) ) { free(sb); return NULL; }
+ return sb;
+}
+
+bool ReadChecksum(int fd, initrd_superblock_t* sb, uint8_t* dest)
+{
+ uint32_t offset = sb->fssize - sb->sumsize;
+ return preadall(fd, dest, sb->sumsize, offset) == sb->sumsize;
+}
+
+uint8_t* GetChecksum(int fd, initrd_superblock_t* sb)
+{
+ uint8_t* checksum = (uint8_t*) malloc(sb->sumsize);
+ if ( !checksum ) { return NULL; }
+ if ( !ReadChecksum(fd, sb, checksum) ) { free(checksum); return NULL; }
+ return checksum;
+}
+
+bool ReadInode(int fd, initrd_superblock_t* sb, uint32_t ino,
+ initrd_inode_t* dest)
+{
+ uint32_t inodepos = sb->inodeoffset + sb->inodesize * ino;
+ return preadall(fd, dest, sizeof(*dest), inodepos) == sizeof(*dest);
+}
+
+initrd_inode_t* GetInode(int fd, initrd_superblock_t* sb, uint32_t ino)
+{
+ initrd_inode_t* inode = (initrd_inode_t*) malloc(sizeof(initrd_inode_t));
+ if ( !inode ) { return NULL; }
+ if ( !ReadInode(fd, sb, ino, inode) ) { free(inode); return NULL; }
+ return inode;
+}
+
+initrd_inode_t* CloneInode(const initrd_inode_t* src)
+{
+ initrd_inode_t* result = (initrd_inode_t*) malloc(sizeof(*src));
+ if ( !result ) { return NULL; }
+ memcpy(result, src, sizeof(*src));
+ return result;
+}
+
+bool ReadInodeData(int fd, initrd_superblock_t* sb, initrd_inode_t* inode,
+ uint8_t* dest, size_t size)
+{
+ if ( inode->size < size ) { errno = EINVAL; return false; }
+ return preadall(fd, dest, size, inode->dataoffset) == size;
+}
+
+uint8_t* GetInodeData(int fd, initrd_superblock_t* sb, initrd_inode_t* inode,
+ size_t size)
+{
+ uint8_t* buf = (uint8_t*) malloc(size);
+ if ( !buf ) { return NULL; }
+ if ( !ReadInodeData(fd, sb, inode, buf, size) ) { free(buf); return NULL; }
+ return buf;
+}
+
+uint8_t* GetInodeData(int fd, initrd_superblock_t* sb, initrd_inode_t* inode)
+{
+ return GetInodeData(fd, sb, inode, inode->size);
+}
+
+uint32_t Traverse(int fd, initrd_superblock_t* sb, initrd_inode_t* inode,
+ const char* name)
+{
+ if ( !INITRD_S_ISDIR(inode->mode) ) { errno = ENOTDIR; return 0; }
+ uint8_t* direntries = GetInodeData(fd, sb, inode);
+ if ( !direntries ) { return 0; }
+ uint32_t result = 0;
+ uint32_t offset = 0;
+ while ( offset < inode->size )
+ {
+ initrd_dirent_t* dirent = (initrd_dirent_t*) (direntries + offset);
+ if ( dirent->namelen && !strcmp(dirent->name, name) )
+ {
+ result = dirent->inode;
+ break;
+ }
+ offset += dirent->reclen;
+ }
+ free(direntries);
+ if ( !result ) { errno = ENOENT; }
+ return result;
+}
+
+bool CheckSumCRC32(const char* name, int fd, initrd_superblock_t* sb)
+{
+ uint32_t* checksump = (uint32_t*) GetChecksum(fd, sb);
+ if ( !checksump ) { return false; }
+ uint32_t checksum = *checksump;
+ free(checksump);
+ uint32_t amount = sb->fssize - sb->sumsize;
+ uint32_t filesum;
+ if ( !CRC32File(&filesum, name, fd, 0, amount) ) { return false; }
+ if ( checksum != filesum ) { errno = EILSEQ; return false; }
+ return true;
+}
+
+bool CheckSum(const char* name, int fd, initrd_superblock_t* sb)
+{
+ switch ( sb->sumalgorithm )
+ {
+ case INITRD_ALGO_CRC32: return CheckSumCRC32(name, fd, sb);
+ default:
+ fprintf(stderr, "Warning: unsupported checksum algorithm: %s\n", name);
+ return true;
+ }
+}
+
+initrd_inode_t* ResolvePath(int fd, initrd_superblock_t* sb,
+ initrd_inode_t* inode, const char* path)
+{
+ if ( !path[0] ) { return CloneInode(inode); }
+ if ( path[0] == '/' )
+ {
+ if ( !INITRD_S_ISDIR(inode->mode) ) { errno = ENOTDIR; return NULL; }
+ return ResolvePath(fd, sb, inode, path+1);
+ }
+ size_t elemlen = strcspn(path, "/");
+ char* elem = Substring(path, 0, elemlen);
+ uint32_t ino = Traverse(fd, sb, inode, elem);
+ free(elem);
+ if ( !ino ) { return NULL; }
+ initrd_inode_t* child = GetInode(fd, sb, ino);
+ if ( !child ) { return NULL; }
+ if ( !path[elemlen] ) { return child; }
+ initrd_inode_t* result = ResolvePath(fd, sb, child, path + elemlen);
+ free(child);
+ return result;
+}
+
+bool ListDirectory(int fd, initrd_superblock_t* sb, initrd_inode_t* dir,
+ bool all)
+{
+ if ( !INITRD_S_ISDIR(dir->mode) ) { errno = ENOTDIR; return false; }
+ uint8_t* direntries = GetInodeData(fd, sb, dir);
+ if ( !direntries ) { return false; }
+ uint32_t offset = 0;
+ while ( offset < dir->size )
+ {
+ initrd_dirent_t* dirent = (initrd_dirent_t*) (direntries + offset);
+ if ( dirent->namelen && (all || dirent->name[0] != '.'))
+ {
+ printf("%s\n", dirent->name);
+ }
+ offset += dirent->reclen;
+ }
+ free(direntries);
+ return true;
+}
+
+bool PrintFile(int fd, initrd_superblock_t* sb, initrd_inode_t* inode)
+{
+ if ( INITRD_S_ISDIR(inode->mode ) ) { errno = EISDIR; return false; }
+ uint32_t sofar = 0;
+ while ( sofar < inode->size )
+ {
+ const size_t BUFFER_SIZE = 16UL * 1024UL;
+ uint8_t buffer[BUFFER_SIZE];
+ uint32_t available = inode->size - sofar;
+ uint32_t count = available < BUFFER_SIZE ? available : BUFFER_SIZE;
+ if ( !ReadInodeData(fd, sb, inode, buffer, count) ) { return false; }
+ if ( writeall(1, buffer, count) != count ) { return false; }
+ sofar += count;
+ }
+ return true;
+}
+
+void Usage(FILE* fp, const char* argv0)
+{
+ fprintf(fp, "usage: %s [--check] (ls | cat) \n", argv0);
+ fprintf(fp, "Accesses data in a Sortix kernel init ramdisk.\n");
+}
+
+void Help(FILE* fp, const char* argv0)
+{
+ Usage(fp, argv0);
+}
+
+void Version(FILE* fp, const char* argv0)
+{
+ fprintf(fp, "initrdfs 0.2\n");
+ fprintf(fp, "Copyright (C) 2012 Jonas 'Sortie' Termansen\n");
+ fprintf(fp, "This is free software; see the source for copying conditions. There is NO\n");
+ fprintf(fp, "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
+ fprintf(fp, "website: http://www.maxsi.org/software/sortix/\n");
+}
+
+int main(int argc, char* argv[])
+{
+ bool all = false;
+ bool check = false;
+ const char* argv0 = argv[0];
+ if ( argc < 2 ) { Usage(stdout, argv0); exit(0); }
+ for ( int i = 1; i < argc; i++ )
+ {
+ const char* arg = argv[i];
+ if ( arg[0] != '-' ) { continue; }
+ argv[i] = NULL;
+ if ( !strcmp(arg, "--") ) { break; }
+ if ( !strcmp(arg, "--help") ) { Help(stdout, argv0); exit(0); }
+ if ( !strcmp(arg, "--usage") ) { Usage(stdout, argv0); exit(0); }
+ if ( !strcmp(arg, "--version") ) { Version(stdout, argv0); exit(0); }
+ if ( !strcmp(arg, "-a") ) { all = true; continue; }
+ if ( !strcmp(arg, "--check") ) { check = true; continue; }
+ fprintf(stderr, "%s: unknown option: %s\n", argv0, arg);
+ Usage(stderr, argv0);
+ exit(1);
+ }
+
+ const char* initrd = NULL;
+ const char* cmd = NULL;
+ const char* path = NULL;
+ int args = 0;
+ for ( int i = 1; i < argc; i++ )
+ {
+ if ( !argv[i] ) { continue; }
+ switch ( ++args )
+ {
+ case 1: initrd = argv[i]; break;
+ case 2: cmd = argv[i]; break;
+ case 3: path = argv[i]; break;
+ }
+ }
+
+ const char* errmsg = NULL;
+ if ( !errmsg && !initrd ) { errmsg = "no initrd specified"; }
+ if ( !errmsg && !cmd ) { errmsg = "no command specified"; }
+ if ( !errmsg && !path ) { errmsg = "no path specified"; }
+ if ( !errmsg && 3 < args ) { errmsg = "too many arguments"; }
+
+ if ( errmsg )
+ {
+ fprintf(stderr, "%s: %s\n", argv0, errmsg),
+ Usage(stderr, argv0);
+ exit(1);
+ }
+
+ int fd = open(initrd, O_RDONLY);
+ if ( fd < 0 ) { error(1, errno, "open: %s", initrd); }
+
+ initrd_superblock_t* sb = GetSuperBlock(fd);
+ if ( !sb ) { error(1, errno, "read: %s", initrd); }
+
+ if ( check && !CheckSum(initrd, fd, sb) )
+ {
+ error(1, errno, "checksum error: %s", initrd);
+ }
+
+ if ( path[0] != '/' ) { error(1, ENOENT, "%s", path); }
+
+ initrd_inode_t* root = GetInode(fd, sb, sb->root);
+ if ( !root ) { error(1, errno, "read: %s", initrd); }
+
+ initrd_inode_t* inode = ResolvePath(fd, sb, root, path+1);
+ if ( !inode ) { error(1, errno, "%s", path); }
+
+ free(root);
+
+ if ( !strcmp(cmd, "cat") )
+ {
+ if ( !PrintFile(fd, sb, inode) ) { error(1, errno, "%s", path); }
+ }
+ else if ( !strcmp(cmd, "ls") )
+ {
+ initrd_inode_t* dir = inode;
+ if ( !ListDirectory(fd, sb, dir, all) ) { error(1, errno, "%s", path); }
+ }
+ else
+ {
+ fprintf(stderr, "%s: unrecognized command: %s", argv0, cmd);
+ exit(1);
+ }
+
+ free(inode);
+ free(sb);
+ close(fd);
+
+ return 0;
+}
+
diff --git a/mkinitrd/lsinitrd.cpp b/mkinitrd/lsinitrd.cpp
deleted file mode 100644
index 002c6efe..00000000
--- a/mkinitrd/lsinitrd.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-/******************************************************************************
-
- 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
index fdef0037..95e6a23d 100644
--- a/mkinitrd/mkinitrd.cpp
+++ b/mkinitrd/mkinitrd.cpp
@@ -1,6 +1,6 @@
-/******************************************************************************
+/*******************************************************************************
- COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
This file is part of Sortix.
@@ -18,271 +18,408 @@
with Sortix. If not, see .
mkinitrd.cpp
- Produces a simple ramdisk meant for bootstrapping the Sortix kernel.
+ Produces a simple ramdisk filesystem readable by the Sortix kernel.
-******************************************************************************/
+*******************************************************************************/
-#include
-#include
-#include
#include
#include
-#include
#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
#include
-bool writeall(int fd, const void* p, size_t size)
+#include "crc32.h"
+
+#if !defined(sortix)
+__BEGIN_DECLS
+size_t preadall(int fd, void* buf, size_t count, off_t off);
+size_t preadleast(int fd, void* buf, size_t least, size_t max, off_t off);
+size_t pwriteall(int fd, const void* buf, size_t count, off_t off);
+size_t pwriteleast(int fd, const void* buf, size_t least, size_t max, off_t off);
+size_t readall(int fd, void* buf, size_t count);
+size_t readleast(int fd, void* buf, size_t least, size_t max);
+size_t writeall(int fd, const void* buf, size_t count);
+size_t writeleast(int fd, const void* buf, size_t least, size_t max);
+__END_DECLS
+#endif
+
+uint32_t HostModeToInitRD(mode_t mode)
{
- const uint8_t* buffer = (const uint8_t*) p;
+ uint32_t result = mode & 0777; // Lower 9 bits per POSIX and tradition.
+ if ( S_ISVTX & mode ) { result |= INITRD_S_ISVTX; }
+ if ( S_ISSOCK(mode) ) { result |= INITRD_S_IFSOCK; }
+ if ( S_ISLNK(mode) ) { result |= INITRD_S_IFLNK; }
+ if ( S_ISREG(mode) ) { result |= INITRD_S_IFREG; }
+ if ( S_ISBLK(mode) ) { result |= INITRD_S_IFBLK; }
+ if ( S_ISDIR(mode) ) { result |= INITRD_S_IFDIR; }
+ if ( S_ISCHR(mode) ) { result |= INITRD_S_IFCHR; }
+ if ( S_ISFIFO(mode) ) { result |= INITRD_S_IFIFO; }
+ return result;
+}
- size_t bytesWritten = 0;
+mode_t InitRDModeToHost(uint32_t mode)
+{
+ mode_t result = mode & 0777; // Lower 9 bits per POSIX and tradition.
+ if ( INITRD_S_ISVTX & mode ) { result |= S_ISVTX; }
+ if ( INITRD_S_ISSOCK(mode) ) { result |= S_IFSOCK; }
+ if ( INITRD_S_ISLNK(mode) ) { result |= S_IFLNK; }
+ if ( INITRD_S_ISREG(mode) ) { result |= S_IFREG; }
+ if ( INITRD_S_ISBLK(mode) ) { result |= S_IFBLK; }
+ if ( INITRD_S_ISDIR(mode) ) { result |= S_IFDIR; }
+ if ( INITRD_S_ISCHR(mode) ) { result |= S_IFCHR; }
+ if ( INITRD_S_ISFIFO(mode) ) { result |= S_IFIFO; }
+ return result;
+}
- while ( bytesWritten < size )
+struct Node;
+struct DirEntry;
+
+struct DirEntry
+{
+ char* name;
+ Node* node;
+};
+
+struct Node
+{
+ char* path;
+ uint32_t ino;
+ uint32_t nlink;
+ size_t direntsused;
+ size_t direntslength;
+ DirEntry* dirents;
+ mode_t mode;
+ time_t ctime;
+ time_t mtime;
+};
+
+void FreeNode(Node* node)
+{
+ if ( 1 < node->nlink ) { node->nlink--; return; }
+ for ( size_t i = 0; i < node->direntsused; i++ )
{
- ssize_t written = write(fd, buffer + bytesWritten, size - bytesWritten);
- if ( written < 0 ) { return false; }
- bytesWritten += written;
+ DirEntry* entry = node->dirents + i;
+ if ( strcmp(entry->name, ".") != 0 && strcmp(entry->name, "..") != 0 )
+ {
+ FreeNode(entry->node);
+ }
+ free(entry->name);
+ }
+ free(node->dirents);
+ free(node->path);
+ free(node);
+}
+
+Node* RecursiveSearch(const char* rootpath, uint32_t* ino, Node* parent = NULL)
+{
+ struct stat st;
+ if ( lstat(rootpath, &st) ) { perror(rootpath); return NULL; }
+
+ Node* node = (Node*) calloc(1, sizeof(Node));
+ if ( !node ) { return NULL; }
+
+ node->mode = st.st_mode;
+ node->ino = (*ino)++;
+ node->ctime = st.st_ctime;
+ node->mtime = st.st_mtime;
+
+ char* pathclone = strdup(rootpath);
+ if ( !pathclone ) { perror("strdup"); free(node); return NULL; }
+
+ node->path = pathclone;
+
+ if ( !S_ISDIR(st.st_mode) ) { return node; }
+
+ DIR* dir = opendir(rootpath);
+ if ( !dir ) { perror(rootpath); FreeNode(node); return NULL; }
+
+ size_t rootpathlen = strlen(rootpath);
+
+ bool successful = true;
+ struct dirent* entry;
+ while ( (entry = readdir(dir)) )
+ {
+ size_t namelen = strlen(entry->d_name);
+ size_t subpathlen = namelen + 1 + rootpathlen;
+ char* subpath = (char*) malloc(subpathlen+1);
+ if ( !subpath ) { perror("malloc"); successful = false; break; }
+ stpcpy(stpcpy(stpcpy(subpath, rootpath), "/"), entry->d_name);
+
+ Node* child = NULL;
+ if ( !strcmp(entry->d_name, ".") ) { child = node; }
+ if ( !strcmp(entry->d_name, "..") ) { child = parent ? parent : node; }
+ if ( !child ) { child = RecursiveSearch(subpath, ino, node); }
+ free(subpath);
+ if ( !child ) { successful = false; break; }
+
+ if ( node->direntsused == node->direntslength )
+ {
+ size_t oldlength = node->direntslength;
+ size_t newlength = oldlength ? 2 * oldlength : 8;
+ size_t newsize = sizeof(DirEntry) * newlength;
+ DirEntry* newdirents = (DirEntry*) realloc(node->dirents, newsize);
+ if ( !newdirents ) { perror("realloc"); successful = false; break; }
+ node->dirents = newdirents;
+ node->direntslength = newlength;
+ }
+
+ char* nameclone = strdup(entry->d_name);
+ if ( !nameclone ) { perror("strdup"); successful = false; break; }
+
+ DirEntry* entry = node->dirents + node->direntsused++;
+
+ entry->name = nameclone;
+ entry->node = child;
+ }
+
+ closedir(dir);
+ if ( !successful ) { FreeNode(node); return NULL; }
+ return node;
+}
+
+bool WriteNode(struct initrd_superblock* sb, int fd, const char* outputname,
+ Node* node)
+{ {
+ uint32_t filesize = 0;
+ uint32_t origfssize = sb->fssize;
+ uint32_t dataoff = origfssize;
+ uint32_t filestart = dataoff;
+
+ if ( S_ISLNK(node->mode) ) // Symbolic link
+ {
+ const size_t NAME_SIZE = 1024UL;
+ char name[NAME_SIZE];
+ ssize_t namelen = readlink(node->path, name, NAME_SIZE);
+ if ( namelen < 0 ) { goto ioreadlink; }
+ filesize = (uint32_t) namelen;
+ if ( pwriteall(fd, name, filesize, dataoff) < filesize ) goto ioread;
+ dataoff += filesize;
+ }
+ else if ( S_ISREG(node->mode) ) // Regular file
+ {
+ int nodefd = open(node->path, O_RDONLY);
+ if ( nodefd < 0 ) { goto ioopen; }
+ const size_t BUFFER_SIZE = 16UL * 1024UL;
+ uint8_t buffer[BUFFER_SIZE];
+ ssize_t amount;
+ while ( 0 < (amount = read(nodefd, buffer, BUFFER_SIZE)) )
+ {
+ if ( pwriteall(fd, buffer, amount, dataoff) < (size_t) amount )
+ {
+ close(nodefd);
+ goto iowrite;
+ }
+ dataoff += amount;
+ filesize += amount;
+ }
+ close(nodefd);
+ if ( amount < 0 ) { goto ioread; }
+ }
+ else if ( S_ISDIR(node->mode) ) // Directory
+ {
+ for ( size_t i = 0; i < node->direntsused; i++ )
+ {
+ DirEntry* entry = node->dirents + i;
+ const char* name = entry->name;
+ size_t namelen = strlen(entry->name);
+ struct initrd_dirent dirent;
+ dirent.inode = entry->node->ino;
+ dirent.namelen = (uint16_t) namelen;
+ dirent.reclen = sizeof(dirent) + dirent.namelen + 1;
+ dirent.reclen += dirent.reclen % 4; // Align entries.
+ size_t entsize = sizeof(dirent);
+ ssize_t hdramt = pwriteall(fd, &dirent, entsize, dataoff);
+ ssize_t nameamt = pwriteall(fd, name, namelen+1, dataoff + entsize);
+ if ( hdramt < (ssize_t) entsize || nameamt < (ssize_t) (namelen+1) )
+ goto iowrite;
+ filesize += dirent.reclen;
+ dataoff += dirent.reclen;
+ }
+ }
+
+ struct initrd_inode inode;
+ inode.mode = HostModeToInitRD(node->mode);
+ inode.uid = 1;
+ inode.gid = 1;
+ inode.nlink = node->nlink;
+ inode.ctime = (uint64_t) node->ctime;
+ inode.mtime = (uint64_t) node->mtime;
+ inode.dataoffset = filestart;
+ inode.size = filesize;
+
+ uint32_t inodepos = sb->inodeoffset + node->ino * sb->inodesize;
+ uint32_t inodesize = sizeof(inode);
+ if ( pwriteall(fd, &inode, inodesize, inodepos) < inodesize ) goto iowrite;
+
+ uint32_t increment = dataoff - origfssize;
+ sb->fssize += increment;
+
+ return true;
+}
+ ioreadlink:
+ error(0, errno, "readlink: %s", node->path);
+ return false;
+ ioopen:
+ error(0, errno, "open: %s", node->path);
+ return false;
+ ioread:
+ error(0, errno, "read: %s", node->path);
+ return false;
+ iowrite:
+ error(0, errno, "write: %s", outputname);
+ return false;
+}
+
+bool WriteNodeRecursive(struct initrd_superblock* sb, int fd,
+ const char* outputname, Node* node)
+{
+ if ( !WriteNode(sb, fd, outputname, node) ) { return false; }
+
+ if ( !S_ISDIR(node->mode) ) { return true; }
+
+ for ( size_t i = 0; i < node->direntsused; i++ )
+ {
+ DirEntry* entry = node->dirents + i;
+ const char* name = entry->name;
+ Node* child = entry->node;
+ if ( !strcmp(name, ".") || !strcmp(name, ".." ) ) { continue; }
+ if ( !WriteNodeRecursive(sb, fd, outputname, child) ) { return false; }
}
return true;
}
-uint8_t ContinueChecksum(uint8_t checksum, const void* p, size_t size)
+bool Format(const char* outputname, int fd, uint32_t inodecount, Node* root)
{
- const uint8_t* buffer = (const uint8_t*) p;
- while ( size-- )
+ struct initrd_superblock sb;
+ memset(&sb, 0, sizeof(sb));
+ strncpy(sb.magic, "sortix-initrd-2", sizeof(sb.magic));
+ sb.revision = 0;
+ sb.fssize = sizeof(sb);
+ sb.inodesize = sizeof(initrd_inode);
+ sb.inodeoffset = sizeof(sb);
+ sb.inodecount = inodecount;
+ sb.root = root->ino;
+
+ uint32_t inodebytecount = sb.inodesize * sb.inodecount;
+ sb.fssize += inodebytecount;
+
+ if ( !WriteNodeRecursive(&sb, fd, outputname, root) ) { return false; }
+
+ uint32_t crcsize = sizeof(uint32_t);
+ sb.sumalgorithm = INITRD_ALGO_CRC32;
+ sb.sumsize = crcsize;
+ sb.fssize += sb.sumsize;
+
+ if ( pwriteall(fd, &sb, sizeof(sb), 0) < sizeof(sb) )
{
- checksum += *buffer++;
+ error(0, errno, "write: %s", outputname);
+ return false;
}
- return checksum;
+
+ uint32_t checksize = sb.fssize - sb.sumsize;
+ uint32_t crc;
+ if ( !CRC32File(&crc, outputname, fd, 0, checksize) ) { return false; }
+ if ( pwriteall(fd, &crc, crcsize, checksize) < crcsize ) { return false; }
+
+ return true;
}
-void usage(int argc, char* argv[])
+bool Format(const char* pathname, uint32_t inodecount, Node* root)
{
- 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");
+ int fd = open(pathname, O_RDWR | O_CREAT | O_TRUNC, 0666);
+ bool result = Format(pathname, fd, inodecount, root);
+ close(fd);
+ return result;
}
-void version()
+void Usage(FILE* fp, const char* argv0)
{
- 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");
+ fprintf(fp, "usage: %s -o \n", argv0);
+ fprintf(fp, "Creates a init ramdisk for the Sortix kernel.\n");
}
-bool verbose = false;
+void Help(FILE* fp, const char* argv0)
+{
+ Usage(fp, argv0);
+}
+
+void Version(FILE* fp, const char* argv0)
+{
+ fprintf(fp, "mkinitrd 0.2\n");
+ fprintf(fp, "Copyright (C) 2012 Jonas 'Sortie' Termansen\n");
+ fprintf(fp, "This is free software; see the source for copying conditions. There is NO\n");
+ fprintf(fp, "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
+ fprintf(fp, "website: http://www.maxsi.org/software/sortix/\n");
+}
int main(int argc, char* argv[])
{
+ const char* argv0 = argv[0];
+ if ( argc < 2 ) { Usage(stdout, argv0); exit(0); }
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 )
+ int argsleft = argc - i - 1;
+ const char* arg = argv[i];
+ if ( arg[0] != '-' ) { continue; }
+ argv[i] = NULL;
+ if ( !strcmp(arg, "--") ) { break; }
+ if ( !strcmp(arg, "--help") ) { Help(stdout, argv0); exit(0); }
+ if ( !strcmp(arg, "--usage") ) { Usage(stdout, argv0); exit(0); }
+ if ( !strcmp(arg, "--version") ) { Version(stdout, argv0); exit(0); }
+ if ( !strcmp(arg, "-o") || !strcmp(arg, "--output") )
{
- if ( i + 1 < argc )
+ if ( argsleft < 1 )
{
- dest = argv[i+1];
- argv[i+1] = NULL;
+ fprintf(stderr, "No output file specified\n");
+ Usage(stderr, argv0);
+ exit(1);
}
- 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++;
+ dest = argv[++i]; argv[i] = NULL;
+ continue;
}
+ fprintf(stderr, "%s: unknown option: %s\n", argv0, arg);
+ Usage(stderr, argv0);
+ exit(1);
}
- 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;
- }
-
- // Keep track of the file checksum.
- Sortix::InitRD::Trailer trailer;
- trailer.sum = 0;
-
- // Write the initrd headers.
- Sortix::InitRD::Header header;
- memset(&header, 0, sizeof(header));
- strcpy(header.magic, "sortix-initrd-1");
- header.numfiles = numfiles;
- trailer.sum = ContinueChecksum(trailer.sum, &header, sizeof(header));
- 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;
+ const char* rootstr = NULL;
+ int args = 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;
- }
-
- trailer.sum = ContinueChecksum(trailer.sum, &fileheader, sizeof(fileheader));
- 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;
- }
-
- trailer.sum = ContinueChecksum(trailer.sum, &buffer, bytesread);
- if ( !writeall(fd, buffer, bytesread) )
- {
- error(0, errno, "write: %s", dest);
- close(fd);
- unlink(dest);
- return 1;
- }
-
- readsofar += bytesread;
- }
-
- fileoffset += filesize;
- filenum++;
-
- close(filefd);
+ if ( !argv[i] ) { continue; }
+ args++;
+ rootstr = argv[i];
}
- if ( !writeall(fd, &trailer, sizeof(trailer)) )
+ const char* errmsg = NULL;
+ if ( !errmsg && args < 1 ) { errmsg = "no root specified"; }
+ if ( !errmsg && 1 < args ) { errmsg = "too many roots"; }
+ if ( !errmsg && !dest ) { errmsg = "no destination specified"; }
+
+ if ( errmsg )
{
- error(0, errno, "write: %s", dest);
- close(fd);
- unlink(dest);
- return 1;
+ fprintf(stderr, "%s: %s\n", argv0, errmsg),
+ Usage(stderr, argv0);
+ exit(1);
}
+ uint32_t inodecount = 1;
+ Node* root = RecursiveSearch(rootstr, &inodecount);
+ if ( !root ) { exit(1); }
+
+ if ( !Format(dest, inodecount, root) ) { exit(1); }
+
+ FreeNode(root);
+
return 0;
}
+
diff --git a/sortix/fs/initfs.cpp b/sortix/fs/initfs.cpp
index c5bc0558..941788e6 100644
--- a/sortix/fs/initfs.cpp
+++ b/sortix/fs/initfs.cpp
@@ -1,6 +1,6 @@
/******************************************************************************
- COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
+ Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
This file is part of Sortix.
@@ -141,11 +141,13 @@ namespace Sortix
typedef Device DevDirectory;
public:
- DevInitFSDir();
+ DevInitFSDir(uint32_t dir);
virtual ~DevInitFSDir();
private:
size_t position;
+ uint32_t dir;
+ uint32_t numfiles;
public:
virtual void Rewind();
@@ -153,9 +155,11 @@ namespace Sortix
};
- DevInitFSDir::DevInitFSDir()
+ DevInitFSDir::DevInitFSDir(uint32_t dir)
{
- position = 0;
+ this->position = 0;
+ this->dir = dir;
+ this->numfiles = InitRD::GetNumFiles(dir);
}
DevInitFSDir::~DevInitFSDir()
@@ -170,17 +174,20 @@ namespace Sortix
int DevInitFSDir::Read(sortix_dirent* dirent, size_t available)
{
if ( available <= sizeof(sortix_dirent) ) { return -1; }
- if ( InitRD::GetNumFiles() <= position )
+ if ( numfiles <= position )
{
dirent->d_namelen = 0;
dirent->d_name[0] = 0;
return 0;
}
- const char* name = InitRD::GetFilename(position);
+ const char* name = InitRD::GetFilename(dir, position);
size_t namelen = String::Length(name);
size_t needed = sizeof(sortix_dirent) + namelen + 1;
+ // Oh right, the kernel is stupid and doesn't support dot and dotdot.
+ if ( name[0] == '.' ) { position++; return Read(dirent, available); }
+
if ( available < needed )
{
dirent->d_namelen = needed;
@@ -210,13 +217,16 @@ namespace Sortix
if ( !path[0] || (path[0] == '/' && !path[1]) )
{
if ( lowerflags != O_SEARCH ) { Error::Set(EISDIR); return NULL; }
- return new DevInitFSDir();
+ return new DevInitFSDir(InitRD::Root());
}
if ( *path++ != '/' ) { Error::Set(ENOENT); return NULL; }
- const byte* buffer = InitRD::Open(path, &buffersize);
- if ( !buffer ) { Error::Set(ENOENT); return NULL; }
+ uint32_t ino = InitRD::Traverse(InitRD::Root(), path);
+ if ( !ino ) { return NULL; }
+
+ const byte* buffer = InitRD::Open(ino, &buffersize);
+ if ( !buffer ) { return NULL; }
if ( lowerflags == O_SEARCH ) { Error::Set(ENOTDIR); return NULL; }
if ( lowerflags != O_RDONLY ) { Error::Set(EROFS); return NULL; }
diff --git a/sortix/include/sortix/initrd.h b/sortix/include/sortix/initrd.h
index 6176995b..db370157 100644
--- a/sortix/include/sortix/initrd.h
+++ b/sortix/include/sortix/initrd.h
@@ -1,6 +1,6 @@
-/******************************************************************************
+/*******************************************************************************
- COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
This file is part of Sortix.
@@ -14,46 +14,89 @@
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 .
+ 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.
+ The Sortix init ramdisk filesystem format.
-******************************************************************************/
+*******************************************************************************/
#ifndef SORTIX_INITRD_H
#define SORTIX_INITRD_H
-namespace Sortix
+#include
+
+__BEGIN_DECLS
+
+#define INITRD_ALGO_CRC32 0
+
+#define INITRD_S_IXOTH 01
+#define INITRD_S_IWOTH 02
+#define INITRD_S_IROTH 03
+#define INITRD_S_IRWXO 07
+#define INITRD_S_IXGRP 010
+#define INITRD_S_IWGRP 020
+#define INITRD_S_IRGRP 040
+#define INITRD_S_IRWXG 070
+#define INITRD_S_IXUSR 0100
+#define INITRD_S_IWUSR 0200
+#define INITRD_S_IRUSR 0400
+#define INITRD_S_IRWXU 0700
+#define INITRD_S_IFMT 0xF000
+#define INITRD_S_IFSOCK 0xC000
+#define INITRD_S_IFLNK 0xA000
+#define INITRD_S_IFREG 0x8000
+#define INITRD_S_IFBLK 0x6000
+#define INITRD_S_IFDIR 0x4000
+#define INITRD_S_IFCHR 0x2000
+#define INITRD_S_IFIFO 0x1000
+/* Intentionally not part of Sortix. */
+/*#define INITRD_S_ISUID 0x0800 */
+/*#define INITRD_S_ISGID 0x0400 */
+#define INITRD_S_ISVTX 0x0200
+#define INITRD_S_ISSOCK(mode) ((mode & INITRD_S_IFMT) == INITRD_S_IFSOCK)
+#define INITRD_S_ISLNK(mode) ((mode & INITRD_S_IFMT) == INITRD_S_IFLNK)
+#define INITRD_S_ISREG(mode) ((mode & INITRD_S_IFMT) == INITRD_S_IFREG)
+#define INITRD_S_ISBLK(mode) ((mode & INITRD_S_IFMT) == INITRD_S_IFBLK)
+#define INITRD_S_ISDIR(mode) ((mode & INITRD_S_IFMT) == INITRD_S_IFDIR)
+#define INITRD_S_ISCHR(mode) ((mode & INITRD_S_IFMT) == INITRD_S_IFCHR)
+#define INITRD_S_ISFIFO(mode) ((mode & INITRD_S_IFMT) == INITRD_S_IFIFO)
+
+typedef struct initrd_superblock
{
- namespace InitRD
- {
- struct Header;
- struct FileHeader;
+ char magic[16]; // "sortix-initrd-2"
+ uint32_t fssize;
+ uint32_t revision;
+ uint32_t inodesize;
+ uint32_t inodecount;
+ uint32_t inodeoffset;
+ uint32_t root;
+ uint32_t sumalgorithm;
+ uint32_t sumsize;
+} initrd_superblock_t;
- struct Header
- {
- char magic[16]; // Contains "sortix-initrd-1"
- uint32_t numfiles;
- // FileHeader[numfiles];
- };
+typedef struct initrd_inode
+{
+ uint32_t mode;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t nlink;
+ uint64_t ctime;
+ uint64_t mtime;
+ uint32_t dataoffset;
+ uint32_t size;
+} initrd_inode_t;
- 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];
- };
+typedef struct initrd_dirent
+{
+ uint32_t inode;
+ uint16_t reclen;
+ uint16_t namelen;
+ char name[0];
+} initrd_dirent_t;
- struct Trailer
- {
- uint8_t sum; // sum of all bytes but the trailer.
- };
- }
-}
+__END_DECLS
#endif
+
diff --git a/sortix/include/sortix/stat.h b/sortix/include/sortix/stat.h
index 12a37afd..0e88bd7b 100644
--- a/sortix/include/sortix/stat.h
+++ b/sortix/include/sortix/stat.h
@@ -1,6 +1,6 @@
/*******************************************************************************
- COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2012.
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
This file is part of Sortix.
@@ -59,17 +59,25 @@ struct stat
#define S_IWUSR 0200
#define S_IRUSR 0400
#define S_IRWXU 0700
-#define S_IFDIR 0040000
-#define S_IFBLK 0060000
-#define S_IFREG 0100000
-#define S_IFLNK 0200000 /* not the same as in Linux */
-/* TODO: Define the other useful values and implement their features. */
-
-#define S_ISBLK(m) ((m) & S_IFBLK)
-#define S_ISDIR(m) ((m) & S_IFDIR)
-#define S_ISREG(m) ((m) & S_IFREG)
-#define S_ISLNK(m) ((m) & S_IFLNK)
-/* TODO: Define the other useful macros and implement their features. */
+#define S_IFMT 0xF000
+#define S_IFSOCK 0xC000
+#define S_IFLNK 0xA000
+#define S_IFREG 0x8000
+#define S_IFBLK 0x6000
+#define S_IFDIR 0x4000
+#define S_IFCHR 0x2000
+#define S_IFIFO 0x1000
+/* Intentionally not part of Sortix. */
+/*#define S_ISUID 0x0800 */
+/*#define S_ISGID 0x0400 */
+#define S_ISVTX 0x0200
+#define S_ISSOCK(mode) ((mode & S_IFMT) == S_IFSOCK)
+#define S_ISLNK(mode) ((mode & S_IFMT) == S_IFLNK)
+#define S_ISREG(mode) ((mode & S_IFMT) == S_IFREG)
+#define S_ISBLK(mode) ((mode & S_IFMT) == S_IFBLK)
+#define S_ISDIR(mode) ((mode & S_IFMT) == S_IFDIR)
+#define S_ISCHR(mode) ((mode & S_IFMT) == S_IFCHR)
+#define S_ISFIFO(mode) ((mode & S_IFMT) == S_IFIFO)
__END_DECLS
diff --git a/sortix/initrd.cpp b/sortix/initrd.cpp
index 527acfd3..e24f67f5 100644
--- a/sortix/initrd.cpp
+++ b/sortix/initrd.cpp
@@ -1,6 +1,6 @@
-/******************************************************************************
+/*******************************************************************************
- COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
+ Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
This file is part of Sortix.
@@ -14,119 +14,222 @@
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 .
+ You should have received a copy of the GNU General Public License along with
+ Sortix. If not, see .
initrd.cpp
- Declares the structure of the Sortix ramdisk.
+ Provides low-level access to a Sortix init ramdisk.
-******************************************************************************/
+*******************************************************************************/
#include
+#include
+#include
#include
-#include "initrd.h"
+#include
#include
#include
+#include
+#include "initrd.h"
#include "syscall.h"
-#include
-
-#include // DEBUG
using namespace Maxsi;
-namespace Sortix
+namespace Sortix {
+namespace InitRD {
+
+uint8_t* initrd;
+size_t initrdsize;
+const initrd_superblock_t* sb;
+
+static uint32_t HostModeToInitRD(mode_t mode)
{
- namespace InitRD
+ uint32_t result = mode & 0777; // Lower 9 bits per POSIX and tradition.
+ if ( S_ISVTX & mode ) { result |= INITRD_S_ISVTX; }
+ if ( S_ISSOCK(mode) ) { result |= INITRD_S_IFSOCK; }
+ if ( S_ISLNK(mode) ) { result |= INITRD_S_IFLNK; }
+ if ( S_ISREG(mode) ) { result |= INITRD_S_IFREG; }
+ if ( S_ISBLK(mode) ) { result |= INITRD_S_IFBLK; }
+ if ( S_ISDIR(mode) ) { result |= INITRD_S_IFDIR; }
+ if ( S_ISCHR(mode) ) { result |= INITRD_S_IFCHR; }
+ if ( S_ISFIFO(mode) ) { result |= INITRD_S_IFIFO; }
+ return result;
+}
+
+static mode_t InitRDModeToHost(uint32_t mode)
+{
+ mode_t result = mode & 0777; // Lower 9 bits per POSIX and tradition.
+ if ( INITRD_S_ISVTX & mode ) { result |= S_ISVTX; }
+ if ( INITRD_S_ISSOCK(mode) ) { result |= S_IFSOCK; }
+ if ( INITRD_S_ISLNK(mode) ) { result |= S_IFLNK; }
+ if ( INITRD_S_ISREG(mode) ) { result |= S_IFREG; }
+ if ( INITRD_S_ISBLK(mode) ) { result |= S_IFBLK; }
+ if ( INITRD_S_ISDIR(mode) ) { result |= S_IFDIR; }
+ if ( INITRD_S_ISCHR(mode) ) { result |= S_IFCHR; }
+ if ( INITRD_S_ISFIFO(mode) ) { result |= S_IFIFO; }
+ return result;
+}
+
+uint32_t Root()
+{
+ return sb->root;
+}
+
+static const initrd_inode_t* GetInode(uint32_t inode)
+{
+ if ( sb->inodecount <= inode ) { Error::Set(EINVAL); return NULL; }
+ uint32_t pos = sb->inodeoffset + sb->inodesize * inode;
+ return (const initrd_inode_t*) (initrd + pos);
+}
+
+bool Stat(uint32_t ino, struct stat* st)
+{
+ const initrd_inode_t* inode = GetInode(ino);
+ if ( !inode ) { return false; }
+ st->st_ino = ino;
+ st->st_mode = HostModeToInitRD(inode->mode);
+ st->st_nlink = inode->nlink;
+ st->st_uid = inode->uid;
+ st->st_gid = inode->gid;
+ st->st_size = inode->size;
+ st->st_atime = inode->mtime;
+ st->st_ctime = inode->ctime;
+ st->st_mtime = inode->mtime;
+ st->st_blksize = 1;
+ st->st_blocks = inode->size;
+ return true;
+}
+
+uint8_t* Open(uint32_t ino, size_t* size)
+{
+ const initrd_inode_t* inode = GetInode(ino);
+ if ( !inode ) { return NULL; }
+ *size = inode->size;
+ return initrd + inode->dataoffset;
+}
+
+uint32_t Traverse(uint32_t ino, const char* name)
+{
+ const initrd_inode_t* inode = GetInode(ino);
+ if ( !inode ) { return 0; }
+ if ( !INITRD_S_ISDIR(inode->mode) ) { Error::Set(ENOTDIR); return 0; }
+ uint32_t offset = 0;
+ while ( offset < inode->size )
{
- byte* initrd;
- size_t initrdsize;
-#ifdef JSSORTIX
- // JSVM never tells JSSortix how big the initrd is!
- const bool CHECK_CHECKSUM = false;
-#else
- const bool CHECK_CHECKSUM = true;
-#endif
-
- size_t GetNumFiles()
+ uint32_t pos = inode->dataoffset + offset;
+ const initrd_dirent* dirent = (const initrd_dirent*) (initrd + pos);
+ if ( dirent->namelen && !String::Compare(dirent->name, name) )
{
- Header* header = (Header*) initrd;
- return header->numfiles;
- }
- const char* GetFilename(size_t index)
- {
- Header* header = (Header*) initrd;
- if ( index >= header->numfiles ) { return NULL; }
- FileHeader* fhtbl = (FileHeader*) (initrd + sizeof(Header));
- FileHeader* fileheader = &(fhtbl[index]);
- return fileheader->name;
+ return dirent->inode;
}
+ offset += dirent->reclen;
+ }
+ Error::Set(ENOENT);
+ return 0;
+}
- uint8_t ContinueChecksum(uint8_t checksum, const void* p, size_t size)
- {
- const uint8_t* buffer = (const uint8_t*) p;
- while ( size-- )
- {
- checksum += *buffer++;
- }
- return checksum;
- }
- void CheckSum()
- {
- Trailer* trailer = (Trailer*) (initrd + initrdsize - sizeof(Trailer));
- uint8_t checksum = ContinueChecksum(0, initrd, initrdsize - sizeof(Trailer));
- if ( trailer->sum != checksum )
- {
- PanicF("InitRD Checksum failed: the ramdisk may have been "
- "corrupted by the bootloader: Got %u instead of %u "
- "when checking the ramdisk at 0x%p + 0x%zx bytes\n",
- checksum, trailer->sum, initrd, initrdsize);
- }
- }
+const char* GetFilename(uint32_t dir, size_t index)
+{
+ const initrd_inode_t* inode = GetInode(dir);
+ if ( !inode ) { return 0; }
+ if ( !INITRD_S_ISDIR(inode->mode) ) { Error::Set(ENOTDIR); return 0; }
+ uint32_t offset = 0;
+ while ( offset < inode->size )
+ {
+ uint32_t pos = inode->dataoffset + offset;
+ const initrd_dirent* dirent = (const initrd_dirent*) (initrd + pos);
+ if ( index-- == 0 ) { return dirent->name; }
+ offset += dirent->reclen;
+ }
+ Error::Set(EINVAL);
+ return NULL;
+}
- void Init(addr_t phys, size_t size)
- {
- // First up, map the initrd onto the kernel's address space.
- addr_t virt = Memory::GetInitRD();
- size_t amount = 0;
- while ( amount < size )
- {
- if ( !Memory::MapKernel(phys + amount, virt + amount) )
- {
- Panic("Unable to map the init ramdisk into virtual memory");
- }
- amount += 0x1000UL;
- }
+size_t GetNumFiles(uint32_t dir)
+{
+ const initrd_inode_t* inode = GetInode(dir);
+ if ( !inode ) { return 0; }
+ if ( !INITRD_S_ISDIR(inode->mode) ) { Error::Set(ENOTDIR); return 0; }
+ uint32_t offset = 0;
+ size_t numentries = 0;
+ while ( offset < inode->size )
+ {
+ uint32_t pos = inode->dataoffset + offset;
+ const initrd_dirent* dirent = (const initrd_dirent*) (initrd + pos);
+ numentries++;
+ offset += dirent->reclen;
+ }
+ return numentries;
+}
- Memory::Flush();
-
- initrd = (byte*) virt;
- initrdsize = size;
- if ( size < sizeof(Header) ) { PanicF("initrd.cpp: initrd is too small"); }
- Header* header = (Header*) initrd;
- if ( String::Compare(header->magic, "sortix-initrd-1") != 0 ) { PanicF("initrd.cpp: invalid magic value in the initrd"); }
- size_t sizeneeded = sizeof(Header) + header->numfiles * sizeof(FileHeader);
- if ( size < sizeneeded ) { PanicF("initrd.cpp: initrd is too small"); }
- // TODO: We need to do more validation here!
-
- if ( CHECK_CHECKSUM ) { CheckSum(); }
- }
-
- byte* Open(const char* filepath, size_t* size)
- {
- Header* header = (Header*) initrd;
- FileHeader* fhtbl = (FileHeader*) (initrd + sizeof(Header));
- for ( uint32_t i = 0; i < header->numfiles; i++ )
- {
- FileHeader* fileheader = &(fhtbl[i]);
-
- if ( String::Compare(filepath, fileheader->name) != 0 ) { continue; }
-
- *size = fileheader->size;
- return initrd + fileheader->offset;
- }
-
- return NULL;
- }
+void CheckSum()
+{
+ uint32_t amount = sb->fssize - sb->sumsize;
+ uint8_t* filesum = initrd + amount;
+ if ( sb->sumalgorithm != INITRD_ALGO_CRC32 )
+ {
+ Log::PrintF("Warning: InitRD checksum algorithm not supported\n");
+ return;
+ }
+ uint32_t crc32 = *((uint32_t*) filesum);
+ uint32_t filecrc32 = CRC32::Hash(initrd, amount);
+ if ( crc32 != filecrc32 )
+ {
+ PanicF("InitRD had checksum %X, expected %X: this means the ramdisk "
+ "may have been corrupted by the bootloader.", filecrc32, crc32);
}
}
+
+void Init(addr_t phys, size_t size)
+{
+ // First up, map the initrd onto the kernel's address space.
+ addr_t virt = Memory::GetInitRD();
+ size_t amount = 0;
+ while ( amount < size )
+ {
+ if ( !Memory::MapKernel(phys + amount, virt + amount) )
+ {
+ Panic("Unable to map the init ramdisk into virtual memory");
+ }
+ amount += 0x1000UL;
+ }
+
+ Memory::Flush();
+
+ initrd = (uint8_t*) virt;
+ initrdsize = size;
+
+ if ( size < sizeof(*sb) ) { PanicF("initrd is too small"); }
+ sb = (const initrd_superblock_t*) initrd;
+
+ if ( !String::StartsWith(sb->magic, "sortix-initrd") )
+ {
+ Panic("Invalid magic value in initrd. This means the ramdisk may have "
+ "been corrupted by the bootloader, or that an incompatible file "
+ "has been passed to the kernel.");
+ }
+
+ if ( String::Compare(sb->magic, "sortix-initrd-1") == 0 )
+ {
+ Panic("Sortix initrd format version 1 is no longer supported.");
+ }
+
+ if ( String::Compare(sb->magic, "sortix-initrd-2") != 0 )
+ {
+ Panic("The initrd has a format that isn't supported. Perhaps it is "
+ "too new? Try downgrade or regenerate the initrd.");
+ }
+
+ if ( size < sb->fssize )
+ {
+ PanicF("The initrd said it is %u bytes, but the kernel was only passed "
+ "%zu bytes by the bootloader, which is not enough.", sb->fssize,
+ size);
+ }
+
+ CheckSum();
+}
+
+} // namespace InitRD
+} // namespace Sortix
diff --git a/sortix/initrd.h b/sortix/initrd.h
index a3d9826d..a5531d65 100644
--- a/sortix/initrd.h
+++ b/sortix/initrd.h
@@ -1,6 +1,6 @@
-/******************************************************************************
+/*******************************************************************************
- COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
+ Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
This file is part of Sortix.
@@ -14,26 +14,29 @@
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 .
+ 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.
+ Provides low-level access to a Sortix init ramdisk.
-******************************************************************************/
+*******************************************************************************/
#ifndef SORTIX_INITRD_KERNEL_H
#define SORTIX_INITRD_KERNEL_H
-namespace Sortix
-{
- namespace InitRD
- {
- void Init(addr_t phys, size_t size);
- byte* Open(const char* filepath, size_t* size);
- const char* GetFilename(size_t index);
- size_t GetNumFiles();
- }
-}
+namespace Sortix {
+namespace InitRD {
+
+void Init(addr_t phys, size_t size);
+uint32_t Root();
+bool Stat(uint32_t inode, struct stat* st);
+uint8_t* Open(uint32_t inode, size_t* size);
+uint32_t Traverse(uint32_t inode, const char* name);
+const char* GetFilename(uint32_t dir, size_t index);
+size_t GetNumFiles(uint32_t dir);
+
+} // namespace InitRD
+} // namespace Sortix
#endif
diff --git a/sortix/kernel.cpp b/sortix/kernel.cpp
index 50b1bb1a..9d7b33e0 100644
--- a/sortix/kernel.cpp
+++ b/sortix/kernel.cpp
@@ -1,6 +1,6 @@
/*******************************************************************************
- COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011, 2012.
+ Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
This file is part of Sortix.
@@ -197,6 +197,7 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo)
// time to load the initial user-space programs and start execution of
// the actual operating system.
+ uint32_t inode;
byte* program;
size_t programsize;
@@ -214,7 +215,9 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo)
idle->addrspace = idleaddrspace;
Memory::SwitchAddressSpace(idleaddrspace);
Scheduler::SetDummyThreadOwner(idle);
- program = InitRD::Open("idle", &programsize);
+ inode = InitRD::Traverse(InitRD::Root(), "idle");
+ if ( inode == NULL ) { PanicF("initrd did not contain 'idle'"); }
+ program = InitRD::Open(inode, &programsize);
if ( program == NULL ) { PanicF("initrd did not contain 'idle'"); }
addr_t idlestart = ELF::Construct(idle, program, programsize);
if ( !idlestart ) { Panic("could not construct ELF image for idle process"); }
@@ -228,7 +231,9 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo)
init->addrspace = initaddrspace;
Memory::SwitchAddressSpace(initaddrspace);
Scheduler::SetDummyThreadOwner(init);
- program = InitRD::Open("init", &programsize);
+ inode = InitRD::Traverse(InitRD::Root(), "init");
+ if ( inode == NULL ) { PanicF("initrd did not contain 'init'"); }
+ program = InitRD::Open(inode, &programsize);
if ( program == NULL ) { PanicF("initrd did not contain 'init'"); }
addr_t initstart = ELF::Construct(init, program, programsize);
if ( !initstart ) { Panic("could not construct ELF image for init process"); }