libvtreefs: use libfsdriver
Change-Id: I0e6446bd0ccc3b89edc237be441ebfd92585f352
This commit is contained in:
		
							parent
							
								
									81db4f2cff
								
							
						
					
					
						commit
						0dc5c83ec2
					
				@ -2,8 +2,8 @@
 | 
			
		||||
PROG=	gpio
 | 
			
		||||
SRCS=	gpio.c
 | 
			
		||||
 | 
			
		||||
DPADD+=	${LIBBLOCKDRIVER} ${LIBSYS} ${LIBGPIO} ${LIBCLKCONF}
 | 
			
		||||
LDADD+=	-lvtreefs -lsys -lgpio -lclkconf
 | 
			
		||||
DPADD+=	${LIBVTREEFS} ${LIBFSDRIVER} ${LIBSYS} ${LIBGPIO} ${LIBCLKCONF}
 | 
			
		||||
LDADD+=	-lvtreefs -lfsdriver -lsys -lgpio -lclkconf
 | 
			
		||||
 | 
			
		||||
# This is a system driver.
 | 
			
		||||
CPPFLAGS+= -D_SYSTEM=1
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@ CPPFLAGS+= -I${NETBSDSRCDIR}/minix
 | 
			
		||||
CPPFLAGS+= -I${NETBSDSRCDIR}/minix/fs
 | 
			
		||||
CPPFLAGS+= -I${NETBSDSRCDIR}/minix/servers
 | 
			
		||||
 | 
			
		||||
DPADD+=	${LIBVTREEFS} ${LIBMINIXFS}
 | 
			
		||||
LDADD+=	-lvtreefs -lminixfs
 | 
			
		||||
DPADD+=	${LIBVTREEFS} ${LIBFSDRIVER}
 | 
			
		||||
LDADD+=	-lvtreefs -lfsdriver
 | 
			
		||||
 | 
			
		||||
.include <minix.service.mk>
 | 
			
		||||
 | 
			
		||||
@ -89,7 +89,7 @@ int main(void)
 | 
			
		||||
	stat.size 	= 0;
 | 
			
		||||
	stat.dev 	= NO_DEV;
 | 
			
		||||
 | 
			
		||||
	/* Start VTreeFS. This call does not return. */
 | 
			
		||||
	/* Start VTreeFS. */
 | 
			
		||||
	start_vtreefs(&hooks, NR_INODES, &stat, NR_PROCS + NR_TASKS);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,9 @@
 | 
			
		||||
NOGCCERROR=yes
 | 
			
		||||
NOCLANGERROR=yes
 | 
			
		||||
CPPFLAGS+= -D_MINIX_SYSTEM
 | 
			
		||||
 | 
			
		||||
# Makefile for libvtreefs
 | 
			
		||||
 | 
			
		||||
NOGCCERROR=yes
 | 
			
		||||
 | 
			
		||||
CPPFLAGS+= -D_MINIX_SYSTEM
 | 
			
		||||
 | 
			
		||||
LIB=	vtreefs
 | 
			
		||||
 | 
			
		||||
CPPFLAGS+= -I${NETBSDSRCDIR}/include
 | 
			
		||||
@ -17,7 +17,6 @@ SRCS=	\
 | 
			
		||||
	sdbm.c \
 | 
			
		||||
	stadir.c \
 | 
			
		||||
	table.c \
 | 
			
		||||
	utility.c \
 | 
			
		||||
	vtreefs.c
 | 
			
		||||
 | 
			
		||||
.include <bsd.lib.mk>
 | 
			
		||||
 | 
			
		||||
@ -8,13 +8,8 @@
 | 
			
		||||
 | 
			
		||||
EXTERN struct fs_hooks *vtreefs_hooks;
 | 
			
		||||
 | 
			
		||||
EXTERN message fs_m_in;
 | 
			
		||||
EXTERN message fs_m_out;
 | 
			
		||||
 | 
			
		||||
EXTERN dev_t fs_dev;
 | 
			
		||||
 | 
			
		||||
EXTERN int fs_mounted;
 | 
			
		||||
 | 
			
		||||
extern int(*fs_call_vec[]) (void);
 | 
			
		||||
extern struct fsdriver vtreefs_table;
 | 
			
		||||
 | 
			
		||||
#endif /* _VTREEFS_GLO_H */
 | 
			
		||||
 | 
			
		||||
@ -1,29 +1,8 @@
 | 
			
		||||
#define _SYSTEM		1	/* tell headers that this is the kernel */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/queue.h>
 | 
			
		||||
#include <sys/ucred.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include <minix/config.h>
 | 
			
		||||
#include <minix/callnr.h>
 | 
			
		||||
#include <minix/type.h>
 | 
			
		||||
#include <minix/const.h>
 | 
			
		||||
#include <minix/com.h>
 | 
			
		||||
#include <minix/syslib.h>
 | 
			
		||||
#include <minix/sysutil.h>
 | 
			
		||||
#include <minix/bitmap.h>
 | 
			
		||||
#include <minix/vfsif.h>
 | 
			
		||||
#include <minix/endpoint.h>
 | 
			
		||||
#include <minix/drivers.h>
 | 
			
		||||
#include <minix/vtreefs.h>
 | 
			
		||||
#include <minix/fsdriver.h>
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
#include "glo.h"
 | 
			
		||||
