Subversion Repositories HelenOS

Compare Revisions

Problem with comparison.

Ignore whitespace Rev HEAD → Rev 2387

/branches/fs/uspace/fs/Makefile
0,0 → 1,94
#
# Copyright (c) 2006 Martin Decky
# 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.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 configuration
#
-include Makefile.config
 
## Setup toolchain
#
 
LIBC_PREFIX = ../libc
SOFTINT_PREFIX = ../softint
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
OUTPUT = fs
SOURCES = \
glo.c \
table.c \
block.c \
inode.c \
super.c \
filedes.c \
open.c \
read.c \
path.c \
stadir.c \
utility.c \
dir.c \
printing.c \
../share/connect.c \
../share/message.c \
fs.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend
-rm -f *.o
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld -e __entry_driver $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/fs/uspace/fs/utility.c
0,0 → 1,110
/* This file contains a few general purpose utility routines. */
 
/* Methods:
* fetch_name: go get a path name from user space
* no_sys: reject a system call that FS does not handle
* conv2: does byte swapping on a 16-bit int
* conv4: does byte swapping on a 32-bit long
* fs_strncmp: same like strncmp
*/
 
 
#include <unistd.h>
#include "fs.h"
#include "block.h"
#include "file.h"
#include "fproc.h"
#include "inode.h"
 
 
int fetch_name(char* path, int len)
{
/* Go get path and put it in 'user_path' */
 
register char *rpu, *rpm;
 
/* Check name length for validity */
if (len <= 0) {
err_code = FS_EINVAL;
return FS_EGENERIC;
}
 
if (len > PATH_MAX) {
err_code = FS_ENAMETOOLONG;
return FS_EGENERIC;
}
 
rpu = &user_path[0];
rpm = path;
do { *rpu++ = *rpm++;
} while (--len);
return OK;
}
int no_sys()
{
/* Somebody has used an illegal system call number */
print_console("FS_NOSYS called, illegal system call number!\n");
return FS_EINVAL;
}
unsigned conv2(int norm, int w)
{
/* Possibly swap a 16-bit word between 8086 and 68000 byte order. */
 
if (norm) /* TRUE if no swap, FALSE for byte swap */
return((unsigned) w & 0xFFFF);
return(((w&BYTE) << 8) | ( (w>>8) & BYTE));
}
 
long conv4(int norm, long x)
{
/* Possibly swap a 32-bit long between 8086 and 68000 byte order. */
unsigned lo, hi;
long l;
if (norm) /* byte order was already ok */
return(x);
lo = conv2(FALSE, (int) x & 0xFFFF); /* low-order half, byte swapped */
hi = conv2(FALSE, (int) (x>>16) & 0xFFFF); /* high-order half, swapped */
l = ((long) lo <<16) | hi;
return l;
}
 
int fs_strncmp(const char *src, const char *dst, size_t len)
{
int i, src_len, dst_len;
if (src == NULL) {
if (dst == NULL)
return 0;
return -1;
}
if (dst == NULL)
return 1;
 
src_len = strlen(src);
dst_len = strlen(dst);
 
for (i = 0; i < len && i < src_len && i < dst_len; i++) {
if (src[i] > dst[i])
return 1;
if (src[i] < dst[i])
return -1;
}
 
return 0;
}
/branches/fs/uspace/fs/type.h
0,0 → 1,62
/* Declaration of the basic used types which are part of the V1 and V2 inode
* as it is on the disk (not in memory).
*/
 
 
#ifndef _TYPE_H
#define _TYPE_H
 
#include <sys/time.h>
 
/* Types used in disk, inode, etc. data structures. */
typedef unsigned short mode_t; /* file type and permissions bits */
typedef char nlink_t; /* number of links to a file */
typedef short dev_t; /* holds (major|minor) device pair */
typedef char gid_t; /* group id */
typedef unsigned short ino_t; /* i-node number */
typedef unsigned long offset_t; /* offset within a file */
typedef int pid_t; /* process id (must be signed) */
typedef short uid_t; /* user id */
typedef unsigned long zone_t; /* zone number */
typedef unsigned short zone1_t; /* zone number for V1 file systems */
typedef unsigned long block_num_t; /* block number */
typedef unsigned long bit_t; /* bit number in a bit map */
typedef unsigned short bitchunk_t; /* collection of bits in a bitmap */
 
typedef unsigned char u8_t; /* 8 bit type */
typedef unsigned short u16_t; /* 16 bit type */
typedef unsigned long u32_t; /* 32 bit type */
 
typedef char i8_t; /* 8 bit signed type */
typedef short i16_t; /* 16 bit signed type */
typedef long i32_t; /* 32 bit signed type */
 
//typedef unsigned long phys_bytes;/* physical addresses and lengths in bytes */
/* Declaration of the V1 inode as it is on the disk (not in core). */
typedef struct { /* V1.x disk inode */
mode_t d1_mode; /* file type, protection, etc. */
uid_t d1_uid; /* user id of the file's owner */
offset_t d1_size; /* current file size in bytes */
time_t d1_mtime; /* when was file data last changed */
gid_t d1_gid; /* group number */
nlink_t d1_nlinks; /* how many links to this file */
zone1_t d1_zone[V1_NR_TZONES]; /* block nums for direct, ind, and dbl ind */
} d1_inode_t;
 
/* Declaration of the V2 inode as it is on the disk (not in core). */
typedef struct { /* V2.x disk inode */
mode_t d2_mode; /* file type, protection, etc. */
u16_t d2_nlinks; /* how many links to this file. HACK! */
uid_t d2_uid; /* user id of the file's owner. */
u16_t d2_gid; /* group number HACK! */
offset_t d2_size; /* current file size in bytes */
time_t d2_atime; /* when was file data last accessed */
time_t d2_mtime; /* when was file data last changed */
time_t d2_ctime; /* when was inode data last changed */
zone_t d2_zone[V2_NR_TZONES]; /* block nums for direct, ind, and dbl ind */
} d2_inode_t;
 
#endif /* _TYPE_H */
 
/branches/fs/uspace/fs/tree.txt
0,0 → 1,5
/.bash_logout
/kernel/arch
/kernel/doc/AUTHORS
/kernel/doc/BUGS_FOUND
/uspace/fs/fs.c
/branches/fs/uspace/fs/table.c
0,0 → 1,23
/* This file contains the table used to map system call numbers onto the
* routines that perform them.
*/
 
#include "fs.h"
#include "file.h"
#include "fproc.h"
#include "inode.h"
#include "super.h"
 
int (*call_vector[FS_CALLS])(void) = {
no_sys, /* 0 = unused */
do_open, /* 1 = open */
do_lseek, /* 2 = seek */
do_read, /* 3 = read */
do_close, /* 4 = close */
do_chdir, /* 5 = chdir */
do_stat, /* 6 = stat */
do_fstat, /* 7 = fstat */
do_sum, /* 8 = dsum */
do_readentry /* 9 = readentry */
};
 
/branches/fs/uspace/fs/super.c
0,0 → 1,154
/* Superblock support. */
 
/* Methods:
* init_super: initializes the superblock structure for later use
* get_super: return pointer at the superblock
* read_super: read a superblock
*/
 
#include <string.h>
#include "fs.h"
#include "block.h"
#include "inode.h"
#include "super.h"
#include <stdio.h>
 
 
super_block_t* super_block;
static int v1(int magic, int *version, int *extend);
static int v2(int magic ,int*version, int *extend);
static int get_native(int magic, int *version, int *extend);
 
int (*versions[TOTAL_VERSIONS])(int , int*, int*) = {
v1, /* 0 = V1 version */
v2 /* 1 = V2 version */
};
 
int init_super_block()
{
super_block = (super_block_t*)malloc(sizeof(super_block_t));
if (super_block != NULL)
return TRUE;
 
return FALSE;
}
super_block_t *get_super()
{
return super_block;
}
 
int read_super(register super_block_t *sp)
{
/* Read a superblock. */
register block_t *bp;
int magic, version, extend, native;
 
bp = get_block(SUPER_BLOCK);
memcpy((void *)sp, (void *)(bp->b.b__data), (size_t)SUPER_SIZE);
magic = sp->s_magic; /* determines file system type */
 
/* Get file system version and type. */
native = get_native(magic, &version, &extend);
 
if (native == FS_EINVAL) {
print_console("Unknown version of file system\n");
print_console("Magic is bad\n");
return FS_EINVAL;
}
/* In V1, the device size was kept in a short, s_nzones, which limited
* devices to 32K zones. For V2, it was decided to keep the size as a
* long. However, just changing s_nzones to a long would not work, since
* then the position of s_magic in the super block would not be the same
* in V1 and V2 file systems, and there would be no way to tell whether
* a newly mounted file system was V1 or V2. The solution was to introduce
* a new variable, s_zones, and copy the size there.
*
* Calculate some other numbers that depend on the version here too, to
* hide some of the differences.
*/
 
if (version == V1) {
sp->s_zones = sp->s_nzones; /* only V1 needs this copy */
sp->s_inodes_per_block = V1_INODES_PER_BLOCK;
sp->s_ndzones = V1_NR_DZONES;
sp->s_nindirs = V1_INDIRECTS;
}
else {
sp->s_inodes_per_block = V2_INODES_PER_BLOCK;
sp->s_ndzones = V2_NR_DZONES;
sp->s_nindirs = V2_INDIRECTS;
}
sp->s_isearch = 0; /* inode searches initially start at 0 */
sp->s_zsearch = 0; /* zone searches initially start at 0 */
sp->s_version = version;
sp->s_native = native;
sp->s_extend = extend;
 
/* Make a few basic checks to see if super block looks reasonable. */
if (sp->s_imap_blocks < 1 || sp->s_zmap_blocks < 1
|| sp->s_ninodes < 1 || sp->s_zones < 1
|| (unsigned) sp->s_log_zone_size > 4) {
return FS_EINVAL;
}
return OK;
}
 
