ftp.nice.ch/pub/next/unix/disk/vmount.0.6a.s.tar.gz#/vmount.0.6a.s/file_ops.c

This is file_ops.c in view mode; [Download] [Up]

/*
 * Name: file_ops.c
 * Description: Functions that can be called from the NFS interface.
 * Author: Christian Starkjohann <cs@hal.kph.tuwien.ac.at>
 * Date: 1996-11-14
 * Copyright: GNU-GPL
 * Tabsize: 4
 */

#include <linux/autoconf.h>
#include <linux/fs.h>
#include <linux/affs_fs.h>
#include <linux/ext2_fs.h>
#include <linux/ext_fs.h>
#include <linux/hpfs_fs.h>
#include <linux/iso_fs.h>
#include <linux/minix_fs.h>
#include <linux/msdos_fs.h>
#include <linux/ncp_fs.h>
#include <linux/nfs_fs.h>
#include <linux/proc_fs.h>
#include <linux/smb_fs.h>
#include <linux/sysv_fs.h>
#include <linux/ufs_fs.h>
#include <linux/umsdos_fs.h>
#include <linux/xia_fs.h>
#include "my_defines.h"

#define	DPRINTF(arg)	if(debug_mode & DEBUG_FOPS)	dprintf arg

extern void	init_ntfs_fs(void);

#define	MY_DEVICE				256
#define	TRANSFER_BUFFER_SIZE	50000

/* ------------------------------------------------------------------------- */

extern void	bzero(void *block, int size);
extern void	*malloc(int size);

extern int	my_blocksize;

/* ------------------------------------------------------------------------- */

struct super_block				my_superblock;
static struct file_system_type	*fs_types = NULL;

/* ------------------------------------------------------------------------- */

int register_filesystem(struct file_system_type *fstype)
{
	DPRINTF(("registering filesystem %s\n", fstype->name));
	fstype->next = fs_types;
	fs_types = fstype;
	return 0;
}

/* ------------------------------------------------------------------------- */

static void	my_sync_super(void)
{
struct super_block	*s = &my_superblock;

	if(s->s_dirt && s->s_op->write_super != NULL){
		s->s_op->write_super(s);
		s->s_dirt = 0;
	}
}

/* ------------------------------------------------------------------------- */

void	my_sync(void)
{
	my_sync_super();
	my_sync_inodes();
	my_sync_blocks();
}

/* ------------------------------------------------------------------------- */

static int	is_valid_fs(struct file_system_type *fs)
{
struct super_block	s;

	bzero(&s, sizeof(s));
	s.s_dev = MY_DEVICE;
	s.s_flags = MS_RDONLY;
	return fs->read_super(&s, "", 0) != 0;
}

/* ------------------------------------------------------------------------- */

char	*valid_filesystems(void)
{
struct file_system_type	*fs;
static char				fslist[1024];	/* don't like static limits.... */

	fslist[0] = 0;
	for(fs=fs_types;fs!=NULL;fs=fs->next){
		if(is_valid_fs(fs)){
			if(fslist[0] != 0)
				strcat(fslist, " ");
			strcat(fslist, fs->name);
		}
	}
	return fslist;
}

/* ------------------------------------------------------------------------- */

static int	do_my_mount(struct file_system_type *fs, int flags, void *data, int *root_i)
{
struct super_block	*s = &my_superblock;

	DPRINTF(("do_my_mount(fs=%s, flags=0x%x)\n", fs->name, flags));
	s->s_dev = MY_DEVICE;
	s->s_flags = flags;
	if (!fs->read_super(s, data, 0)){
		return -1;
	}
	s->s_dev = MY_DEVICE;
	s->s_covered = s->s_mounted;	/* used for error output! should be NULL */
	s->s_type = fs;
	*root_i = s->s_mounted->i_ino;
	if(s->s_op->write_super != NULL){
		s->s_op->write_super(s);
		s->s_dirt = 0;
	}
	my_sync();
	return 0;
}

/* ------------------------------------------------------------------------- */

int	my_mount(char *fsname, int options, void *data, int *root_inode)
{
struct file_system_type	*fs;

	bzero(&my_superblock, sizeof(my_superblock));
	for(fs=fs_types;fs!=NULL;fs=fs->next){
		if(strcmp(fsname, fs->name) == 0){
			break;
		}
	}
	if(fs != NULL){
		return do_my_mount(fs, options & MNT_RONLY ? MS_RDONLY : 0,
														data, root_inode);
	}else{
		printk("filesystem ->%s<- not found\n", fsname);
		return -1;
	}
}

