1
0
Fork 0
mirror of https://github.com/hermitcore/libhermit.git synced 2025-03-09 00:00:03 +01:00

remove obsolete file system

This commit is contained in:
Stefan Lankes 2015-11-15 22:24:58 +01:00
parent 60359f0aae
commit 1c436520b3
13 changed files with 8 additions and 1396 deletions

View file

@ -4,7 +4,7 @@ ARCH = x86
NAME = hermit
LWIPDIRS = lwip/src/arch lwip/src/api lwip/src/core lwip/src/core/ipv4 lwip/src/netif
DRIVERDIRS = drivers/net
KERNDIRS = kernel mm libkern fs arch/$(ARCH)/kernel arch/$(ARCH)/mm $(LWIPDIRS) $(DRIVERDIRS)
KERNDIRS = kernel mm libkern arch/$(ARCH)/kernel arch/$(ARCH)/mm $(LWIPDIRS) $(DRIVERDIRS)
SUBDIRS = $(KERNDIRS)
GIT_VERSION := $(shell git describe --abbrev=6 --dirty --always --tags)
TODAY := $(shell date +'%Y%m%d')
@ -95,7 +95,7 @@ tools:
$(NAME).elf:
@echo [LD] $(NAME).elf
$Q$(LD_FOR_TARGET) $(LDFLAGS) -o $(NAME).elf $^ tools/initrd.o
$Q$(LD_FOR_TARGET) $(LDFLAGS) -o $(NAME).elf $^
@echo [OBJCOPY] $(NAME).bin
$Q$(OBJCOPY_FOR_TARGET) -j .mboot -j .kmsg -j .initrd -j .text -j .text.startup -j .data -j .rodata -j .bss -O binary $(NAME).elf $(NAME).bin

View file