int v1(int magic, int* version, int *extend)
{
if (magic == SUPER_MAGIC || magic == conv2(BYTE_SWAP,SUPER_MAGIC)) {
*version = V1; *extend = FALSE;
return TRUE;
}
if (magic == SUPER_MAGIC2 || magic == conv2(BYTE_SWAP,SUPER_MAGIC2)) {
*version = V1; *extend = TRUE;
return TRUE;
}
 
return FALSE;
}
 
int v2(int magic, int *version, int *extend)
{
if (magic == SUPER_V2 || magic == conv2(BYTE_SWAP,SUPER_V2)) {
*version = V2; *extend = FALSE;
return TRUE;
}
if (magic == SUPER_V2E || magic == conv2(BYTE_SWAP,SUPER_V2E)) {
*version = V2; *extend = TRUE;
return TRUE;
}
 
return FALSE;
}
 
int get_native(int magic, int *version, int *extend)
{
int i, result;
/* Get file system version and type */
for (i = 0; i < TOTAL_VERSIONS; i++) {
result = versions[i](magic, version, extend);
if (result) {
return result;
}
}
 
return FS_EINVAL;
}
/branches/fs/uspace/fs/super.h
0,0 → 1,50
/*
* The s_ninodes field gives the number of inodes available
* for files and directories, including the root directory. Inode 0 is
* on the disk, but not used. Thus s_ninodes = 4 means that 5 bits will be
* used in the bit map, bit 0, which is always 1 and not used, and bits 1-4
* for files and directories. The disk layout is:
*
* Item # blocks
* boot block 1
* super block 1
* inode map s_imap_blocks
* zone map s_zmap_blocks
* inodes (s_ninodes + 'inodes per block' - 1)/'inodes per block'
* unused whatever is needed to fill out the current zone
* data zones (s_zones - s_firstdatazone) << s_log_zone_size
*
*/
 
#ifndef _SUPER_H
#define _SUPER_H
 
#define NIL_SUPER (super_block_t *) 0
 
typedef struct {
ino_t s_ninodes; /* # usable inodes on the minor device */
zone1_t s_nzones; /* total device size, including bit maps etc */
short s_imap_blocks; /* # of blocks used by inode bit map */
short s_zmap_blocks; /* # of blocks used by zone bit map */
zone1_t s_firstdatazone; /* number of first data zone */
short s_log_zone_size; /* log2 of blocks/zone */
offset_t s_max_size; /* maximum file size on this device */
short s_magic; /* magic number to recognize super-blocks */
short s_pad; /* try to avoid compiler-dependent padding */
zone_t s_zones; /* number of zones (replaces s_nzones in V2) */
/* The following items are only used when the super_block is in memory. */
unsigned s_inodes_per_block; /* precalculated from magic number */
int s_native; /* set to 1 iff not byte swapped file system */
int s_version; /* file system version, zero means bad magic */
int s_extend; /* 1 if file system support 30 chars in file name */
int s_ndzones; /* # direct zones in an inode */
int s_nindirs; /* # indirect zones per indirect block */
bit_t s_isearch; /* inodes below this bit number are in use */
bit_t s_zsearch; /* all zones below this bit number are in use*/
} super_block_t;
 
extern super_block_t* super_block;
 
#endif /* _SUPER_H */
/branches/fs/uspace/fs/stat.h
0,0 → 1,17
/* Definition of a struct that is used in the stat and fstat calls.
* The information in this struct comes from the i-node of some file.
* These calls are the only approved way to inspect i-nodes.
*/
 
 
#ifndef _STAT_H
#define _STAT_H
 
typedef struct {
ino_t st_ino; /* i-node number */
mode_t st_mode; /* file mode, protection bits, etc. */
short int st_nlink; /* # links; TEMPORARY HACK: should be nlink_t*/
offset_t st_size; /* file size */
} stat_t;
 
#endif /* _STAT_H */
/branches/fs/uspace/fs/stadir.c
0,0 → 1,140
/* This file contains the code for performing four system calls relating to
* status and directories.
*/
 
/* Methods:
* do_chdir: perform the CHDIR system call
* do_stat: perform the STAT system call
* do_fstat: perform the FSTAT system call
*/
 
 
#include "fs.h"
#include "stat.h"
#include "file.h"
#include "fproc.h"
#include "inode.h"
#include "param.h"
 
 
static int change(inode_t **iip, char *name_ptr, int len);
static int stat_inode(inode_t *rip, filp_t *fil_ptr, char *user_addr);
int do_chdir()
{
/* Perform the chdir(file_name) system call */
int r;
 
r = change(&fp->fp_workdir, file_name, strlen(file_name)+1);
return r;
}
int change(inode_t **iip, char *name_ptr, int len)
{
/*
* iip: pointer to the inode pointer for the dir
* name_ptr: pointer to the directory name to change to
* len: length of the directory name string
*/
 
/* Do the actual work for chdir() and chroot(). */
inode_t *rip;
register int r;
r = OK;
 
/* Try to open the new directory. */
if (fetch_name(name_ptr, len) != OK)
return err_code;
if ((rip = eat_path(user_path)) == NIL_INODE)
return err_code;
/* It must be a directory and also be searchable. */
if ((rip->i_mode & I_TYPE) != I_DIRECTORY)
r = FS_ENOTDIR;
 
/* If error, return inode. */
if (r != OK) {
put_inode(rip);
return r;
}
/* Everything is OK. Make the change. */
put_inode(*iip); /* release the old directory */
*iip = rip; /* acquire the new one */
 
return OK;
}
int do_stat()
{
/* Perform the stat(name, buf) system call. */
register inode_t *rip;
register int r;
/* Both stat() and fstat() use the same routine to do the real work. That
* routine expects an inode, so acquire it temporarily.
*/
if (fetch_name(file_name, strlen(file_name)+1) != OK)
return err_code;
if ((rip = eat_path(user_path)) == NIL_INODE)
return err_code;
r = stat_inode(rip, NIL_FILP, fp->buffer); /* actually do the work.*/
put_inode(rip); /* release the inode */
return r;
}
int do_fstat()
{
/* Perform the fstat(fd, buf) system call. */
register filp_t *rfilp;
 
/* Is the file descriptor valid? */
if ((rfilp = get_filp(fd)) == NIL_FILP)
return err_code;
if (rfilp->filp_ino == NIL_INODE)
return FS_ENOENT;
return(stat_inode(rfilp->filp_ino, NIL_FILP, fp->buffer));
}
int stat_inode(register inode_t *rip, filp_t *fil_ptr, char *user_addr)
{
/*
* rip: pointer to inode to stat
* fil_ptr: filp pointer, supplied by 'fstat'
* user_addr: user space address where stat buf goes
*/
 
/* Common code for stat and fstat system calls. */
stat_t statbuf;
/* Fill in the statbuf struct. */
statbuf.st_ino = rip->i_num;
statbuf.st_mode = rip->i_mode;
statbuf.st_nlink = rip->i_nlinks & BYTE;
statbuf.st_size = rip->i_size;
/* Copy infomations to userspace. */
memcpy(user_addr, &statbuf, sizeof(statbuf));
return OK;
}
 
/branches/fs/uspace/fs/read.c
0,0 → 1,251
/* This file contains the heart of the mechanism used to read files.
* Read requests are split up into chunks that do not cross block
* boundaries. Each chunk is then processed in turn.
*/
 
/* Methods:
* do_read: perform the READ system call
* read_map: given an inode and file position, look up its zone number
* rd_indir: read an entry in an indirect block
*/
 
#include <stdio.h>
#include "fs.h"
#include "block.h"
#include "file.h"
#include "fproc.h"
#include "inode.h"
#include "super.h"
#include "param.h"
 
 
static int read_chunk(inode_t *rip, offset_t position,
unsigned off, int chunk, char *buff);
 
