panthema / 2006 / SDIOS06 / sdios06 / src / minixfs / minixfs-server.cc (Download File)
/*****************************************************************
 * Source file : src/minixfs/minixfs.idl
 * Platform    : V4 IA32
 * Mapping     : CORBA C
 * 
 * Generated by IDL4 1.0.2 (roadrunner) on 05/07/2006 23:28
 * Report bugs to haeberlen@ira.uka.de
 *****************************************************************/
#include <config.h>

#include <idl4glue.h>

#include <new>
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include <sdi/log.h>
#include <sdi/util.h>
#include <sdi/panic.h>
#include <sdi/locator.h>

#include <if/iflocator.h>

#include "minixfs-server.h"
#include "minixfs.h"
#include "datastructures.h"
#include "filesystem.h"

// do a printf on error conditions
//#define PRINT_ERROR

namespace {
	const size_t MAX_BUFSIZE = 8192;
}

/*
 * structure of an objectid_t in the driver:
 * The upper 8 bit are the filesystem number, the lower 24 bit the inode number
 */
struct minix_objectid_t {
	union {
		struct {
			unsigned int inode : 24;
			unsigned int filesystem : 8;
		};	
		objectid_t objectid;
	};
} __attribute__((packed));
ASSERT_SIZE(minix_objectid_t, sizeof(objectid_t));

/* Interface minixfs */
IDL4_INLINE void minixfs_GetEntry_implementation(CORBA_Object _caller, const objectid_t directory_handle, const CORBA_char *name, const interfaceid_t interfaceid, L4_ThreadId_t *server, objectid_t *object_handle, idl4_server_environment *_env)
{
	const minix_objectid_t& dir_handle
		= reinterpret_cast<const minix_objectid_t&> (directory_handle);
	if(dir_handle.filesystem >= filesystem_count) {
#ifdef PRINT_ERROR
		printf("Invalid filesystem");
#endif
		CORBA_exception_set (_env, ex_invalid_objectid, 0);
		return;
	}
	
	FileSystem* fs = filesystems[dir_handle.filesystem];
	
	INodeWrapper dirinode;
	ErrorCode res = fs->store.readINode(&dirinode, dir_handle.inode);
	if(res != NO_ERROR) {
#ifdef PRINT_ERROR
		printf("Couldn't read inode %d\n", dir_handle.inode);
#endif
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}
	if(!dirinode.isDir()) {
#ifdef PRINT_ERROR
		printf("objectid is not a directory\n");
#endif
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}	
	
	INodeWrapper entry;
	res = fs->getDirectoryEntry(&dirinode, &entry, name);
	if(res != NO_ERROR) {
#ifdef PRINT_ERROR
		printf("DirEntry '%s' not found\n", name);
#endif
		CORBA_exception_set(_env, ex_not_found, 0);
		return;
	}
	
	switch(interfaceid) {
		case IF_DIRECTORY_ID:
			if(!entry.isDir()) {
#ifdef PRINT_ERROR
				printf("Entry is not a directory\n");
#endif
				CORBA_exception_set(_env, ex_not_supported, 0);
				return;
			}
			break;
		case IF_FILE_ID:
			if(!entry.isFile()) {
#ifdef PRINT_ERROR
				printf("Entry is not a file\n");
#endif
				CORBA_exception_set(_env, ex_not_supported, 0);
				return;
			}
			break;
		default:
			CORBA_exception_set(_env, ex_not_supported, 0);
			break;
	}

	*server = L4_Myself();	
	minix_objectid_t& result = reinterpret_cast<minix_objectid_t&> (*object_handle);
	result.filesystem = dir_handle.filesystem;
	result.inode = entry.num;
}

IDL4_PUBLISH_MINIXFS_GETENTRY(minixfs_GetEntry_implementation);

