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
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>
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;
+# Makefile for libvtreefs
+
NOGCCERROR=yes
-NOCLANGERROR=yes
-CPPFLAGS+= -D_MINIX_SYSTEM
-# Makefile for libvtreefs
+CPPFLAGS+= -D_MINIX_SYSTEM
LIB= vtreefs
sdbm.c \
stadir.c \
table.c \
- utility.c \
vtreefs.c
.include <bsd.lib.mk>
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 */
-#define _SYSTEM 1 /* tell headers that this is the kernel */
+#include <minix/drivers.h>
+#include <minix/vtreefs.h>
+#include <minix/fsdriver.h>
-#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/vtreefs.h>
#include "glo.h"
#include "proto.h"
/* Initialize the inode-related state.
*/
struct inode *node;
- int i;
+ unsigned int i;
assert(inodes > 0);
assert(nr_indexed_entries >= 0);
/*===========================================================================*
* 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.
*/
*/
static int last_checked = 0;
struct inode *node;
- int count;
+ unsigned int count;
assert(TAILQ_EMPTY(&unused_inodes));
*/
CHECK_INODE(node);
- assert(node->i_count >= 0);
node->i_count++;
}
/*===========================================================================*
* 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.
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;
/* 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 */
/*===========================================================================*
* 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.
*/
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. */
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;
}
/* 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. */
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;
}
/*===========================================================================*
* fs_unmount *
*===========================================================================*/
-int fs_unmount(void)
+void fs_unmount(void)
{
/* Unmount the file system.
*/
/* 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;
}
#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;
-
- 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)
- 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 (path[len-1] != 0) return EINVAL;
-
- /* 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;
- }
+ struct inode *node, *child;
+ int r;
- /* Start the actual lookup. */
- if ((cur_ino = get_inode(dir_ino_nr)) == NULL)
+ if ((node = find_inode(dir_nr)) == NULL)
return EINVAL;
- /* Chroot'ed environment? */
- if (root_ino_nr > 0)
- root_ino = find_inode(root_ino_nr);
- else
- root_ino = NULL;
+ if (!S_ISDIR(node->i_stat.mode))
+ return ENOTDIR;
- 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;
+ if (strlen(name) > PNAME_MAX)
+ return ENAMETOOLONG;
- /* Get the next path component. The result is a non-empty
- * string.
+ 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 {
+ /* Progress into a directory entry. Call the lookup hook, if
+ * present, before doing the actual lookup.
*/
- 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);
- } 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.
- */
- 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;
- }
-
- ptr = path;
- continue;
- }
+ 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;
}
- if (r != OK)
- break;
-
- /* We have found a new file. Continue from this file. */
- assert(next_ino != NULL);
-
- put_inode(cur_ino);
-
- cur_ino = next_ino;
+ if ((child = get_inode_by_name(node, name)) == NULL)
+ return ENOENT;
}
- /* 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);
+ /* On success, open the resulting file and return its details. */
+ ref_inode(child);
- /* 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;
- }
+ 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;
- /* 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;
}
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 */
#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.
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;
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;
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);
}
#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) {
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));
- statvfs.f_flag = ST_NOTRUNC;
- statvfs.f_namemax = PNAME_MAX;
+ buf->f_flag = ST_NOTRUNC;
+ buf->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;
}
#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];
+++ /dev/null
-/* 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;
-}
#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;
/* 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 *
*===========================================================================*/
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..
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);
}
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>