/* ------------------------------------------------------------------------- */

int	my_unmount(void)
{
struct super_block	*sb = &my_superblock;

	DPRINTF(("my_unmount()\n"));
	iput(sb->s_mounted);	/* free mounted inode */
	my_sync();
	if(sb->s_op && sb->s_op->put_super)
		sb->s_op->put_super(sb);
	my_sync_inodes();
	my_sync_blocks();
	return 0;
}

/* ------------------------------------------------------------------------- */

static int	check_access(struct inode *inode, int mode)
{
int		i, igid = inode->i_gid, iuid = inode->i_uid;

	if(nfs_uid == 0){		/* root may do everything */
		return 1;
	}
	if(id_is_fixed(IDBUF_USR))
		iuid = fixed_id(IDBUF_USR);
	if(id_is_fixed(IDBUF_GRP))
		igid = fixed_id(IDBUF_GRP);
	if(nfs_uid == iuid){	/* you may always access your own files */
		return 1;
	}
	if(iuid == nfs_uid){
		return (inode->i_mode & (mode << 6)) != 0;
	}
	for(i=0;i<nfs_gidslen;i++){
		if(igid == nfs_gids[i]){
			return (inode->i_mode & (mode << 3)) != 0;
		}
	}
	return (inode->i_mode & mode) != 0;
}

/* ------------------------------------------------------------------------- */

#define	CHECK_WRITE(inode, iputs)									\
	if(!check_access(inode, 2)){									\
		error = -MY_NFSERR_ACCES;									\
		DPRINTF(("write access for %ld denied\n", inode->i_ino));	\
		iputs;														\
		goto do_return;												\
	}

#define	CHECK_READ(inode, iputs)									\
	if(!check_access(inode, 4)){									\
		error = -MY_NFSERR_ACCES;									\
		DPRINTF(("read access for %ld denied\n", inode->i_ino));	\
		iputs;														\
		goto do_return;												\
	}

#define	CHECK_EXEC(inode, iputs)									\
	if(!check_access(inode, 1)){									\
		error = -MY_NFSERR_ACCES;									\
		DPRINTF(("search access for %ld denied\n", inode->i_ino));	\
		iputs;														\
		goto do_return;												\
	}

#define	CHECK_ATTR(inode, iputs)										\
	{	int	iuid = inode->i_uid;										\
		if(id_is_fixed(IDBUF_USR))										\
			iuid = fixed_id(IDBUF_USR);									\
		if(nfs_uid != 0 && iuid != nfs_uid){							\
			error = -MY_NFSERR_ACCES;									\
			DPRINTF(("chmod access for %ld denied\n", inode->i_ino));	\
			iputs;														\
			goto do_return;												\
		}																\
	}

/* ------------------------------------------------------------------------- */

static void	set_attr(struct inode *inode, my_attr_t *attr)
{
int		i;

	if(attr->mode != -1 && inode->i_mode != attr->mode){
		inode->i_mode = (inode->i_mode & ~07777) | (attr->mode & 07777);
		inode->i_dirt = 1;
	}
	if(nfs_uid == 0 && attr->uid != -1 && inode->i_uid != attr->uid){
		inode->i_uid = attr->uid;
		inode->i_dirt = 1;
	}
	if(attr->gid != -1 && inode->i_gid != attr->gid){
		for(i=0;i<nfs_gidslen;i++){
			if(nfs_gids[i] == attr->gid){
				inode->i_gid = attr->gid;
				inode->i_dirt = 1;
				break;
			}
		}
	}
	if(attr->mtime != -1 && inode->i_mtime != attr->mtime){
		inode->i_mtime = attr->mtime;
		inode->i_dirt = 1;
	}
}

/* ------------------------------------------------------------------------- */