int do_read()
{
/* Perform read(fd, buffer, nbytes) call. */
register inode_t *rip;
register filp_t *f;
offset_t bytes_left, f_size, position;
unsigned int off, cum_io;
int oflags, r, chunk;
int regular;
mode_t mode_word;
void *old_addr;
 
/* If the file descriptor is valid, get the inode, size and mode. */
if (nbytes < 0)
return FS_EINVAL;
 
if ((f = get_filp(fd)) == NIL_FILP)
return err_code;
 
if (f->filp_mode == FILP_CLOSED)
return FS_EIO;
if (nbytes == 0)
return 0;
position = f->filp_pos;
if (position > MAX_FILE_POS)
return FS_EINVAL;
 
if (position + nbytes < position)
return FS_EINVAL; /* unsigned overflow */
oflags = f->filp_flags;
rip = f->filp_ino;
f_size = rip->i_size;
r = OK;
cum_io = 0;
mode_word = rip->i_mode & I_TYPE;
regular = (mode_word == I_REGULAR);
status = OK; /* set to EIO if disk error occurs */
old_addr = fp->buffer;
/* Split the transfer into chunks that don't span two blocks. */
while (nbytes != 0) {
off = (unsigned int)(position % BLOCK_SIZE); /* offset in blk*/
chunk = MIN(nbytes, BLOCK_SIZE - off);
if (chunk < 0) {
chunk = BLOCK_SIZE - off;
}
bytes_left = f_size - position;
 
if (position >= f_size) {
break; /* we are beyond EOF */
}
if (chunk > bytes_left)
chunk = (int)bytes_left;
 
/* Read 'chunk' bytes. */
r = read_chunk(rip, position, off, chunk, fp->buffer);
if (status < 0)
break;
/* Update counters and pointers. */
fp->buffer += chunk * sizeof(char); /* user buffer address */
nbytes -= chunk; /* bytes yet to be read */
cum_io += chunk; /* bytes read so far */
position += chunk; /* position within the file */
}
if (bytes_left <= 0 || nbytes == 0)
status = END_OF_FILE;
 
fp->buffer = old_addr;
f->filp_pos = position;
rip->i_seek = NO_SEEK;
if (status != OK) {
r = status; /* check for disk error */
}
if (status == END_OF_FILE) {
r = OK;
}
if (r == OK) {
fp->fp_cum_io_partial = 0;
print_console("File was successfully read into buffer\n");
 
return cum_io;
}
else {
print_console("Some error occured during reading the file\n");
return r;
}
}
static int read_chunk(register inode_t *rip, offset_t position, unsigned off,
int chunk, char *buff)
{
/*
* rip: pointer to inode for file to be read
* position: position within file to read or write
* off: off within the current block
* chunk: number of bytes to read or write
* buff: virtual address of the user buffer
*/
 
/* Read (part of) a block. */
register block_t *bp;
block_num_t b;
b = read_map(rip, position);
/* Reading from a nonexistent block. Must read as all zeros.*/
if (b == NO_BLOCK) {
bp = get_zero_block(); /* get a zero block */
}
else {
bp = get_block(b);
}
 
/* Copy a chunk from the block buffer to user space. */
memcpy((void *)buff, (void *)(bp->b.b__data+off), chunk);
return OK;
}
block_num_t read_map(register inode_t *rip, offset_t position)
{
/* Given an inode and a position within the corresponding file, locate the
* block (not zone) number in which that position is to be found and return it.
*/
register block_t *bp;
register zone_t z;
int scale, boff, dzones, nr_indirects, index, zind, ex;
block_num_t b;
long excess, zone, block_pos;
scale = rip->i_sp->s_log_zone_size; /* for block-zone conversion */
block_pos = position/BLOCK_SIZE; /* relative blk # in file */
zone = block_pos >> scale; /* position's zone */
boff = (int) (block_pos - (zone << scale) ); /* relative blk # within zone */
dzones = rip->i_ndzones;
nr_indirects = rip->i_nindirs;
/* Is 'position' to be found in the inode itself? */
if (zone < dzones) {
zind = (int)zone; /* index should be an int */
z = rip->i_zone[zind];
if (z == NO_ZONE)
return NO_BLOCK;
b = ((block_num_t) z << scale) + boff;
return b;
}
/* It is not in the inode, so it must be single or double indirect. */
excess = zone - dzones; /* first Vx_NR_DZONES don't count */
if (excess < nr_indirects) {
/* 'position' can be located via the single indirect block. */
z = rip->i_zone[dzones];
}
else {
/* 'position' can be located via the double indirect block. */
if ( (z = rip->i_zone[dzones+1]) == NO_ZONE)
return NO_BLOCK;
 
excess -= nr_indirects; /* single indir doesn't count*/
b = (block_num_t) z << scale;
bp = get_block(b); /* get double indirect block */
index = (int) (excess/nr_indirects);
z = rd_indir(bp, index); /* z= zone for single*/
excess = excess % nr_indirects; /* index into single ind blk */
}
/* 'z' is zone num for single indirect block; 'excess' is index into it. */
if (z == NO_ZONE)
return NO_BLOCK;
 
b = (block_num_t) z << scale; /* b is blk # for single ind */
bp = get_block(b); /* get single indirect block */
ex = (int) excess; /* need an integer */
z = rd_indir(bp, ex); /* get block pointed to */
if (z == NO_ZONE)
return NO_BLOCK;
 
b = ((block_num_t) z << scale) + boff;
 
return b;
}
zone_t rd_indir(block_t *bp, int index)
{
 
super_block_t *sp;
zone_t zone;
sp = get_super(); /* need super block to find file sys type */
/* read a zone from an indirect block */
if (sp->s_version == V1) {
zone = (zone_t)bp->b.b__v1_ind[index];
}
else {
zone = (zone_t)bp->b.b__v2_ind[index];
}
if (zone != NO_ZONE && (zone < (zone_t)sp->s_firstdatazone || zone >= sp->s_zones)) {
print_console_int("Illegal zone number %d ", zone);
print_console_int("in indirect block, index %d\n", index);
}
 
return zone;
}
/branches/fs/uspace/fs/proto.h
0,0 → 1,77
/* Function prototypes. */
 
 
#ifndef _PROTO_H
#define _PROTO_H
 
#include "block.h"
#include "inode.h"
#include "super.h"
#include "file.h"
#include "../share/shared_proto.h"
 
 
/* block.c */
int init_block(void);
block_t *get_block(block_num_t block);
block_t *get_zero_block(void);
void read_block(block_t *bp);
/* dir.c */
int do_sum(void);
int do_readentry(void);
/* filedes.c */
filp_t *find_filp(inode_t *rip);
int get_fd(int start, int *k, filp_t **fpt);
filp_t *get_filp(int fild);
 
/* inode.c */
void dup_inode(inode_t *rip);
void put_inode(inode_t *rip);
inode_t *get_inode(int numb);
void read_inode(inode_t *rip);
/* open.c */
int do_close(void);
int do_lseek(void);
int do_open(void);
/* path.c */
inode_t *eat_path(char *path);
inode_t *last_dir(char *path, char *string, int string_length);
inode_t *advance(inode_t *dirp, char *string, int string_length);
int search_dir(register inode_t *ldir_ptr,
char string [NAME_MAX], ino_t *numb, int flag);
int search_dir_ex(register inode_t *ldir_ptr,
char string[NAME_MAX_EX], ino_t *numb, int flag);
/* printing.c */
int init_printing(void);
int print_console(char *str);
int print_console_int(char *str, int arg);
 
/* read.c */
int do_read(void);
block_num_t read_map(inode_t *rip, offset_t position);
zone_t rd_indir(block_t *bp, int index);
/* stadir.c */
int do_chdir(void);
int do_fstat(void);
int do_stat(void);
/* super.c */
int init_super_block(void);
super_block_t *get_super(void);
int read_super(super_block_t *sp);
/* utility.c */
int fetch_name(char *path, int len);
int no_sys(void);
unsigned conv2(int norm, int w);
long conv4(int norm, long x);
int fs_strncmp(const char *src, const char *dst, size_t len);
 
 
#endif /* _PROTO_H */
/branches/fs/uspace/fs/printing.c
0,0 → 1,149
/* Functions for printing on console. */
 
 
/* Methods:
* init_printing: connects to SERVICE_CONSOLE and initializes used data structures
* print_console: prints char* on console
* print_console_int: prints int argument with specified conversion inside input string
*/
 
 
#include <string.h>
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <async.h>
#include "fs.h"
#include "../console/console.h"
 
#define TOTAL_CONVERSIONS 5
#define BUFF_SIZE 10
 
 
/* Table of printing conversions for: d, i, u, c, %. */
char conversions[TOTAL_CONVERSIONS];
char format_string[3] = "%";
 
static int validate_string(char conv);
 
int init_printing()
{
/* Attempt to connect to SERVICE_CONSOLE fail. */
if (!connect_to_con(&con_phone, CON_CONN_ATTEMPTS))
return FALSE;
 
conversions[0] = 'd';
conversions[1] = 'i';
conversions[2] = 'u';
conversions[3] = 'c';
conversions[4] = '%';
}
 