IDL4_INLINE void minixfs_EnumerateEntry_implementation(CORBA_Object _caller, const objectid_t directory_handle, const interfaceid_t interfaceid, const L4_Word_t entry, L4_ThreadId_t *server, objectid_t *object_handle, CORBA_char **name, idl4_server_environment *_env)
{
	const minix_objectid_t& dir_handle
		= reinterpret_cast<const minix_objectid_t&> (directory_handle);
	if(dir_handle.filesystem >= filesystem_count) {
#ifdef PRINT_ERROR
		printf("Invalid filesystem");
#endif
		CORBA_exception_set (_env, ex_invalid_objectid, 0);
		return;
	}
	
	FileSystem* fs = filesystems[dir_handle.filesystem];
	
	INodeWrapper dirinode;
	ErrorCode res = fs->store.readINode(&dirinode, dir_handle.inode);
	if(res != NO_ERROR) {
#ifdef PRINT_ERROR
		printf("Couldn't read inode %d\n", dir_handle.inode);
#endif
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}
	if(!dirinode.isDir()) {
#ifdef PRINT_ERROR
		printf("objectid is not a directory\n");
#endif
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}
	
	// TODO handle interfaces...
	if(interfaceid != (interfaceid_t) ANY_INTERFACE) {
#ifdef PRINT_ERROR
		printf("Enumerating specific interfaces not supported yet\n");
#endif
		*server = L4_nilthread;
		*object_handle = 0;
		return;
	}	
	
	ObjectStore::DataPointer pointer;
	fs->store.initDataPointer(pointer, &dirinode);
	res = fs->store.seek(pointer, entry * sizeof(DirectoryEntry));
	if(res != NO_ERROR) {
#ifdef PRINT_ERROR
		printf("Entry %lu doesn't exist\n", entry);
#endif
		*server = L4_nilthread;
		*object_handle = 0;
		fs->store.close(pointer);
		return;
	}
	DirectoryEntry dir_entry;
	if(fs->store.read(pointer, &dir_entry, sizeof(dir_entry)) != sizeof(dir_entry)) {
#ifdef PRINT_ERROR
		printf("Entry %lu doesn't exist\n", entry);
#endif
		*server = L4_nilthread;
		*object_handle = 0;
		fs->store.close(pointer);
		return;
	}
	fs->store.close(pointer);

	size_t i;
	for(i = 0; i < sizeof(dir_entry.name) && dir_entry.name[i] != 0; ++i) {
		(*name)[i] = dir_entry.name[i];
	}
	(*name)[i] = 0;
	
	*server = L4_Myself();
	minix_objectid_t& resultid = reinterpret_cast<minix_objectid_t&> (*object_handle);
	resultid.filesystem = dir_handle.filesystem;
	resultid.inode = dir_entry.inode;

	return;
}

IDL4_PUBLISH_MINIXFS_ENUMERATEENTRY(minixfs_EnumerateEntry_implementation);

IDL4_INLINE void minixfs_Read_implementation(CORBA_Object _caller, const objectid_t filehandle, const uint32_t pos, const idlsize_t size, buffer_t *buffer, idl4_server_environment *_env)
{
	const minix_objectid_t& handle
		= reinterpret_cast<const minix_objectid_t&> (filehandle);
	if(handle.filesystem >= filesystem_count) {
#ifdef PRINT_ERROR
		printf("Invalid filesystem %d(%d)", handle.filesystem, filesystem_count);
#endif
		buffer->_length = 0;
		CORBA_exception_set (_env, ex_invalid_objectid, 0);
		return;
	}
	
	FileSystem* fs = filesystems[handle.filesystem];
	
	INodeWrapper inode;
	ErrorCode res = fs->store.readINode(&inode, handle.inode);
	if(res != NO_ERROR) {
#ifdef PRINT_ERROR
		printf("Couldn't read inode %d\n", handle.inode);
#endif
		buffer->_length = 0;
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}
	if(!inode.isFile()) {
#ifdef PRINT_ERROR
		printf("objectid is not a file\n");
#endif
		buffer->_length = 0;
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}
	
	ObjectStore::DataPointer pointer;
	fs->store.initDataPointer(pointer, &inode);
	res = fs->store.seek(pointer, pos);
	if(res != NO_ERROR) {
#ifdef PRINT_ERROR
		printf("Couldn't seek to %u\n", pos);
#endif
		buffer->_length = 0;
		fs->store.close(pointer);
		return;
	}

	size_t readsize = size;
	assert(readsize <= MAX_BUFSIZE);
	
	buffer->_length = fs->store.read(pointer, buffer->_buffer, readsize);
	fs->store.close(pointer);
}

IDL4_PUBLISH_MINIXFS_READ(minixfs_Read_implementation);

IDL4_INLINE void minixfs_Write_implementation(CORBA_Object _caller, const objectid_t filehandle, const uint32_t pos, idlsize_t* size, buffer_t *buffer, idl4_server_environment *_env)
{
	const minix_objectid_t& handle
		= reinterpret_cast<const minix_objectid_t&> (filehandle);
	if(handle.filesystem >= filesystem_count) {
#ifdef PRINT_ERROR
		printf("Invalid filesystem %d(%d)", handle.filesystem, filesystem_count);
#endif
		buffer->_length = 0;
		CORBA_exception_set (_env, ex_invalid_objectid, 0);
		return;
	}
	
	FileSystem* fs = filesystems[handle.filesystem];
	
	INodeWrapper inode;
	ErrorCode res = fs->store.readINode(&inode, handle.inode);
	if(res != NO_ERROR) {
#ifdef PRINT_ERROR
		printf("Couldn't read inode %d\n", handle.inode);
#endif
		buffer->_length = 0;
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}
	if(!inode.isFile()) {
#ifdef PRINT_ERROR
		printf("objectid is not a file\n");
#endif
		buffer->_length = 0;
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}
	
	ObjectStore::DataPointer pointer;
	fs->store.initDataPointer(pointer, &inode);
	res = fs->store.seek(pointer, pos);
	if(res != NO_ERROR) {
#ifdef PRINT_ERROR
		printf("Couldn't seek to %u\n", pos);
#endif
		buffer->_length = 0;
		fs->store.close(pointer);
		return;
	}
	
	*size = fs->store.write(pointer, buffer->_buffer, buffer->_length);
	fs->store.close(pointer);
}

