From 21e1553eb5d00d26c2df2dab004f7a41e667dd09 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= <korli@users.berlios.de>
Date: Mon, 27 Feb 2006 23:34:05 +0000
Subject: [PATCH] haiku version of iso9660 filesystem working, except for
 autodetection

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16539 a95241bf-73f2-0310-859d-f6bbb57e9c96
---
 .../kernel/file_systems/iso9660/Jamfile       |   9 +-
 .../kernel/file_systems/iso9660/cache.h       | 103 ----
 .../kernel/file_systems/iso9660/fsproto.h     | 240 --------
 src/add-ons/kernel/file_systems/iso9660/iso.c |  18 +-
 src/add-ons/kernel/file_systems/iso9660/iso.h |  16 +-
 .../kernel/file_systems/iso9660/iso9660.cpp   | 568 ++++++++++++++++++
 .../kernel/file_systems/iso9660/iso9660.h     |  34 ++
 ...ernel_interface.c => kernel_interface.cpp} | 488 +++++++++------
 8 files changed, 930 insertions(+), 546 deletions(-)
 delete mode 100644 src/add-ons/kernel/file_systems/iso9660/cache.h
 delete mode 100644 src/add-ons/kernel/file_systems/iso9660/fsproto.h
 create mode 100644 src/add-ons/kernel/file_systems/iso9660/iso9660.cpp
 create mode 100644 src/add-ons/kernel/file_systems/iso9660/iso9660.h
 rename src/add-ons/kernel/file_systems/iso9660/{kernel_interface.c => kernel_interface.cpp} (66%)

diff --git a/src/add-ons/kernel/file_systems/iso9660/Jamfile b/src/add-ons/kernel/file_systems/iso9660/Jamfile
index 8680b6564b..cf6d22354b 100644
--- a/src/add-ons/kernel/file_systems/iso9660/Jamfile
+++ b/src/add-ons/kernel/file_systems/iso9660/Jamfile
@@ -20,13 +20,20 @@ oldOPTIM = $(OPTIM) ;
 
 	defines = [ FDefines $(defines) ] ;
 	SubDirCcFlags $(defines) -Wall -Wno-multichar ;
+	SubDirC++Flags $(defines) -Wall -Wno-multichar -fno-rtti ;
 }
 
 KernelAddon iso9660 : kernel file_systems :
 	iso.c
-	kernel_interface.c
+	iso9660.cpp
+	kernel_interface.cpp
+	kernel_cpp.cpp
 	;
 