int validate_string(char conv)
{
int i;
/* Check if the conversion character matches conversions table. */
for (i = 0; i < TOTAL_CONVERSIONS; i++){
if (conv == conversions[i]) {
return TRUE;
}
}
 
return FALSE;
}
 
int print_console(char *str)
{
int i, len;
char c;
/* Must be connected to the CONSOLE_SERVICE. */
if (con_phone < 0)
return FALSE;
len = strlen(str);
if (len == 0)
return TRUE;
for (i = 0; i < len; i++) {
c = *str++;
async_req_2(con_phone, CONSOLE_PUTCHAR, c, 0, NULL, NULL); /* Do the work. */
}
 
return TRUE;
}
 
int print_console_int(char *str, int arg)
{
int i, retval, len, front_side, offset;
char conversion;
char buffer[BUFF_SIZE];
char *front, *back;
 
len = strlen(str);
 
if (len == 0)
return TRUE;
front = malloc((len+1) * sizeof(char));
back = malloc((len+1) * sizeof(char));
front_side = TRUE;
/* Copy front side of source string. */
for (i = 0; i < len; i++) {
if (str[i] == '%') {
front_side = FALSE;
break;
}
front[i] = str[i];
}
/* Character '%' was not found. Print it in a normal way, without int argument. */
if (front_side) {
return (print_console(str));
}
/* Character '%' was the last in the input string - error. */
if (i == (len-1)) {
return FALSE;
}
front[i] = '\0';
conversion = str[++i];
retval = validate_string(conversion);
if (!retval) {
return FALSE;
}
offset = ++i;
/* Copy back side of source string. */
for (;i < len; i++) {
back[i-offset] = str[i];
}
 
back[i] = '\0';
 
/* Two characters '%' in source string. */
if (conversion == '%') {
print_console(front);
print_console(back);
return TRUE;
}
/* Other 'normal' case. */
print_console(front);
format_string[1] = conversion;
sprintf(buffer, format_string, arg);
print_console(buffer);
print_console(back);
 
return TRUE;
}
/branches/fs/uspace/fs/path.c
0,0 → 1,331
/* This file contains the procedures that look up path names in the directory
* system and determine the inode number that goes with a given path name.
*/
 
/* Methods:
* eat_path: the 'main' routine of the path-to-inode conversion mechanism
* last_dir: find the final directory on a given path
* advance: parse one component of a path name
* search_dir: search a directory for a string and return its inode number
* search_dir_ex: used for extended versions
*/
 
 
#include <string.h>
#include "fs.h"
#include "block.h"
#include "file.h"
#include "fproc.h"
#include "inode.h"
#include "super.h"
 
 
static char *get_name(char *old_name, char *string, int string_length);
 
