/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; |
} |
/** |
* @} |
*/ |