static void	get_attr(struct inode *inode, my_attr_t *attr)
{
	attr->mode = inode->i_mode;
	attr->nlink = inode->i_nlink;
	attr->uid = inode->i_uid;
	attr->gid = inode->i_gid;
	attr->size = S_ISDIR(attr->mode) && inode->i_size == 0 ?
					100000 : inode->i_size;		/* fake a directory size */
	attr->blocksize = inode->i_blksize > 0 ? inode->i_blksize : PAGE_SIZE;
	attr->blocks = inode->i_blocks > 0 ?
			inode->i_blocks : (attr->size + my_blocksize - 1) / my_blocksize;
	attr->fileid = inode->i_ino;
	attr->atime = inode->i_atime;
	attr->mtime = inode->i_mtime;
	attr->ctime = inode->i_ctime;
	attr->rdev = inode->i_rdev;
}

/* ------------------------------------------------------------------------- */

#define	FIND_INODE(inode, fh, ops, iputs)				\
	if((inode = iget(&my_superblock, fh)) == NULL){		\
		DPRINTF(("invalid inode %d: not found in %s/%d\n",\
							fh, __FILE__, __LINE__));	\
		iputs;											\
		error = -MY_NFSERR_STALE;						\
		goto do_return;									\
	}													\
	if((ops = inode->i_op) == NULL){					\
		printk("invalid inode %d: no inode operations in %s/%d\n",\
								fh, __FILE__, __LINE__);\
		iput(inode);									\
		iputs;											\
		error = -MY_NFSERR_STALE;						\
		goto do_return;									\
	}

#define	VALIDATE(operation, iputs)		\
	if(!(operation)){					\
		DPRINTF(("invalid operation in %s/%d\n", __FILE__, __LINE__));\
		iputs;							\
		error = -EINVAL;				\
		goto do_return;					\
	}

#define	RETAIN(inode)	(inode)->i_count++

/* ------------------------------------------------------------------------- */

static int	fo_new(int is_dir, int *fh, my_attr_t *fa, int dir,
												char *name, my_attr_t *sa)
{
struct inode			*inode, *new_inode = NULL;
struct inode_operations	*ops;
int						error = 0;

	FIND_INODE(inode, dir, ops, ;);
	VALIDATE(ops->lookup, ;);
	CHECK_WRITE(inode, ;);
	if(is_dir){
		VALIDATE(ops->mkdir, ;);
		RETAIN(inode);	/* retain for mkdir */
		error = ops->mkdir(inode, name, strlen(name), sa->mode);
		if(error)	goto do_return;
		RETAIN(inode);	/* retain for second operation */
		error = ops->lookup(inode, name, strlen(name), &new_inode);
	}else{
		RETAIN(inode);	/* retain for additional lookup or unlink */
		if(sa->size == 0){
			VALIDATE(ops->unlink, iput(inode));
			ops->unlink(inode, name, strlen(name));	/* ignore errors */
		}else{
			if(ops->lookup(inode, name, strlen(name), &new_inode) == 0){
				*fh = new_inode->i_ino;
				get_attr(new_inode, fa);
				iput(new_inode);
				iput(inode);
				return 0;
			}
		}
		VALIDATE(ops->create, ;);
		RETAIN(inode);	/* retain for create */
		error = ops->create(inode, name, strlen(name), sa->mode, &new_inode);
	}
	if(error)
		goto do_return;
	*fh = new_inode->i_ino;
	new_inode->i_uid = nfs_uid;
	new_inode->i_gid = nfs_gid;
	new_inode->i_dirt = 1;
	set_attr(new_inode, sa);
	new_inode->i_mode &= ~S_IFMT;
	new_inode->i_mode |= is_dir ? S_IFDIR : S_IFREG;
	get_attr(new_inode, fa);
	iput(new_inode);
do_return:
	iput(inode);
	return error;
}

/* ------------------------------------------------------------------------- */

int	fo_create(int *fh, my_attr_t *fa, int dir, char *name, my_attr_t *sa)
{
	DPRINTF(("fo_create(ino=%d, name=%s)\n", dir, name));
	return fo_new(0, fh, fa, dir, name, sa);
}

/* ------------------------------------------------------------------------- */

int	fo_mkdir(int *fh, my_attr_t *fa, int dir, char *name, my_attr_t *sa)
{
	DPRINTF(("fo_mkdir(ino=%d, name=%s)\n", dir, name));
	return fo_new(1, fh, fa, dir, name, sa);
}

/* ------------------------------------------------------------------------- */

int	fo_getattr(my_attr_t *fa, int fh)
{
struct inode			*inode;
struct inode_operations	*ops;
int						error = 0;

	DPRINTF(("fo_getattr(ino=%d)\n", fh));
	FIND_INODE(inode, fh, ops, ;);
	get_attr(inode, fa);
	iput(inode);
do_return:
	return error;
}