inode_t *eat_path(char *path)
{
/* Parse the path 'path' and put its inode in the inode table. If not possible,
* return NIL_INODE as function value and an error code in 'err_code'.
*/
register inode_t *ldip, *rip;
super_block_t *sp;
int name_len;
char string[name_len]; /* hold 1 path component name here */
name_len = NAME_MAX;
if ((sp = get_super()) == NIL_SUPER)
return NIL_INODE;
 
if (sp->s_extend) {
name_len = NAME_MAX_EX;
}
 
/* First open the path down to the final directory. */
if ( (ldip = last_dir(path, string, name_len)) == NIL_INODE)
return NIL_INODE; /* we couldn't open final directory */
 
/* The path consisting only of "/" is a special case, check for it. */
if (string[0] == '\0')
return ldip;
/* Get final component of the path. */
rip = advance(ldip, string, name_len);
put_inode(ldip);
 
return rip;
}
inode_t *last_dir(char *path, char *string, int string_length)
{
/* Given a path, 'path', located in the fs address space, parse it as
* far as the last directory, fetch the inode for the last directory into
* the inode table, and return a pointer to the inode. In
* addition, return the final component of the path in 'string'.
* If the last directory can't be opened, return NIL_INODE and
* the reason for failure in 'err_code'.
*/
register inode_t *rip;
register char *new_name;
register inode_t *new_ip;
/* Is the path absolute or relative? Initialize 'rip' accordingly. */
rip = (*path == '/' ? fp->fp_rootdir : fp->fp_workdir);
/* If dir has been removed or path is empty, return FS_ENOENT. */
if (rip->i_nlinks == 0 || *path == '\0') {
err_code = FS_ENOENT;
return NIL_INODE;
}
dup_inode(rip); /* inode will be returned with put_inode */
/* Scan the path component by component. */
while (TRUE) {
/* Extract one component. */
if ( (new_name = get_name(path, string, string_length)) == (char*) 0) {
put_inode(rip); /* bad path in user space */
return NIL_INODE;
}
if (*new_name == '\0')
{
if ( (rip->i_mode & I_TYPE) == I_DIRECTORY)
return rip; /* normal exit */
else {
/* last file of path prefix is not a directory */
put_inode(rip);
err_code = FS_ENOTDIR;
return NIL_INODE;
}
}
/* There is more path. Keep parsing. */
new_ip = advance(rip, string, string_length);
put_inode(rip);
 
if (new_ip == NIL_INODE) {
return NIL_INODE;
}
/* The call to advance() succeeded. Fetch next component. */
path = new_name;
rip = new_ip;
}
}
char *get_name(char *old_name, char *string, int string_length)
{
/* Given a pointer to a path name in fs space, 'old_name', copy the next
* component to 'string' and pad with zeros. A pointer to that part of
* the name as yet unparsed is returned. Roughly speaking,
* 'get_name' = 'old_name' - 'string'.
*
* This routine follows the standard convention that /usr/ast, /usr//ast,
* //usr///ast and /usr/ast/ are all equivalent.
*/
register int c;
register char *np, *rnp;
np = string; /* 'np' points to current position */
rnp = old_name; /* 'rnp' points to unparsed string */
while ((c = *rnp) == '/')
rnp++; /* skip leading slashes */
/* Copy the unparsed path, 'old_name', to the array, 'string'. */
while ( rnp < &old_name[PATH_MAX] && c != '/' && c != '\0') {
if (np < &string[string_length])
*np++ = c;
c = *++rnp; /* advance to next character */
}
/* To make /usr/ast/ equivalent to /usr/ast, skip trailing slashes. */
while (c == '/' && rnp < &old_name[PATH_MAX])
c = *++rnp;
/* Padding with zeroes */
if (np < &string[string_length])
*np = '\0'; /* Terminate string */
if (rnp >= &old_name[PATH_MAX]) {
err_code = FS_ENAMETOOLONG;
return((char *) 0);
}
 
return rnp;
}
inode_t *advance(inode_t *dirp, char *string, int string_length)
{
/* Given a directory and a component of a path, look up the component in
* the directory, find the inode, open it, and return a pointer to its inode
* slot. If it can't be done, return NIL_INODE.
*/
register inode_t *rip;
int r;
ino_t numb;
/* If 'string' is empty, yield same inode straight away. */
if (string[0] == '\0')
return get_inode((int) dirp->i_num);
/* Check for NIL_INODE. */
if (dirp == NIL_INODE)
return NIL_INODE;
/* If 'string' is not present in the directory, signal error. */
if (dirp->i_sp->s_extend) {
r = search_dir_ex(dirp, string, &numb, LOOK_UP);
}
else {
r = search_dir(dirp, string, &numb, LOOK_UP);
}
if (r != OK) {
err_code = r;
return NIL_INODE;
}
/* Don't go beyond the current root directory */
if (dirp == fp->fp_rootdir && strcmp(string, "..") == 0)
return(get_inode((int) dirp->i_num));
/* The component has been found in the directory. Get inode. */
if ( (rip = get_inode((int) numb)) == NIL_INODE)
return NIL_INODE;
return rip; /* return pointer to inode's component */
}
int search_dir(register inode_t *ldir_ptr, char string[NAME_MAX], ino_t *numb, int flag)
{
/* This function searches the directory whose inode is pointed to by 'ldip':
* if (flag == LOOK_UP) search for 'string' and return inode # in 'numb';
* if (flag == IS_EMPTY) return OK if only . and .. in dir else ENOTEMPTY;
*/
 
register direct_t *dp;
register block_t *bp;
int r, match;
offset_t pos;
unsigned old_slots;
block_num_t b;
/* If 'ldir_ptr' is not a pointer to a dir inode, error. */
if ((ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY)
return FS_ENOTDIR;
r = OK;
/* Step through the directory one block at a time. */
old_slots = (unsigned)(ldir_ptr->i_size/DIR_ENTRY_SIZE);
match = 0; /* set when a string match occurs */
for (pos = 0; pos < ldir_ptr->i_size; pos += BLOCK_SIZE) {
b = read_map(ldir_ptr, pos); /* get block number */
/* Since directories don't have holes, 'b' cannot be NO_BLOCK. */
bp = get_block(b); /* get a dir block */
/* Search a directory block. */
for (dp = &bp->b.b__dir[0]; dp < &bp->b.b__dir[NR_DIR_ENTRIES]; dp++) {
/* Match occurs if string found. */
if (dp->d_ino != 0) {
if (flag == IS_EMPTY) {
/* If this test succeeds, dir is not empty. */
if (strcmp(dp->d_name, "." ) != 0 &&
strcmp(dp->d_name, "..") != 0)
match = 1;
}
else {
if (fs_strncmp(dp->d_name, string, NAME_MAX) == 0)
match = 1;
}
}
if (match) {
/* LOOK_UP or DELETE found what it wanted. */
r = OK;
if (flag == IS_EMPTY) {
r = FS_ENOTEMPTY;
}
else {
*numb = (int) dp->d_ino;
}
return r;
}
}
}
/* The whole directory has now been searched. */
return(flag == IS_EMPTY ? OK : FS_ENOENT);
}
 
int search_dir_ex(register inode_t *ldir_ptr, char string[NAME_MAX_EX], ino_t *numb, int flag)
{
/* Same as above, but for extened directory etries - 30 chars in name of file. */
 
register directex_t *dp;
register block_t *bp;
int r, match;
offset_t pos;
unsigned old_slots;
block_num_t b;
/* If 'ldir_ptr' is not a pointer to a dir inode, error. */
if ( (ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY)
return FS_ENOTDIR;
r = OK;
/* Step through the directory one block at a time. */
old_slots = (unsigned)(ldir_ptr->i_size/DIR_ENTRY_SIZE_EX);
match = 0; /* set when a string match occurs */
for (pos = 0; pos < ldir_ptr->i_size; pos += BLOCK_SIZE) {
b = read_map(ldir_ptr, pos); /* get block number */
/* Since directories don't have holes, 'b' cannot be NO_BLOCK. */
bp = get_block(b); /* get a dir block */
/* Search a directory block. */
for (dp = &bp->b.b__direx[0]; dp < &bp->b.b__direx[NR_DIR_ENTRIES_EX]; dp++) {
/* Match occurs if string found. */
if (dp->d_ino != 0) {
if (flag == IS_EMPTY) {
/* If this test succeeds, dir is not empty. */
if (strcmp(dp->d_name, "." ) != 0 &&
strcmp(dp->d_name, "..") != 0) match = 1;
}
else {
if (fs_strncmp(dp->d_name, string, NAME_MAX_EX) == 0)
match = 1;
}
}
if (match) {
/* LOOK_UP or DELETE found what it wanted. */
r = OK;
if (flag == IS_EMPTY) {
r = FS_ENOTEMPTY;
}
else {
*numb = (int)dp->d_ino;
}
return r;
}
}
}
/* The whole directory has now been searched. */
return(flag == IS_EMPTY ? OK : FS_ENOENT);
}
/branches/fs/uspace/fs/param.h
0,0 → 1,16
/* Synonym names for message parameters. */
 
 
#ifndef _PARAM_H
#define _PARAM_H
 
/* Shortcuts of message parameters. */
#define id_task message_params.id_task
#define fd message_params.fd
#define whence message_params.whence
#define nbytes message_params.nbytes
#define offset message_params.offset
#define file_name message_params.fname
#define entry_number message_params.entry_number
 
#endif /* _PARAM_H */
/branches/fs/uspace/fs/open.c
0,0 → 1,120
/* This file contains the procedures for opening, closing, and seeking on files. */
 
/* Methods:
* do_open: perform the OPEN system call
* do_close: perform the CLOSE system call
* do_lseek: perform the SEEK system call
*/
 
 
#include "fs.h"
#include "block.h"
#include "file.h"
#include "fproc.h"
#include "inode.h"
#include "param.h"
 
int do_open()
{
/* Perform the open(file_name) system call */
int r;
register inode_t *rip;
filp_t *fil_ptr;
r = fetch_name(file_name, strlen(file_name)+1);
if (r != OK)
return err_code; /* name was bad */
/* See if file descriptor and filp slots are available. */
if ( (r = get_fd(0, &fd, &fil_ptr)) != OK)
return r;
 
/* Scan path name. */
if ( (rip = eat_path(user_path)) == NIL_INODE)
return err_code;
/* Claim the file descriptor and filp slot and fill them in. */
fp->fp_filp[fd] = fil_ptr;
fil_ptr->filp_count = 1;
fil_ptr->filp_ino = rip;
fil_ptr->filp_flags = R_BIT;
return fd;
}
int do_close()
{
 
/* Perform the close(fd) system call. */
register filp_t *rfilp;
register inode_t *rip;
/* First locate the inode that belongs to the file descriptor */
if ( (rfilp = get_filp(fd)) == NIL_FILP)
return err_code;
 
rip = rfilp->filp_ino; /* 'rip' points to the inode */
 
if (--rfilp->filp_count == 0) {
put_inode(rip);
}
 
fp->fp_filp[fd] = NIL_FILP;
return OK;
}
int do_lseek()
{
/* Perform the seek(ls_fd, offset, whence) system call. */
register filp_t *rfilp;
register offset_t pos, new_pos;
/* Check to see if the file descriptor is valid. */
if ( (rfilp = get_filp(fd)) == NIL_FILP)
return err_code;
/* The value of 'whence' determines the start position to use. */
switch(whence) {
case 0: pos = 0;
break;
case 1: pos = rfilp->filp_pos;
break;
case 2: pos = rfilp->filp_ino->i_size;
break;
default: return FS_EINVAL;
}
/* Check for overflow. */
if (((long)offset > 0) && ((long)(pos + offset) < (long)pos))
return FS_EINVAL;
if (((long)offset < 0) && ((long)(pos + offset) > (long)pos))
return FS_EINVAL;
new_pos = pos + offset;
/* Check for setting behind the end. */
if ((new_pos) > rfilp->filp_ino->i_size) {
pos = rfilp->filp_ino->i_size;
}
else if (new_pos < 0) {
pos = 0;
}
else {
pos = new_pos;
}
rfilp->filp_pos = pos;
 
return pos;
}
 
/branches/fs/uspace/fs/limits.h
0,0 → 1,17
/* Constants which define limits of file system capabilities. */
 
#ifndef _LIMITS_H_
#define _LIMITS_H_
 
/* Number of slots in the process table for user processes. */
#define NR_PROCS 20
 
#define NAME_MAX 14 // #chars in file name
#define NAME_MAX_EX 30 // #chars in file name - extended versions
#define PATH_MAX 255 // #chars in path name
#define OPEN_MAX 20 // open files a process may have
 
/* Maximum of messages that can be sent in phase of initiating of new consumer connection. */
#define COUNTER_MAX 5
 
#endif /* _LIMITS_H_ */
/branches/fs/uspace/fs/inode.c
0,0 → 1,170
/* This file manages the inode table. There are procedures to allocate and
* deallocate inodes, acquire, erase, and release them, and read and write
* them from the disk.
*/
 
/* Methods:
* get_inode: search inode table for a given inode; if not there, read it
* read_inode: read a disk block and extract an inode
* v1_copy_inode copy from disk inode (V1.x) to in-memory inode struct
* v2_copy_inode copy from disk inode (V2.x) to in-memory inode structs
* put_inode indicate that an inode is no longer needed in memory
* dup_inode: indicate that someone else is using an inode table entry
*/
 
#include "fs.h"
#include "block.h"
#include "file.h"
#include "fproc.h"
#include "inode.h"
#include "super.h"
 
 
inode_t inode[NR_INODES];
 
static void v1_copy_inode(inode_t *rip, d1_inode_t *dip, int normal);
static void v2_copy_inode(inode_t *rip, d2_inode_t *dip, int normal);
 
 
inode_t *get_inode(int numb)
{
/* Find a slot in the inode table, load the specified inode into it, and
* return a pointer to the slot.
*/
register inode_t *rip, *xp;
/* Search the inode table both for numb and a free slot. */
xp = NIL_INODE;
for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) {
if (rip->i_count > 0) { /* only check used slots for numb */
if (rip->i_num == numb) {
/* This is the inode that we are looking for. */
rip->i_count++;
return rip; /* numb found */
}
}
else {
xp = rip; /* remember this free slot for later */
}
}
/* Inode we want is not currently in use. Did we find a free slot? */
if (xp == NIL_INODE) { /* inode table completely full */
err_code = FS_ENFILE;
return NIL_INODE;
}
/* A free inode slot has been located. Load the inode into it. */
xp->i_num = numb;
xp->i_count = 1;
read_inode(xp);
return xp;
}
void read_inode(register inode_t *rip)
{
/* An entry in the inode table is to be copied from the disk. */
register block_t *bp;
register super_block_t *sp;
d1_inode_t *dip1;
d2_inode_t *dip2;
block_num_t b, offset;
/* Get the block where the inode resides. */
sp = get_super(); /* get pointer to super block */
rip->i_sp = sp; /* inode must contain super block pointer */
offset = sp->s_imap_blocks + sp->s_zmap_blocks + 2;
b = (block_num_t)(rip->i_num - 1)/sp->s_inodes_per_block + offset;
bp = get_block(b);
dip1 = bp->b.b__v1_ino + (rip->i_num - 1) % V1_INODES_PER_BLOCK;
dip2 = bp->b.b__v2_ino + (rip->i_num - 1) % V2_INODES_PER_BLOCK;
/* Copy inode to the in-core table, swapping bytes if need be. */
if (sp->s_version == V1) {
v1_copy_inode(rip, dip1, sp->s_native);
}
else {
v2_copy_inode(rip, dip2, sp->s_native);
}
}
void v1_copy_inode(inode_t *rip, d1_inode_t *dip, int normal)
{
 
/* The V1.x IBM disk, the V1.x 68000 disk, and the V2 disk (same for IBM and
* 68000) all have different inode layouts. When an inode is read or written
* this routine handles the conversions so that the information in the inode
* table is independent of the disk structure from which the inode came.
* This routine copies from V1 disks.
*/
 
int i;
 
/* Some check is made for valid number of inode. */
if (rip == NIL_INODE || dip == NULL)
return;
/* Copy V1.x inode to the in-memory table, swapping bytes if need be. */
rip->i_mode = conv2(normal, dip->d1_mode);
rip->i_size = conv4(normal, dip->d1_size);
rip->i_nlinks = (nlink_t)dip->d1_nlinks; /* 1 char */
rip->i_ndzones = V1_NR_DZONES;
rip->i_nindirs = V1_INDIRECTS;
for (i = 0; i < V1_NR_TZONES; i++)
rip->i_zone[i] = conv2(normal, dip->d1_zone[i]);
}
void v2_copy_inode(inode_t *rip, d2_inode_t *dip, int normal)
{
/* Same as old_icopy, but to/from V2 disk layout. */
 
int i;
/* Some check is made for valid number of inode. */
if (rip == NIL_INODE || dip == NULL)
return;
/* Copy V2.x inode to the in-core table, swapping bytes if need be. */
rip->i_mode = conv2(normal, dip->d2_mode);
rip->i_size = conv4(normal, dip->d2_size);
rip->i_nlinks = conv2(normal, dip->d2_nlinks);
rip->i_ndzones = V2_NR_DZONES;
rip->i_nindirs = V2_INDIRECTS;
for (i = 0; i < V2_NR_TZONES; i++)
rip->i_zone[i] = conv4(normal, dip->d2_zone[i]);
}
 
void put_inode(inode_t *rip)
{
/* The caller is no longer using this inode. */
 
if (rip == NIL_INODE)
return;
 
rip->i_count--;
}
void dup_inode(inode_t *rip)
{
/* This routine is a simplified form of get_inode() for the case where
* the inode pointer is already known.
*/
 
if (rip == NIL_INODE)
return;
 
rip->i_count++;
}
 
/branches/fs/uspace/fs/inode.h
0,0 → 1,37
/* Inode table. This table holds inodes that are currently in use. In some
* cases they have been opened by an open() or creat() system call, in other
* cases the file system itself needs the inode for one reason or another,
* such as to search a directory for a path name.
* The first part of the struct holds fields that are present on the
* disk; the second part holds fields not present on the disk.
*/
 
#ifndef _INODE_H
#define _INODE_H
 
#include "super.h"
 
#define NIL_INODE (inode_t *) 0 /* indicates absence of inode slot */
 
#define NO_SEEK 0 /* i_seek = NO_SEEK if last op was not SEEK */
#define ISEEK 1 /* i_seek = ISEEK if last op was SEEK */
 
typedef struct {
mode_t i_mode; /* file type, protection, etc. */
nlink_t i_nlinks; /* how many links to this file */
offset_t i_size; /* current file size in bytes */
zone_t i_zone[V2_NR_TZONES]; /* zone numbers for direct, ind, and dbl ind */
 
/* The following items are not present on the disk. */
dev_t i_dev; /* which device is the inode on */
ino_t i_num; /* inode number on its (minor) device */
int i_count; /* # times inode used; 0 means slot is free */
int i_ndzones; /* # direct zones (NR_DZONES) */
int i_nindirs; /* # indirect zones per indirect block */
super_block_t *i_sp; /* pointer to super block for inode's device */
char i_seek; /* set on LSEEK, cleared on READ */
} inode_t;
 
extern inode_t inode[NR_INODES];
 
#endif /* _INODE_H */
/branches/fs/uspace/fs/glo.c
0,0 → 1,28
/* Global variables declaring. */
 
 
#include "fs.h"
#include "file.h"
#include "fproc.h"
#include "inode.h"
#include "../share/message.h"
 
 
/* File System global variables. */
fproc_t *fp; /* pointer to caller's fproc struct */
fproc_t fproc[NR_PROCS]; /* per process information table */
filp_t filp[NR_FILPS]; /* filp table */
 
/* The parameters of the call are kept here. */
message_params_t message_params; /* parameters of the input message */
int rd_phone; /* call number of RAMDISK driver task */
int con_phone; /* call number of CONSOLE service */
char user_path[PATH_MAX]; /* storage for user path name */
 
/* Data needed for communication with RAMDISK. */
void *buffer; /* buffer for storing data retrieved from RAMDISK */
 
/* The following variables are used for returning results to the caller. */
int err_code; /* temporary storage for error number */
int status; /* status of last disk i/o request */
 
/branches/fs/uspace/fs/glo.h
0,0 → 1,29
/* Global variables */
 
 
#ifndef _GLO_H
#define _GLO_H
 
#include "fproc.h"
#include "../share/message.h"
 
/* File System global variables. */
extern fproc_t *fp; /* pointer to caller's fproc struct */
 
/* The parameters of the call are kept here. */
extern message_params_t message_params; /* parameters of the input message */
extern int rd_phone; /* call number of RAMDISK driver task */
extern int con_phone; /* call number of CONSOLE service */
extern char user_path[PATH_MAX]; /* storage for user path name */
 
/* Data needed for communication with RAMDISK. */
extern void *buffer; /* buffer storing copied data */
 
/* The following variables are used for returning results to the caller */
extern int err_code; /* temporary storage for error number */
extern int status; /* status of last disk i/o request */
 
/* Data which need initialization. */
extern int (*call_vector[])(void); /* sys call table */
 
#endif /* _GLO_H */
/branches/fs/uspace/fs/fs.h
0,0 → 1,20
/* This is the master header for fs. It includes some other files
* and defines the principal constants.
*/
 
#ifndef _FS_H
#define _FS_H
 
#include <ipc/ipc.h>
#include <stdio.h>
#include <stdlib.h>
#include "../share/base_const.h"
 
#include "limits.h"
#include "errno.h"
#include "const.h"
#include "type.h"
#include "proto.h"
#include "glo.h"
 
#endif /* _FS_H */
/branches/fs/uspace/fs/fproc.h
0,0 → 1,22
/* This is the per-process information. A slot is reserved for each potential
* process.
*/
 
#ifndef _FPROC_H
#define _FPROC_H
 
typedef struct {
inode_t *fp_workdir; /* pointer to working directory's inode */
inode_t *fp_rootdir; /* pointer to current root dir (see chroot) */
filp_t *fp_filp[OPEN_MAX];/* the file descriptor table */
int fp_cum_io_partial; /* partial byte count if read can't finish */
pid_t fp_pid; /* process id */
int connected; /* is connection valid? */
void *buffer; /* buffer for data */
} fproc_t;
 
extern fproc_t fproc[NR_PROCS];
 
#endif /* _FPROC_H */
 
/branches/fs/uspace/fs/filedes.c
0,0 → 1,87
/* This file contains the procedures that manipulate file descriptors. */
 
/*
* Methods:
* get_fd: look for free file descriptor and free filp slots
* get_filp: look up the filp entry for a given file descriptor
* find_filp: find a filp slot that points to a given inode
*/
 
 
#include "fs.h"
#include "file.h"
#include "fproc.h"
#include "inode.h"
int get_fd(int start, int *k, filp_t **fpt)
{
/* Look for a free file descriptor and a free filp slot. */
register filp_t *f;
register int i;
*k = -1; /* we need a way to tell if file desc found */
/* Search the fproc fp_filp table for a free file descriptor. */
for (i = start; i < OPEN_MAX; i++) {
if (fp->fp_filp[i] == NIL_FILP) {
/* A file descriptor has been located. */
*k = i;
break;
}
}
/* Check to see if a file descriptor has been found. */
if (*k < 0)
return FS_EMFILE; /* this is why we initialized k to -1 */
/* Now that a file descriptor has been found, look for a free filp slot. */
for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
if (f->filp_count == 0) {
f->filp_mode = R_BIT;
f->filp_pos = 0L;
f->filp_flags = 0;
*fpt = f;
return OK;
}
}
/* If control passes here, the filp table must be full. Report that back. */
return FS_ENFILE;
}
filp_t *get_filp(int fild)
{
/* See if 'fild' refers to a valid file descr. If so, return its filp ptr. */
err_code = FS_EBADF;
if (fild < 0 || fild >= OPEN_MAX )
return NIL_FILP;
return(fp->fp_filp[fild]); /* may also be NIL_FILP */
}
filp_t *find_filp(register inode_t *rip)
{
/* Find a filp slot that refers to the inode 'rip' in a way as described.
* Used for determining whether somebody is still interested in.
* Like 'get_fd' it performs its job by linear search through the filp table.
*/
register filp_t *f;
for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
if (f->filp_count != 0 && f->filp_ino == rip){
return f;
}
}
/* If control passes here, the filp wasn't there. Report that back. */
return NIL_FILP;
}
 