IDL4_PUBLISH_MINIXFS_WRITE(minixfs_Write_implementation);

IDL4_INLINE void minixfs_GetFileSize_implementation(CORBA_Object _caller, const objectid_t filehandle, idlsize_t *filesize, idl4_server_environment *_env)
{
	const minix_objectid_t& handle
		= reinterpret_cast<const minix_objectid_t&> (filehandle);
	if(handle.filesystem >= filesystem_count) {
#ifdef PRINT_ERROR
		printf("Invalid filesystem %d(%d)\n", handle.filesystem, filesystem_count);
#endif
		CORBA_exception_set (_env, ex_invalid_objectid, 0);
		return;
	}
	
	FileSystem* fs = filesystems[handle.filesystem];
	
	INodeWrapper inode;
	ErrorCode res = fs->store.readINode(&inode, handle.inode);
	if(res != NO_ERROR) {
#ifdef PRINT_ERROR
		printf("Couldn't read inode %d\n", handle.inode);
#endif
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}
	if(!inode.isFile()) {
#ifdef PRINT_ERROR
		printf("objectid is not a file\n");
#endif
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}
	
	*filesize = inode.size;
}

IDL4_PUBLISH_MINIXFS_GETFILESIZE(minixfs_GetFileSize_implementation);

IDL4_INLINE void minixfs_Create_implementation(CORBA_Object _caller, const objectid_t dir, const CORBA_char *name, L4_ThreadId_t *server, objectid_t *newhandle, idl4_server_environment *_env)
{
	const minix_objectid_t& handle
		= reinterpret_cast<const minix_objectid_t&> (dir);
	if(handle.filesystem >= filesystem_count) {
#ifdef PRINT_ERROR
		printf("Invalid filesystem %d(%d)\n", handle.filesystem, filesystem_count);
#endif
		CORBA_exception_set (_env, ex_invalid_objectid, 0);
		return;
	}
	
	FileSystem* fs = filesystems[handle.filesystem];

	// read parent directory inode
	INodeWrapper inode;
	ErrorCode res = fs->store.readINode(&inode, handle.inode);
	if(res != NO_ERROR) {
#ifdef PRINT_ERROR
		printf("Couldn't read inode %d\n", handle.inode);
#endif
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}
	if(!inode.isDir()) {
#ifdef PRINT_ERROR
		printf("objectid is not a directory\n");
#endif
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}

	// create new inode
	INodeWrapper* newinode = fs->store.allocINode(INode::TYPE_FILE);
	if(newinode == NULL) {
#ifdef PRINT_ERROR
		printf("Couldn't create new INode\n");
#endif
		CORBA_exception_set(_env, ex_disk_full, 0);
		return;
	}

	// link inode to directory
	res = fs->linkINode(&inode, name, newinode);
	if(res != NO_ERROR) {
		delete newinode;
#ifdef PRINT_ERROR
		printf("Couldn't link inode to directory\n");
#endif
		CORBA_exception_set(_env, ex_disk_full, 0);
		return;
	}

	*server = L4_Myself();
	minix_objectid_t& newminixhandle
		= reinterpret_cast<minix_objectid_t&> (newhandle);
	newminixhandle.filesystem = handle.filesystem;
	newminixhandle.inode = newinode->num;
	
	delete newinode;
}

IDL4_PUBLISH_MINIXFS_CREATE(minixfs_Create_implementation);

IDL4_INLINE void minixfs_Remove_implementation(CORBA_Object _caller, const objectid_t dir, const objectid_t handle, idl4_server_environment *_env)
{
  /* implementation of IF_FILEDIRECTORY::Remove */
  
  return;
}

IDL4_PUBLISH_MINIXFS_REMOVE(minixfs_Remove_implementation);