#include "proto.h"
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ void init_inodes(unsigned int inodes, struct inode_stat *stat,
 | 
			
		||||
	/* Initialize the inode-related state.
 | 
			
		||||
	 */
 | 
			
		||||
	struct inode *node;
 | 
			
		||||
	int i;
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
 | 
			
		||||
	assert(inodes > 0);
 | 
			
		||||
	assert(nr_indexed_entries >= 0);
 | 
			
		||||
@ -134,7 +134,7 @@ static int parent_index_hash(struct inode *parent, index_t index)
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				purge_inode				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
void purge_inode(struct inode *parent)
 | 
			
		||||
static void purge_inode(struct inode *parent)
 | 
			
		||||
{
 | 
			
		||||
	/* Delete a deletable inode to make room for a new inode.
 | 
			
		||||
	 */
 | 
			
		||||
@ -149,7 +149,7 @@ void purge_inode(struct inode *parent)
 | 
			
		||||
	 */
 | 
			
		||||
	static int last_checked = 0;
 | 
			
		||||
	struct inode *node;
 | 
			
		||||
	int count;
 | 
			
		||||
	unsigned int count;
 | 
			
		||||
 | 
			
		||||
	assert(TAILQ_EMPTY(&unused_inodes));
 | 
			
		||||
 | 
			
		||||
@ -484,7 +484,6 @@ void ref_inode(struct inode *node)
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	CHECK_INODE(node);
 | 
			
		||||
	assert(node->i_count >= 0);
 | 
			
		||||
 | 
			
		||||
	node->i_count++;
 | 
			
		||||
}
 | 
			
		||||
@ -581,7 +580,7 @@ int is_inode_deleted(struct inode *node)
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				fs_putnode				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int fs_putnode(void)
 | 
			
		||||
int fs_putnode(ino_t ino_nr, unsigned int count)
 | 
			
		||||
{
 | 
			
		||||
	/* Find the inode specified by the request message, and decrease its
 | 
			
		||||
	 * reference count.
 | 
			
		||||
@ -589,14 +588,13 @@ int fs_putnode(void)
 | 
			
		||||
	struct inode *node;
 | 
			
		||||
 | 
			
		||||
	/* Get the inode specified by its number. */
 | 
			
		||||
	if ((node = find_inode(fs_m_in.m_vfs_fs_putnode.inode)) == NULL)
 | 
			
		||||
	if ((node = find_inode(ino_nr)) == NULL)
 | 
			
		||||
		return EINVAL;
 | 
			
		||||
 | 
			
		||||
	/* Decrease the reference count. */
 | 
			
		||||
	node->i_count -= fs_m_in.m_vfs_fs_putnode.count - 1;
 | 
			
		||||
 | 
			
		||||
	assert(node->i_count > 0);
 | 
			
		||||
	assert(node->i_count >= count);
 | 
			
		||||
 | 
			
		||||
	node->i_count -= count - 1;
 | 
			
		||||
	put_inode(node);
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
 | 
			
		||||
@ -18,7 +18,7 @@ struct inode {
 | 
			
		||||
	/* Inode metadata */
 | 
			
		||||
	struct inode_stat i_stat;	/* POSIX attributes */
 | 
			
		||||
	char i_name[PNAME_MAX + 1];	/* name of the inode in the parent */
 | 
			
		||||
	int i_count;			/* reference count */
 | 
			
		||||
	unsigned int i_count;		/* reference count */
 | 
			
		||||
	index_t i_index;		/* index number in parent / NO_INDEX */
 | 
			
		||||
	int i_indexed;			/* number of indexed entries */
 | 
			
		||||
	cbdata_t i_cbdata;		/* callback data */
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				fs_rdlink				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int fs_rdlink(void)
 | 
			
		||||
ssize_t fs_rdlink(ino_t ino_nr, struct fsdriver_data *data, size_t bytes)
 | 
			
		||||
{
 | 
			
		||||
	/* Retrieve symbolic link target.
 | 
			
		||||
	 */
 | 
			
		||||
@ -14,7 +14,7 @@ int fs_rdlink(void)
 | 
			
		||||
	size_t len;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if ((node = find_inode(fs_m_in.m_vfs_fs_rdlink.inode)) == NULL)
 | 
			
		||||
	if ((node = find_inode(ino_nr)) == NULL)
 | 
			
		||||
		return EINVAL;
 | 
			
		||||
 | 
			
		||||
	/* Call the rdlink hook. */
 | 
			
		||||
@ -28,14 +28,12 @@ int fs_rdlink(void)
 | 
			
		||||
	len = strlen(path);
 | 
			
		||||
	assert(len > 0 && len < sizeof(path));
 | 
			
		||||
 | 
			
		||||
	if (len > fs_m_in.m_vfs_fs_rdlink.mem_size)
 | 
			
		||||
		len = fs_m_in.m_vfs_fs_rdlink.mem_size;
 | 
			
		||||
	if (len > bytes)
 | 
			
		||||
		len = bytes;
 | 
			
		||||
 | 
			
		||||
	/* Copy out the result. */
 | 
			
		||||
	r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_rdlink.grant, 0,
 | 
			
		||||
		(vir_bytes) path, len);
 | 
			
		||||
	if (r != OK) return r;
 | 
			
		||||
	if ((r = fsdriver_copyout(data, 0, path, len)) != OK)
 | 
			
		||||
		return r;
 | 
			
		||||
 | 
			
		||||
	fs_m_out.m_fs_vfs_rdlink.nbytes = len;
 | 
			
		||||
	return OK;
 | 
			
		||||
	return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,21 +1,23 @@
 | 
			
		||||
/* VTreeFS - mount.c - by Alen Stojanov and David van Moolenbroek */
 | 
			
		||||
 | 
			
		||||
#include "inc.h"
 | 
			
		||||
#include <minix/vfsif.h>
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				fs_readsuper				     *
 | 
			
		||||
 *				fs_mount				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int fs_readsuper(void)
 | 
			
		||||
int fs_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node,
 | 
			
		||||
	unsigned int *res_flags)
 | 
			
		||||
{
 | 
			
		||||
	/* This function gets the root inode and sends back its details.
 | 
			
		||||
	 */
 | 
			
		||||
	struct inode *root;
 | 
			
		||||
 | 
			
		||||
	/* Get the device number, for stat requests. */
 | 
			
		||||
	fs_dev = fs_m_in.m_vfs_fs_readsuper.device;
 | 
			
		||||
	fs_dev = dev;
 | 
			
		||||
 | 
			
		||||
	/* The VTreeFS must not be mounted as a root file system. */
 | 
			
		||||
	if (fs_m_in.m_vfs_fs_readsuper.flags & REQ_ISROOT)
 | 
			
		||||
	if (flags & REQ_ISROOT)
 | 
			
		||||
		return EINVAL;
 | 
			
		||||
 | 
			
		||||
	/* Get the root inode and increase its reference count. */
 | 
			
		||||
@ -27,15 +29,14 @@ int fs_readsuper(void)
 | 
			
		||||
		vtreefs_hooks->init_hook();
 | 
			
		||||
 | 
			
		||||
	/* Return the root inode's properties. */
 | 
			
		||||
	fs_m_out.m_fs_vfs_readsuper.inode = get_inode_number(root);
 | 
			
		||||
	fs_m_out.m_fs_vfs_readsuper.mode = root->i_stat.mode;
 | 
			
		||||
	fs_m_out.m_fs_vfs_readsuper.file_size = root->i_stat.size;
 | 
			
		||||
	fs_m_out.m_fs_vfs_readsuper.uid = root->i_stat.uid;
 | 
			
		||||
	fs_m_out.m_fs_vfs_readsuper.gid = root->i_stat.gid;
 | 
			
		||||
	fs_m_out.m_fs_vfs_readsuper.device = NO_DEV;
 | 
			
		||||
	fs_m_out.m_fs_vfs_readsuper.flags = RES_NOFLAGS;
 | 
			
		||||
	root_node->fn_ino_nr = get_inode_number(root);
 | 
			
		||||
	root_node->fn_mode = root->i_stat.mode;
 | 
			
		||||
	root_node->fn_size = root->i_stat.size;
 | 
			
		||||
	root_node->fn_uid = root->i_stat.uid;
 | 
			
		||||
	root_node->fn_gid = root->i_stat.gid;
 | 
			
		||||
	root_node->fn_dev = NO_DEV;
 | 
			
		||||
 | 
			
		||||
	fs_mounted = TRUE;
 | 
			
		||||
	*res_flags = RES_NOFLAGS;
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
@ -43,7 +44,7 @@ int fs_readsuper(void)
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				fs_unmount				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int fs_unmount(void)
 | 
			
		||||
void fs_unmount(void)
 | 
			
		||||
{
 | 
			
		||||
	/* Unmount the file system.
 | 
			
		||||
	 */
 | 
			
		||||
@ -57,9 +58,4 @@ int fs_unmount(void)
 | 
			
		||||
	/* The system is unmounted. Call the cleanup hook. */
 | 
			
		||||
	if (vtreefs_hooks->cleanup_hook != NULL)
 | 
			
		||||
		vtreefs_hooks->cleanup_hook();
 | 
			
		||||
 | 
			
		||||
	/* We can now be shut down safely. */
 | 
			
		||||
	fs_mounted = FALSE;
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -2,313 +2,59 @@
 | 
			
		||||
 | 
			
		||||
#include "inc.h"
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				access_as_dir				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
static int access_as_dir(struct inode *node, vfs_ucred_t *ucred)
 | 
			
		||||
{
 | 
			
		||||
	/* Check whether the given inode may be accessed as directory.
 | 
			
		||||
	 * Return OK or an appropriate error code.
 | 
			
		||||
	 */
 | 
			
		||||
	mode_t mask;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	/* The inode must be a directory to begin with. */
 | 
			
		||||
	if (!S_ISDIR(node->i_stat.mode)) return ENOTDIR;
 | 
			
		||||
 | 
			
		||||
	/* The caller must have search access to the directory.
 | 
			
		||||
	 * Root always does.
 | 
			
		||||
	 */
 | 
			
		||||
	if (ucred->vu_uid == SUPER_USER) return OK;
 | 
			
		||||
 | 
			
		||||
	if (ucred->vu_uid == node->i_stat.uid) mask = S_IXUSR;
 | 
			
		||||
	else if (ucred->vu_gid == node->i_stat.gid) mask = S_IXGRP;
 | 
			
		||||
	else {
 | 
			
		||||
		mask = S_IXOTH;
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < ucred->vu_ngroups; i++) {
 | 
			
		||||
			if (ucred->vu_sgroups[i] == node->i_stat.gid) {
 | 
			
		||||
				mask = S_IXGRP;
 | 
			
		||||
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (node->i_stat.mode & mask) ? OK : EACCES;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				next_name				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
static int next_name(char **ptr, char **start, char name[PNAME_MAX+1])
 | 
			
		||||
{
 | 
			
		||||
	/* Get the next path component from a path.
 | 
			
		||||
	 */
 | 
			
		||||
	char *p;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (p = *ptr; *p == '/'; p++);
 | 
			
		||||
 | 
			
		||||
	*start = p;
 | 
			
		||||
 | 
			
		||||
	if (*p) {
 | 
			
		||||
		for (i = 0; *p && *p != '/' && i <= PNAME_MAX; p++, i++)
 | 
			
		||||
			name[i] = *p;
 | 
			
		||||
 | 
			
		||||
		if (i > PNAME_MAX)
 | 
			
		||||
			return ENAMETOOLONG;
 | 
			
		||||
 | 
			
		||||
		name[i] = 0;
 | 
			
		||||
	} else {
 | 
			
		||||
		strcpy(name, ".");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*ptr = p;
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				go_up					     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
static int go_up(struct inode *node, struct inode **parent)
 | 
			
		||||
{
 | 
			
		||||
	/* Given a directory inode, progress into the parent directory.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	*parent = get_parent_inode(node);
 | 
			
		||||
 | 
			
		||||
	/* Trapped in a deleted directory? Should not be possible. */
 | 
			
		||||
	if (*parent == NULL)
 | 
			
		||||
		return ENOENT;
 | 
			
		||||
 | 
			
		||||
	ref_inode(*parent);
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				go_down					     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
static int go_down(struct inode *parent, char *name, struct inode **child)
 | 
			
		||||
{
 | 
			
		||||
	/* Given a directory inode and a name, progress into a directory entry.
 | 
			
		||||
	 */
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	/* Call the lookup hook, if present, before doing the actual lookup. */
 | 
			
		||||
	if (!is_inode_deleted(parent) && vtreefs_hooks->lookup_hook != NULL) {
 | 
			
		||||
		r = vtreefs_hooks->lookup_hook(parent, name,
 | 
			
		||||
			get_inode_cbdata(parent));
 | 
			
		||||
		if (r != OK) return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((*child = get_inode_by_name(parent, name)) == NULL)
 | 
			
		||||
		return ENOENT;
 | 
			
		||||
 | 
			
		||||
	ref_inode(*child);
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				resolve_link				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
static int resolve_link(struct inode *node, char pptr[PATH_MAX], char *tail)
 | 
			
		||||
{
 | 
			
		||||
	/* Given a symbolic link, resolve and return the contents of the link.
 | 
			
		||||
	 */
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
	size_t len;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	assert(vtreefs_hooks->rdlink_hook != NULL);
 | 
			
		||||
	assert(!is_inode_deleted(node));
 | 
			
		||||
 | 
			
		||||
	r = vtreefs_hooks->rdlink_hook(node, path, sizeof(path),
 | 
			
		||||
		get_inode_cbdata(node));
 | 
			
		||||
	if (r != OK) return r;
 | 
			
		||||
 | 
			
		||||
	len = strlen(path);
 | 
			
		||||
	assert(len > 0 && len < sizeof(path));
 | 
			
		||||
 | 
			
		||||
	if (len + strlen(tail) >= sizeof(path))
 | 
			
		||||
		return ENAMETOOLONG;
 | 
			
		||||
 | 
			
		||||
	strlcat(path, tail, sizeof(path));
 | 
			
		||||
 | 
			
		||||
	strlcpy(pptr, path, PATH_MAX);
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				fs_lookup				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int fs_lookup(void)
 | 
			
		||||
int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node_details,
 | 
			
		||||
	int *is_mountpt)
 | 
			
		||||
{
 | 
			
		||||
	/* Resolve a path string to an inode.
 | 
			
		||||
	 */
 | 
			
		||||
	ino_t dir_ino_nr, root_ino_nr;
 | 
			
		||||
	struct inode *cur_ino, *next_ino, *root_ino;
 | 
			
		||||
	char path[PATH_MAX], name[PNAME_MAX+1];
 | 
			
		||||
	char *ptr, *last;
 | 
			
		||||
	vfs_ucred_t ucred;
 | 
			
		||||
	size_t len;
 | 
			
		||||
	int r, r2, symloop;
 | 
			
		||||
	struct inode *node, *child;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	dir_ino_nr = fs_m_in.m_vfs_fs_lookup.dir_ino;
 | 
			
		||||
	root_ino_nr = fs_m_in.m_vfs_fs_lookup.root_ino;
 | 
			
		||||
	len = fs_m_in.m_vfs_fs_lookup.path_len;
 | 
			
		||||
 | 
			
		||||
	/* Fetch the path name. */
 | 
			
		||||
	if (len < 1 || len > PATH_MAX)
 | 
			
		||||
	if ((node = find_inode(dir_nr)) == NULL)
 | 
			
		||||
		return EINVAL;
 | 
			
		||||
 | 
			
		||||
	r = sys_safecopyfrom(fs_m_in.m_source,
 | 
			
		||||
		fs_m_in.m_vfs_fs_lookup.grant_path, 0, (vir_bytes) path,
 | 
			
		||||
		(phys_bytes) len);
 | 
			
		||||
	if (r != OK) return r;
 | 
			
		||||
	if (!S_ISDIR(node->i_stat.mode))
 | 
			
		||||
		return ENOTDIR;
 | 
			
		||||
 | 
			
		||||
	if (path[len-1] != 0) return EINVAL;
 | 
			
		||||
	if (strlen(name) > PNAME_MAX)
 | 
			
		||||
		return ENAMETOOLONG;
 | 
			
		||||
 | 
			
		||||
	/* Fetch the caller's credentials. */
 | 
			
		||||
	if (fs_m_in.m_vfs_fs_lookup.flags & PATH_GET_UCRED) {
 | 
			
		||||
		assert(fs_m_in.m_vfs_fs_lookup.ucred_size == sizeof(ucred));
 | 
			
		||||
 | 
			
		||||
		r = sys_safecopyfrom(fs_m_in.m_source,
 | 
			
		||||
			fs_m_in.m_vfs_fs_lookup.grant_ucred, 0,
 | 
			
		||||
			(vir_bytes) &ucred, fs_m_in.m_vfs_fs_lookup.ucred_size);
 | 
			
		||||
 | 
			
		||||
		if (r != OK)
 | 
			
		||||
			return r;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		ucred.vu_uid = fs_m_in.m_vfs_fs_lookup.uid;
 | 
			
		||||
		ucred.vu_gid = fs_m_in.m_vfs_fs_lookup.gid;
 | 
			
		||||
		ucred.vu_ngroups = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Start the actual lookup. */
 | 
			
		||||
	if ((cur_ino = get_inode(dir_ino_nr)) == NULL)
 | 
			
		||||
		return EINVAL;
 | 
			
		||||
 | 
			
		||||
	/* Chroot'ed environment? */
 | 
			
		||||
	if (root_ino_nr > 0)
 | 
			
		||||
		root_ino = find_inode(root_ino_nr);
 | 
			
		||||
	else
 | 
			
		||||
		root_ino = NULL;
 | 
			
		||||
 | 
			
		||||
	symloop = 0;
 | 
			
		||||
 | 
			
		||||
	for (ptr = last = path; ptr[0] != 0; ) {
 | 
			
		||||
		/* There is more path to process. That means that the current
 | 
			
		||||
		 * file is now being accessed as a directory. Check type and
 | 
			
		||||
		 * permissions.
 | 
			
		||||
		 */
 | 
			
		||||
		if ((r = access_as_dir(cur_ino, &ucred)) != OK)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		/* Get the next path component. The result is a non-empty
 | 
			
		||||
		 * string.
 | 
			
		||||
		 */
 | 
			
		||||
		if ((r = next_name(&ptr, &last, name)) != OK)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		if (!strcmp(name, ".") ||
 | 
			
		||||
				(cur_ino == root_ino && !strcmp(name, "..")))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (!strcmp(name, "..")) {
 | 
			
		||||
			if (cur_ino == get_root_inode())
 | 
			
		||||
				r = ELEAVEMOUNT;
 | 
			
		||||
			else
 | 
			
		||||
				r = go_up(cur_ino, &next_ino);
 | 
			
		||||
	if (!strcmp(name, ".")) {
 | 
			
		||||
		/* Stay in the given directory. */
 | 
			
		||||
		child = node;
 | 
			
		||||
	} else if (!strcmp(name, "..")) {
 | 
			
		||||
		/* Progress into the parent directory. */
 | 
			
		||||
		if ((child = get_parent_inode(node)) == NULL)
 | 
			
		||||
			return ENOENT;	/* deleted? should not be possible */
 | 
			
		||||
	} else {
 | 
			
		||||
			r = go_down(cur_ino, name, &next_ino);
 | 
			
		||||
 | 
			
		||||
			/* Perform symlink resolution if we have to. */
 | 
			
		||||
			if (r == OK && S_ISLNK(next_ino->i_stat.mode) &&
 | 
			
		||||
				(ptr[0] != '\0' ||
 | 
			
		||||
				!(fs_m_in.m_vfs_fs_lookup.flags & PATH_RET_SYMLINK))) {
 | 
			
		||||
 | 
			
		||||
				if (++symloop == _POSIX_SYMLOOP_MAX) {
 | 
			
		||||
					put_inode(next_ino);
 | 
			
		||||
 | 
			
		||||
					r = ELOOP;
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				/* Resolve the symlink, and append the
 | 
			
		||||
				 * remaining unresolved part of the path.
 | 
			
		||||
		/* Progress into a directory entry. Call the lookup hook, if
 | 
			
		||||
		 * present, before doing the actual lookup.
 | 
			
		||||
		 */
 | 
			
		||||
				r = resolve_link(next_ino, path, ptr);
 | 
			
		||||
 | 
			
		||||
				put_inode(next_ino);
 | 
			
		||||
 | 
			
		||||
				if (r != OK)
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				/* If the symlink is absolute, return it to
 | 
			
		||||
				 * VFS.
 | 
			
		||||
				 */
 | 
			
		||||
				if (path[0] == '/') {
 | 
			
		||||
					r = ESYMLINK;
 | 
			
		||||
					last = path;
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
		if (!is_inode_deleted(node) &&
 | 
			
		||||
		    vtreefs_hooks->lookup_hook != NULL) {
 | 
			
		||||
			r = vtreefs_hooks->lookup_hook(node, name,
 | 
			
		||||
				get_inode_cbdata(node));
 | 
			
		||||
			if (r != OK) return r;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
				ptr = path;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
		if ((child = get_inode_by_name(node, name)) == NULL)
 | 
			
		||||
			return ENOENT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		if (r != OK)
 | 
			
		||||
			break;
 | 
			
		||||
	/* On success, open the resulting file and return its details. */
 | 
			
		||||
	ref_inode(child);
 | 
			
		||||
 | 
			
		||||
		/* We have found a new file. Continue from this file. */
 | 
			
		||||
		assert(next_ino != NULL);
 | 
			
		||||
	node_details->fn_ino_nr = get_inode_number(child);
 | 
			
		||||
	node_details->fn_mode = child->i_stat.mode;
 | 
			
		||||
	node_details->fn_size = child->i_stat.size;
 | 
			
		||||
	node_details->fn_uid = child->i_stat.uid;
 | 
			
		||||
	node_details->fn_gid = child->i_stat.gid;
 | 
			
		||||
	node_details->fn_dev = child->i_stat.dev;
 | 
			
		||||
 | 
			
		||||
		put_inode(cur_ino);
 | 
			
		||||
 | 
			
		||||
		cur_ino = next_ino;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If an error occurred, close the file and return error information.
 | 
			
		||||
	 */
 | 
			
		||||
	if (r != OK) {
 | 
			
		||||
		put_inode(cur_ino);
 | 
			
		||||
 | 
			
		||||
		/* We'd need support for this here. */
 | 
			
		||||
		assert(r != EENTERMOUNT);
 | 
			
		||||
 | 
			
		||||
		/* Copy back the path if we resolved at least one symlink. */
 | 
			
		||||
		if (symloop > 0 && (r == ELEAVEMOUNT || r == ESYMLINK)) {
 | 
			
		||||
			r2 = sys_safecopyto(fs_m_in.m_source,
 | 
			
		||||
				fs_m_in.m_vfs_fs_lookup.grant_path, 0,
 | 
			
		||||
				(vir_bytes) path, strlen(path) + 1);
 | 
			
		||||
 | 
			
		||||
			if (r2 != OK)
 | 
			
		||||
				r = r2;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (r == ELEAVEMOUNT || r == ESYMLINK) {
 | 
			
		||||
			fs_m_out.m_fs_vfs_lookup.offset = (int) (last - path);
 | 
			
		||||
			fs_m_out.m_fs_vfs_lookup.symloop = symloop;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* On success, leave the resulting file open and return its details. */
 | 
			
		||||
	fs_m_out.m_fs_vfs_lookup.inode = get_inode_number(cur_ino);
 | 
			
		||||
	fs_m_out.m_fs_vfs_lookup.mode = cur_ino->i_stat.mode;
 | 
			
		||||
	fs_m_out.m_fs_vfs_lookup.file_size = cur_ino->i_stat.size;
 | 
			
		||||
	fs_m_out.m_fs_vfs_lookup.uid = cur_ino->i_stat.uid;
 | 
			
		||||
	fs_m_out.m_fs_vfs_lookup.gid = cur_ino->i_stat.gid;
 | 
			
		||||
	fs_m_out.m_fs_vfs_lookup.device = cur_ino->i_stat.dev;
 | 
			
		||||
	*is_mountpt = FALSE;
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -11,31 +11,34 @@ void put_inode(struct inode *node);
 | 
			
		||||
void ref_inode(struct inode *node);
 | 
			
		||||
int get_inode_number(struct inode *node);
 | 
			
		||||
int is_inode_deleted(struct inode *node);
 | 
			
		||||
int fs_putnode(void);
 | 
			
		||||
int fs_putnode(ino_t ino_nr, unsigned int count);
 | 
			
		||||
 | 
			
		||||
/* link.c */
 | 
			
		||||
int fs_rdlink(void);
 | 
			
		||||
ssize_t fs_rdlink(ino_t ino_nr, struct fsdriver_data *data, size_t bytes);
 | 
			
		||||
 | 
			
		||||
/* mount.c */
 | 
			
		||||
int fs_readsuper(void);
 | 
			
		||||
int fs_unmount(void);
 | 
			
		||||
int fs_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node,
 | 
			
		||||
	unsigned int *res_flags);
 | 
			
		||||
void fs_unmount(void);
 | 
			
		||||
 | 
			
		||||
/* main.c */
 | 
			
		||||
void fs_other(const message *m_ptr, int ipc_status);
 | 
			
		||||
 | 
			
		||||
/* path.c */
 | 
			
		||||
int fs_lookup(void);
 | 
			
		||||
int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
 | 
			
		||||
	int *is_mountpt);
 | 
			
		||||
 | 
			
		||||
/* read.c */
 | 
			
		||||
int fs_read(void);
 | 
			
		||||
int fs_getdents(void);
 | 
			
		||||
ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
 | 
			
		||||
	off_t pos, int call);
 | 
			
		||||
ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
 | 
			
		||||
	off_t *pos);
 | 
			
		||||
 | 
			
		||||
/* sdbm.c */
 | 
			
		||||
long sdbm_hash(char *str, int len);
 | 
			
		||||
 | 
			
		||||
/* stadir.c */
 | 
			
		||||
int fs_stat(void);
 | 
			
		||||
int fs_statvfs(void);
 | 
			
		||||
 | 
			
		||||
/* utility.c */
 | 
			
		||||
int no_sys(void);
 | 
			
		||||
int do_noop(void);
 | 
			
		||||
int fs_stat(ino_t ino_nr, struct stat *buf);
 | 
			
		||||
int fs_statvfs(struct statvfs *buf);
 | 
			
		||||
 | 
			
		||||
#endif /* _VTREEFS_PROTO_H */
 | 
			
		||||
 | 
			
		||||
@ -2,40 +2,33 @@
 | 
			
		||||
 | 
			
		||||
#include "inc.h"
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#include <minix/minlib.h>
 | 
			
		||||
 | 
			
		||||
#define GETDENTS_BUFSIZ 4096
 | 
			
		||||
#define DWORD_ALIGN(len) (((len) + sizeof(long) - 1) & ~(sizeof(long) - 1))
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				fs_read					     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int fs_read(void)
 | 
			
		||||
ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
 | 
			
		||||
	off_t pos, int __unused call)
 | 
			
		||||
{
 | 
			
		||||
	/* Read from a file.
 | 
			
		||||
	 */
 | 
			
		||||
	cp_grant_id_t gid;
 | 
			
		||||
	struct inode *node;
 | 
			
		||||
	off_t pos;
 | 
			
		||||
	size_t len;
 | 
			
		||||
	char *ptr;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	/* Try to get inode by to its inode number. */
 | 
			
		||||
	if ((node = find_inode(fs_m_in.m_vfs_fs_readwrite.inode)) == NULL)
 | 
			
		||||
	/* Try to get inode by its inode number. */
 | 
			
		||||
	if ((node = find_inode(ino_nr)) == NULL)
 | 
			
		||||
		return EINVAL;
 | 
			
		||||
 | 
			
		||||
	/* Check whether the node is a regular file. */
 | 
			
		||||
	if (!S_ISREG(node->i_stat.mode))
 | 
			
		||||
		return EINVAL;
 | 
			
		||||
 | 
			
		||||
	/* Get the values from the request message. */
 | 
			
		||||
	gid = fs_m_in.m_vfs_fs_readwrite.grant;
 | 
			
		||||
	pos = fs_m_in.m_vfs_fs_readwrite.seek_pos;
 | 
			
		||||
 | 
			
		||||
	/* Call the read hook, if any. */
 | 
			
		||||
	if (!is_inode_deleted(node) && vtreefs_hooks->read_hook != NULL) {
 | 
			
		||||
		len = fs_m_in.m_vfs_fs_readwrite.nbytes;
 | 
			
		||||
		len = bytes;
 | 
			
		||||
 | 
			
		||||
		/* On success, the read hook provides us with a pointer to the
 | 
			
		||||
		 * resulting data. This avoids copying overhead.
 | 
			
		||||
@ -43,51 +36,41 @@ int fs_read(void)
 | 
			
		||||
		r = vtreefs_hooks->read_hook(node, pos, &ptr, &len,
 | 
			
		||||
			get_inode_cbdata(node));
 | 
			
		||||
 | 
			
		||||
		assert(len <= fs_m_in.m_vfs_fs_readwrite.nbytes);
 | 
			
		||||
		assert(len <= bytes);
 | 
			
		||||
 | 
			
		||||
		/* Copy the resulting data to user space. */
 | 
			
		||||
		if (r == OK && len > 0) {
 | 
			
		||||
			r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_readwrite.grant,
 | 
			
		||||
				0, (vir_bytes) ptr, len);
 | 
			
		||||
		}
 | 
			
		||||
		if (r == OK && len > 0)
 | 
			
		||||
			r = fsdriver_copyout(data, 0, ptr, len);
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Feign an empty file. */
 | 
			
		||||
		r = OK;
 | 
			
		||||
		len = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (r == OK) {
 | 
			
		||||
		fs_m_out.m_fs_vfs_readwrite.seek_pos = pos + len;
 | 
			
		||||
		fs_m_out.m_fs_vfs_readwrite.nbytes = len;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
	return (r != OK) ? r : len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				fs_getdents				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int fs_getdents(void)
 | 
			
		||||
ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
 | 
			
		||||
	off_t *posp)
 | 
			
		||||
{
 | 
			
		||||
	/* Retrieve directory entries.
 | 
			
		||||
	 */
 | 
			
		||||
	struct inode *node, *child = NULL;
 | 
			
		||||
	struct dirent *dent;
 | 
			
		||||
	char *name;
 | 
			
		||||
	size_t len, off, user_off, user_left;
 | 
			
		||||
	struct fsdriver_dentry fsdentry;
 | 
			
		||||
	struct inode *node, *child;
 | 
			
		||||
	const char *name;
 | 
			
		||||
	off_t pos;
 | 
			
		||||
	int r, skip, get_next, indexed;
 | 
			
		||||
	static char buf[GETDENTS_BUFSIZ];
 | 
			
		||||
 | 
			
		||||
	if (fs_m_in.m_vfs_fs_getdents.seek_pos >= ULONG_MAX)
 | 
			
		||||
	if (*posp >= ULONG_MAX)
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	if ((node = find_inode(fs_m_in.m_vfs_fs_getdents.inode)) == NULL)
 | 
			
		||||
	if ((node = find_inode(ino_nr)) == NULL)
 | 
			
		||||
		return EINVAL;
 | 
			
		||||
 | 
			
		||||
	off = 0;
 | 
			
		||||
	user_off = 0;
 | 
			
		||||
	user_left = fs_m_in.m_vfs_fs_getdents.mem_size;
 | 
			
		||||
	indexed = node->i_indexed;
 | 
			
		||||
	get_next = FALSE;
 | 
			
		||||
	child = NULL;
 | 
			
		||||
@ -98,8 +81,12 @@ int fs_getdents(void)
 | 
			
		||||
		if (r != OK) return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (pos = fs_m_in.m_vfs_fs_getdents.seek_pos; ; pos++) {
 | 
			
		||||
	fsdriver_dentry_init(&fsdentry, data, bytes, buf, sizeof(buf));
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		/* Determine which inode and name to use for this entry. */
 | 
			
		||||
		pos = (*posp)++;
 | 
			
		||||
 | 
			
		||||
		if (pos == 0) {
 | 
			
		||||
			/* The "." entry. */
 | 
			
		||||
			child = node;
 | 
			
		||||
@ -158,56 +145,13 @@ int fs_getdents(void)
 | 
			
		||||
			name = child->i_name;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* record length incl. alignment. */
 | 
			
		||||
                len = _DIRENT_RECLEN(dent, strlen(name));
 | 
			
		||||
 | 
			
		||||
		/* Is the user buffer too small to store another record? */
 | 
			
		||||
		if (user_off + off + len > user_left) {
 | 
			
		||||
			/* Is the user buffer too small for even a single
 | 
			
		||||
			 * record?
 | 
			
		||||
			 */
 | 
			
		||||
			if (user_off == 0 && off == 0)
 | 
			
		||||
				return EINVAL;
 | 
			
		||||
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* If our own buffer cannot contain the new record, copy out
 | 
			
		||||
		 * first.
 | 
			
		||||
		 */
 | 
			
		||||
		if (off + len > sizeof(buf)) {
 | 
			
		||||
			r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_getdents.grant,
 | 
			
		||||
				user_off, (vir_bytes) buf, off);
 | 
			
		||||
			if (r != OK) return r;
 | 
			
		||||
 | 
			
		||||
			user_off += off;
 | 
			
		||||
			user_left -= off;
 | 
			
		||||
			off = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Fill in the actual directory entry. */
 | 
			
		||||
		dent = (struct dirent *) &buf[off];
 | 
			
		||||
		dent->d_ino = (ino_t) get_inode_number(child);
 | 
			
		||||
		dent->d_reclen = len;
 | 
			
		||||
		dent->d_type = fs_mode_to_type(child->i_stat.mode);
 | 
			
		||||
		dent->d_namlen = strlen(name);
 | 
			
		||||
		strcpy(dent->d_name, name);
 | 
			
		||||
 | 
			
		||||
		off += len;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If there is anything left in our own buffer, copy that out now. */
 | 
			
		||||
	if (off > 0) {
 | 
			
		||||
		r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_getdents.grant,
 | 
			
		||||
			user_off, (vir_bytes) buf, off);
 | 
			
		||||
		if (r != OK)
 | 
			
		||||
		/* Add the directory entry to the output. */
 | 
			
		||||
		r = fsdriver_dentry_add(&fsdentry,
 | 
			
		||||
			(ino_t) get_inode_number(child), name, strlen(name),
 | 
			
		||||
			IFTODT(child->i_stat.mode));
 | 
			
		||||
		if (r < 0)
 | 
			
		||||
			return r;
 | 
			
		||||
	} while (r > 0);
 | 
			
		||||
 | 
			
		||||
		user_off += off;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fs_m_out.m_fs_vfs_getdents.seek_pos = pos;
 | 
			
		||||
	fs_m_out.m_fs_vfs_getdents.nbytes = user_off;
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
	return fsdriver_dentry_finish(&fsdentry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -2,37 +2,30 @@
 | 
			
		||||
 | 
			
		||||
#include "inc.h"
 | 
			
		||||
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <sys/statvfs.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				fs_stat					     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int fs_stat(void)
 | 
			
		||||
int fs_stat(ino_t ino_nr, struct stat *buf)
 | 
			
		||||
{
 | 
			
		||||
	/* Retrieve file status.
 | 
			
		||||
	 */
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
	struct stat statbuf;
 | 
			
		||||
	time_t cur_time;
 | 
			
		||||
	struct inode *node;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if ((node = find_inode(fs_m_in.m_vfs_fs_stat.inode)) == NULL)
 | 
			
		||||
	if ((node = find_inode(ino_nr)) == NULL)
 | 
			
		||||
		return EINVAL;
 | 
			
		||||
 | 
			
		||||
	memset(&statbuf, 0, sizeof(struct stat));
 | 
			
		||||
 | 
			
		||||
	/* Fill in the basic info. */
 | 
			
		||||
	statbuf.st_dev = fs_dev;
 | 
			
		||||
	statbuf.st_ino = get_inode_number(node);
 | 
			
		||||
	statbuf.st_mode = node->i_stat.mode;
 | 
			
		||||
	statbuf.st_nlink = !is_inode_deleted(node);
 | 
			
		||||
	statbuf.st_uid = node->i_stat.uid;
 | 
			
		||||
	statbuf.st_gid = node->i_stat.gid;
 | 
			
		||||
	statbuf.st_rdev = (dev_t) node->i_stat.dev;
 | 
			
		||||
	statbuf.st_size = node->i_stat.size;
 | 
			
		||||
	buf->st_dev = fs_dev;
 | 
			
		||||
	buf->st_ino = get_inode_number(node);
 | 
			
		||||
	buf->st_mode = node->i_stat.mode;
 | 
			
		||||
	buf->st_nlink = !is_inode_deleted(node);
 | 
			
		||||
	buf->st_uid = node->i_stat.uid;
 | 
			
		||||
	buf->st_gid = node->i_stat.gid;
 | 
			
		||||
	buf->st_rdev = (dev_t) node->i_stat.dev;
 | 
			
		||||
	buf->st_size = node->i_stat.size;
 | 
			
		||||
 | 
			
		||||
	/* If it is a symbolic link, return the size of the link target. */
 | 
			
		||||
	if (S_ISLNK(node->i_stat.mode) && vtreefs_hooks->rdlink_hook != NULL) {
 | 
			
		||||
@ -40,34 +33,28 @@ int fs_stat(void)
 | 
			
		||||
			get_inode_cbdata(node));
 | 
			
		||||
 | 
			
		||||
		if (r == OK)
 | 
			
		||||
			statbuf.st_size = strlen(path);
 | 
			
		||||
			buf->st_size = strlen(path);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Take the current time as file time for all files. */
 | 
			
		||||
	cur_time = time(NULL);
 | 
			
		||||
	statbuf.st_atime = cur_time;
 | 
			
		||||
	statbuf.st_mtime = cur_time;
 | 
			
		||||
	statbuf.st_ctime = cur_time;
 | 
			
		||||
	buf->st_atime = cur_time;
 | 
			
		||||
	buf->st_mtime = cur_time;
 | 
			
		||||
	buf->st_ctime = cur_time;
 | 
			
		||||
 | 
			
		||||
	/* Copy the struct to user space. */
 | 
			
		||||
	return sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_stat.grant, 0,
 | 
			
		||||
		(vir_bytes) &statbuf, (phys_bytes) sizeof(statbuf));
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				fs_statvfs				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int fs_statvfs(void)
 | 
			
		||||
int fs_statvfs(struct statvfs *buf)
 | 
			
		||||
{
 | 
			
		||||
	/* Retrieve file system statistics.
 | 
			
		||||
	 */
 | 
			
		||||
	struct statvfs statvfs;
 | 
			
		||||
 | 
			
		||||
	memset(&statvfs, 0, sizeof(statvfs));
 | 
			
		||||
	buf->f_flag = ST_NOTRUNC;
 | 
			
		||||
	buf->f_namemax = PNAME_MAX;
 | 
			
		||||
 | 
			
		||||
	statvfs.f_flag = ST_NOTRUNC;
 | 
			
		||||
	statvfs.f_namemax = PNAME_MAX;
 | 
			
		||||
 | 
			
		||||
	return sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_statvfs.grant,
 | 
			
		||||
				0, (vir_bytes) &statvfs, sizeof(statvfs));
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3,43 +3,15 @@
 | 
			
		||||
#define _TABLE
 | 
			
		||||
#include "inc.h"
 | 
			
		||||
 | 
			
		||||
int (*fs_call_vec[])(void) = {
 | 
			
		||||
	no_sys,		/*  0			*/
 | 
			
		||||
	no_sys,		/*  1	getnode		*/
 | 
			
		||||
	fs_putnode,	/*  2	putnode		*/
 | 
			
		||||
	no_sys,         /*  3	slink		*/
 | 
			
		||||
	no_sys,		/*  4	ftrunc		*/
 | 
			
		||||
	no_sys,		/*  5	chown		*/
 | 
			
		||||
	no_sys,		/*  6	chmod		*/
 | 
			
		||||
	do_noop,	/*  7	inhibread	*/
 | 
			
		||||
	fs_stat,	/*  8	stat		*/
 | 
			
		||||
	no_sys,		/*  9	utime		*/
 | 
			
		||||
	fs_statvfs,	/* 10	statvfs		*/
 | 
			
		||||
	no_sys,		/* 11	bread		*/
 | 
			
		||||
	no_sys,		/* 12	bwrite		*/
 | 
			
		||||
	no_sys,		/* 13	unlink		*/
 | 
			
		||||
	no_sys,		/* 14	rmdir		*/
 | 
			
		||||
	fs_unmount,	/* 15	unmount		*/
 | 
			
		||||
	do_noop,	/* 16	sync		*/
 | 
			
		||||
	do_noop,	/* 17	new_driver	*/
 | 
			
		||||
	no_sys,		/* 18	flush		*/
 | 
			
		||||
	fs_read,	/* 19	read		*/
 | 
			
		||||
	no_sys,		/* 20	write		*/
 | 
			
		||||
	no_sys,		/* 21	mknod		*/
 | 
			
		||||
	no_sys,		/* 22	mkdir		*/
 | 
			
		||||
	no_sys,		/* 23	create		*/
 | 
			
		||||
	no_sys,		/* 24	link		*/
 | 
			
		||||
	no_sys,		/* 25	rename		*/
 | 
			
		||||
	fs_lookup,	/* 26	lookup		*/
 | 
			
		||||
	no_sys,		/* 27	mountpoint	*/
 | 
			
		||||
	fs_readsuper,	/* 28	readsuper	*/
 | 
			
		||||
	no_sys,		/* 29	newnode		*/
 | 
			
		||||
	fs_rdlink,	/* 30	rdlink		*/
 | 
			
		||||
	fs_getdents,	/* 31	getdents	*/
 | 
			
		||||
	no_sys,		/* 32   peek            */
 | 
			
		||||
	no_sys,		/* 33   bpeek           */
 | 
			
		||||
struct fsdriver vtreefs_table = {
 | 
			
		||||
	.fdr_mount	= fs_mount,
 | 
			
		||||
	.fdr_unmount	= fs_unmount,
 | 
			
		||||
	.fdr_lookup	= fs_lookup,
 | 
			
		||||
	.fdr_putnode	= fs_putnode,
 | 
			
		||||
	.fdr_read	= fs_read,
 | 
			
		||||
	.fdr_getdents	= fs_getdents,
 | 
			
		||||
	.fdr_rdlink	= fs_rdlink,
 | 
			
		||||
	.fdr_stat	= fs_stat,
 | 
			
		||||
	.fdr_statvfs	= fs_statvfs,
 | 
			
		||||
	.fdr_other	= fs_other
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* This should not fail with "array size is negative": */
 | 
			
		||||
extern int
 | 
			
		||||
	dummy[sizeof(fs_call_vec) == NREQS * sizeof(fs_call_vec[0]) ? 1 : -1];
 | 
			
		||||
 | 
			
		||||
@ -1,29 +0,0 @@
 | 
			
		||||
/* VTreeFS - utility.c - by Alen Stojanov and David van Moolenbroek */
 | 
			
		||||
 | 
			
		||||
#include "inc.h"
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				no_sys					     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int no_sys(void)
 | 
			
		||||
{
 | 
			
		||||
	/* This call is not recognized by VTreeFS. If a message hook is
 | 
			
		||||
	 * defined, let it handle the call; otherwise return ENOSYS.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if (vtreefs_hooks->message_hook != NULL)
 | 
			
		||||
		return vtreefs_hooks->message_hook(&fs_m_in);
 | 
			
		||||
 | 
			
		||||
	return ENOSYS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				do_noop					     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int do_noop(void)
 | 
			
		||||
{
 | 
			
		||||
	/* This call has no effect.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
@ -2,10 +2,6 @@
 | 
			
		||||
 | 
			
		||||
#include "inc.h"
 | 
			
		||||
 | 
			
		||||
static int get_work(void);
 | 
			
		||||
static void send_reply(int err, int transid);
 | 
			
		||||
static void got_signal(int signal);
 | 
			
		||||
 | 
			
		||||
static unsigned int inodes;
 | 
			
		||||
static struct inode_stat *root_stat;
 | 
			
		||||
static index_t root_entries;
 | 
			
		||||
@ -21,12 +17,23 @@ static int init_server(int UNUSED(type), sef_init_info_t *UNUSED(info))
 | 
			
		||||
	/* Initialize the virtual tree. */
 | 
			
		||||
	init_inodes(inodes, root_stat, root_entries);
 | 
			
		||||
 | 
			
		||||
	/* Do not yet allow any requests except REQ_READSUPER. */
 | 
			
		||||
	fs_mounted = FALSE;
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				got_signal				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
static void got_signal(int signal)
 | 
			
		||||
{
 | 
			
		||||
	/* We received a signal.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if (signal != SIGTERM)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	fsdriver_terminate();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				sef_local_startup			     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
@ -42,18 +49,36 @@ static void sef_local_startup(void)
 | 
			
		||||
	sef_startup();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				fs_other				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
void fs_other(const message *m_ptr, int __unused ipc_status)
 | 
			
		||||
{
 | 
			
		||||
	/* We received a message that is not among the recognized file system
 | 
			
		||||
	 * requests.  Call the message hook, if there is one.
 | 
			
		||||
	 */
 | 
			
		||||
	message msg;
 | 
			
		||||
 | 
			
		||||
	if (vtreefs_hooks->message_hook != NULL) {
 | 
			
		||||
		/* Not all of vtreefs's users play nice with the message, so
 | 
			
		||||
		 * make a copy to allow it to be modified.
 | 
			
		||||
		 */
 | 
			
		||||
		msg = *m_ptr;
 | 
			
		||||
 | 
			
		||||
		vtreefs_hooks->message_hook(&msg);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				start_vtreefs				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
void start_vtreefs(struct fs_hooks *hooks, unsigned int nr_inodes,
 | 
			
		||||
		struct inode_stat *stat, index_t nr_indexed_entries)
 | 
			
		||||
{
 | 
			
		||||
	/* This is the main routine of this service. The main loop consists of
 | 
			
		||||
	 * three major activities: getting new work, processing the work, and
 | 
			
		||||
	 * sending the reply. The loop exits when the process is signaled to
 | 
			
		||||
	 * exit; due to limitations of SEF, it can not return to the caller.
 | 
			
		||||
	/* This is the main routine of this service. It uses the main loop as
 | 
			
		||||
	 * provided by the fsdriver library. The routine returns once the file
 | 
			
		||||
	 * system has been unmounted and the process is signaled to exit.
 | 
			
		||||
	 */
 | 
			
		||||
	int call_nr, err, transid;
 | 
			
		||||
 | 
			
		||||
	/* Use global variables to work around the inability to pass parameters
 | 
			
		||||
	 * through SEF to the initialization function..
 | 
			
		||||
@ -65,95 +90,7 @@ void start_vtreefs(struct fs_hooks *hooks, unsigned int nr_inodes,
 | 
			
		||||
 | 
			
		||||
	sef_local_startup();
 | 
			
		||||
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		get_work();
 | 
			
		||||
 | 
			
		||||
		transid = TRNS_GET_ID(fs_m_in.m_type);
 | 
			
		||||
		fs_m_in.m_type = TRNS_DEL_ID(fs_m_in.m_type);
 | 
			
		||||
		if (fs_m_in.m_type == 0) {
 | 
			
		||||
			assert(!IS_VFS_FS_TRANSID(transid));
 | 
			
		||||
			fs_m_in.m_type = transid;	/* Backwards compat. */
 | 
			
		||||
			transid = 0;
 | 
			
		||||
		} else
 | 
			
		||||
			assert(IS_VFS_FS_TRANSID(transid));
 | 
			
		||||
 | 
			
		||||
		call_nr = fs_m_in.m_type;
 | 
			
		||||
 | 
			
		||||
		if (fs_m_in.m_source != VFS_PROC_NR) {
 | 
			
		||||
			if (vtreefs_hooks->message_hook != NULL) {
 | 
			
		||||
				/* If the request is not among the recognized
 | 
			
		||||
				 * requests, call the message hook.
 | 
			
		||||
				 */
 | 
			
		||||
				vtreefs_hooks->message_hook(&fs_m_in);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (fs_mounted || call_nr == REQ_READSUPER) {
 | 
			
		||||
			call_nr -= FS_BASE;
 | 
			
		||||
 | 
			
		||||
			if (call_nr >= 0 && call_nr < NREQS) {
 | 
			
		||||
				err = (*fs_call_vec[call_nr])();
 | 
			
		||||
			} else {
 | 
			
		||||
				err = ENOSYS;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else err = EINVAL;
 | 
			
		||||
 | 
			
		||||
		send_reply(err, transid);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				get_work				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
static int get_work(void)
 | 
			
		||||
{
 | 
			
		||||
	/* Retrieve work. Return the call number.
 | 
			
		||||
	 */
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if ((r = sef_receive(ANY, &fs_m_in)) != OK)
 | 
			
		||||
		panic("receive failed: %d", r);
 | 
			
		||||
 | 
			
		||||
	return fs_m_in.m_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				send_reply				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
static void send_reply(int err, int transid)
 | 
			
		||||
{
 | 
			
		||||
	/* Send a reply to the caller.
 | 
			
		||||
	 */
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	fs_m_out.m_type = err;
 | 
			
		||||
	if (IS_VFS_FS_TRANSID(transid)) {
 | 
			
		||||
		fs_m_out.m_type = TRNS_ADD_ID(fs_m_out.m_type, transid);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((r = ipc_send(fs_m_in.m_source, &fs_m_out)) != OK)
 | 
			
		||||
		panic("unable to send reply: %d", r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				got_signal				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
static void got_signal(int signal)
 | 
			
		||||
{
 | 
			
		||||
	/* We received a signal. If it is a termination signal, and the file
 | 
			
		||||
	 * system has already been unmounted, clean up and exit.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if (signal != SIGTERM)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (fs_mounted)
 | 
			
		||||
		return;
 | 
			
		||||
	fsdriver_task(&vtreefs_table);
 | 
			
		||||
 | 
			
		||||
	cleanup_inodes();
 | 
			
		||||
 | 
			
		||||
	exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
PROG =	devman
 | 
			
		||||
SRCS =  main.c device.c buf.c bind.c
 | 
			
		||||
 | 
			
		||||
DPADD+=	${LIBSYS} 
 | 
			
		||||
LDADD =  -lvtreefs -lsys 
 | 
			
		||||
DPADD+=	${LIBVTREEFS} ${LIBFSDRIVER} ${LIBSYS}
 | 
			
		||||
LDADD+=  -lvtreefs -lfsdriver -lsys
 | 
			
		||||
 | 
			
		||||
.include <minix.service.mk>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user