/branches/fs/uspace/fs/file.h
0,0 → 1,22
/* This is the filp table. It is an intermediary between file descriptors and
* inodes. A slot is free if filp_count == 0.
*/
#ifndef _FILE_H
#define _FILE_H
 
typedef struct {
mode_t filp_mode; /* RW bits, telling how file is opened */
int filp_flags; /* flags from open and fcntl */
int filp_count; /* how many file descriptors share this slot?*/
inode_t *filp_ino; /* pointer to the inode */
offset_t filp_pos; /* file position */
} filp_t;
 
extern filp_t filp[NR_FILPS];
#define FILP_CLOSED 0 /* filp_mode: associated device closed */
#define NIL_FILP (filp_t *) 0 /* indicates absence of a filp slot */
 
#endif /* _FILE_H */
 
 
/branches/fs/uspace/fs/errno.h
0,0 → 1,24
/* Error codes */
 
 
#ifndef _ERRNO_H
#define _ERRNO_H
 
/* 256-512 are user error codes */
#define FS_ERROR_BASE -256 /* Base for FS error codes */
#define FS_ENOENT (FS_ERROR_BASE-1) /* no such file or directory */
#define FS_EIO (FS_ERROR_BASE-2) /* input/output error */
#define FS_EBADF (FS_ERROR_BASE-3) /* bad file descriptor */
#define FS_ENOTDIR (FS_ERROR_BASE-4) /* not a directory */
#define FS_EINVAL (FS_ERROR_BASE-5) /* invalid argument */
#define FS_ENFILE (FS_ERROR_BASE-6) /* too many open files in system */
#define FS_EMFILE (FS_ERROR_BASE-7) /* too many open files */
#define FS_EFBIG (FS_ERROR_BASE-8) /* file too large */
#define FS_ENAMETOOLONG (FS_ERROR_BASE-9) /* file name too long */
#define FS_ENOTEMPTY (FS_ERROR_BASE-10) /* directory not empty */
#define FS_EBADCALL (FS_ERROR_BASE-11) /* out of range of filesystem's call */
#define FS_EGENERIC (FS_ERROR_BASE-12) /* other error */
#define FS_ECONNECT (FS_ERROR_BASE-13) /* new consument initiating connection error */
#define FS_ENOTCONNECT (FS_ERROR_BASE-14) /* disconnected consument tried to call some function */
 