IDL4_INLINE void minixfs_MkDir_implementation(CORBA_Object _caller, const objectid_t parentdir, const CORBA_char *name, idl4_server_environment *_env)
{
 	const minix_objectid_t& handle
		= reinterpret_cast<const minix_objectid_t&> (parentdir);
	if(handle.filesystem >= filesystem_count) {
#ifdef PRINT_ERROR
		printf("Invalid filesystem %d(%d)\n", handle.filesystem, filesystem_count);
#endif
		CORBA_exception_set (_env, ex_invalid_objectid, 0);
		return;
	}
	
	FileSystem* fs = filesystems[handle.filesystem];

	// read parent directory inode
	INodeWrapper inode;
	ErrorCode res = fs->store.readINode(&inode, handle.inode);
	if(res != NO_ERROR) {
#ifdef PRINT_ERROR
		printf("Couldn't read inode %d\n", handle.inode);
#endif
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}
	if(!inode.isDir()) {
#ifdef PRINT_ERROR
		printf("objectid is not a directory\n");
#endif
		CORBA_exception_set(_env, ex_invalid_objectid, 0);
		return;
	}

	res = fs->createDirectory(&inode, name);
	if(res != NO_ERROR) {
#ifdef PRINT_ERROR
		printf("Couldn't create directory\n");
#endif
		CORBA_exception_set(_env, ex_disk_full, 0);
		return;
	}
}

IDL4_PUBLISH_MINIXFS_MKDIR(minixfs_MkDir_implementation);

IDL4_INLINE void minixfs_RmDir_implementation(CORBA_Object _caller, objectid_t *parendir, const objectid_t handle, idl4_server_environment *_env)
{

}

IDL4_PUBLISH_MINIXFS_RMDIR(minixfs_RmDir_implementation);

void *minixfs_vtable_4[MINIXFS_DEFAULT_VTABLE_SIZE] = MINIXFS_DEFAULT_VTABLE_4;
void *minixfs_vtable_5[MINIXFS_DEFAULT_VTABLE_SIZE] = MINIXFS_DEFAULT_VTABLE_5;
void *minixfs_vtable_6[MINIXFS_DEFAULT_VTABLE_SIZE] = MINIXFS_DEFAULT_VTABLE_6;
void *minixfs_vtable_11[MINIXFS_DEFAULT_VTABLE_SIZE] = MINIXFS_DEFAULT_VTABLE_11;
void *minixfs_vtable_discard[MINIXFS_DEFAULT_VTABLE_SIZE] = MINIXFS_DEFAULT_VTABLE_DISCARD;
void **minixfs_itable[16] = { minixfs_vtable_discard, minixfs_vtable_discard, minixfs_vtable_discard, minixfs_vtable_discard, minixfs_vtable_4, minixfs_vtable_5, minixfs_vtable_6, minixfs_vtable_discard, minixfs_vtable_discard, minixfs_vtable_discard, minixfs_vtable_discard, minixfs_vtable_11, minixfs_vtable_discard, minixfs_vtable_discard, minixfs_vtable_discard, minixfs_vtable_discard };

static void announce()
{
	/* Announce file service */
    CORBA_Environment env (idl4_default_environment);
        
	for(size_t i = 0; i < filesystem_count; ++i) {
		char name[128];
		snprintf(name, sizeof(name), "minixfs%u", i);
		minix_objectid_t handle;
		handle.filesystem = i;
		handle.inode = 1;
		if(Register(GetLocator(), name, IF_DIRECTORY_ID, handle.objectid) != OK
		    || Register(GetLocator(), name, IF_ENUMERABLE_ID, handle.objectid) != OK
			|| Register(GetLocator(), name, IF_FILE_ID, handle.objectid) != OK) {
			panic("Problem registering minixfs");
		}
	}	
}

void minixfs_server()
{
	L4_ThreadId_t partner;
	L4_MsgTag_t msgtag;
	idl4_msgbuf_t msgbuf;
	long cnt;

	idl4_msgbuf_init(&msgbuf);
	for (cnt = 0;cnt < MINIXFS_STRBUF_SIZE;cnt++)
		idl4_msgbuf_add_buffer(&msgbuf, malloc(MAX_BUFSIZE), MAX_BUFSIZE);

	announce();    

	while(true) {
		partner = L4_nilthread;
		msgtag.raw = 0;
		cnt = 0;

		while (true) {
			idl4_msgbuf_sync(&msgbuf);

			idl4_reply_and_wait(&partner, &msgtag, &msgbuf, &cnt);

			if (idl4_is_error(&msgtag))
				break;

			idl4_process_request(&partner, &msgtag, &msgbuf, &cnt, minixfs_itable[idl4_get_interface_id(&msgtag) & MINIXFS_IID_MASK][idl4_get_function_id(&msgtag) & MINIXFS_FID_MASK]);
		}
	}
}

void minixfs_discard()
{
	panic("minixfs message discarded");
}