/* ------------------------------------------------------------------------- */

int	fo_lookup(int *fh, my_attr_t *fa, int dir, char *name)
{
struct inode			*inode, *found_inode = NULL;
struct inode_operations	*ops;
int						error = 0;

	DPRINTF(("fo_lookup(ino=%d, name=%s)\n", dir, name));
	FIND_INODE(inode, dir, ops, ;);
	CHECK_READ(inode, iput(inode));
	VALIDATE(ops->lookup, iput(inode));
	if((error = ops->lookup(inode, name, strlen(name), &found_inode)) != 0)
		goto do_return;
	get_attr(found_inode, fa);
	*fh = found_inode->i_ino;
	iput(found_inode);
do_return:
	return error;
}

/* ------------------------------------------------------------------------- */

struct my_dirinfo{
	my_direntry_t	**entries;
	int				max_bytes;
	int				*put_cookie;
	int				called;
};

/* ------------------------------------------------------------------------- */

static int	callback(void *arg, const char *name, int namelen,
													off_t offs, ino_t inum)
{
struct my_dirinfo	*di = arg;
my_direntry_t		*p;

	di->called = 1;
	if(di->put_cookie != NULL)
		*(di->put_cookie) = offs;
	di->max_bytes -= namelen + 1 + sizeof(my_direntry_t);
	if(di->max_bytes < 0){
		DPRINTF(("callback(): stopping\n"));
		return -1;
	}
	p = malloc(sizeof(my_direntry_t));
	p->fh = inum;
	p->name = malloc(namelen + 1);
	memcpy(p->name, name, namelen);
	p->name[namelen] = 0;
	p->cookie = -1;
	di->put_cookie = &p->cookie;
	p->next = NULL;
	*(di->entries) = p;
	di->entries = &p->next;
	DPRINTF(("callback(): added ->%s<- offset=%d, inode=%d\n",
											p->name, (int)offs, (int)inum));
	return 0;
}

/* ------------------------------------------------------------------------- */

int	fo_readdir(my_direntry_t **result, int *eof, int max_bytes,
														int dir, int cookie)
{
struct inode			*inode;
struct inode_operations	*ops;
struct file_operations	*fops;
struct file				filp;
int						error = 0;
struct my_dirinfo		dirinfo;

	*result = NULL;
	dirinfo.entries = result;
	dirinfo.max_bytes = max_bytes;
	dirinfo.put_cookie = NULL;
	dirinfo.called = 0;
	DPRINTF(("fo_readdir(ino=%d, cookie=%d, max=%d)\n",dir,cookie,max_bytes));
	FIND_INODE(inode, dir, ops, ;);
	CHECK_EXEC(inode, ;);
	CHECK_READ(inode, ;);
	VALIDATE(ops->default_file_ops, ;);
	fops = ops->default_file_ops;
	VALIDATE(fops->readdir, ;);
	bzero(&filp, sizeof(filp));
	filp.f_mode = inode->i_mode;
	filp.f_pos = cookie;
	do{
		dirinfo.called = 0;
		error = fops->readdir(inode, &filp, &dirinfo, callback);
		if(error < 0)
			break;
	}while(dirinfo.max_bytes > 0 && dirinfo.called);
	if(dirinfo.put_cookie != NULL)
		*(dirinfo.put_cookie) = filp.f_pos;
do_return:
	*eof = !dirinfo.called;
	iput(inode);
	return error;
}

/* ------------------------------------------------------------------------- */

int	fo_setattr(my_attr_t *fa, int fh, my_attr_t *sa)
{
struct inode			*inode;
struct inode_operations	*ops;
int						error = 0;

	DPRINTF(("fo_setattr(ino=%d)\n", fh));
	FIND_INODE(inode, fh, ops, ;);
	CHECK_ATTR(inode, iput(inode));
	set_attr(inode, sa);
	get_attr(inode, fa);
	iput(inode);
do_return:
	return error;
}

/* ------------------------------------------------------------------------- */