#endif /* _ERRNO_H */
/branches/fs/uspace/fs/dir.c
0,0 → 1,95
/* This file contains the procedures for support directory operations. */
 
/* Methods:
* do_sum: return total number of directory entries
* do_readentry: fill in the user buffer with directory entry specified by number
*/
 
 
#include <stdio.h>
#include "fs.h"
#include "dir.h"
#include "block.h"
#include "inode.h"
#include "param.h"
 
 
int do_sum()
{
/* Perform dsum system call. */
 
inode_t *rip;
int dir_count;
offset_t dir_size;
rip = fp->fp_workdir;
dir_size = rip->i_size;
/* We must calculate with both versions of directory entry sizes. */
if (rip->i_sp->s_extend) {
dir_count = dir_size/DIR_ENTRY_SIZE;
}
else {
dir_count = dir_size/DIR_ENTRY_SIZE_EX;
}
if (dir_size % DIR_ENTRY_SIZE_EX != 0) {
print_console("dir_size % DIR_ENTRY_SIZE_EX != 0\n");
}
 
return dir_count;
}
int do_readentry()
{
/* Perform readentry(numb, buffer) system call. */
 
int actual_sum, extend;
offset_t pos;
inode_t *rip;
block_num_t b;
block_t *bp;
register int r;
direct_t *dir;
directex_t *direx;
/* Get actual number of directory entries within the block. */
actual_sum = do_sum();
if (entry_number < 0 || actual_sum <= entry_number)
return FS_EINVAL;
rip = fp->fp_workdir;
extend = rip->i_sp->s_extend;
 
if (extend) {
pos = entry_number * DIR_ENTRY_SIZE_EX;
}
else {
pos = entry_number * DIR_ENTRY_SIZE;
}
 
/* Get number of block within the entry is. */
b = read_map(rip, pos);
if (b == NO_BLOCK)
return 0;
bp = get_block(b);
 
/* Copy the entry data into address space of actual consument. */
if (extend) {
direx = &bp->b.b__direx[entry_number];
memcpy(fp->buffer, (void*)direx, DIR_ENTRY_SIZE_EX);
}
else {
dir = &bp->b.b__dir[entry_number];
memcpy(fp->buffer, (void*)dir, DIR_ENTRY_SIZE);
}
 
r = (extend ? DIR_ENTRY_SIZE_EX : DIR_ENTRY_SIZE);
return r;
}
 
 
/branches/fs/uspace/fs/dir.h
0,0 → 1,27
/* The layout of a directory. */
 
 
#ifndef _DIR_H
#define _DIR_H
 
#define DIRBLKSIZ 512 /* size of directory block */
#define DIRSIZ 14
#define DIRSIZEX 30
 
#include "inode.h"
 
typedef struct {
ino_t d_ino;
char d_name[DIRSIZ];
} direct_t;
 
typedef struct {
ino_t d_ino;
char d_name[DIRSIZEX];
} directex_t;
 
direct_t direct;
directex_t directex;
 
#endif /* _DIR_H */
 
/branches/fs/uspace/fs/const.h
0,0 → 1,141
/* Constants of all file system. Some of them are not used here in
* current version, but will be used in later versions probably.
*/
 
#ifndef _CONST_H
#define _CONST_H
 
/* Defined in ../share/base_const.h */
/*
#define FALSE 0
#define TRUE 1
#define OK 0
*/
 
#define BLOCK_SIZE 1024 /* # bytes in a disk block */
#define MAJOR 8 /* major device = (dev>>MAJOR) & 0377 */
#define MINOR 0 /* minor device = (dev>>MINOR) & 0377 */
#define BYTE 0377 /* mask for 8 bits */
#define NO_NUM 0x8000 /* used as numerical argument to panic() */
 
/* Not used here. */
#define NR_SEGS 3 /* # segments per process */
#define T 0 /* proc[i].mem_map[T] is for text */
#define D 1 /* proc[i].mem_map[D] is for data */
#define S 2 /* proc[i].mem_map[S] is for stack */
 
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
 
//#define FS_PROC_NR SERVICE_FS /* process number of file system */
 
#define I_NOT_ALLOC 0000000 /* this inode is free */
 
#define I_TYPE 0170000 /* this field gives inode type */
#define I_REGULAR 0100000 /* regular file, not dir or special */
#define I_DIRECTORY 0040000 /* file is a directory */
#define I_BLOCK_SPECIAL 0060000 /* block special file */
#define I_CHAR_SPECIAL 0020000 /* character special file */
 
#define MAX_FILE_POS ((off_t) 037777777777) /* largest legal file offset */
 
#define R_BIT 0000004 /* Rwx protection bit */
#define W_BIT 0000002 /* rWx protection bit */
#define X_BIT 0000001 /* rwX protection bit */
 
#define NO_BLOCK ((block_num_t) 0) /* absence of a block number */
#define NO_ZONE ((zone_t) 0) /* absence of a zone number */
#define NO_DEV ((dev_t) 0) /* absence of a device numb */
 
 
/* Tables sizes. */
#define V1_NR_DZONES 7 /* # direct zone numbers in a V1 inode */
#define V1_NR_TZONES 9 /* total # zone numbers in a V1 inode */
#define V2_NR_DZONES 7 /* # direct zone numbers in a V2 inode */
#define V2_NR_TZONES 10 /* total # zone numbers in a V2 inode */
 
#define NR_FILPS 128 /* # slots in filp table */
#define NR_INODES 64 /* # slots in "in core" inode table */
 