+SEARCH on [ FGristFiles
+		kernel_cpp.cpp
+	] = [ FDirName $(HAIKU_TOP) src system kernel util ] ;
+
 rule InstallISO9660
 {
 	Depends $(<) : $(>) ;
diff --git a/src/add-ons/kernel/file_systems/iso9660/cache.h b/src/add-ons/kernel/file_systems/iso9660/cache.h
deleted file mode 100644
index b491d141d7..0000000000
--- a/src/add-ons/kernel/file_systems/iso9660/cache.h
+++ /dev/null
@@ -1,103 +0,0 @@
-#ifndef _CACHE_H_
-#define _CACHE_H_
-
-#include <BeBuild.h>
-
-typedef struct hash_ent {
-	int              dev;
-	off_t            bnum;
-	off_t            hash_val;
-	void            *data;
-	struct hash_ent *next;
-} hash_ent;
-
-
-typedef struct hash_table {
-    hash_ent **table;
-    int        max;
-    int        mask;          /* == max - 1 */
-    int        num_elements;
-} hash_table;
-
-
-#define HT_DEFAULT_MAX   128
-
-
-typedef struct cache_ent {
-	int               dev;
-	off_t             block_num;
-	int               bsize;
-	volatile int      flags;
-
-	void             *data;
-	void             *clone;         /* copy of data by set_block_info() */
-	int               lock;
-
-	void            (*func)(off_t bnum, size_t num_blocks, void *arg);
-	off_t             logged_bnum;
-	void             *arg;
-
-	struct cache_ent *next,          /* points toward mru end of list */
-	                 *prev;          /* points toward lru end of list */
-
-} cache_ent;
-
-#define CE_NORMAL    0x0000     /* a nice clean pristine page */
-#define CE_DIRTY     0x0002     /* needs to be written to disk */
-#define CE_BUSY      0x0004     /* this block has i/o happening, don't touch it */
-
-
-typedef struct cache_ent_list {
-	cache_ent *lru;              /* tail of the list */
-	cache_ent *mru;              /* head of the list */
-} cache_ent_list;
-
-
-typedef struct block_cache {
-	lock        	lock;
-	int         	flags;
-    int         	cur_blocks;
-	int         	max_blocks;
-	hash_table  	ht;
-
-	cache_ent_list  normal,       /* list of "normal" blocks (clean & dirty) */
-		            locked;       /* list of clean and locked blocks */
-} block_cache;
-
-#if 0   /* XXXdbg -- need to deal with write through caches */
-#define DC_WRITE_THROUGH    0x0001  /* cache is write-through (for floppies) */
-#endif
-
-#define ALLOW_WRITES  1
-#define NO_WRITES     0
-
-extern _IMPEXP_KERNEL int   init_block_cache(int max_blocks, int flags);
-extern _IMPEXP_KERNEL void  shutdown_block_cache(void);
-
-extern _IMPEXP_KERNEL void  force_cache_flush(int dev, int prefer_log_blocks);
-extern _IMPEXP_KERNEL int   flush_blocks(int dev, off_t bnum, int nblocks);
-extern _IMPEXP_KERNEL int   flush_device(int dev, int warn_locked);
-
-extern _IMPEXP_KERNEL int   init_cache_for_device(int fd, off_t max_blocks);
-extern _IMPEXP_KERNEL int   remove_cached_device_blocks(int dev, int allow_write);
-
-extern _IMPEXP_KERNEL void *get_block(int dev, off_t bnum, int bsize);
-extern _IMPEXP_KERNEL void *get_empty_block(int dev, off_t bnum, int bsize);
-extern _IMPEXP_KERNEL int   release_block(int dev, off_t bnum);
-extern _IMPEXP_KERNEL int   mark_blocks_dirty(int dev, off_t bnum, int nblocks);
-
-
-extern _IMPEXP_KERNEL int  cached_read(int dev, off_t bnum, void *data, off_t num_blocks, int bsize);
-extern _IMPEXP_KERNEL int  cached_write(int dev, off_t bnum, const void *data,
-				  off_t num_blocks, int bsize);
-extern _IMPEXP_KERNEL int  cached_write_locked(int dev, off_t bnum, const void *data,
-						 off_t num_blocks, int bsize);
-extern _IMPEXP_KERNEL int  set_blocks_info(int dev, off_t *blocks, int nblocks,
-					 void (*func)(off_t bnum, size_t nblocks, void *arg),
-					 void *arg);
-
-
-extern _IMPEXP_KERNEL size_t read_phys_blocks (int fd, off_t bnum, void *data, uint num_blocks, int bsize);
-extern _IMPEXP_KERNEL size_t write_phys_blocks(int fd, off_t bnum, void *data, uint num_blocks, int bsize);
-
-#endif /* _CACHE_H_ */
diff --git a/src/add-ons/kernel/file_systems/iso9660/fsproto.h b/src/add-ons/kernel/file_systems/iso9660/fsproto.h
deleted file mode 100644
index 000809c3bc..0000000000
--- a/src/add-ons/kernel/file_systems/iso9660/fsproto.h
+++ /dev/null
@@ -1,240 +0,0 @@
-#ifndef _FSPROTO_H
-#define _FSPROTO_H
-
-#include <sys/dirent.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <iovec.h>
-
-#include <OS.h>
-#include <fs_attr.h>
-#include <fs_info.h>
-#include <BeBuild.h>
-#include <Drivers.h>
-
-typedef dev_t		nspace_id;
-typedef ino_t		vnode_id;
-
-/*
- * PUBLIC PART OF THE FILE SYSTEM PROTOCOL
- */
-
-#define		WSTAT_MODE		0x0001
-#define		WSTAT_UID		0x0002
-#define		WSTAT_GID		0x0004
-#define		WSTAT_SIZE		0x0008
-#define		WSTAT_ATIME		0x0010
-#define		WSTAT_MTIME		0x0020
-#define		WSTAT_CRTIME	0x0040
-
-#define		WFSSTAT_NAME	0x0001
-
-#define		B_ENTRY_CREATED		1
-#define		B_ENTRY_REMOVED		2
-#define		B_ENTRY_MOVED		3
-#define		B_STAT_CHANGED		4
-#define		B_ATTR_CHANGED		5
-#define		B_DEVICE_MOUNTED	6
-#define		B_DEVICE_UNMOUNTED	7
-
-#define		B_STOP_WATCHING     0x0000
-#define		B_WATCH_NAME		0x0001
-#define		B_WATCH_STAT		0x0002
-#define		B_WATCH_ATTR		0x0004
-#define		B_WATCH_DIRECTORY	0x0008
-
-#define		SELECT_READ			1
-#define		SELECT_WRITE		2
-#define 	SELECT_EXCEPTION	3
-
-#define		B_CUR_FS_API_VERSION	2
-
-struct attr_info;
-struct index_info;
-
-typedef int	op_read_vnode(void *ns, vnode_id vnid, char r, void **node);
-typedef int	op_write_vnode(void *ns, void *node, char r);
-typedef int	op_remove_vnode(void *ns, void *node, char r);
-typedef int	op_secure_vnode(void *ns, void *node);
-
-typedef int	op_walk(void *ns, void *base, const char *file, char **newpath,
-					vnode_id *vnid);
-
-typedef int	op_access(void *ns, void *node, int mode);
-
-typedef int	op_create(void *ns, void *dir, const char *name,
-					int omode, int perms, vnode_id *vnid, void **cookie);
-typedef int	op_mkdir(void *ns, void *dir, const char *name,	int perms);
-typedef int	op_symlink(void *ns, void *dir, const char *name,
-					const char *path);
-typedef int op_link(void *ns, void *dir, const char *name, void *node);
-
-typedef int	op_rename(void *ns, void *olddir, const char *oldname,
-					void *newdir, const char *newname);
-typedef int	op_unlink(void *ns, void *dir, const char *name);
-typedef int	op_rmdir(void *ns, void *dir, const char *name);
-
-typedef int	op_readlink(void *ns, void *node, char *buf, size_t *bufsize);
-
-typedef int op_opendir(void *ns, void *node, void **cookie);
-typedef int	op_closedir(void *ns, void *node, void *cookie);
-typedef int	op_rewinddir(void *ns, void *node, void *cookie);
-typedef int	op_readdir(void *ns, void *node, void *cookie, long *num,
-					struct dirent *buf, size_t bufsize);
-
-typedef int	op_open(void *ns, void *node, int omode, void **cookie);
-typedef int	op_close(void *ns, void *node, void *cookie);
-typedef int op_free_cookie(void *ns, void *node, void *cookie);
-typedef int op_read(void *ns, void *node, void *cookie, off_t pos, void *buf,
-					size_t *len);
-typedef int op_write(void *ns, void *node, void *cookie, off_t pos,
-					const void *buf, size_t *len);
-typedef int op_readv(void *ns, void *node, void *cookie, off_t pos, const iovec *vec,
-					size_t count, size_t *len);
-typedef int op_writev(void *ns, void *node, void *cookie, off_t pos, const iovec *vec,
-					size_t count, size_t *len);
-typedef int	op_ioctl(void *ns, void *node, void *cookie, int cmd, void *buf,
-					size_t len);
-typedef	int	op_setflags(void *ns, void *node, void *cookie, int flags);
-
-typedef int	op_rstat(void *ns, void *node, struct stat *);
-typedef int op_wstat(void *ns, void *node, struct stat *, long mask);
-typedef int	op_fsync(void *ns, void *node);
-
-typedef int	op_select(void *ns, void *node, void *cookie, uint8 event,
-				uint32 ref, selectsync *sync);
-typedef int	op_deselect(void *ns, void *node, void *cookie, uint8 event,
-				selectsync *sync);
-
-typedef int	op_initialize(const char *devname, void *parms, size_t len);
-typedef int	op_mount(nspace_id nsid, const char *devname, ulong flags,
-					void *parms, size_t len, void **data, vnode_id *vnid);
-typedef int	op_unmount(void *ns);
-typedef int	op_sync(void *ns);
-typedef int op_rfsstat(void *ns, struct fs_info *);
-typedef int op_wfsstat(void *ns, struct fs_info *, long mask);
-
-
-typedef int	op_open_attrdir(void *ns, void *node, void **cookie);
-typedef int	op_close_attrdir(void *ns, void *node, void *cookie);
-typedef int	op_rewind_attrdir(void *ns, void *node, void *cookie);
-typedef int	op_read_attrdir(void *ns, void *node, void *cookie, long *num,
-					struct dirent *buf, size_t bufsize);
-typedef int	op_remove_attr(void *ns, void *node, const char *name);
-typedef	int	op_rename_attr(void *ns, void *node, const char *oldname,
-					const char *newname);
-typedef int	op_stat_attr(void *ns, void *node, const char *name,
-					struct attr_info *buf);
-
-typedef int	op_write_attr(void *ns, void *node, const char *name, int type,
-					const void *buf, size_t *len, off_t pos);
-typedef int	op_read_attr(void *ns, void *node, const char *name, int type,
-					void *buf, size_t *len, off_t pos);
-
-typedef int	op_open_indexdir(void *ns, void **cookie);
-typedef int	op_close_indexdir(void *ns, void *cookie);
-typedef int	op_rewind_indexdir(void *ns, void *cookie);
-typedef int	op_read_indexdir(void *ns, void *cookie, long *num,
-					struct dirent *buf, size_t bufsize);
-typedef int	op_create_index(void *ns, const char *name, int type, int flags);
-typedef int	op_remove_index(void *ns, const char *name);
-typedef	int	op_rename_index(void *ns, const char *oldname, 
-					const char *newname);
-typedef int	op_stat_index(void *ns, const char *name, struct index_info *buf);
-
-typedef int	op_open_query(void *ns, const char *query, ulong flags,
-					port_id port, long token, void **cookie);
-typedef int	op_close_query(void *ns, void *cookie);
-typedef int	op_read_query(void *ns, void *cookie, long *num,
-					struct dirent *buf, size_t bufsize);
-
-typedef struct vnode_ops {
-	op_read_vnode			(*read_vnode);
-	op_write_vnode			(*write_vnode);
-	op_remove_vnode			(*remove_vnode);
-	op_secure_vnode			(*secure_vnode);
-	op_walk					(*walk);
-	op_access				(*access);
-	op_create				(*create);
-	op_mkdir				(*mkdir);
-	op_symlink				(*symlink);
-	op_link					(*link);
-	op_rename				(*rename);
-	op_unlink				(*unlink);
-	op_rmdir				(*rmdir);
-	op_readlink				(*readlink);
-	op_opendir				(*opendir);
-	op_closedir				(*closedir);
-	op_free_cookie			(*free_dircookie);
-	op_rewinddir			(*rewinddir);
-	op_readdir				(*readdir);
-	op_open					(*open);
-	op_close				(*close);
-	op_free_cookie			(*free_cookie);
-	op_read					(*read);
-	op_write				(*write);
-	op_readv				(*readv);
-	op_writev				(*writev);
-	op_ioctl				(*ioctl);
-	op_setflags				(*setflags);
-	op_rstat				(*rstat);
-	op_wstat				(*wstat);
-	op_fsync				(*fsync);
-	op_initialize			(*initialize);
-	op_mount				(*mount);
-	op_unmount				(*unmount);
-	op_sync					(*sync);
-	op_rfsstat				(*rfsstat);
-	op_wfsstat				(*wfsstat);
-	op_select				(*select);
-	op_deselect				(*deselect);
-	op_open_indexdir		(*open_indexdir);
-	op_close_indexdir		(*close_indexdir);
-	op_free_cookie			(*free_indexdircookie);
-	op_rewind_indexdir		(*rewind_indexdir);
-	op_read_indexdir		(*read_indexdir);
-	op_create_index			(*create_index);
-	op_remove_index			(*remove_index);
-	op_rename_index			(*rename_index);
-	op_stat_index			(*stat_index);
-	op_open_attrdir			(*open_attrdir);
-	op_close_attrdir		(*close_attrdir);
-	op_free_cookie			(*free_attrdircookie);
-	op_rewind_attrdir		(*rewind_attrdir);
-	op_read_attrdir			(*read_attrdir);
-	op_write_attr			(*write_attr);
-	op_read_attr			(*read_attr);
-	op_remove_attr			(*remove_attr);
-	op_rename_attr			(*rename_attr);
-	op_stat_attr			(*stat_attr);
-	op_open_query			(*open_query);
-	op_close_query			(*close_query);
-	op_free_cookie			(*free_querycookie);
-	op_read_query			(*read_query);
-} vnode_ops;
-
-extern _IMPEXP_KERNEL int	new_path(const char *path, char **copy);
-extern _IMPEXP_KERNEL void	free_path(char *p);
-
-extern _IMPEXP_KERNEL int	notify_listener(int op, nspace_id nsid,
-									vnode_id vnida,	vnode_id vnidb,
-									vnode_id vnidc, const char *name);
-extern _IMPEXP_KERNEL int	send_notification(port_id port, long token,
-									ulong what, long op, nspace_id nsida,
-									nspace_id nsidb, vnode_id vnida,
-									vnode_id vnidb, vnode_id vnidc,
-									const char *name);
-extern _IMPEXP_KERNEL int	get_vnode(nspace_id nsid, vnode_id vnid, void **data);
-extern _IMPEXP_KERNEL int	put_vnode(nspace_id nsid, vnode_id vnid);
-extern _IMPEXP_KERNEL int	new_vnode(nspace_id nsid, vnode_id vnid, void *data);
-extern _IMPEXP_KERNEL int	remove_vnode(nspace_id nsid, vnode_id vnid);
-extern _IMPEXP_KERNEL int	unremove_vnode(nspace_id nsid, vnode_id vnid);
-extern _IMPEXP_KERNEL int	is_vnode_removed(nspace_id nsid, vnode_id vnid);
-
-
-extern _EXPORT vnode_ops	fs_entry;
-extern _EXPORT int32		api_version;
-
-#endif
diff --git a/src/add-ons/kernel/file_systems/iso9660/iso.c b/src/add-ons/kernel/file_systems/iso9660/iso.c
index b31c6d1d79..9ba8ee3444 100644
--- a/src/add-ons/kernel/file_systems/iso9660/iso.c
+++ b/src/add-ons/kernel/file_systems/iso9660/iso.c
@@ -16,18 +16,18 @@
 #include <Drivers.h>
 #include <OS.h>
 #include <lock.h>
-#include <cache.h>
 #include <KernelExport.h> 
 #include <string.h>
 #include <dirent.h>
 #include <time.h>
 #include <malloc.h>
 #include <ByteOrder.h>
+#include <fs_cache.h>
 
 #include "rock.h"
 #include "iso.h"
 
-#define TRACE_ISO9660 0
+//#define TRACE_ISO9660 1
 #if TRACE_ISO9660
 #	define TRACE(x) dprintf x
 #else
@@ -39,9 +39,6 @@
 static status_t unicode_to_utf8(const char	*src, int32	*srcLen, char *dst, int32 *dstLen);
 
 
-// Size of primary volume descriptor for ISO9660
-#define ISO_PVD_SIZE 882
-
 // ISO9660 should start with this string
 const char *kISO9660IDString = "CD001";
 
@@ -55,7 +52,7 @@ static int		InitVolDate(ISOVolDate *date, char *buf);
 static int		InitRecDate(ISORecDate *date, char *buf);
 static int		InitVolDesc(nspace *vol, char *buf);
 
-#if 0	// currently unused
+#if 0  // currently unused
 static int
 GetLogicalBlockSize(int fd)
 {
@@ -91,7 +88,6 @@ GetNumDeviceBlocks(int fd, int block_size)
 }
 #endif
 
-
 static int
 GetDeviceBlockSize(int fd)
 {
@@ -271,7 +267,7 @@ ISOMount(const char *path, const int flags, nspace **newVol, bool allow_joliet)
 
 				/* Initialize access to the cache so that we can do cached i/o */
 				TRACE(("ISO9660: cache init: dev %d, max blocks %Ld\n", vol->fd, maxBlocks));
-				init_cache_for_device(vol->fd,maxBlocks);
+				vol->fBlockCache = block_cache_create(vol->fd, maxBlocks, vol->logicalBlkSize[FS_DATA_FORMAT]);
 				is_iso = true;
 			} else if ((*buffer == 0x02) && is_iso && allow_joliet) {
 				// ISO_VD_SUPPLEMENTARY
@@ -347,13 +343,13 @@ ISOReadDirEnt(nspace *ns, dircookie *cookie, struct dirent *dirent, size_t bufsi
 
 	// If we're at the end of the data in a block, move to the next block.	
 	while (1) {
-		blockData = (char *)get_block(ns->fd, cookie->block,
+		blockData = (char *)block_cache_get_etc(ns->fBlockCache, cookie->block, 0,
 							ns->logicalBlkSize[FS_DATA_FORMAT]);
 		block_out = true;
 
 		if (blockData != NULL && *(blockData + cookie->pos) == 0) {
 			//NULL data, move to next block.
-			release_block(ns->fd, cookie->block);
+			block_cache_put(ns->fBlockCache, cookie->block);
 			block_out = false;
 			totalRead += ns->logicalBlkSize[FS_DATA_FORMAT] - cookie->pos;
 			cookie->pos = 0;
@@ -397,7 +393,7 @@ ISOReadDirEnt(nspace *ns, dircookie *cookie, struct dirent *dirent, size_t bufsi
 	}
 
 	if (block_out)
-		release_block(ns->fd, cacheBlock);
+		block_cache_put(ns->fBlockCache, cacheBlock);
 
 	TRACE(("ISOReadDirEnt - EXIT, result is %s, vnid is %Lu\n", strerror(result), dirent->d_ino));
 	return result;
diff --git a/src/add-ons/kernel/file_systems/iso9660/iso.h b/src/add-ons/kernel/file_systems/iso9660/iso.h
index 656b78113d..3f268aabdc 100644
--- a/src/add-ons/kernel/file_systems/iso9660/iso.h
+++ b/src/add-ons/kernel/file_systems/iso9660/iso.h
@@ -10,13 +10,16 @@
 
 #include <stdio.h>
 #include <sys/types.h>
-#include <fsproto.h>
+#include <fs_interface.h>
 #include <lock.h>
 #include <time.h>
 #include <endian.h>
 
 #include <SupportDefs.h>
 
+// Size of primary volume descriptor for ISO9660
+#define ISO_PVD_SIZE 882
+
 // ISO structure has both msb and lsb first data. These let you do a 
 // compile-time switch for different platforms.
 
@@ -168,10 +171,11 @@ typedef struct attrfilemap
 typedef struct nspace
 {
 	// Start of members other drivers will definitely want.
-	nspace_id		id;				// ID passed in to fs_mount
+	mount_id		id;				// ID passed in to fs_mount
 	int				fd;				// File descriptor
 	int				fdOfSession;	// File descriptor of the (mounted) session
 	//unsigned int 	blockSize;  	// usually need this, but it's part of ISO
+	void                            *fBlockCache;
 		
 	char			devicePath[127];
 	//off_t			numBlocks;		// May need this, but it's part of ISO
@@ -222,9 +226,17 @@ typedef struct nspace
 	uint8			fileStructVers;		// File structure version								byte882
 } nspace;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int 		ISOMount(const char *path, const int flags, nspace** newVol, bool allow_joliet);
 int			ISOReadDirEnt(nspace* ns, dircookie* cookie, struct dirent* buf, size_t bufsize);
 int			InitNode(vnode* rec, char* buf, int* bytesRead, uint8 joliet_level);
 int			ConvertRecDate(ISORecDate* inDate, time_t* outDate);
 
+#ifdef __cplusplus
+}
+#endif 
+
 #endif
diff --git a/src/add-ons/kernel/file_systems/iso9660/iso9660.cpp b/src/add-ons/kernel/file_systems/iso9660/iso9660.cpp
new file mode 100644
index 0000000000..44aff14f3f
--- /dev/null
+++ b/src/add-ons/kernel/file_systems/iso9660/iso9660.cpp
@@ -0,0 +1,568 @@
+//----------------------------------------------------------------------
+//  This software is part of the OpenBeOS distribution and is covered 
+//  by the OpenBeOS license.
+//---------------------------------------------------------------------
+/*!
+	\file iso9660.cpp
+	\brief disk_scanner filesystem module for iso9660 CD-ROM filesystems
+
+	<h5>iso9660</h5>
+	The standard to which this module is written is ECMA-119 second
+	edition, a freely available iso9660 equivalent.
+	
+	<h5>Joliet</h5>
+	Joliet support comes courtesy of the following document:
+	
+	http://www-plateau.cs.berkeley.edu/people/chaffee/jolspec.htm
+	
+	As specified there, the existence of any of the following escape
+	sequences in a supplementary volume descriptor's "escape sequences"
+	field denotes a Joliet volume descriptor using unicode ucs-2
+	character encoding (2-byte characters, big-endian):
+	
+	- UCS-2 Level 1: 0x252F40 == "%/@"
+	- UCS-2 Level 2: 0x252F43 == "%/C"
+	- UCS-2 Level 3: 0x252F45 == "%/E"
+
+	The following UCS-2 characters are considered illegal (we allow them,
+	printing out a warning if encountered):
+	
+	- All values between 0x0000 and 0x001f inclusive == control chars
+	- 0x002A == '*'
+	- 0x002F == '/'
+	- 0x003A == ':'
+	- 0x003B == ';'
+	- 0x003F == '?'
+	- 0x005C == '\'	
+*/
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include <ByteOrder.h>
+#include <fs_info.h>
+#include <KernelExport.h>
+
+#include "iso.h"
+#include "iso9660.h"
+
+//#define TRACE(x) ;
+#define TRACE(x) dprintf x
+
+// misc constants
+static const char *kISO9660Signature = "CD001";
+static const uint32 kVolumeDescriptorLength = 2048;
+#define ISO9660_VOLUME_IDENTIFIER_LENGTH 32
+#define ISO9660_ESCAPE_SEQUENCE_LENGTH 32
+
+//! Volume descriptor types
+typedef enum {
+	ISO9660VD_BOOT,
+	ISO9660VD_PRIMARY,
+	ISO9660VD_SUPPLEMENTARY,
+	ISO9660VD_PARTITION,
+	ISO9660VD_TERMINATOR = 255
+} iso9660_volume_descriptor_type;
+
+/*! \brief The portion of the volume descriptor common to all
+    descriptor types.
+*/
+typedef struct iso9660_common_volume_descriptor {
+	uchar volume_descriptor_type;
+	char standard_identifier[5];	// should be 'CD001'
+	uchar volume_descriptor_version;
+	// Remaining bytes are unused
+} __attribute__((packed)) iso9660_common_volume_descriptor;
+
+/*! \brief Primary volume descriptor
+*/
+typedef struct iso9660_primary_volume_descriptor {
+	iso9660_common_volume_descriptor info;
+	uchar volume_flags;
+	char system_identifier[32];
+	char volume_identifier[ISO9660_VOLUME_IDENTIFIER_LENGTH];
+	uchar unused01[8];
+	uint32 volume_space_size_little_endian;
+	uint32 volume_space_size_big_endian;
+	uchar unused02[ISO9660_ESCAPE_SEQUENCE_LENGTH];	
+	uint16 volume_set_size_little_endian;
+	uint16 volume_set_size_big_endian;
+	uint16 volume_sequence_number_little_endian;
+	uint16 volume_sequence_number_big_endian;
+	uint16 logical_block_size_little_endian;
+	uint16 logical_block_size_big_endian;
+	uint32 path_table_size_little_endian;
+	uint32 path_table_size_big_endian;
+	uint32 ignored02[4];
+	uchar root_directory_record[34];
+	char volume_set_identifier[28];
+	// Remaining bytes are disinteresting to us
+} __attribute__((packed)) iso9660_primary_volume_descriptor;
+
+typedef struct iso9660_supplementary_volume_descriptor {
+	iso9660_common_volume_descriptor info;
+	uchar volume_flags;
+	char system_identifier[32];
+	char volume_identifier[ISO9660_VOLUME_IDENTIFIER_LENGTH];
+	uchar unused01[8];
+	uint32 volume_space_size_little_endian;
+	uint32 volume_space_size_big_endian;
+	char escape_sequences[ISO9660_ESCAPE_SEQUENCE_LENGTH];	
+	uint16 volume_set_size_little_endian;
+	uint16 volume_set_size_big_endian;
+	uint16 volume_sequence_number_little_endian;
+	uint16 volume_sequence_number_big_endian;
+	uint16 logical_block_size_little_endian;
+	uint16 logical_block_size_big_endian;
+	uint32 path_table_size_little_endian;
+	uint32 path_table_size_big_endian;
+	uint32 ignored02[4];
+	uchar root_directory_record[34];
+	char volume_set_identifier[28];
+	// Remaining bytes are disinteresting to us
+} __attribute__((packed)) iso9660_supplementary_volume_descriptor;
+
+typedef struct iso9660_directory_record {
+	uint8 length;
+	uint8 extended_attribute_record_length;
+	uint32 location_le;
+	uint32 location_be;
+	uint32 data_length;
+	uchar ignored[14];
+	uint16 volume_space_le;
+} __attribute__((packed)) iso9660_directory_record;
+
+//----------------------------------------------------------------------------
+// iso9660_info
+//----------------------------------------------------------------------------
+
+/*! \brief Creates a new iso9660_info struct with empty volume names.
+
+	\note Use the applicable set_XYZ_volume_name() functions rather than
+	messing with the volume name data members directly.
+*/
+iso9660_info::iso9660_info()
+	: iso9660_volume_name(NULL)
+	, joliet_volume_name(NULL)
+{
+}
+
+/*! \brief Destroys the struct, freeing the volume name strings.
+*/
+iso9660_info::~iso9660_info()
+{
+	if (iso9660_volume_name) {
+		free(iso9660_volume_name);
+		iso9660_volume_name = NULL;
+	}
+	if (joliet_volume_name) {
+		free(joliet_volume_name);
+		joliet_volume_name = NULL;
+	}
+}
+
+/*! \brief Returns true if a valid volume name exists.
+*/
+bool
+iso9660_info::is_valid()
+{
+	return iso9660_volume_name || joliet_volume_name;
+}
+
+/*! \brief Sets the iso9660 volume name.
+
+	\param name UTF-8 string containing the name.
+	\param length The length (in bytes) of the string.
+*/
+void
+iso9660_info::set_iso9660_volume_name(const char *name, uint32 length)
+{
+	set_string(&iso9660_volume_name, name, length);
+}
+
+/*! \brief Sets the Joliet volume name.
+
+	\param name UTF-8 string containing the name.
+	\param length The length (in bytes) of the string.
+*/
+void
+iso9660_info::set_joliet_volume_name(const char *name, uint32 length)
+{
+	set_string(&joliet_volume_name, name, length);
+}
+
+/*! \brief Returns the volume name of highest precedence.
+
+	Currently, the ordering is (decreasingly):
+	- Joliet
+	- iso9660
+*/
+const char*
+iso9660_info::get_preferred_volume_name()
+{
+	if (joliet_volume_name)
+		return joliet_volume_name;
+	else
+		return iso9660_volume_name;
+}
+
+/*! \brief Copies the given string into the old string, managing memory
+	deallocation and allocation as necessary.
+*/
+void
+iso9660_info::set_string(char **string, const char *new_string, uint32 new_length)
+{
+	TRACE(("iso9660_info::set_string(%p (`%s'), `%s', %ld)\n", string, *string, new_string, new_length));
+	if (string) {
+		char *&old_string = *string; 
+		if (old_string)
+			free(old_string);
+		if (new_string) {
+			old_string = (char*)malloc(new_length+1);
+			if (old_string) {
+				strncpy(old_string, new_string, new_length);
+				old_string[new_length] = 0;
+			}
+		} else {
+			old_string = NULL;
+		}
+	}			
+}
+
+//----------------------------------------------------------------------------
+// C functions
+//----------------------------------------------------------------------------
+
+/*! \brief Converts the given unicode character to utf8.
+
+	Courtesy Mr. Axel Dörfler.
+	
+	\todo Once OpenTracker's locale kit is done, perhaps that functionality
+	should be used rather than outright stealing the code.
+*/
+static
+void
+unicode_to_utf8(uint32 c, char **out)
+{
+	char *s = *out;
+
+	if (c < 0x80)
+		*(s++) = c;
+	else if (c < 0x800) {
+		*(s++) = 0xc0 | (c>>6);
+		*(s++) = 0x80 | (c & 0x3f);
+	} else if (c < 0x10000) {
+		*(s++) = 0xe0 | (c>>12);
+		*(s++) = 0x80 | ((c>>6) & 0x3f);
+		*(s++) = 0x80 | (c & 0x3f);
+	} else if (c <= 0x10ffff) {
+		*(s++) = 0xf0 | (c>>18);
+		*(s++) = 0x80 | ((c>>12) & 0x3f);
+		*(s++) = 0x80 | ((c>>6) & 0x3f);
+		*(s++) = 0x80 | (c & 0x3f);
+	}
+	*out = s;
+}
+
+static
+const char*
+volume_descriptor_type_to_string(iso9660_volume_descriptor_type type)
+{
+	switch (type) {
+		case ISO9660VD_BOOT:          return "boot";
+		case ISO9660VD_PRIMARY:       return "primary";
+		case ISO9660VD_SUPPLEMENTARY: return "supplementary";
+		case ISO9660VD_PARTITION:     return "partiton";
+		case ISO9660VD_TERMINATOR:    return "terminator";
+		default:                      return "invalid";
+	}
+}
+
+static
+void
+dump_common_volume_descriptor(iso9660_common_volume_descriptor *common, const char *indent,
+                              bool print_header)
+{
+	if (print_header)
+		TRACE(("%siso9660_common_volume_descriptor:\n", indent));
+	
+	TRACE(("%s  volume descriptor type    == %d (%s)\n", indent,
+	       common->volume_descriptor_type,
+	       volume_descriptor_type_to_string((iso9660_volume_descriptor_type)common->volume_descriptor_type)));
+	TRACE(("%s  standard identifier       == %.5s (%s)\n", indent, common->standard_identifier,
+	       strncmp(common->standard_identifier, kISO9660Signature, 5) == 0 ? "valid" : "INVALID"));
+	TRACE(("%s  volume descriptor version == %d\n", indent, common->volume_descriptor_version));
+}
+
+static
+void
+dump_directory_record(iso9660_directory_record *record, const char *indent);
+
+static
+void
+dump_primary_volume_descriptor(iso9660_primary_volume_descriptor *primary, const char *indent,
+                              bool print_header)
+{
+	if (print_header)
+		TRACE(("%siso9660_primary_volume_descriptor:\n", indent));
+	
+	dump_common_volume_descriptor(&(primary->info), indent, false);
+	TRACE(("%s  volume identifier         == `%.32s'\n", indent,
+	       primary->volume_identifier));
+	TRACE(("%s  volume space size         == %ld\n", indent,
+	       primary->volume_space_size_little_endian));
+	TRACE(("%s  volume set size           == %d\n", indent,
+	       primary->volume_set_size_little_endian));
+	TRACE(("%s  volume sequence number    == %d\n", indent,
+	       primary->volume_sequence_number_little_endian));
+	TRACE(("%s  logical block size        == %d\n", indent,
+	       primary->logical_block_size_little_endian));
+	TRACE(("%s  path table size           == %ld\n", indent,
+	       primary->path_table_size_little_endian));
+	TRACE(("%s  volume set identifier     == %.28s\n", indent,
+	       primary->volume_set_identifier));
+	dump_directory_record((iso9660_directory_record*)primary->root_directory_record, indent);
+}
+
+static
+void
+dump_supplementary_volume_descriptor(iso9660_supplementary_volume_descriptor *supplementary, const char *indent,
+                              bool print_header)
+{
+	if (print_header)
+		TRACE(("%siso9660_supplementary_volume_descriptor:\n", indent));
+		
+	dump_primary_volume_descriptor((iso9660_primary_volume_descriptor*)supplementary, indent, false);
+	TRACE(("%s  escape sequences          ==", indent));
+	for (int i = 0; i < ISO9660_ESCAPE_SEQUENCE_LENGTH; i++) {
+		TRACE((" %2x", supplementary->escape_sequences[i]));
+		if (i == ISO9660_ESCAPE_SEQUENCE_LENGTH/2-1)
+			TRACE(("\n                                "));
+	}
+	TRACE(("\n"));
+}
+		
+static
+void
+dump_directory_record(iso9660_directory_record *record, const char *indent)
+{
+	TRACE(("%s  root directory record:\n", indent));
+	TRACE(("%s    length                    == %d\n", indent, record->length));
+	TRACE(("%s    location                  == %ld\n", indent, record->location_le));
+	TRACE(("%s    data length               == %ld\n", indent, record->data_length));
+	TRACE(("%s    volume sequence number    == %d\n", indent, record->volume_space_le));
+}
+
+static
+status_t
+check_common_volume_descriptor(iso9660_common_volume_descriptor *common)
+{
+	status_t error = common ? B_OK : B_BAD_VALUE;
+	if (!error) {
+		error = strncmp(common->standard_identifier, kISO9660Signature,
+		                5) == 0 ? B_OK : B_BAD_DATA;
+	}
+	return error;
+}
+
+
+// iso9660_fs_identify
+/*! \brief Returns true if the given partition is a valid iso9660 partition.
+
+	See fs_identify_hook() for more information.
+	
+	\todo Fill in partitionInfo->mounted_at with something useful.
+*/
+status_t
+iso9660_fs_identify(int deviceFD, iso9660_info *info)
+{
+	bool result = false;
+	uchar *buffer = NULL;
+	bool exit = false;
+	status_t error = B_OK;
+	nspace *vol;
+	
+	TRACE(("identify(%d, %p)\n", deviceFD, info));
+	off_t offset = 0x8000;
+		   
+	vol = (nspace *)calloc(sizeof(nspace), 1);
+        if (vol == NULL) {
+                return ENOMEM;
+        }
+
+	vol->fd = deviceFD;
+		   
+	// Read through the volume descriptors looking for a primary descriptor.
+	// If for some reason there are more than one primary descriptor, the
+	// volume name from the last encountered descriptor will be used.
+	while (!error && !exit) {// && count++ < 10) {
+		iso9660_common_volume_descriptor *common = NULL;
+		
+		// Read the block containing the current descriptor
+		error = read_pos (vol->fdOfSession, offset, (void *)&buffer, ISO_PVD_SIZE);
+		offset += ISO_PVD_SIZE;
+		if (error < ISO_PVD_SIZE) {
+                        break;
+                }
+
+		common = (iso9660_common_volume_descriptor*)buffer;
+		error = check_common_volume_descriptor(common);
+//		dump_common_volume_descriptor(common, "", true);
+		
+		// Handle each type of descriptor appropriately
+		if (!error) {
+			TRACE(("found %s descriptor\n", volume_descriptor_type_to_string((iso9660_volume_descriptor_type)common->volume_descriptor_type)));
+
+			switch (common->volume_descriptor_type) {
+				case ISO9660VD_BOOT:
+					break;
+					
+				case ISO9660VD_PRIMARY:
+				{
+					int i;
+					iso9660_primary_volume_descriptor *primary = (iso9660_primary_volume_descriptor*)buffer;
+					
+					dump_primary_volume_descriptor(primary, "  ", true);
+					
+					// Cut off any trailing spaces from the volume id. Note
+					// that this allows for spaces INSIDE the volume id, even
+					// though that's not technically allowed by the standard;
+					// this was necessary to support certain RedHat 6.2 CD-ROMs
+					// from a certain Linux company who shall remain unnamed. ;-)
+					for (i = ISO9660_VOLUME_IDENTIFIER_LENGTH-1; i >= 0; i--) {
+						if (primary->volume_identifier[i] != 0x20)
+							break;
+					}
+
+					// Give a holler if the iso9660 name is already set
+					if (info->iso9660_volume_name) {
+						char str[ISO9660_VOLUME_IDENTIFIER_LENGTH+1];
+						strncpy(str, primary->volume_identifier, i+1);
+						str[i+1] = 0;
+						TRACE(("duplicate iso9660 volume name found, using latter (`%s') "
+						       "instead of former (`%s')\n", str,
+						       info->iso9660_volume_name));
+					}
+					
+					info->set_iso9660_volume_name(primary->volume_identifier, i+1);
+					info->maxBlocks = primary->volume_set_size_little_endian;
+					break;
+				}
+					
+				case ISO9660VD_SUPPLEMENTARY:
+				{
+					iso9660_supplementary_volume_descriptor *supplementary = (iso9660_supplementary_volume_descriptor*)buffer;
+					dump_supplementary_volume_descriptor((iso9660_supplementary_volume_descriptor*)supplementary, "  ", true);
+					
+					// Copy and null terminate the escape sequences
+					char escapes[ISO9660_ESCAPE_SEQUENCE_LENGTH+1];
+					strncpy(escapes, supplementary->escape_sequences, ISO9660_ESCAPE_SEQUENCE_LENGTH);
+					escapes[ISO9660_ESCAPE_SEQUENCE_LENGTH] = 0;
+					
+					// Check for a Joliet VD
+					if (strstr(escapes, "%/@") || strstr(escapes, "%/C") || strstr(escapes, "%/E")) {
+						char str[(ISO9660_VOLUME_IDENTIFIER_LENGTH*3/2)+1];
+							// Since we're dealing with 16-bit Unicode, each UTF-8 sequence
+							// will be at most 3 bytes long. So we need 3/2 as many chars as
+							// we start out with. 
+						char *str_iterator = str;
+						uint16 ch;
+						
+						// Walk thru the unicode volume name, converting to utf8 as we go.
+						for (int i = 0;
+						       (ch = B_BENDIAN_TO_HOST_INT16(((uint16*)supplementary->volume_identifier)[i]))
+						       && i < ISO9660_VOLUME_IDENTIFIER_LENGTH;
+						         i++) {
+							// Give a warning if the character is technically illegal
+							if (   ch <= 0x001F
+							    || ch == 0x002A
+							    || ch == 0x002F
+							    || ch == 0x003A
+							    || ch == 0x003B
+							    || ch == 0x003F
+							    || ch == 0x005C)
+							{
+								TRACE(("warning: illegal Joliet character found: 0%4x\n", ch));
+							}
+	
+							// Convert to utf-8
+							unicode_to_utf8(ch, &str_iterator);
+						}
+						*str_iterator = 0;
+						
+						// Give a holler if the joliet name is already set
+						if (info->joliet_volume_name) {
+							TRACE(("duplicate joliet volume name found, using latter (`%s') "
+							       "instead of former (`%s')\n", str,
+							       info->joliet_volume_name));
+						}
+						
+						info->set_joliet_volume_name(str, strlen(str));							
+					} // end "if Joliet VD"
+					break;
+				}
+					
+				case ISO9660VD_PARTITION:
+					break;
+					
+				case ISO9660VD_TERMINATOR:
+					exit = true;
+					break;
+					
+				default:
+					break;
+			}
+		}
+		if (buffer) {
+			free(buffer);
+			buffer = NULL;
+		}	
+	} 
+
+	free(vol);
+
+	return error;
+/*	
+	switch (error) {
+		case B_OK:
+			if (info.is_valid()) {
+				result = true;
+				if (partitionInfo->file_system_short_name)
+					strcpy(partitionInfo->file_system_short_name, "iso9660");
+				if (partitionInfo->file_system_long_name)
+					strcpy(partitionInfo->file_system_long_name, "iso9660 CD-ROM File System");
+				partitionInfo->file_system_flags = B_FS_IS_PERSISTENT;
+				if (priority)
+					*priority = 0;
+				// Copy the volume name of highest precedence
+				if (partitionInfo->volume_name) {
+					TRACE(("%s: iso9660 name: `%s'\n", kModuleDebugName, info.iso9660_volume_name));
+					TRACE(("%s: joliet name:  `%s'\n", kModuleDebugName, info.joliet_volume_name));
+					const char *name = info.get_preferred_volume_name();
+					int length = strlen(name);
+					if (length > B_FILE_NAME_LENGTH-1)
+						length = B_FILE_NAME_LENGTH-1;
+					strncpy(partitionInfo->volume_name, name, length);
+					partitionInfo->volume_name[length] = 0;
+				}
+				return 0.8;
+			}			
+			break;
+			
+		case B_BAD_DATA:
+			TRACE(("%s: identify: bad signature\n", kModuleDebugName));
+			break;
+		
+		default:
+			TRACE(("%s: identify error: 0x%lx\n", kModuleDebugName,
+		           error));
+		    break;
+	}
+
+	return 0.0;
+*/
+}
+
diff --git a/src/add-ons/kernel/file_systems/iso9660/iso9660.h b/src/add-ons/kernel/file_systems/iso9660/iso9660.h
new file mode 100644
index 0000000000..ef3ee57def
--- /dev/null
+++ b/src/add-ons/kernel/file_systems/iso9660/iso9660.h
@@ -0,0 +1,34 @@
+#ifndef _ISO9660_H
+#define _ISO9660_H
+
+/*! \brief Contains all the info of interest pertaining to an
+	iso9660 volume.
+
+	Currently supported character set encoding styles (in decreasing
+	order of precedence):
+	- Joliet (UCS-12 (16-bit unicode), which is converted to UTF-8)
+	- iso9660 (some absurdly tiny character set, but we actually allow UTF-8)
+*/
+struct iso9660_info {
+	iso9660_info();
+	~iso9660_info();
+
+	bool is_valid();
+
+	void set_iso9660_volume_name(const char *name, uint32 length);
+	void set_joliet_volume_name(const char *name, uint32 length);
+
+	const char* get_preferred_volume_name();
+
+	char *iso9660_volume_name;
+	char *joliet_volume_name;
+	
+	off_t maxBlocks;
+
+	void set_string(char **string, const char *new_string, uint32 new_length);
+};
+
+status_t iso9660_fs_identify(int deviceFD, iso9660_info *info);
+
+#endif
+
diff --git a/src/add-ons/kernel/file_systems/iso9660/kernel_interface.c b/src/add-ons/kernel/file_systems/iso9660/kernel_interface.cpp
similarity index 66%
rename from src/add-ons/kernel/file_systems/iso9660/kernel_interface.c
rename to src/add-ons/kernel/file_systems/iso9660/kernel_interface.cpp
index 30bb3c21fa..b317a89ac8 100644
--- a/src/add-ons/kernel/file_systems/iso9660/kernel_interface.c
+++ b/src/add-ons/kernel/file_systems/iso9660/kernel_interface.cpp
@@ -13,21 +13,31 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <string.h>
-#include <time.h>
 #include <ctype.h>
 #include <stdio.h>
 #include <dirent.h>
 #include <sys/stat.h>
-#include <KernelExport.h>
 #include <time.h>
-#include <fsproto.h>
 #include <lock.h>
-#include <cache.h>
 #include <malloc.h>
 
-#include "iso.h"
+#include <KernelExport.h>
+#include <NodeMonitor.h>
+#include <fs_interface.h>
+#include <fs_cache.h>
 
-#define TRACE_ISO9660 0
+#include <fs_attr.h>
+#include <fs_info.h>
+#include <fs_index.h>
+#include <fs_query.h>
+#include <fs_volume.h>
+
+#include <util/kernel_cpp.h>
+
+#include "iso.h"
+#include "iso9660.h"
+
+//#define TRACE_ISO9660 1
 #if TRACE_ISO9660
 #	define TRACE(x) dprintf x
 #else
@@ -36,125 +46,101 @@
 
 
 /*  Start of fundamental (read-only) required functions */
-static int		fs_mount(nspace_id nsid, const char *device, ulong flags,
-						void *parms, size_t len, void **data, vnode_id *vnid);
-static int		fs_unmount(void *_ns);
+static status_t		fs_mount(mount_id mountID, const char *device, uint32 flags, 
+				const char *args, void **_data, vnode_id *_rootID);
+static status_t		fs_unmount(void *ns);
 
-int				fs_walk(void *_ns, void *_base, const char *file,
-						char **newpath, vnode_id *vnid);
+static status_t		fs_walk(void *_ns, void *_base, const char *file, 
+				vnode_id *_vnodeID, int *_type);
 
-int				fs_read_vnode(void *_ns, vnode_id vnid, char r, void **node);
-int				fs_write_vnode(void *_ns, void *_node, char r);
-static int		fs_read_stat(void *_ns, void *_node, struct stat *st);
-static int		fs_open(void *_ns, void *_node, int omode, void **cookie);
-static int		fs_read(void *_ns, void *_node, void *cookie, off_t pos,
-						void *buf, size_t *len);
+static status_t		fs_read_vnode(void *_ns, vnode_id vnid, void **node, bool reenter);
+static status_t		fs_release_vnode(void *_ns, void *_node, bool reenter);
+static status_t		fs_read_stat(void *_ns, void *_node, struct stat *st);
+static status_t		fs_open(void *_ns, void *_node, int omode, void **cookie);
+static status_t		fs_read(void *_ns, void *_node, void *cookie, off_t pos,
+				void *buf, size_t *len);
 /// fs_free_cookie - free cookie for file created in open.
-static int		fs_free_cookie(void *ns, void *node, void *cookie);
-static int		fs_close(void *ns, void *node, void *cookie);
+static status_t		fs_free_cookie(void *ns, void *node, void *cookie);
+static status_t		fs_close(void *ns, void *node, void *cookie);
 
 // fs_access - checks permissions for access.
-static int		fs_access(void *_ns, void *_node, int mode);
+static status_t		fs_access(void *_ns, void *_node, int mode);
 
 // fs_opendir - creates fs-specific "cookie" struct that can tell where
 //					we are at in the directory list.
-static int		fs_open_dir(void* _ns, void* _node, void** cookie);
+static status_t		fs_open_dir(void* _ns, void* _node, void** cookie);
 // fs_readdir - read 1 or more dirents, keep state in cookie, return
 //					0 when no more entries.
-static int		fs_read_dir(void *_ns, void *_node, void *cookie,
-					long *num, struct dirent *buf, size_t bufsize);
+static status_t		fs_read_dir(void *_ns, void *_node, void *cookie, struct dirent *buf,
+				size_t bufsize, uint32 *_num);
 // fs_rewinddir - set cookie to represent beginning of directory, so
 //					later fs_readdir calls start at beginning.
-static int		fs_rewind_dir(void *_ns, void *_node, void *cookie);
+static status_t		fs_rewind_dir(void *_ns, void *_node, void *cookie);
 // fs_closedir - Do whatever you need to to close a directory (sometimes
 //					nothing), but DON'T free the cookie!
-static int		fs_close_dir(void *_ns, void *_node, void *cookie);
+static status_t		fs_close_dir(void *_ns, void *_node, void *cookie);
 // fs_fee_dircookie - Free the fs-specific cookie struct
-static int		fs_free_dir_cookie(void *_ns, void *_node, void *cookie);
+static status_t		fs_free_dir_cookie(void *_ns, void *_node, void *cookie);
 
 // fs_rfsstat - Fill in fs_info struct for device.
-static int		fs_read_fs_stat(void *_ns, struct fs_info *);
+static status_t		fs_read_fs_stat(void *_ns, struct fs_info *);
 
 // fs_readlink - Read in the name of a symbolic link.
-static int 		fs_read_link(void *_ns, void *_node, char *buf, size_t *bufsize);
+static status_t 		fs_read_link(void *_ns, void *_node, char *buf, size_t *bufsize);
 
 
+//	#pragma mark - Scanning
 
-/* vnode_ops struct. Fill this in to tell the kernel how to call
-	functions in your driver.
-*/
-
-vnode_ops fs_entry = {
-	&fs_read_vnode,						// read_vnode func ptr
-	&fs_write_vnode,					// write_vnode func ptr
-	NULL, 								// remove_vnode func ptr
-	NULL,								// secure_vnode func ptr
-	&fs_walk,							// walk func ptr
-	&fs_access,							// access func ptr
-	NULL, 								// create func ptr
-	NULL, 								// mkdir func ptr
-	NULL,
-	NULL,
-	NULL,
-	NULL, 								// unlink func ptr
-	NULL, 								// rmdir func ptr
-	&fs_read_link,						// readlink func ptr
-	&fs_open_dir,						// opendir func ptr
-	&fs_close_dir,						// closedir func ptr
-	&fs_free_dir_cookie,				// free_dircookie func ptr
-	&fs_rewind_dir,						// rewinddir func ptr
-	&fs_read_dir,						// readdir func ptr
-	&fs_open,							// open file func ptr
-	&fs_close,							// close file func ptr
-	&fs_free_cookie,					// free cookie func ptr
-	&fs_read,							// read file func ptr
-	NULL, 								// write file func ptr
-	NULL, /* readv */
-	NULL, /* writev */
-	NULL,								// ioctl func ptr
-	NULL,								// setflags file func ptr
-	&fs_read_stat,						// rstat func ptr
-	NULL, 								// wstat func ptr
-	NULL,
-	NULL, 								// initialize func ptr
-	&fs_mount,							// mount func ptr
-	&fs_unmount,						// unmount func ptr
-	NULL,								// sync func ptr
-	&fs_read_fs_stat,					// rfsstat func ptr
-	NULL,								// wfsstat func ptr
-	NULL,
-	NULL,
-	NULL,								// open indexdir func ptr
-	NULL,								// close indexdir func ptr
-	NULL,								// free indexdir cookie func ptr
-	NULL,								// rewind indexdir func ptr
-	NULL,								// read indexdir func ptr
-	NULL,								// create index func ptr
-	NULL,								// remove index func ptr
-	NULL,								// rename index func ptr
-	NULL,								// stat index func ptr
-	NULL, //&isofs_open_attrdir,		// open attrdir func ptr
-	NULL, //&isofs_close_attrdir,		// close attrdir func ptr
-	NULL, //&isofs_free_attrdir_cookie,	// free attrdir cookie func ptr
-	NULL, //&isofs_rewind_attrdir,		// rewind attrdir func ptr
-	NULL, //&isofs_read_attrdir,		// read attrdir func ptr
-	NULL,								// write attr func ptr
-	NULL, //&isofs_read_attr,			// read attr func ptr
-	NULL,								// remove attr func ptr
-	NULL,								// rename attr func ptr
-	NULL, //&isofs_stat_attr,			// stat attr func ptr
-	NULL,								// open query func ptr
-	NULL,								// close query func ptr
-	NULL,								// free query cookie func ptr
-	NULL								// read query func ptr
+struct identify_cookie {
+	iso9660_info info;
 };
 
-int32	api_version = B_CUR_FS_API_VERSION;
+
+static float
+fs_identify_partition(int fd, partition_data *partition, void **_cookie)
+{
+	iso9660_info info;
+	status_t status = iso9660_fs_identify(fd, &info);
+	if (status != B_OK)
+		return status;
+
+	identify_cookie *cookie = new identify_cookie;
+	memcpy(&cookie->info, &info, sizeof(info));
+
+	*_cookie = cookie;
+	return 0.8f;
+}
 
 
-static int 
-fs_mount(nspace_id nsid, const char *device, ulong flags, void *parms,
-		size_t len, void **data, vnode_id *vnid)
+static status_t
+fs_scan_partition(int fd, partition_data *partition, void *_cookie)
+{
+	identify_cookie *cookie = (identify_cookie *)_cookie;
+
+	partition->status = B_PARTITION_VALID;
+	partition->flags |= B_PARTITION_FILE_SYSTEM | B_PARTITION_READ_ONLY ;
+	partition->block_size = ISO_PVD_SIZE;
+	partition->content_size = ISO_PVD_SIZE * cookie->info.maxBlocks;
+	partition->content_name = strdup(cookie->info.get_preferred_volume_name());
+	if (partition->content_name == NULL)
+		return B_NO_MEMORY;
+
+	return B_OK;
+}
+
+
+static void
+fs_free_identify_partition_cookie(partition_data *partition, void *_cookie)
+{
+	identify_cookie *cookie = (identify_cookie *)_cookie;
+
+	delete cookie;
+}
+
+
+static status_t
+fs_mount(mount_id mountID, const char *device, uint32 flags,
+	const char *args, void **_data, vnode_id *_rootID)
 {
 	/*
 	Kernel passes in nspace_id, (representing a disk or partition?)
@@ -167,7 +153,7 @@ fs_mount(nspace_id nsid, const char *device, ulong flags, void *parms,
 	fs driver functions. vnid should also be passed back to the kernel, 
 	representing the vnode id of the root vnode.
 	*/
-	int result = EINVAL;
+	status_t result = EINVAL;
 		// return EINVAL if it's not a device compatible with the driver.
 	bool allow_joliet = true;
 	nspace *vol;
@@ -179,21 +165,12 @@ fs_mount(nspace_id nsid, const char *device, ulong flags, void *parms,
 
 	// Check for a 'nojoliet' parm
 	// all we check for is the existance of 'nojoliet' in the parms.
-	if (parms != NULL) {
+	if (args != NULL) {
 		uint32 i;
 		char *spot;
-		char *buf;
+		char *buf = strdup(args);
 
-		// Make sure the len argument isn't too large
-		if (len > 1024) 
-			return EINVAL;
-		
-		buf = malloc(len + 1);
-		if (!buf)
-			return ENOMEM;
-		
-		memcpy(buf, parms, len);
-		buf[len] = 0;
+		uint32 len = strlen(buf);
 		// lower case the parms data
 		for (i = 0; i < len + 1; i++) 
 			buf[i] = tolower(buf[i]);
@@ -202,7 +179,7 @@ fs_mount(nspace_id nsid, const char *device, ulong flags, void *parms,
 		spot = strstr(buf, "nojoliet");
 		if (spot != NULL)
 			allow_joliet = false;
-
+	
 		free(buf);
 	}
 
@@ -213,15 +190,15 @@ fs_mount(nspace_id nsid, const char *device, ulong flags, void *parms,
 	if (result == B_NO_ERROR) {
 		//vnode_id rootID = vol->rootDirRec.startLBN[FS_DATA_FORMAT];
 		//*vnid = rootID;
-		*vnid = ISO_ROOTNODE_ID;
-		*data = (void*)vol;
-		
-		vol->id = nsid;
+		*_rootID = ISO_ROOTNODE_ID;
+		*_data = (void*)vol;
+				
+		vol->id = mountID;
 
 		// You MUST do this. Create the vnode for the root.
-		result = new_vnode(nsid, *vnid, (void*)&(vol->rootDirRec));
+		result = publish_vnode(mountID, *_rootID, (void*)&(vol->rootDirRec));
 		if (result != B_NO_ERROR) {
-			remove_cached_device_blocks(vol->fd, 0);
+			block_cache_delete(vol->fBlockCache, false);
 			free(vol);
 			result = EINVAL;
 		} else 
@@ -231,15 +208,15 @@ fs_mount(nspace_id nsid, const char *device, ulong flags, void *parms,
 }
 
 
-static int		
+static status_t
 fs_unmount(void *_ns)
 {
-	int result = B_NO_ERROR;
+	status_t result = B_NO_ERROR;
 	nspace *ns = (nspace *)_ns;
 
 	TRACE(("fs_unmount - ENTER\n"));
 
-	remove_cached_device_blocks(ns->fd, 0);
+	block_cache_delete(ns->fBlockCache, false);
 	close(ns->fdOfSession);
 	result = close(ns->fd);
 
@@ -250,7 +227,7 @@ fs_unmount(void *_ns)
 }
 
 
-static int		
+static status_t
 fs_read_fs_stat(void *_ns, struct fs_info *fss)
 {
 	// Fill in fs_info struct for device.
@@ -304,10 +281,8 @@ fs_read_fs_stat(void *_ns, struct fs_info *fss)
 	the specified file. When you find it, call get_vnode on its vnid to init
 	it for the kernel.
 */
-
-int		
-fs_walk(void *_ns, void *base, const char *file, char **newpath, 
-			vnode_id *vnid)
+static status_t
+fs_walk(void *_ns, void *base, const char *file, vnode_id *_vnodeID, int *_type)
 {
 	/* Starting at the base, find file in the subdir, and return path
 		string and vnode id of file. */
@@ -315,7 +290,7 @@ fs_walk(void *_ns, void *base, const char *file, char **newpath,
 	vnode *baseNode = (vnode*)base;
 	uint32 dataLen = baseNode->dataLen[FS_DATA_FORMAT];
 	vnode *newNode = NULL;
-	int	result = ENOENT;
+	status_t result = ENOENT;
 	bool done = FALSE;
 	uint32 totalRead = 0;
 	off_t block = baseNode->startLBN[FS_DATA_FORMAT];
@@ -326,16 +301,18 @@ fs_walk(void *_ns, void *base, const char *file, char **newpath,
 	if (strcmp(file, ".") == 0)  {
 		// base directory
 		TRACE(("fs_walk - found \".\" file.\n"));
-		*vnid = baseNode->id;
-		if (get_vnode(ns->id, *vnid, (void **)&newNode) != 0)
+		*_vnodeID = baseNode->id;
+		*_type = S_IFDIR;
+		if (get_vnode(ns->id, *_vnodeID, (void **)&newNode) != 0)
     		result = EINVAL;
 	    else
 	    	result = B_NO_ERROR;
 	} else if (strcmp(file, "..") == 0) {
 		// parent directory
 		TRACE(("fs_walk - found \"..\" file.\n"));
-		*vnid = baseNode->parID;
-		if (get_vnode(ns->id, *vnid, (void **)&newNode) != 0)
+		*_vnodeID = baseNode->parID;
+		*_type = S_IFDIR;
+		if (get_vnode(ns->id, *_vnodeID, (void **)&newNode) != 0)
 			result = EINVAL;
 		else
 			result = B_NO_ERROR;
@@ -346,7 +323,7 @@ fs_walk(void *_ns, void *base, const char *file, char **newpath,
 		while ((totalRead < dataLen) && !done) {
 			off_t cachedBlock = block;
 			
-			blockData = (char *)get_block(ns->fd, block,  ns->logicalBlkSize[FS_DATA_FORMAT]);
+			blockData = (char *)block_cache_get_etc(ns->fBlockCache, block, 0, ns->logicalBlkSize[FS_DATA_FORMAT]);
 			if (blockData != NULL) {
 				int bytesRead = 0;
 				off_t blockBytesRead = 0;
@@ -375,10 +352,10 @@ fs_walk(void *_ns, void *base, const char *file, char **newpath,
 							&& !strncmp(node.fileIDString, file, strlen(file)))
 						{
 							TRACE(("fs_walk - success, found vnode at block %Ld, pos %Ld\n", block, blockBytesRead));
-							*vnid = (block << 30) + (blockBytesRead & 0xFFFFFFFF);
-							TRACE(("fs_walk - New vnode id is %Ld\n", *vnid));
+							*_vnodeID = (block << 30) + (blockBytesRead & 0xFFFFFFFF);
+							TRACE(("fs_walk - New vnode id is %Ld\n", *_vnodeID));
 
-							if (get_vnode(ns->id, *vnid, (void **)&newNode) != 0)
+							if (get_vnode(ns->id, *_vnodeID, (void **)&newNode) != 0)
 								result = EINVAL;
 							else {
 								newNode->parID = baseNode->id;
@@ -410,33 +387,26 @@ fs_walk(void *_ns, void *base, const char *file, char **newpath,
 				block++;
 				
 				TRACE(("fs_walk - moving to next block %Ld, total read %Ld\n", block, totalRead));
-				release_block(ns->fd, cachedBlock);
+				block_cache_put(ns->fBlockCache, cachedBlock);
 
 			} else
 				done = TRUE;
 		}
 
-		// Check to see if vnode is a symbolic link. If so, fill in the newpath variable
-		// with the path to the real file, and call put_vnode.
-		if (newNode != NULL) {
-			if (S_ISLNK(newNode->attr.stat[FS_DATA_FORMAT].st_mode) && newpath != NULL) {
-				TRACE(("fs_walk - symbolic link file \'%s\' requested.\n", newNode->attr.slName));
-				result = new_path(newNode->attr.slName, newpath);
-				put_vnode(ns->id, *vnid);
-			}
-		}
+		*_type = newNode->attr.stat[FS_DATA_FORMAT].st_mode;
+
 	}
-	TRACE(("fs_walk - EXIT, result is %s, vnid is %Lu\n", strerror(result), *vnid));
+	TRACE(("fs_walk - EXIT, result is %s, vnid is %Lu\n", strerror(result), *_vnodeID));
 	return result;
 }
 
 
-int		
-fs_read_vnode(void *_ns, vnode_id vnid, char reenter, void **node)
+static status_t
+fs_read_vnode(void *_ns, vnode_id vnid, void **node, bool reenter)
 {
 	uint32 block, pos;
 	nspace *ns = (nspace*)_ns;
-	int result = B_NO_ERROR;
+	status_t result = B_NO_ERROR;
 	vnode *newNode = (vnode*)calloc(sizeof(vnode), 1);
 
 	(void)reenter;
@@ -453,16 +423,16 @@ fs_read_vnode(void *_ns, vnode_id vnid, char reenter, void **node)
 			memcpy(newNode, &(ns->rootDirRec), sizeof(vnode));
 			*node = (void*)newNode;
 		} else {
-			char *blockData = (char *)get_block(ns->fd, block, ns->logicalBlkSize[FS_DATA_FORMAT]);
+			char *blockData = (char *)block_cache_get_etc(ns->fBlockCache, block, 0, ns->logicalBlkSize[FS_DATA_FORMAT]);
 
 			if (pos > ns->logicalBlkSize[FS_DATA_FORMAT]) {
 				if (blockData != NULL)
-					release_block(ns->fd, block);
+					block_cache_put(ns->fBlockCache, block);
 
 				result = EINVAL;
 		 	} else if (blockData != NULL) {
 				result = InitNode(newNode, blockData + pos, NULL, ns->joliet_level);
-				release_block(ns->fd, block);
+				block_cache_put(ns->fBlockCache, block);
 				newNode->id = vnid;
 
 				TRACE(("fs_read_vnode - init result is %s\n", strerror(result)));
@@ -478,10 +448,10 @@ fs_read_vnode(void *_ns, vnode_id vnid, char reenter, void **node)
 }
 
 
-int
-fs_write_vnode(void *ns, void *_node, char reenter)
+static status_t
+fs_release_vnode(void *ns, void *_node, bool reenter)
 {
-	int result = B_NO_ERROR;
+	status_t result = B_NO_ERROR;
 	vnode *node = (vnode*)_node;
 
 	(void)ns;
@@ -505,7 +475,7 @@ fs_write_vnode(void *ns, void *_node, char reenter)
 }
 
 
-static int		
+static status_t
 fs_read_stat(void *_ns, void *_node, struct stat *st)
 {
 	nspace *ns = (nspace*)_ns;
@@ -534,10 +504,10 @@ fs_read_stat(void *_ns, void *_node, struct stat *st)
 }
 
 
-static int		
+static status_t
 fs_open(void *_ns, void *_node, int omode, void **cookie)
 {
-	int result = B_NO_ERROR;
+	status_t result = B_NO_ERROR;
 
 	(void)_ns;
 	(void)cookie;
@@ -552,17 +522,17 @@ fs_open(void *_ns, void *_node, int omode, void **cookie)
 }
 
 
-static int		
+static status_t
 fs_read(void *_ns, void *_node, void *cookie, off_t pos, void *buf, size_t *len)
 {
 	nspace *ns = (nspace *)_ns;			// global stuff
 	vnode *node = (vnode *)_node;		// The read file vnode.
 	uint16 blockSize = ns->logicalBlkSize[FS_DATA_FORMAT];
 	uint32 startBlock = node->startLBN[FS_DATA_FORMAT] + (pos / blockSize);
-	off_t blockPos = pos %blockSize;
+	off_t blockPos = pos % blockSize;
 	off_t numBlocks = 0;
 	uint32 dataLen = node->dataLen[FS_DATA_FORMAT];
-	int result = B_NO_ERROR;
+	status_t result = B_NO_ERROR;
 	size_t endLen = 0;
 	size_t reqLen = *len;
 	size_t startLen =  0;
@@ -596,7 +566,7 @@ fs_read(void *_ns, void *_node, void *cookie, off_t pos, void *buf, size_t *len)
 
 	// Compute the length of the partial end-block read, if any.
 	if (reqLen + blockPos > blockSize)
-		endLen = (reqLen +blockPos) % blockSize;
+		endLen = (reqLen + blockPos) % blockSize;
 
 	// Compute the number of middle blocks to read.
 	numBlocks = ((reqLen - endLen - startLen) /  blockSize);
@@ -620,12 +590,12 @@ fs_read(void *_ns, void *_node, void *cookie, off_t pos, void *buf, size_t *len)
 	// Read in the first, potentially partial, block.
 	if (startLen > 0) {
 		off_t cachedBlock = startBlock;
-		char *blockData = (char *)get_block(ns->fd, startBlock, blockSize);
+		char *blockData = (char *)block_cache_get_etc(ns->fBlockCache, startBlock, 0, blockSize);
 		if (blockData != NULL) {
 			//dprintf("fs_read - copying first block, len is %d.\n", startLen);
 			memcpy(buf, blockData+blockPos, startLen);
 			*len += startLen;
-			release_block(ns->fd, cachedBlock);
+			block_cache_put(ns->fBlockCache, cachedBlock);
 			startBlock++;	
 		}
 		else result = EIO;
@@ -634,23 +604,31 @@ fs_read(void *_ns, void *_node, void *cookie, off_t pos, void *buf, size_t *len)
 	// Read in the middle blocks.
 	if (numBlocks > 0 && result == B_NO_ERROR) {
 		TRACE(("fs_read - getting middle blocks\n"));
+		/*
 		result = cached_read(ns->fd, startBlock, 
 					((char *)buf) + startLen, 
 					numBlocks, 
 					blockSize);
-		if (result == B_NO_ERROR)
-			*len += blockSize * numBlocks;
+		*/
+		for (int32 i=startBlock; i<startBlock+numBlocks; i++) {
+			char *blockData = (char *)block_cache_get_etc(ns->fBlockCache, i, 0, blockSize);
+			memcpy(((char *)buf) + startLen + (i - startBlock) * blockSize, blockData, blockSize);
+			*len += blockSize;
+			block_cache_put(ns->fBlockCache, i);
+		}
+		/*if (result == B_NO_ERROR)
+			*len += blockSize * numBlocks;*/
 	}
 
 	// Read in the last partial block.
 	if (result == B_NO_ERROR && endLen > 0) {
 		off_t endBlock = startBlock + numBlocks;
-		char *endBlockData = (char*)get_block(ns->fd, endBlock, blockSize);
+		char *endBlockData = (char*)block_cache_get_etc(ns->fBlockCache, endBlock, 0, blockSize);
 		if (endBlockData != NULL) {
 			char *endBuf = ((char *)buf) + (reqLen - endLen);
 
 			memcpy(endBuf, endBlockData, endLen);
-			release_block(ns->fd, endBlock);
+			block_cache_put(ns->fBlockCache, endBlock);
 			*len += endLen;
 		} else
 			result = EIO;
@@ -661,7 +639,7 @@ fs_read(void *_ns, void *_node, void *cookie, off_t pos, void *buf, size_t *len)
 }
 
 
-static int		
+static status_t
 fs_close(void *ns, void *node, void *cookie)
 {
 	(void)ns;
@@ -670,10 +648,10 @@ fs_close(void *ns, void *node, void *cookie)
 
 	//dprintf("fs_close - ENTER\n");
 	//dprintf("fs_close - EXIT\n");
-	return 0;
+	return B_OK;
 }
 
-static int		
+static status_t
 fs_free_cookie(void *ns, void *node, void *cookie)
 {
 	(void)ns;
@@ -684,11 +662,11 @@ fs_free_cookie(void *ns, void *node, void *cookie)
 	//dprintf("fs_free_cookie - ENTER\n");
 	//if (cookie != NULL) free (cookie);
 	//dprintf("fs_free_cookie - EXIT\n");
-	return 0;
+	return B_OK;
 }
 
 // fs_access - checks permissions for access.
-static int		
+static status_t
 fs_access(void *ns, void *node, int mode)
 {
 	(void)ns;
@@ -700,14 +678,14 @@ fs_access(void *ns, void *node, int mode)
 	// mode - requested permissions on node.
 	//dprintf("fs_access - ENTER\n");
 	//dprintf("fs_access - EXIT\n");
-	return 0;
+	return B_OK;
 }
 
-static int
+static status_t
 fs_read_link(void *_ns, void *_node, char *buffer, size_t *_bufferSize)
 {
 	vnode *node = (vnode *)_node;
-	int	result = EINVAL;
+	status_t result = EINVAL;
 
 	(void)_ns;
 
@@ -726,11 +704,11 @@ fs_read_link(void *_ns, void *_node, char *buffer, size_t *_bufferSize)
 }
 
 
-static int		
+static status_t
 fs_open_dir(void *_ns, void *_node, void **cookie)
 {
 	vnode *node = (vnode *)_node;
-	int result = B_NO_ERROR;
+	status_t result = B_NO_ERROR;
 	dircookie *dirCookie = (dircookie *)malloc(sizeof(dircookie));
 
 	(void)_ns;
@@ -755,11 +733,11 @@ fs_open_dir(void *_ns, void *_node, void **cookie)
 }
 
 
-static int		
-fs_read_dir(void *_ns, void *_node, void *_cookie, long *num, 
-	struct dirent *buffer, size_t bufferSize)
+static status_t
+fs_read_dir(void *_ns, void *_node, void *_cookie, struct dirent *buffer,
+	size_t bufferSize, uint32 *num)
 {
-	int result = B_NO_ERROR;
+	status_t result = B_NO_ERROR;
 	nspace *ns = (nspace *)_ns;
 	dircookie *dirCookie = (dircookie *)_cookie;
 
@@ -786,10 +764,10 @@ fs_read_dir(void *_ns, void *_node, void *_cookie, long *num,
 }
 			
 
-static int		
+static status_t
 fs_rewind_dir(void *ns, void *node, void* _cookie)
 {
-	int	result = EINVAL;
+	status_t result = EINVAL;
 	dircookie *cookie = (dircookie*)_cookie;
 
 	(void)ns;
@@ -806,7 +784,7 @@ fs_rewind_dir(void *ns, void *node, void* _cookie)
 }
 
 
-static int		
+static status_t
 fs_close_dir(void *ns, void *node, void *cookie)
 {
 	(void)ns;
@@ -818,11 +796,11 @@ fs_close_dir(void *ns, void *node, void *cookie)
 	// cookie	- current cookie for directory.	
 	//dprintf("fs_closedir - ENTER\n");
 	//dprintf("fs_closedir - EXIT\n");
-	return 0;
+	return B_OK;
 }
 
 
-static int		
+static status_t
 fs_free_dir_cookie(void *ns, void *node, void *cookie)
 {
 	(void)ns;
@@ -836,5 +814,137 @@ fs_free_dir_cookie(void *ns, void *node, void *cookie)
 		free(cookie);
 
 	//dprintf("fs_free_dircookie - EXIT\n");
-	return 0;
+	return B_OK;
 }
+
+//	#pragma mark -
+
+
+static status_t
+iso_std_ops(int32 op, ...)
+{
+	switch (op) {
+		case B_MODULE_INIT:
+			return B_OK;
+		case B_MODULE_UNINIT:
+			return B_OK;
+		default:
+			return B_ERROR;
+	}
+}
+
+
+static file_system_module_info sISO660FileSystem = {
+	{
+		"file_systems/iso9660" B_CURRENT_FS_API_VERSION,
+		0,
+		iso_std_ops,
+	},
+
+	"ISO9660 File System",
+
+	// scanning
+	fs_identify_partition,
+	fs_scan_partition,
+	fs_free_identify_partition_cookie,
+	NULL,	// free_partition_content_cookie()
+
+	&fs_mount,
+	&fs_unmount,
+	&fs_read_fs_stat,
+	NULL,
+	NULL,
+
+	/* vnode operations */
+	&fs_walk,
+	NULL, 	// &fs_get_vnode_name()
+	&fs_read_vnode,
+	&fs_release_vnode,
+	NULL, 	// &fs_remove_vnode()
+
+	/* VM file access */
+	NULL, 	// &fs_can_page
+	NULL,	// &fs_read_pages
+	NULL, 	// &fs_write_pages
+
+	NULL,	// &fs_get_file_map
+
+	NULL, 	// &fs_ioctl
+	NULL, 	// &fs_set_flags
+	NULL,	// &bfs_select
+	NULL,	// &bfs_deselect
+	NULL, 	// &fs_fsync
+
+	&fs_read_link,
+	NULL,						// write link
+	NULL, 	// &fs_create_symlink,
+
+	NULL, 	// &fs_link,
+	NULL,	// &fs_unlink
+	NULL, 	// &fs_rename
+
+	&fs_access,
+	&fs_read_stat,
+	NULL, 	// &fs_write_stat
+
+	/* file operations */
+	NULL, 	// &fs_create
+	&fs_open,
+	&fs_close,
+	&fs_free_cookie,
+	&fs_read,
+	NULL, 	// &fs_write
+
+	/* directory operations */
+	NULL, 	// &fs_create_dir
+	NULL, 	// &fs_remove_dir
+	&fs_open_dir,
+	&fs_close_dir,
+	&fs_free_dir_cookie,
+	&fs_read_dir,
+	&fs_rewind_dir,
+	
+	/* attribute directory operations */
+	NULL, 	// &fs_open_attr_dir
+	NULL, 	// &fs_close_attr_dir
+	NULL,	// &fs_free_attr_dir_cookie
+	NULL,	// &fs_read_attr_dir
+	NULL,	// &fs_rewind_attr_dir
+
+	/* attribute operations */
+	NULL,	// &fs_create_attr
+	NULL, 	// &fs_open_attr
+	NULL,	// &fs_close_attr
+	NULL,	// &fs_free_attr_cookie
+	NULL,	// &fs_read_attr
+	NULL,	// &fs_write_attr
+
+	NULL,	// &fs_read_attr_stat
+	NULL,	// &fs_write_attr_stat
+	NULL,	// &fs_rename_attr
+	NULL,	// &fs_remove_attr
+
+	/* index directory & index operations */
+	NULL,	// &fs_open_index_dir
+	NULL,	// &fs_close_index_dir
+	NULL,	// &fs_free_index_dir_cookie
+	NULL,	// &fs_read_index_dir
+	NULL,	// &fs_rewind_index_dir
+
+	NULL,	// &fs_create_index
+	NULL,	// &fs_remove_index
+	NULL,	// &fs_stat_index
+
+	/* query operations */
+	NULL,	// &fs_open_query
+	NULL,	// &fs_close_query
+	NULL,	// &fs_free_query_cookie
+	NULL,	// &fs_read_query
+	NULL,	// &fs_rewind_query
+};
+
+module_info *modules[] = {
+	(module_info *)&sISO660FileSystem,
+	NULL,
+};
+