static int	fo_rm(int is_dir, int dir, char *name)
{
struct inode			*inode;
struct inode_operations	*ops;
int						error = 0;
int						(*rmop)(struct inode *,const char *,int);

	DPRINTF(("fo_rm(ino=%d, name=%s)\n", dir, name));
	FIND_INODE(inode, dir, ops, ;);
	CHECK_WRITE(inode, iput(inode));
	rmop = is_dir ? ops->rmdir : ops->unlink;
	VALIDATE(rmop, iput(inode));
	if((error = rmop(inode, name, strlen(name))) != 0)
		goto do_return;
do_return:
	return error;
}

/* ------------------------------------------------------------------------- */

int	fo_remove(int dir, char *name)
{
	return fo_rm(0, dir, name);
}

/* ------------------------------------------------------------------------- */

int	fo_rmdir(int dir, char *name)
{
	return fo_rm(1, dir, name);
}

/* ------------------------------------------------------------------------- */

int	fo_rename(int fromdir, char *fromname, int todir, char *toname)
{
struct inode			*from_i, *to_i;
struct inode_operations	*from_o, *to_o;
int						error = 0;

	DPRINTF(("fo_rename(ino=%d, name=%s, ino=%d, name=%s)\n", fromdir,
												fromname, todir, toname));
	FIND_INODE(from_i, fromdir, from_o, ;);
	CHECK_WRITE(from_i, iput(from_i));
	FIND_INODE(to_i, todir, to_o, iput(from_i));
	CHECK_WRITE(to_i, iput(from_i); iput(to_i));
	VALIDATE(from_o->rename, iput(from_i); iput(to_i));
	error = from_o->rename(from_i, fromname, strlen(fromname),
										to_i, toname, strlen(toname), 0);
do_return:
	return error;
}

/* ------------------------------------------------------------------------- */

int	fo_statfs(my_statfs_t *fsstat)
{
struct statfs	stat;

	DPRINTF(("fo_statfs()\n"));
	if(!my_superblock.s_op->statfs)
		return -EINVAL;
	my_superblock.s_op->statfs(&my_superblock, &stat, sizeof(stat));
	fsstat->type = stat.f_type;
	fsstat->bsize = stat.f_bsize;
	fsstat->blocks = stat.f_blocks;
	fsstat->bfree = stat.f_bfree;
	fsstat->bavail = stat.f_bavail;
	fsstat->files = stat.f_files;
	fsstat->ffree = stat.f_ffree;
	return 0;
}

/* ------------------------------------------------------------------------- */

int	fo_read(my_attr_t *fa, int *len, char **data, int fh, int offs, int count)
{
static char				transfer_buf[TRANSFER_BUFFER_SIZE];
struct inode			*inode;
struct inode_operations	*ops;
struct file_operations	*fops;
struct file				filp;
int						error = 0;

	DPRINTF(("fo_read(ino=%d, offs=%d, len=%d)\n", fh, offs, count));
	*data = transfer_buf;
	FIND_INODE(inode, fh, ops, ;);
	CHECK_READ(inode, ;);
	if(offs + count > inode->i_size)
		count = inode->i_size - offs;
	if(count <= 0){	/* nothing to be done */
		get_attr(inode, fa);
		*len = 0;
		goto do_return;
	}
	VALIDATE(ops->default_file_ops, ;);
	fops = ops->default_file_ops;
	VALIDATE(fops->read, ;);
	bzero(&filp, sizeof(filp));
	filp.f_mode = inode->i_mode;
	filp.f_pos = offs;
	if(count > sizeof(transfer_buf))
		count = sizeof(transfer_buf);
	error = fops->read(inode, &filp, transfer_buf, count);
	*len = error;
	error = error < 0 ? error : 0;
	get_attr(inode, fa);
do_return:
	iput(inode);
	DPRINTF(("fo_read() returns %d\n", error));
	return error;
}

/* ------------------------------------------------------------------------- */

int	fo_write(my_attr_t *fa, int fh, int offset, int count, char *data)
{
struct inode			*inode;
struct inode_operations	*ops;
struct file_operations	*fops;
struct file				filp;
int						error = 0;

	DPRINTF(("fo_write(ino=%d, offs=%d, len=%d)\n", fh, offset, count));
	FIND_INODE(inode, fh, ops, ;);
	CHECK_WRITE(inode, ;);
	if(count <= 0){	/* nothing to be done */
		get_attr(inode, fa);
		goto do_return;
	}
	VALIDATE(ops->default_file_ops, ;);
	fops = ops->default_file_ops;
	VALIDATE(fops->write, ;);
	bzero(&filp, sizeof(filp));
	filp.f_mode = inode->i_mode;
	filp.f_pos = offset;
	error = fops->write(inode, &filp, data, count);
	error = error < 0 ? error : 0;
	get_attr(inode, fa);
do_return:
	iput(inode);
	DPRINTF(("fo_write() returns %d\n", error));
	return error;
}