/* The type of sizeof may be (unsigned) long. Use the following macro for
* taking the sizes of small objects so that there are no surprises like
* (small) long constants being passed to routines expecting an int.
*/
#define usizeof(t) ((unsigned) sizeof(t))
 
 
/* File system macros corresponding with given versions. */
#define SUPER_MAGIC 0x137F /* magic number for V1 file systems */
#define SUPER_MAGIC2 0x138F /* magic number for V1 file systems - 30 char names */
#define SUPER_V2 0x2468 /* magic number for V2 file systems */
#define SUPER_V2E 0x2478 /* magic number for V2 file systems - 30 char names */
 
#define TOTAL_VERSIONS 2 /* number of versions of file system */
 
#define V1 1 /* version number of V2 file systems */
#define V2 2 /* version number of V2 file systems */
 
#define LOOK_UP 0 /* tells search_dir to lookup string */
#define IS_EMPTY 3 /* tells search_dir to ret. OK or ENOTEMPTY */
 
#define BYTE_SWAP 0 /* tells conv2/conv4 to swap bytes */
#define DONT_SWAP 1 /* tells conv2/conv4 not to swap bytes */
 
#define END_OF_FILE (-104) /* eof detected */
#define ROOT_INODE 1 /* inode number for root directory */
#define BOOT_BLOCK ((block_num_t) 0) /* block number of boot block */
#define SUPER_BLOCK ((block_num_t) 1) /* block number of super block */
/* For normal version. */
#define DIR_ENTRY_SIZE usizeof (direct_t) /* # bytes/dir entry */
#define NR_DIR_ENTRIES (BLOCK_SIZE/DIR_ENTRY_SIZE) /* # dir entries/blk */
 
/* For extended version. */
#define DIR_ENTRY_SIZE_EX usizeof (directex_t) /* # bytes/dir entry */
#define NR_DIR_ENTRIES_EX (BLOCK_SIZE/DIR_ENTRY_SIZE_EX) /* # dir entries/blk */
 
#define SUPER_SIZE usizeof (super_block_t) /* super_block size */
 
 
/* Derived sizes pertaining to the V1 file system. */
#define V1_ZONE_NUM_SIZE usizeof (zone1_t) /* # bytes in V1 zone */
#define V1_INODE_SIZE usizeof (d1_inode_t) /* bytes in V1 dsk ino */
#define V1_INDIRECTS (BLOCK_SIZE/V1_ZONE_NUM_SIZE) /* # zones/indir block */
#define V1_INODES_PER_BLOCK (BLOCK_SIZE/V1_INODE_SIZE)/* # V1 dsk inodes/blk */
/* Derived sizes pertaining to the V2 file system. */
#define V2_ZONE_NUM_SIZE usizeof (zone_t) /* # bytes in V2 zone */
#define V2_INODE_SIZE usizeof (d2_inode_t) /* bytes in V2 dsk ino */
#define V2_INDIRECTS (BLOCK_SIZE/V2_ZONE_NUM_SIZE) /* # zones/indir block */
#define V2_INODES_PER_BLOCK (BLOCK_SIZE/V2_INODE_SIZE)/* # V2 dsk inodes/blk */
 
 
/* Filesystem supported operations. */
#define FS_NEW_CONSUMER (FIRST_USER_METHOD + 50) /* this is not file system system call */
 
#define FS_BASE FIRST_USER_METHOD
#define FS_NOSYS (0 + FS_BASE)
#define FS_OPEN (1 + FS_BASE)
#define FS_SEEK (2 + FS_BASE)
#define FS_READ (3 + FS_BASE)
#define FS_CLOSE (4 + FS_BASE)
#define FS_CHDIR (5 + FS_BASE)
#define FS_STAT (6 + FS_BASE)
#define FS_FSTAT (7 + FS_BASE)
#define FS_DSUM (8 + FS_BASE)
#define FS_READENTRY (9 + FS_BASE)
 
#define FS_CALLS 10
 
#define FS_MIN (FS_BASE)
#define FS_MAX (FS_BASE + FS_CALLS)
 
#define FS_IN_RANGE(VAL) ((FS_MIN <= VAL && VAL < FS_MAX)? TRUE:FALSE)
 
/* Number of attempts the FS will try to connect to each defined services. */
#define CON_CONN_ATTEMPTS 1000
#define RD_CONN_ATTEMPTS 1000
 
#endif /* _CONST_H */
/branches/fs/uspace/fs/block.h
0,0 → 1,28
/* Data block. */
 
#ifndef _BLOCK_H
#define _BLOCK_H
 
#include "dir.h"
 
#define DIRECTORY_BLOCK 1 /* directory block */
#define INDIRECT_BLOCK 2 /* pointer block */
 
typedef struct {
union {
char b__data[BLOCK_SIZE]; /* ordinary user data */
direct_t b__dir[NR_DIR_ENTRIES]; /* directory block */
directex_t b__direx[NR_DIR_ENTRIES_EX]; /* extended directory block */
zone1_t b__v1_ind[V1_INDIRECTS]; /* V1 indirect block */
zone_t b__v2_ind[V2_INDIRECTS]; /* V2 indirect block */
d1_inode_t b__v1_ino[V1_INODES_PER_BLOCK]; /* V1 inode block */
d2_inode_t b__v2_ino[V2_INODES_PER_BLOCK]; /* V2 inode block */
} b;
 
block_num_t b_blocknr; /* number of block */
char b_count; /* number of users of this block */
} block_t;
 
extern block_t* work_block;
 
#endif /* _BLOCK_H */
/branches/fs/uspace/fs/block.c
0,0 → 1,76
/* Basic methods for reading blocks. */
 
/* Methods:
* init_block: Allocates memory for working block
* get_block: Returns requested block according its number
* read_block: Process reading of requested block
*/
 
 
#include <stdio.h>
#include <async.h>
#include <sysinfo.h>
#include "fs.h"
#include "block.h"
#include "super.h"
#include "../rd/rd.h"
 
 
block_t* work_block;
 
int init_block()
{
/* Allocating free space for working block. */
work_block = (block_t*)malloc(sizeof(block_t));
if (work_block != NULL)
return TRUE;
 
return FALSE;
}
 
block_t *get_block(register block_num_t block_nr)
{
if (block_nr == NO_BLOCK)
return (get_zero_block());
 
work_block->b_blocknr = block_nr;
read_block(work_block);
 
return work_block;
}
 
block_t *get_zero_block()
{
 
/* Setting all bytes inside block to 0 */
memset(work_block->b.b__data, 0, BLOCK_SIZE);
 
return work_block;
}
 
void read_block(register block_t *bp)
{
 
int r;
offset_t pos, header_size;
 
header_size = sysinfo_value("rd.header_size");
pos = header_size + (offset_t)bp->b_blocknr * BLOCK_SIZE;
/* Reading a block with specified number from ramdisk into shared buffer. */
r = async_req_2(rd_phone, RD_READ_BLOCK, pos, BLOCK_SIZE, NULL, NULL);
if (r < 0) {
print_console_int("Unrecoverable disk error on RAMDISK, block: %d\n", bp->b_blocknr);
print_console_int("Error number: %d\n", r);
status = FS_EIO;
return;
}
/* Copy retrieved data from buffer into work block. */
memcpy((void *)(bp->b.b__data), (void *)buffer, BLOCK_SIZE);
status = BLOCK_SIZE;
}
 
 
/branches/fs/uspace/fs/fs.c
0,0 → 1,119
/*
* Copyright (c) 2006 Martin Decky
* 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.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
 
/** @addtogroup fs
* @{
*/
 
/**
* @file fs.c
* @brief File system driver for HelenOS.
*/
 
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/ns.h>
#include <sysinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <as.h>
#include <ddi.h>
#include <align.h>
#include <bool.h>
#include <errno.h>
#include <async.h>
#include "fs.h"
 
 
static void fs_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
int retval;
 
ipc_answer_fast(iid, 0, 0, 0);
 
while (1) {
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
ipc_answer_fast(callid, 0,0,0);
return;
case FS_OPEN:
//Why doesn't printf do anything in this task?
printf("FS_OPEN called");
char * f_name = (char *) IPC_GET_ARG1(call);
printf("I should open file: %s \n",f_name);
retval = 73;
break;
case FS_READ:
printf("FS_READ called");
unsigned int file_handle = IPC_GET_ARG1(call);
void * buffer = (void *) IPC_GET_ARG2(call);
unsigned int count = IPC_GET_ARG3(call);
//I still don't know how to copy memory to another task :(
//Or can i only map memory?
retval = 0;
break;
default:
retval = EINVAL;
}
ipc_answer_fast(callid, retval, 0, 0);
}
}
 
 
static bool fs_init(void)
{
return true;
}
 
int main(int argc, char **argv)
{
if (fs_init()) {
ipcarg_t phonead;
async_set_client_connection(fs_connection);
/* Register service at nameserver */
if (ipc_connect_to_me(PHONE_NS, SERVICE_FS, 0, &phonead) != 0)
return -1;
async_manager();
/* Never reached */
return 0;
}
return -1;
}
 
/**
* @}
*/