@ -32,7 +32,6 @@
#include <hermit/errno.h>
#include <hermit/processor.h>
#include <hermit/memory.h>
#include <hermit/fs.h>
#include <hermit/vma.h>
#include <hermit/rcce.h>
#include <asm/tss.h>
@ -201,13 +200,11 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg, uint32_t cor
return 0;
}
#define MAX_ARGS (PAGE_SIZE - 2*sizeof(int) - sizeof(vfs_node_t*))
#define MAX_ARGS (PAGE_SIZE - 2*sizeof(int))
/** @brief Structure which keeps all
* relevant data for a new user task to start */
typedef struct {
/// Points to the node with the executable in the file system
vfs_node_t* node;
/// Points to a copy of the executable
char* executable;
/// Socket descriptor if have no file node
@ -235,7 +232,6 @@ static int load_task(load_args_t* largs)
elf_header_t header;
elf_program_header_t prog_header;
//elf_section_header_t sec_header;
fildes_t file;
task_t* curr_task = per_core(current_task);
int ret = -EINVAL;
uint8_t hermit_exec = 0;
@ -243,22 +239,11 @@ static int load_task(load_args_t* largs)
if (!largs)
return -EINVAL;
if (largs->node) {
file.node = largs->node;
file.offset = 0;
file.flags = 0;
} else if (!largs->executable || (largs->sd < 0))
if (!largs->executable || (largs->sd < 0))
return -EINVAL;
curr_task->sd = largs->sd;
if (largs->node) {
ret = read_fs(&file, (uint8_t*)&header, sizeof(elf_header_t));
if (ret < 0) {
kprintf("read_fs failed: %d\n", ret);
goto Lerr;
}
} else memcpy(&header, largs->executable, sizeof(elf_header_t));
memcpy(&header, largs->executable, sizeof(elf_header_t));
if (BUILTIN_EXPECT(header.ident.magic != ELF_MAGIC, 0))
goto Linvalid;
@ -280,13 +265,7 @@ static int load_task(load_args_t* largs)
// interpret program header table
for (i=0; i<header.ph_entry_count; i++) {
if (largs->node) {
file.offset = header.ph_offset+i*header.ph_entry_size;
if (read_fs(&file, (uint8_t*)&prog_header, sizeof(elf_program_header_t)) == 0) {
kprintf("Could not read programm header!\n");
continue;
}
} else memcpy(&prog_header, largs->executable + header.ph_offset+i*header.ph_entry_size, sizeof(elf_program_header_t));
memcpy(&prog_header, largs->executable + header.ph_offset+i*header.ph_entry_size, sizeof(elf_program_header_t));
switch(prog_header.type)
{
@ -328,11 +307,7 @@ static int load_task(load_args_t* largs)
// load program
//kprintf("read programm 0x%zx - 0x%zx\n", prog_header.virt_addr, prog_header.virt_addr + prog_header.file_size);
if (largs->node) {
file.offset = prog_header.offset;
read_fs(&file, (uint8_t*)prog_header.virt_addr, prog_header.file_size);
} else
memcpy((uint8_t*)prog_header.virt_addr, largs->executable + prog_header.offset, prog_header.file_size);
memcpy((uint8_t*)prog_header.virt_addr, largs->executable + prog_header.offset, prog_header.file_size);
if (!(prog_header.flags & PF_W))
page_set_flags(prog_header.virt_addr, npages, flags);
@ -560,58 +535,6 @@ static int user_entry(void* arg)
}
}
/** @brief Luxus-edition of create_user_task functions. Just call with an exe name
*
* @param id Pointer to the tid_t structure which shall be filles
* @param fname Executable's path and filename
* @param argv Arguments list
* @return
* - 0 on success
* - -ENOMEM (-12) or -EINVAL (-22) on failure
*/
int create_user_task_on_core(tid_t* id, const char* fname, char** argv, uint8_t prio, uint32_t core_id)
{
vfs_node_t* node;
int argc = 0;
size_t i, buffer_size = 0;
load_args_t* load_args = NULL;
char *dest, *src;
node = findnode_fs((char*) fname);
if (!node || !(node->type == FS_FILE))
return -EINVAL;
// determine buffer size of argv
if (argv) {
while (argv[argc]) {
buffer_size += (strlen(argv[argc]) + 1);
argc++;
}
}
if (argc <= 0)
return -EINVAL;
if (buffer_size >= MAX_ARGS)
return -EINVAL;
load_args = kmalloc(sizeof(load_args_t));
if (BUILTIN_EXPECT(!load_args, 0))
return -ENOMEM;
load_args->node = node;
load_args->argc = argc;
load_args->sd = -1;
load_args->executable = NULL;
load_args->envc = 0;
dest = load_args->buffer;
for (i=0; i<argc; i++) {
src = argv[i];
while ((*dest++ = *src++) != 0);
}
/* create new task */
return create_task(id, user_entry, load_args, prio, core_id);
}
int create_user_task_form_socket(tid_t* id, int sd, uint8_t prio)
{
int argc;
@ -634,7 +557,6 @@ int create_user_task_form_socket(tid_t* id, int sd, uint8_t prio)
goto out;
}
load_args->node = NULL;
load_args->executable = NULL;
load_args->sd = sd;
load_args->argc = argc;

View file

@ -1,4 +0,0 @@
C_source := fs.c initrd.c
MODULE := fs
include $(TOPDIR)/Makefile.inc

View file

@ -1,246 +0,0 @@
/*
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the University 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 REGENTS 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 <hermit/stdlib.h>
#include <hermit/stdio.h>
#include <hermit/string.h>
#include <hermit/fs.h>
#include <hermit/errno.h>
#include <hermit/spinlock.h>
vfs_node_t* fs_root = NULL; // The root of the filesystem.
ssize_t read_fs(fildes_t* file, uint8_t* buffer, size_t size)
{
vfs_node_t* node = file->node;
ssize_t ret = -EINVAL;
if (BUILTIN_EXPECT(!node || !buffer, 0))
return ret;
spinlock_lock(&node->lock);
// Has the node got a read callback?
if (node->read != 0)
ret = node->read(file, buffer, size);
spinlock_unlock(&node->lock);
return ret;
}
ssize_t write_fs(fildes_t* file, uint8_t* buffer, size_t size)
{
vfs_node_t* node = file->node;
ssize_t ret = -EINVAL;
if (BUILTIN_EXPECT(!node || !buffer, 0))
return ret;
spinlock_lock(&node->lock);
// Has the node got a write callback?
if (node->write != 0)
ret = node->write(file, buffer, size);
spinlock_unlock(&node->lock);
return ret;
}
int open_fs(fildes_t* file, const char* name)
{
uint32_t ret = 0, i, j = 1;
vfs_node_t* file_node = NULL; /* file node */
vfs_node_t* dir_node = NULL;
char fname[MAX_FNAME];
if (BUILTIN_EXPECT(!name, 0))
return ret;
if (name[0] == '/')
file_node = fs_root;
while((name[j] != '\0') || ((file_node != NULL) && (file_node->type == FS_DIRECTORY))) {
i = 0;
while((name[j] != '/') && (name[j] != '\0')) {
fname[i] = name[j];
i++; j++;
}
fname[i] = '\0';
dir_node = file_node; /* file must be a directory */
file_node = finddir_fs(dir_node, fname);
if (name[j] == '/')
j++;
}
//kprintf("dir_node = %p, file_node = %p, name = %s \n", dir_node, file_node, fname);
/* file exists */
if(file_node) {
spinlock_lock(&file_node->lock);
file->node = file_node;
// Has the file_node got an open callback?
if (file_node->open != 0)
ret = file->node->open(file, NULL);
spinlock_unlock(&file_node->lock);
} else if (dir_node) { /* file doesn't exist or opendir was called */
spinlock_lock(&dir_node->lock);
file->node = dir_node;
// Has the dir_node got an open callback?
if (dir_node->open != 0)
ret = dir_node->open(file, fname);
spinlock_unlock(&dir_node->lock);
} else {
ret = -ENOENT;
}
return ret;
}
int close_fs(fildes_t* file)
{
int ret = -EINVAL;
if (BUILTIN_EXPECT(!(file->node), 0))
return ret;
spinlock_lock(&file->node->lock);
// Has the node got a close callback?
if (file->node->close != 0)
ret = file->node->close(file);
spinlock_unlock(&file->node->lock);
return ret;
}
struct dirent* readdir_fs(vfs_node_t * node, uint32_t index)
{
struct dirent* ret = NULL;
if (BUILTIN_EXPECT(!node, 0))
return ret;
spinlock_lock(&node->lock);
// Is the node a directory, and does it have a callback?
if ((node->type == FS_DIRECTORY) && node->readdir != 0)
ret = node->readdir(node, index);
spinlock_unlock(&node->lock);
return ret;
}
vfs_node_t* finddir_fs(vfs_node_t* node, const char *name)
{
vfs_node_t* ret = NULL;
if (BUILTIN_EXPECT(!node, 0))
return ret;
spinlock_lock(&node->lock);
// Is the node a directory, and does it have a callback?
if ((node->type == FS_DIRECTORY) && node->finddir != 0)
ret = node->finddir(node, name);
spinlock_unlock(&node->lock);
return ret;
}
vfs_node_t* mkdir_fs(vfs_node_t* node, const char *name)
{
vfs_node_t* ret = NULL;
if (BUILTIN_EXPECT(!node, 0))
return ret;
spinlock_lock(&node->lock);
if (node->mkdir != 0)
ret = node->mkdir(node, name);
spinlock_unlock(&node->lock);
return ret;
}
vfs_node_t* findnode_fs(const char* name)
{
uint32_t i, j = 1;
vfs_node_t* ret = NULL;
char fname[MAX_FNAME];
if (BUILTIN_EXPECT(!name, 0))
return ret;
if (name[0] == '/')
ret = fs_root;
while((name[j] != '\0') && ret) {
i = 0;
while((name[j] != '/') && (name[j] != '\0')) {
fname[i] = name[j];
i++; j++;
}
fname[i] = '\0';
ret = finddir_fs(ret, fname);
if (name[j] == '/')
j++;
}
return ret;
}
void list_fs(vfs_node_t* node, uint32_t depth)
{
int j, i = 0;
dirent_t* dirent = NULL;
fildes_t* file = kmalloc(sizeof(fildes_t));
file->offset = 0;
file->flags = 0;
while ((dirent = readdir_fs(node, i)) != 0) {
for(j=0; j<depth; j++)
kputs(" ");
kprintf("%s\n", dirent->name);
if (strcmp(dirent->name, ".") && strcmp(dirent->name, "..")) {
vfs_node_t *new_node = finddir_fs(node, dirent->name);
if (new_node) {
if (new_node->type == FS_FILE) {
char buff[16] = {[0 ... 15] = 0x00};
file->node = new_node;
file->offset = 0;
file->flags = 0;
read_fs(file, (uint8_t*)buff, 8);
for(j=0; j<depth+1; j++)
kputs(" ");
kprintf("content: %s\n", buff);
} else list_fs(new_node, depth+1);
}
}
i++;
}
kfree(file);
}