/* ------------------------------------------------------------------------- */

int	fo_link(int from, int dir, char *name)
{
struct inode			*from_i, *dir_i;
struct inode_operations	*from_o, *dir_o;
int						error = 0;

	DPRINTF(("fo_link(ino=%d, dir=%d, name=%s)\n", from, dir, name));
	FIND_INODE(from_i, from, from_o, ;);
	FIND_INODE(dir_i, dir, dir_o, iput(from_i));
	CHECK_WRITE(dir_i, iput(from_i); iput(dir_i));
	VALIDATE(dir_o->link, iput(from_i); iput(dir_i));
	error = dir_o->link(from_i, dir_i, name, strlen(name));
do_return:
	return error;
}

/* ------------------------------------------------------------------------- */

int	fo_readlink(char **path, int fh)
{
struct inode			*inode;
struct inode_operations	*ops;
int						error = 0;
static char				namebuf[2048];

	DPRINTF(("fo_readlink(ino=%d)\n", fh));
	FIND_INODE(inode, fh, ops, ;);
	VALIDATE(ops->readlink, iput(inode));
	*path = namebuf;
	error = ops->readlink(inode, *path, sizeof(namebuf));
	if(error >= 0){
		if(error < sizeof(namebuf))
			namebuf[error] = 0;
		else
			namebuf[sizeof(namebuf)-1] = 0;
	}
do_return:
	return error;
}

/* ------------------------------------------------------------------------- */

int	fo_symlink(int fromdir, char *fromname, char *topath, my_attr_t *sa)
{
struct inode			*dir_i;
struct inode_operations	*dir_o;
int						error = 0;

	DPRINTF(("fo_symlink(dir=%d, name=%s, path=%s)\n", fromdir,
													fromname, topath));
	FIND_INODE(dir_i, fromdir, dir_o, ;);
	CHECK_WRITE(dir_i, iput(dir_i));
	VALIDATE(dir_o->symlink, iput(dir_i));
	error = dir_o->symlink(dir_i, fromname, strlen(fromname), topath);
	/* ignore attributes! links should have all flags set, anyway */
do_return:
	return error;
}

/* ------------------------------------------------------------------------- */

void	fops_regular(void)
{
static int	i = 0;

	if(++i > 10){	/* do a sync every 10s */
		i = 0;
		my_sync();
	}
}

/* ------------------------------------------------------------------------- */

void	fops_init(void)
{
#ifdef CONFIG_EXT_FS
	init_ext_fs();
#endif

#ifdef CONFIG_EXT2_FS
	init_ext2_fs();
#endif

#ifdef CONFIG_XIA_FS
	init_xiafs_fs();
#endif

#ifdef CONFIG_MINIX_FS
	init_minix_fs();
#endif

#ifdef CONFIG_UMSDOS_FS
	init_umsdos_fs();
#endif

#ifdef CONFIG_FAT_FS
	init_fat_fs();
#endif

#ifdef CONFIG_MSDOS_FS
	init_msdos_fs();
#endif

#ifdef CONFIG_VFAT_FS
	init_vfat_fs();
#endif

#ifdef CONFIG_PROC_FS
	init_proc_fs();
#endif

#ifdef CONFIG_NFS_FS
	init_nfs_fs();
#endif

#ifdef CONFIG_SMB_FS
	init_smb_fs();
#endif

#ifdef CONFIG_NCP_FS
	init_ncp_fs();
#endif

#ifdef CONFIG_ISO9660_FS
	init_iso9660_fs();
#endif

#ifdef CONFIG_SYSV_FS
	init_sysv_fs();
#endif

#ifdef CONFIG_HPFS_FS
	init_hpfs_fs();
#endif

#ifdef CONFIG_AFFS_FS
	init_affs_fs();
#endif

#ifdef CONFIG_UFS_FS
	init_ufs_fs();
#endif

#ifdef CONFIG_NTFS_FS
	init_ntfs_fs();
#endif

}

/* ------------------------------------------------------------------------- */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.