View file

@ -1,577 +0,0 @@
/*
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the University 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 REGENTS 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 <hermit/stdlib.h>
#include <hermit/stdio.h>
#include <hermit/string.h>
#include <hermit/fs.h>
#include <hermit/errno.h>
#include <hermit/spinlock.h>
#include <asm/processor.h>
static vfs_node_t initrd_root;
/*
* Note that linker symbols are not variables, they have no memory allocated for
* maintaining a value, rather their address is their value.
*/
extern const void initrd_start, initrd_end;
#define INITRD_MAGIC_NUMBER 0x4711
/*
* Grub maps the initrd as module into the address space of the kernel.
* The module begins with the header "initrd_header_t", which describes
* the number of mounted files and the mount point. The header follows
* by the struct "initrd_file_desc_t" for each file, which will be mounted.
* This struct describes the file properties and the position in the
* module.
*/
typedef struct {
uint32_t magic;
uint32_t nfiles;
char mount_point[MAX_FNAME];
} initrd_header_t;
typedef struct {
uint32_t length;
uint32_t offset;
char fname[MAX_FNAME];
} initrd_file_desc_t;
static ssize_t initrd_read(fildes_t* file, uint8_t* buffer, size_t size)
{
vfs_node_t* node = file->node;
uint32_t i, pos = 0, found = 0;
off_t offset = 0;
char* data = NULL;
block_list_t* blist = &node->block_list;
if (file->flags & O_WRONLY)
return -EACCES;
/* init the tmp offset */
offset = file->offset;
/* searching for the valid data block */
if (offset) {
pos = offset / node->block_size;
offset = offset % node->block_size;
}
do {
for(i=0; i<MAX_DATABLOCKS && !data; i++) {
if (blist->data[i]) {
found++;
if (found > pos)
data = (char*) blist->data[i];
}
}
blist = blist->next;
} while(blist && !data);
if (BUILTIN_EXPECT(!data, 0))
return 0;
/*
* If the data block is not large engough,
* we copy only the rest of the current block.
* The user has to restart the read operation
* for the next block.
*/
if ((offset + size) >= node->block_size)
size = node->block_size - offset;
memcpy(buffer, data + offset, size);
file->offset += size;
return size;
}
static ssize_t initrd_emu_readdir(fildes_t* file, uint8_t* buffer, size_t size)
{
vfs_node_t* node = file->node;
uint32_t i, j, k, count;
uint32_t index = file->offset;
dirent_t* dirent;
dir_block_t* dirblock;
block_list_t* blist = &node->block_list;
do {
for(i=0,count=0; i<MAX_DATABLOCKS; i++) {
dirblock = (dir_block_t*) blist->data[i];
for(j=0; dirblock && j<MAX_DIRENTRIES; j++) {
dirent = &dirblock->entries[j];
if (dirent->vfs_node) {
count++;
if (count > index) {
k=0;
do {
buffer[k] = dirent->name[k];
k++;
} while(dirent->name[k] != '\0');
file->offset++;
return k;
}
}
}
}
blist = blist->next;
} while(blist);
return -EINVAL;
}
static ssize_t initrd_write(fildes_t* file, uint8_t* buffer, size_t size)
{
uint32_t i, pos = 0, found = 0;
off_t offset = 0;
char* data = NULL;
vfs_node_t* node = file->node;
block_list_t* blist = &node->block_list;
if (file->flags & O_RDONLY)
return -EACCES;
if (file->flags & O_APPEND)
file->offset = node->block_size;
/* init the tmp offset */
offset = file->offset;
/* searching for the valid data block */
if (offset) {
pos = offset / MAX_DATAENTRIES;
offset = offset % MAX_DATAENTRIES;
}
do {
for (i = 0; i < MAX_DATABLOCKS && !data; i++) {
if ((size + offset) >= MAX_DATAENTRIES)
size = MAX_DATAENTRIES - offset;
if(!blist->data[i]) {
blist->data[i] = (data_block_t*)
kmalloc(sizeof(data_block_t));
if (blist->data[i])
memset(blist->data[i], 0x00,
sizeof(data_block_t));
}
found++;
if (found > pos) {
data = (char*) blist->data[i];
}
}
if (!blist->next) {
blist->next = (block_list_t*)
kmalloc(sizeof(block_list_t));
if (blist->next)
memset(blist->next, 0x00,
sizeof(block_list_t));
}
blist = blist->next;
} while(blist && !data);
/* you may have to increase nodesize */
if (node->block_size < (file->offset + size))
node->block_size = file->offset + size;
/*
* If the data block is not large engough,
* we copy only the rest of the current block.
* The user has to restart the write operation
* for the next block.
*/
memcpy(data + offset, buffer, size);
file->offset += size;
return size;
}
static int initrd_open(fildes_t* file, const char* name)
{
if (file->node->type == FS_FILE) {
if ((file->flags & O_CREAT) && (file->flags & O_EXCL))
return -EEXIST;
/* in the case of O_TRUNC kfree all the nodes */
if (file->flags & O_TRUNC) {
uint32_t i;
char* data = NULL;
block_list_t* blist = &file->node->block_list;
block_list_t* lastblist = NULL;
/* the first blist pointer have do remain valid. */
for(i=0; i<MAX_DATABLOCKS && !data; i++) {
if (blist->data[i]) {
kfree(blist->data[i]);
}
}
if (blist->next) {
lastblist = blist;
blist = blist->next;
lastblist->next = NULL;
/* kfree all other blist pointers */
do {
for(i=0; i<MAX_DATABLOCKS && !data; i++) {
if (blist->data[i]) {
kfree(blist->data[i]);
}
}
lastblist = blist;
blist = blist->next;
kfree(lastblist);
} while(blist);
}
/* reset the block_size */
file->node->block_size = 0;
}
}
if (file->node->type == FS_DIRECTORY) {
/* opendir was called: */
if (name[0] == '\0')
return 0;
/* open file was called: */
if (!(file->flags & O_CREAT))
return -ENOENT;
uint32_t i, j;
block_list_t* blist = NULL;
/* CREATE FILE */
vfs_node_t* new_node = kmalloc(sizeof(vfs_node_t));
if (BUILTIN_EXPECT(!new_node, 0))
return -EINVAL;
blist = &file->node->block_list;
dir_block_t* dir_block;
dirent_t* dirent;
memset(new_node, 0x00, sizeof(vfs_node_t));
new_node->type = FS_FILE;
new_node->read = initrd_read;
new_node->write = initrd_write;
new_node->open = initrd_open;
spinlock_init(&new_node->lock);
/* create a entry for the new node in the directory block of current node */
do {
for(i=0; i<MAX_DATABLOCKS; i++) {
if (blist->data[i]) {
dir_block = (dir_block_t*) blist->data[i];
for(j=0; j<MAX_DIRENTRIES; j++) {
dirent = &dir_block->entries[j];
if (!dirent->vfs_node) {
dirent->vfs_node = new_node;
strncpy(dirent->name, (char*) name, MAX_FNAME);
goto exit_create_file; // there might be a better Solution ***************
}
}
}
}
/* if all blocks are reserved, we have to allocate a new one */
if (!blist->next) {
blist->next = (block_list_t*) kmalloc(sizeof(block_list_t));
if (blist->next)
memset(blist->next, 0x00, sizeof(block_list_t));
}
blist = blist->next;
} while(blist);
exit_create_file:
file->node = new_node;
file->node->block_size = 0;
}
return 0;
}
static dirent_t* initrd_readdir(vfs_node_t* node, uint32_t index)
{
uint32_t i, j, count;
dirent_t* dirent;
dir_block_t* dirblock;
block_list_t* blist = &node->block_list;
do {
for(i=0,count=0; i<MAX_DATABLOCKS; i++) {
dirblock = (dir_block_t*) blist->data[i];
for(j=0; dirblock && j<MAX_DIRENTRIES; j++) {
dirent = &dirblock->entries[j];
if (dirent->vfs_node) {
count++;
if (count > index)
return dirent;
}
}
}
blist = blist->next;
} while(blist);
return NULL;
}
static vfs_node_t* initrd_finddir(vfs_node_t* node, const char *name)
{
uint32_t i, j;
dir_block_t* dirblock;
dirent_t* dirent;
block_list_t* blist = &node->block_list;
do {
for(i=0; i<MAX_DATABLOCKS; i++) {
dirblock = (dir_block_t*) blist->data[i];
for(j=0; dirblock && j<MAX_DIRENTRIES; j++) {
dirent = &dirblock->entries[j];
if (!strncmp(dirent->name, name, MAX_FNAME))
return dirent->vfs_node;
}
}
blist = blist->next;
} while(blist);
return NULL;
}
static vfs_node_t* initrd_mkdir(vfs_node_t* node, const char* name)
{
uint32_t i, j;
dir_block_t* dir_block;
dir_block_t* tmp;
dirent_t* dirent;
vfs_node_t* new_node;
block_list_t* blist = &node->block_list;
if (BUILTIN_EXPECT(node->type != FS_DIRECTORY, 0))
return NULL;
/* exists already a entry with same name? */
if (initrd_finddir(node, name))
return NULL;
new_node = kmalloc(sizeof(vfs_node_t));
if (BUILTIN_EXPECT(!new_node, 0))
return NULL;
memset(new_node, 0x00, sizeof(vfs_node_t));
new_node->type = FS_DIRECTORY;
new_node->read = &initrd_emu_readdir;
new_node->readdir = &initrd_readdir;
new_node->finddir = &initrd_finddir;
new_node->mkdir = &initrd_mkdir;
new_node->open = &initrd_open;
spinlock_init(&new_node->lock);
/* create default directory entry */
dir_block = (dir_block_t*) kmalloc(sizeof(dir_block_t));
if (BUILTIN_EXPECT(!dir_block, 0))
goto out;
memset(dir_block, 0x00, sizeof(dir_block_t));
new_node->block_list.data[0] = dir_block;
strncpy(dir_block->entries[0].name, ".", MAX_FNAME);
dir_block->entries[0].vfs_node = new_node;
strncpy(dir_block->entries[1].name, "..", MAX_FNAME);
dir_block->entries[1].vfs_node = node;
do {
/* searching for a free directory block */
for(i=0; i<MAX_DATABLOCKS; i++) {
if (blist->data[i]) {
tmp = (dir_block_t*) blist->data[i];
for(j=0; j<MAX_DIRENTRIES; j++) {
dirent = &tmp->entries[j];
if (!dirent->vfs_node) {
dirent->vfs_node = new_node;
strncpy(dirent->name, name, MAX_FNAME);
return new_node;
}
}
}
}
/* if all blocks are reserved, we have to allocate a new one */
if (!blist->next) {
blist->next = (block_list_t*) kmalloc(sizeof(block_list_t));
if (blist->next)
memset(blist->next, 0x00, sizeof(block_list_t));
}
blist = blist->next;
} while(blist);
kfree(dir_block);
out:
kfree(new_node);
return NULL;
}
int initrd_init(void)
{
dir_block_t* dir_block;
vfs_node_t* tmp;
uint32_t i, j, k, l;
#if 0
uint32_t mods_count = 0;
multiboot_module_t* mmodule = NULL;
if (mb_info && (mb_info->flags & MULTIBOOT_INFO_MODS)) {
mmodule = (multiboot_module_t*) ((size_t) mb_info->mods_addr);
mods_count = mb_info->mods_count;
}
#endif
/* Initialize the root directory. */
fs_root = &initrd_root;
memset(&initrd_root, 0x00, sizeof(vfs_node_t));
initrd_root.type = FS_DIRECTORY;
initrd_root.read = &initrd_emu_readdir;
initrd_root.readdir = &initrd_readdir;
initrd_root.finddir = &initrd_finddir;
initrd_root.mkdir = &initrd_mkdir;
initrd_root.open = &initrd_open;
spinlock_init(&initrd_root.lock);
/* create default directory block */
dir_block = (dir_block_t*) kmalloc(sizeof(dir_block_t));
if (BUILTIN_EXPECT(!dir_block, 0))
return -ENOMEM;
memset(dir_block, 0x00, sizeof(dir_block_t));
initrd_root.block_list.data[0] = dir_block;
strncpy(dir_block->entries[0].name, ".", MAX_FNAME);
dir_block->entries[0].vfs_node = fs_root;
strncpy(dir_block->entries[1].name, "..", MAX_FNAME);
dir_block->entries[1].vfs_node = fs_root;
/* create the directory bin and dev */
mkdir_fs(fs_root, "bin");
//mkdir_fs(fs_root, "sbin");
mkdir_fs(fs_root, "dev");
//mkdir_fs(fs_root, "tmp");
/*
* Currently we attached the initrd at the end of the kernel
* => we don't longer use grub to load initrd as module
*/
#if 0
/* For every module.. */
for(i=0; i<mods_count; i++) {
initrd_header_t* header = (initrd_header_t*) ((size_t) mmodule[i].mod_start);
#else
kprintf("Initrd starts at %p and ends at %p\n", &initrd_start, &initrd_end);
for(i=0; i<1; i++) {
initrd_header_t* header = (initrd_header_t*) &initrd_start;
#endif
initrd_file_desc_t* file_desc;
vfs_node_t* new_node;
if (BUILTIN_EXPECT(header->magic != INITRD_MAGIC_NUMBER, 0)) {
kprintf("Invalid magic number for a init ram disk: 0x%x\n", header->magic);
continue;
}
tmp = findnode_fs(header->mount_point);
if (BUILTIN_EXPECT(!tmp, 0)) {
kprintf("Did not found mount point %s.\n", header->mount_point);
continue;
}
if (BUILTIN_EXPECT(tmp->type != FS_DIRECTORY, 0)) {
kprintf("%s is not a valid mount point.\n", header->mount_point);
continue;
}
file_desc = (initrd_file_desc_t*) (header + 1);
for(j=0; j<header->nfiles; j++) {
block_list_t* blist;
dir_block_t* dir_block;
dirent_t* dirent;
if (finddir_fs(tmp, file_desc->fname)) {
kprintf("Error: %s alreay exits\n", file_desc->fname);
goto next_file;
}
/* create a new node and map the module as data block */
new_node = kmalloc(sizeof(vfs_node_t));
if (BUILTIN_EXPECT(!new_node, 0)) {
kprintf("Not enough memory to create new initrd node\n");
goto next_file;
}
memset(new_node, 0x00, sizeof(vfs_node_t));
new_node->type = FS_FILE;
new_node->read = initrd_read;
new_node->write = initrd_write;
new_node->open = initrd_open;
new_node->block_size = file_desc->length;
new_node->block_list.data[0] = ((char*) header) + file_desc->offset;
spinlock_init(&new_node->lock);
/* create a entry for the new node in the directory block of current node */
blist = &tmp->block_list;
do {
for(k=0; k<MAX_DATABLOCKS; k++) {
if (blist->data[k]) {
dir_block = (dir_block_t*) blist->data[k];
for(l=0; l<MAX_DIRENTRIES; l++) {
dirent = &dir_block->entries[l];
if (!dirent->vfs_node) {
dirent->vfs_node = new_node;
strncpy(dirent->name, file_desc->fname, MAX_FNAME);
goto next_file;
}
}
}
}
/* if all blocks are reserved, we have to allocate a new one */
if (!blist->next) {
blist->next = (block_list_t*) kmalloc(sizeof(block_list_t));
if (blist->next)
memset(blist->next, 0x00, sizeof(block_list_t));
}
blist = blist->next;
} while(blist);
next_file:
file_desc++;
}
}
return 0;
}

View file

@ -1,293 +0,0 @@
/*
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the University 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 REGENTS 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.
*/
/**
* @author Stefan Lankes
* @file include/hermit/fs.h
* @brief Filesystem related functions and structures
*/
#ifndef __FS_H__
#define __FS_H__
#include <hermit/stddef.h>
#include <hermit/spinlock_types.h>
#define FS_FILE 0x01
#define FS_DIRECTORY 0x02
#define FS_CHARDEVICE 0x03
//#define FS_BLOCKDEVICE 0x04
//#define FS_PIPE 0x05
//#define FS_SYMLINK 0x06
//#define FS_MOUNTPOINT 0x08 // Is the file an active mountpoint?
/*file descriptor init*/
#define NR_OPEN 100
#define _FOPEN (-1) /* from sys/file.h, kernel use only */
#define _FREAD 0x0001 /* read enabled */
#define _FWRITE 0x0002 /* write enabled */
#define _FAPPEND 0x0008 /* append (writes guaranteed at the end) */
#define _FMARK 0x0010 /* internal; mark during gc() */
#define _FDEFER 0x0020 /* internal; defer for next gc pass */
#define _FASYNC 0x0040 /* signal pgrp when data ready */
#define _FSHLOCK 0x0080 /* BSD flock() shared lock present */
#define _FEXLOCK 0x0100 /* BSD flock() exclusive lock present */
#define _FCREAT 0x0200 /* open with file create */
#define _FTRUNC 0x0400 /* open with truncation */
#define _FEXCL 0x0800 /* error on open if file exists */
#define _FNBIO 0x1000 /* non blocking I/O (sys5 style) */
#define _FSYNC 0x2000 /* do all writes synchronously */
#define _FNONBLOCK 0x4000 /* non blocking I/O (POSIX style) */
#define _FNDELAY _FNONBLOCK /* non blocking I/O (4.2 style) */
#define _FNOCTTY 0x8000 /* don't assign a ctty on this open */
/*open flags*/
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#define O_APPEND _FAPPEND
#define O_CREAT _FCREAT
#define O_TRUNC _FTRUNC
#define O_EXCL _FEXCL
#define O_SYNC _FSYNC
#define O_NONBLOCK _FNONBLOCK
#define O_NOCTTY _FNOCTTY
/*lseek defines*/
#ifndef SEEK_SET
#define SEEK_SET 0 /* set file offset to offset */
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1 /* set file offset to current plus offset */
#endif
#ifndef SEEK_END
#define SEEK_END 2 /* set file offset to EOF plus offset */
#endif
struct vfs_node;
struct fildes;
/** @defgroup fsprototypes FS access function prototypes
*
* These typedefs define the type of callbacks - called when read/write/open/close are called.\n
* They aren't as well documented as the read_fs and so on functions. Just look there for further information.
*
* @{
*/
/** @brief Read function pointer */
typedef ssize_t (*read_type_t) (struct fildes *, uint8_t*, size_t);
/** @brief Write function pointer */
typedef ssize_t (*write_type_t) (struct fildes *, uint8_t*, size_t);
/** @brief Open function pointer */
typedef int (*open_type_t) (struct fildes *, const char *name);
/** @brief Close function pointer */
typedef int (*close_type_t) (struct fildes *);
/** @brief Read directory function pointer */
typedef struct dirent *(*readdir_type_t) (struct vfs_node *, uint32_t);
/** @brief Find directory function pointer */
typedef struct vfs_node *(*finddir_type_t) (struct vfs_node *, const char *name);
/** @brief Make directory function pointer */
typedef struct vfs_node *(*mkdir_type_t) (struct vfs_node *, const char *name);
/** @} */
#define MAX_DATABLOCKS 12
#define MAX_DIRENTRIES 32
#define MAX_DATAENTRIES 4096
/** @brief Block list structure. VFS nodes keep those in a list */
typedef struct block_list {
/// Array with pointers to data blocks
void* data[MAX_DATABLOCKS];
/// Pointer to the next block_list in the list
struct block_list* next;
} block_list_t;
typedef struct vfs_node {
/// The permissions mask.
uint32_t mask;
/// The owning user.
uint32_t uid;
/// The owning group.
uint32_t gid;
/// Includes the node type. See the defines above.
uint32_t type;
/// Open handler function pointer
open_type_t open;
/// Close handler function pointer
close_type_t close;
/// Read handler function pointer
read_type_t read;
/// Write handler function pointer
write_type_t write;
/// Read dir handler function pointer
readdir_type_t readdir;
/// Find dir handler function pointer
finddir_type_t finddir;
/// Make dir handler function pointer
mkdir_type_t mkdir;
/// Lock variable to thread-protect this structure
spinlock_t lock;
/// Block size
size_t block_size;
/// List of blocks
block_list_t block_list;
} vfs_node_t;
/** @brief file descriptor structure */
typedef struct fildes {
vfs_node_t* node; /* */
off_t offset; /* */
int flags; /* */
int mode; /* */
int count; /* number of tasks using this fd */
} fildes_t, *filp_t;
/** @brief Directory entry structure */
typedef struct dirent {
/// Directory name
char name[MAX_FNAME];
/// Corresponding VFS node pointer
vfs_node_t* vfs_node;
} dirent_t;
/** @brief Dir block structure which will keep directory entries */
typedef struct {
/// Array of directory entries
dirent_t entries[MAX_DIRENTRIES];
} dir_block_t;
typedef struct {
///Array of data entries
char entries[MAX_DATAENTRIES];
} data_block_t;
/* Time Value Specification Structures, P1003.1b-1993, p. 261 */
struct timespec {
long tv_sec; /* Seconds */
long tv_nsec; /* Nanoseconds */
};
struct stat
{
uint16_t st_dev; /* ID of device containing file */
uint16_t st_ino; /* inode number */
uint32_t st_mode; /* protection */
unsigned short st_nlink; /* number of hard links */
uint16_t st_uid; /* user ID of owner */
uint16_t st_gid; /* group ID of owner */
uint16_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
struct timespec st_atim; /* time of last access */
struct timespec st_mtim; /* time of last modification */
struct timespec st_ctim; /* time of last status change */
uint32_t st_blksize; /* blocksize for filesystem I/O */
uint32_t st_blocks; /* number of blocks allocated */
} stat_t;
extern vfs_node_t* fs_root; // The root of the filesystem.
/** @defgroup fsfunc FS related functions
*
* Standard read/write/open/close/mkdir functions. Note that these are all suffixed with
* _fs to distinguish them from the read/write/open/close which deal with file descriptors,
* not file nodes.
*
* @{
*/
/** @brief Read from file system into the buffer
* @param file Pointer to the file descriptor to read from
* @param buffer Pointer to buffer to write into
* @param size Number of bytes to read
* @return
* - number of bytes copied (size)
* - 0 on error
*/
ssize_t read_fs(fildes_t* file, uint8_t* buffer, size_t size);
/** @brief Write into the file system from the buffer
* @param file Pointer to the file descriptor to write to
* @param buffer Pointer to buffer to read from
* @param size Number of bytes to read
* @return
* - number of bytes copied (size)
* - 0 on error
*/
ssize_t write_fs(fildes_t* file, uint8_t* buffer, size_t size);
/** @brief Yet to be documented */
int open_fs(fildes_t* file, const char* fname);
/** @brief Yet to be documented */
int close_fs(fildes_t * file);
/** @brief Get dir entry at index
* @param node VFS node to get dir entry from
* @param index Index position of desired dir entry
* @return
* - The desired dir entry
* - NULL on failure
*/
struct dirent *readdir_fs(vfs_node_t * node, uint32_t index);
/** @brief Find a directory by looking for the dir name
* @param node The node where to start the search from
* @param name The dir name string
* @return
* - a VFS node pointer
* - NULL on failure
*/
vfs_node_t* finddir_fs(vfs_node_t * node, const char *name);
/** @brief Make a new directory in a VFS node
* @param node Pointer to the node where the dir is to create in
* @param name Name of the new directory
* @return
* - new VFS node pointer
* - NULL on failure
*/
vfs_node_t* mkdir_fs(vfs_node_t* node, const char* name);
/** @brief Find a node within root file system
* @param name The node name
* @return
* - VFS node pointer
* - NULL on failure
*/
vfs_node_t* findnode_fs(const char* name);
/** @brief List a filesystem hirachically */
void list_fs(vfs_node_t* node, uint32_t depth);
int initrd_init(void);
#endif

View file

@ -127,19 +127,6 @@ int create_kernel_task(tid_t* id, entry_point_t ep, void* args, uint8_t prio);
*/
int create_kernel_task_on_core(tid_t* id, entry_point_t ep, void* args, uint8_t prio, uint32_t core_id);
/** @brief Create a user level task on the current core.
*
* @param id The value behind this pointer will be set to the new task's id
* @param fname Filename of the executable to start the task with
* @param argv Pointer to arguments array
* @param prio Desired priority of the new kernel task
*
* @return
* - 0 on success
* - -EINVAL (-22) or -ENOMEM (-12)on failure
*/
int create_user_task(tid_t* id, const char* fame, char** argv, uint8_t prio);
/** @brief Create a user level task on the current core.
*
* @param id The value behind this pointer will be set to the new task's id

View file

@ -35,7 +35,6 @@
#include <hermit/syscall.h>
#include <hermit/memory.h>
#include <hermit/spinlock.h>
#include <hermit/fs.h>
#include <hermit/rcce.h>
#include <asm/irq.h>
#include <asm/page.h>
@ -119,7 +118,6 @@ static int hermit_init(void)
timer_init();
multitasking_init();
memory_init();
initrd_init();
return 0;
}
@ -245,18 +243,8 @@ static int initd(void* arg)
int32_t magic;
struct sockaddr_in server, client;
//char* argv1[] = {"/bin/hello", NULL};
//char* argv2[] = {"/bin/jacobi", NULL};
//char* argv3[] = {"/bin/stream", NULL};
//char* argv4[] = {"/bin/thr_hello", NULL};
//create_kernel_task(NULL, foo, "foo1", NORMAL_PRIO);
//create_kernel_task(NULL, foo, "foo2", NORMAL_PRIO);
//create_user_task(NULL, "/bin/hello", argv1, NORMAL_PRIO);
//create_user_task(NULL, "/bin/jacobi", argv2, NORMAL_PRIO);
//create_user_task(NULL, "/bin/jacobi", argv2, NORMAL_PRIO);
//create_user_task(NULL, "/bin/stream", argv3, NORMAL_PRIO);
//create_user_task(NULL, "/bin/thr_hello", argv4, NORMAL_PRIO);
init_netifs();
init_rcce();
@ -342,11 +330,6 @@ int main(void)
kprintf("Current allocated memory: %zd KiB\n", atomic_int64_read(&total_allocated_pages) * PAGE_SIZE / 1024ULL);
kprintf("Current available memory: %zd MiB\n", atomic_int64_read(&total_available_pages) * PAGE_SIZE / (1024ULL*1024ULL));
#if 0
kputs("Filesystem:\n");
list_fs(fs_root, 1);
#endif
#if 0
print_pci_adapters();
#endif

View file

@ -469,14 +469,6 @@ out:
return ret;
}
int create_user_task(tid_t* id, const char* fname, char** argv, uint8_t prio)
{
if (prio > MAX_PRIO)
prio = NORMAL_PRIO;
return create_user_task_on_core(id, fname, argv, prio, CORE_ID);
}
int create_kernel_task_on_core(tid_t* id, entry_point_t ep, void* args, uint8_t prio, uint32_t core_id)
{
if (prio > MAX_PRIO)

View file

@ -19,10 +19,6 @@ SECTIONS
.rodata ALIGN(4096) : AT(ADDR(.rodata)) {
*(.rodata)
*(.rodata.*)
. = ALIGN((1 << 12));
initrd_start = .;
*(.initrd)
initrd_end = .;
}
.data ALIGN(4096) : AT(ADDR(.data)) {
*(.data)

View file

@ -5,7 +5,6 @@ CC = gcc
CFLAGS = -O2 -Wall
HEXDUMP = hexdump
LDFLGAS =
INITRDFILES = ../usr/tests/hello #$(shell find ../usr/tests -perm -u+r+x -type f)
PROXYFILES = $(shell find ../usr/tests -perm -u+r+x -type f) $(shell find ../usr/benchmarks -perm -u+r+x -type f)
# Prettify output
@ -22,7 +21,7 @@ endif
default: all
all: init.h make_initrd initrd.o
all: init.h
init.bin: init.asm
@echo [NASM] $@
@ -34,17 +33,6 @@ init.h: init.bin
$Q$(HEXDUMP) -v -e '"0x" 1/1 "%02X" ", "' $< >> $@
$Q@echo "};" >> $@
initrd.o: initrd.S initrd.img
@echo [CC] Build initrd as object file
$Q$(CC) -c -o $@ initrd.S
initrd.img: $(INITRDFILES) make_initrd
@echo [MAKE_INITRD] initrd.img
$Q./make_initrd /bin $(foreach FILE, $(INITRDFILES), $(FILE) $(shell basename $(FILE)))
make_initrd: make_initrd.o
$Q$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
iso:
mkdir iso

View file

@ -1,2 +0,0 @@
.section .initrd
.incbin "initrd.img"

View file

@ -1,134 +0,0 @@
/*
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the University 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 REGENTS 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define INITRD_MAGIC_NUMBER 0x4711
#define MAX_FNAME 128
#define PAGE_SIZE 4096
typedef struct {
uint32_t magic;
uint32_t nfiles;
char mount_point[MAX_FNAME];
} initrd_header_t;
typedef struct {
uint32_t length;
uint32_t offset;
char fname[MAX_FNAME];
} initrd_file_desc_t;
static void print_options(void)
{
printf(" make_initrd mount_point path name [path name]\n");
printf("\n");
printf(" mount_point - mount point of init ram disk, where all file will be mounted.\n");
printf(" path - path to the file, which will be mounted\n");
printf(" name - file name, which will be used be the initrd\n");
}
int main(int argc, char **argv)
{
int i, nfiles = (argc - 2) / 2;
initrd_header_t header;
initrd_file_desc_t* file_desc;
off_t offset;
FILE* istream;
FILE* ostream;
if ((argc < 4) || (strcmp(argv[1], "-h") == 0)) {
print_options();
return 0;
}
memset(&header, 0x00, sizeof(initrd_header_t));
header.magic = INITRD_MAGIC_NUMBER;
header.nfiles = nfiles;
strncpy(header.mount_point, argv[1], MAX_FNAME);
file_desc = (initrd_file_desc_t*) malloc(sizeof(initrd_file_desc_t)*nfiles);
if (!file_desc) {
fprintf(stderr, "No enough memory\n");
return -1;
}
memset(file_desc, 0x00, sizeof(initrd_file_desc_t)*nfiles);
offset = sizeof(initrd_header_t) + nfiles * sizeof(initrd_file_desc_t);
for(i=0; i<nfiles; i++) {
strncpy(file_desc[i].fname, argv[3 + i * 2], MAX_FNAME);
if (offset % PAGE_SIZE)
offset += PAGE_SIZE - offset % PAGE_SIZE;
file_desc[i].offset = offset;
istream = fopen(argv[2 + i * 2], "r");
if (istream == NULL) {
fprintf(stderr, "Error: file not found: %s\n", argv[2 + i * 2]);
return -1;
}
fseek(istream, 0, SEEK_END);
file_desc[i].length = ftell(istream);
offset += file_desc[i].length;
fclose(istream);
}
ostream = fopen("./initrd.img", "w");
if (ostream == NULL) {
fprintf(stderr, "Error: unable to create file\n");
return -1;
}
fwrite(&header, sizeof(initrd_header_t), 1, ostream);
fwrite(file_desc, sizeof(initrd_file_desc_t), nfiles, ostream);
for(i=0; i<nfiles; i++) {
unsigned char *buf = (unsigned char *)malloc(file_desc[i].length);
size_t curr, len = file_desc[i].length;
istream = fopen(argv[2 + i * 2], "r");
while (ftell(ostream) < file_desc[i].offset)
fwrite(buf, 1, sizeof(unsigned char), ostream);
do {
curr = fread(buf, 1, len, istream);
fwrite(buf, 1, len, ostream);
len -= curr;
} while(len > 0);
fclose(istream);
free(buf);
}
fclose(ostream);
return 0;
}