libsffs: use libfsdriver
Change-Id: Id8377873455771c614371e115643cd906d05f12c
This commit is contained in:
parent
ebd3c0673d
commit
a99c939dee
20 changed files with 224 additions and 750 deletions
|
@ -2,7 +2,7 @@
|
||||||
PROG= hgfs
|
PROG= hgfs
|
||||||
SRCS= hgfs.c
|
SRCS= hgfs.c
|
||||||
|
|
||||||
DPADD+= ${LIBSFFS} ${LIBHGFS} ${LIBSYS}
|
DPADD+= ${LIBSFFS} ${LIBHGFS} ${LIBFSDRIVER} ${LIBSYS}
|
||||||
LDADD+= -lsffs -lhgfs -lsys
|
LDADD+= -lsffs -lhgfs -lfsdriver -lsys
|
||||||
|
|
||||||
.include <minix.service.mk>
|
.include <minix.service.mk>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
PROG= vbfs
|
PROG= vbfs
|
||||||
SRCS= vbfs.c
|
SRCS= vbfs.c
|
||||||
|
|
||||||
DPADD+= ${LIBSFFS} ${LIBVBOXFS} ${LIBSYS}
|
DPADD+= ${LIBSFFS} ${LIBVBOXFS} ${LIBFSDRIVER} ${LIBSYS}
|
||||||
LDADD+= -lsffs -lvboxfs -lsys
|
LDADD+= -lsffs -lvboxfs -lfsdriver -lsys
|
||||||
|
|
||||||
.include <minix.service.mk>
|
.include <minix.service.mk>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
NOGCCERROR=yes
|
|
||||||
NOCLANGERROR=yes
|
|
||||||
CPPFLAGS+= -D_MINIX_SYSTEM
|
|
||||||
|
|
||||||
# Makefile for libsffs
|
# Makefile for libsffs
|
||||||
.include <bsd.own.mk>
|
.include <bsd.own.mk>
|
||||||
|
|
||||||
|
NOGCCERROR=yes
|
||||||
|
|
||||||
|
CPPFLAGS+= -D_MINIX_SYSTEM
|
||||||
|
|
||||||
LIB= sffs
|
LIB= sffs
|
||||||
|
|
||||||
SRCS= dentry.c handle.c inode.c link.c lookup.c main.c misc.c mount.c \
|
SRCS= dentry.c handle.c inode.c link.c lookup.c main.c misc.c mount.c \
|
||||||
name.c path.c read.c stat.c table.c util.c verify.c write.c
|
name.c path.c read.c stat.c table.c verify.c write.c
|
||||||
|
|
||||||
.include <bsd.lib.mk>
|
.include <bsd.lib.mk>
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
static LIST_HEAD(hash_head, inode) hash_table[NUM_HASH_SLOTS];
|
static LIST_HEAD(hash_head, inode) hash_table[NUM_HASH_SLOTS];
|
||||||
|
|
||||||
static void del_one_dentry(struct inode *ino);
|
|
||||||
static unsigned int hash_dentry(struct inode *parent, char *name);
|
static unsigned int hash_dentry(struct inode *parent, char *name);
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
|
|
@ -10,10 +10,8 @@ EXTERN char *sffs_name; /* file server name */
|
||||||
EXTERN const struct sffs_table *sffs_table; /* call table */
|
EXTERN const struct sffs_table *sffs_table; /* call table */
|
||||||
EXTERN struct sffs_params *sffs_params; /* parameters */
|
EXTERN struct sffs_params *sffs_params; /* parameters */
|
||||||
|
|
||||||
EXTERN message m_in; /* request message */
|
|
||||||
EXTERN message m_out; /* reply message */
|
|
||||||
EXTERN struct state state; /* global state */
|
EXTERN struct state state; /* global state */
|
||||||
|
|
||||||
extern int(*call_vec[]) (void);
|
extern struct fsdriver sffs_dtable; /* driver table */
|
||||||
|
|
||||||
#endif /* _SFFS_GLO_H */
|
#endif /* _SFFS_GLO_H */
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define _SFFS_INC_H
|
#define _SFFS_INC_H
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
|
#include <minix/fsdriver.h>
|
||||||
#include <minix/vfsif.h>
|
#include <minix/vfsif.h>
|
||||||
#include <minix/optset.h>
|
#include <minix/optset.h>
|
||||||
#include <minix/sffs.h>
|
#include <minix/sffs.h>
|
||||||
|
|
|
@ -273,19 +273,16 @@ int have_used_inode(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_putnode *
|
* do_putnode *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_putnode(void)
|
int do_putnode(ino_t ino_nr, unsigned int count)
|
||||||
{
|
{
|
||||||
/* Decrease an inode's reference count.
|
/* Decrease an inode's reference count.
|
||||||
*/
|
*/
|
||||||
struct inode *ino;
|
struct inode *ino;
|
||||||
int count;
|
|
||||||
|
|
||||||
if ((ino = find_inode(m_in.m_vfs_fs_putnode.inode)) == NULL)
|
if ((ino = find_inode(ino_nr)) == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
count = m_in.m_vfs_fs_putnode.count;
|
if (count > ino->i_ref) return EINVAL;
|
||||||
|
|
||||||
if (count <= 0 || count > ino->i_ref) return EINVAL;
|
|
||||||
|
|
||||||
ino->i_ref -= count - 1;
|
ino->i_ref -= count - 1;
|
||||||
|
|
||||||
|
|
|
@ -15,16 +15,15 @@
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
static int force_remove(char *path, int dir);
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_create *
|
* do_create *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_create(void)
|
int do_create(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
|
||||||
|
struct fsdriver_node *node)
|
||||||
{
|
{
|
||||||
/* Create a new file.
|
/* Create a new file.
|
||||||
*/
|
*/
|
||||||
char path[PATH_MAX], name[NAME_MAX+1];
|
char path[PATH_MAX];
|
||||||
struct inode *parent, *ino;
|
struct inode *parent, *ino;
|
||||||
struct sffs_attr attr;
|
struct sffs_attr attr;
|
||||||
sffs_file_t handle;
|
sffs_file_t handle;
|
||||||
|
@ -34,13 +33,7 @@ int do_create(void)
|
||||||
if (state.s_read_only)
|
if (state.s_read_only)
|
||||||
return EROFS;
|
return EROFS;
|
||||||
|
|
||||||
/* Get path, name, parent inode and possibly inode for the given path. */
|
if ((parent = find_inode(dir_nr)) == NULL)
|
||||||
if ((r = get_name(m_in.m_vfs_fs_create.grant, m_in.m_vfs_fs_create.path_len, name)) != OK)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (!strcmp(name, ".") || !strcmp(name, "..")) return EEXIST;
|
|
||||||
|
|
||||||
if ((parent = find_inode(m_in.m_vfs_fs_create.inode)) == NULL)
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if ((r = verify_dentry(parent, name, path, &ino)) != OK)
|
if ((r = verify_dentry(parent, name, path, &ino)) != OK)
|
||||||
|
@ -59,8 +52,7 @@ int do_create(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform the actual create call. */
|
/* Perform the actual create call. */
|
||||||
r = sffs_table->t_open(path, O_CREAT | O_EXCL | O_RDWR, m_in.m_vfs_fs_create.mode,
|
r = sffs_table->t_open(path, O_CREAT | O_EXCL | O_RDWR, mode, &handle);
|
||||||
&handle);
|
|
||||||
|
|
||||||
if (r != OK) {
|
if (r != OK) {
|
||||||
/* Let's not try to be too clever with error codes here. If something
|
/* Let's not try to be too clever with error codes here. If something
|
||||||
|
@ -115,11 +107,12 @@ int do_create(void)
|
||||||
|
|
||||||
add_dentry(parent, name, ino);
|
add_dentry(parent, name, ino);
|
||||||
|
|
||||||
m_out.m_fs_vfs_create.inode = INODE_NR(ino);
|
node->fn_ino_nr = INODE_NR(ino);
|
||||||
m_out.m_fs_vfs_create.mode = get_mode(ino, attr.a_mode);
|
node->fn_mode = get_mode(ino, attr.a_mode);
|
||||||
m_out.m_fs_vfs_create.file_size = attr.a_size;
|
node->fn_size = attr.a_size;
|
||||||
m_out.m_fs_vfs_create.uid = sffs_params->p_uid;
|
node->fn_uid = sffs_params->p_uid;
|
||||||
m_out.m_fs_vfs_create.gid = sffs_params->p_gid;
|
node->fn_gid = sffs_params->p_gid;
|
||||||
|
node->fn_dev = NO_DEV;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -127,11 +120,11 @@ int do_create(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_mkdir *
|
* do_mkdir *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_mkdir(void)
|
int do_mkdir(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
/* Make a new directory.
|
/* Make a new directory.
|
||||||
*/
|
*/
|
||||||
char path[PATH_MAX], name[NAME_MAX+1];
|
char path[PATH_MAX];
|
||||||
struct inode *parent, *ino;
|
struct inode *parent, *ino;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -139,20 +132,14 @@ int do_mkdir(void)
|
||||||
if (state.s_read_only)
|
if (state.s_read_only)
|
||||||
return EROFS;
|
return EROFS;
|
||||||
|
|
||||||
/* Get the path string and possibly an inode for the given path. */
|
if ((parent = find_inode(dir_nr)) == NULL)
|
||||||
if ((r = get_name(m_in.m_vfs_fs_mkdir.grant, m_in.m_vfs_fs_mkdir.path_len, name)) != OK)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (!strcmp(name, ".") || !strcmp(name, "..")) return EEXIST;
|
|
||||||
|
|
||||||
if ((parent = find_inode(m_in.m_vfs_fs_mkdir.inode)) == NULL)
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if ((r = verify_dentry(parent, name, path, &ino)) != OK)
|
if ((r = verify_dentry(parent, name, path, &ino)) != OK)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* Perform the actual mkdir call. */
|
/* Perform the actual mkdir call. */
|
||||||
r = sffs_table->t_mkdir(path, m_in.m_vfs_fs_mkdir.mode);
|
r = sffs_table->t_mkdir(path, mode);
|
||||||
|
|
||||||
if (r != OK) {
|
if (r != OK) {
|
||||||
if (ino != NULL)
|
if (ino != NULL)
|
||||||
|
@ -232,11 +219,11 @@ static int force_remove(
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_unlink *
|
* do_unlink *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_unlink(void)
|
int do_unlink(ino_t dir_nr, char *name, int call)
|
||||||
{
|
{
|
||||||
/* Delete a file.
|
/* Delete a file.
|
||||||
*/
|
*/
|
||||||
char path[PATH_MAX], name[NAME_MAX+1];
|
char path[PATH_MAX];
|
||||||
struct inode *parent, *ino;
|
struct inode *parent, *ino;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -244,13 +231,7 @@ int do_unlink(void)
|
||||||
if (state.s_read_only)
|
if (state.s_read_only)
|
||||||
return EROFS;
|
return EROFS;
|
||||||
|
|
||||||
/* Get the path string and possibly preexisting inode for the given path. */
|
if ((parent = find_inode(dir_nr)) == NULL)
|
||||||
if ((r = get_name(m_in.m_vfs_fs_unlink.grant, m_in.m_vfs_fs_unlink.path_len, name)) != OK)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (!strcmp(name, ".") || !strcmp(name, "..")) return EPERM;
|
|
||||||
|
|
||||||
if ((parent = find_inode(m_in.m_vfs_fs_unlink.inode)) == NULL)
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if ((r = verify_dentry(parent, name, path, &ino)) != OK)
|
if ((r = verify_dentry(parent, name, path, &ino)) != OK)
|
||||||
|
@ -279,11 +260,11 @@ int do_unlink(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_rmdir *
|
* do_rmdir *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_rmdir(void)
|
int do_rmdir(ino_t dir_nr, char *name, int call)
|
||||||
{
|
{
|
||||||
/* Remove an empty directory.
|
/* Remove an empty directory.
|
||||||
*/
|
*/
|
||||||
char path[PATH_MAX], name[NAME_MAX+1];
|
char path[PATH_MAX];
|
||||||
struct inode *parent, *ino;
|
struct inode *parent, *ino;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -291,14 +272,7 @@ int do_rmdir(void)
|
||||||
if (state.s_read_only)
|
if (state.s_read_only)
|
||||||
return EROFS;
|
return EROFS;
|
||||||
|
|
||||||
/* Get the path string and possibly preexisting inode for the given path. */
|
if ((parent = find_inode(dir_nr)) == NULL)
|
||||||
if ((r = get_name(m_in.m_vfs_fs_unlink.grant, m_in.m_vfs_fs_unlink.path_len, name)) != OK)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (!strcmp(name, ".")) return EINVAL;
|
|
||||||
if (!strcmp(name, "..")) return ENOTEMPTY;
|
|
||||||
|
|
||||||
if ((parent = find_inode(m_in.m_vfs_fs_unlink.inode)) == NULL)
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if ((r = verify_dentry(parent, name, path, &ino)) != OK)
|
if ((r = verify_dentry(parent, name, path, &ino)) != OK)
|
||||||
|
@ -327,12 +301,12 @@ int do_rmdir(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_rename *
|
* do_rename *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_rename(void)
|
int do_rename(ino_t old_dir_nr, char *old_name, ino_t new_dir_nr,
|
||||||
|
char *new_name)
|
||||||
{
|
{
|
||||||
/* Rename a file or directory.
|
/* Rename a file or directory.
|
||||||
*/
|
*/
|
||||||
char old_path[PATH_MAX], new_path[PATH_MAX];
|
char old_path[PATH_MAX], new_path[PATH_MAX];
|
||||||
char old_name[NAME_MAX+1], new_name[NAME_MAX+1];
|
|
||||||
struct inode *old_parent, *new_parent;
|
struct inode *old_parent, *new_parent;
|
||||||
struct inode *old_ino, *new_ino;
|
struct inode *old_ino, *new_ino;
|
||||||
int r;
|
int r;
|
||||||
|
@ -341,20 +315,9 @@ int do_rename(void)
|
||||||
if (state.s_read_only)
|
if (state.s_read_only)
|
||||||
return EROFS;
|
return EROFS;
|
||||||
|
|
||||||
/* Get path strings, names, directory inodes and possibly preexisting inodes
|
/* Get possibly preexisting inodes for the old and new paths. */
|
||||||
* for the old and new paths.
|
if ((old_parent = find_inode(old_dir_nr)) == NULL ||
|
||||||
*/
|
(new_parent = find_inode(new_dir_nr)) == NULL)
|
||||||
if ((r = get_name(m_in.m_vfs_fs_rename.grant_old, m_in.m_vfs_fs_rename.len_old,
|
|
||||||
old_name)) != OK) return r;
|
|
||||||
|
|
||||||
if ((r = get_name(m_in.m_vfs_fs_rename.grant_new, m_in.m_vfs_fs_rename.len_new,
|
|
||||||
new_name)) != OK) return r;
|
|
||||||
|
|
||||||
if (!strcmp(old_name, ".") || !strcmp(old_name, "..") ||
|
|
||||||
!strcmp(new_name, ".") || !strcmp(new_name, "..")) return EINVAL;
|
|
||||||
|
|
||||||
if ((old_parent = find_inode(m_in.m_vfs_fs_rename.dir_old)) == NULL ||
|
|
||||||
(new_parent = find_inode(m_in.m_vfs_fs_rename.dir_new)) == NULL)
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if ((r = verify_dentry(old_parent, old_name, old_path, &old_ino)) != OK)
|
if ((r = verify_dentry(old_parent, old_name, old_path, &old_ino)) != OK)
|
||||||
|
|
|
@ -9,103 +9,6 @@
|
||||||
|
|
||||||
#include "inc.h"
|
#include "inc.h"
|
||||||
|
|
||||||
static int get_mask(vfs_ucred_t *ucred);
|
|
||||||
|
|
||||||
static int access_as_dir(struct inode *ino, struct sffs_attr *attr,
|
|
||||||
int uid, int mask);
|
|
||||||
|
|
||||||
static int next_name(char **ptr, char **start, char name[NAME_MAX+1]);
|
|
||||||
|
|
||||||
static int go_up(char path[PATH_MAX], struct inode *ino,
|
|
||||||
struct inode **res_ino, struct sffs_attr *attr);
|
|
||||||
|
|
||||||
static int go_down(char path[PATH_MAX], struct inode *ino, char *name,
|
|
||||||
struct inode **res_ino, struct sffs_attr *attr);
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* get_mask *
|
|
||||||
*===========================================================================*/
|
|
||||||
static int get_mask(
|
|
||||||
vfs_ucred_t *ucred /* credentials of the caller */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
/* Given the caller's credentials, precompute a search access mask to test
|
|
||||||
* against directory modes.
|
|
||||||
*/
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (ucred->vu_uid == sffs_params->p_uid) return S_IXUSR;
|
|
||||||
|
|
||||||
if (ucred->vu_gid == sffs_params->p_gid) return S_IXGRP;
|
|
||||||
|
|
||||||
for (i = 0; i < ucred->vu_ngroups; i++)
|
|
||||||
if (ucred->vu_sgroups[i] == sffs_params->p_gid) return S_IXGRP;
|
|
||||||
|
|
||||||
return S_IXOTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* access_as_dir *
|
|
||||||
*===========================================================================*/
|
|
||||||
static int access_as_dir(
|
|
||||||
struct inode *ino, /* the inode to test */
|
|
||||||
struct sffs_attr *attr, /* attributes of the inode */
|
|
||||||
int uid, /* UID of the caller */
|
|
||||||
int mask /* search access mask of the caller */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
/* Check whether the given inode may be accessed as directory.
|
|
||||||
* Return OK or an appropriate error code.
|
|
||||||
*/
|
|
||||||
mode_t mode;
|
|
||||||
|
|
||||||
assert(attr->a_mask & SFFS_ATTR_MODE);
|
|
||||||
|
|
||||||
/* The inode must be a directory to begin with. */
|
|
||||||
if (!IS_DIR(ino)) return ENOTDIR;
|
|
||||||
|
|
||||||
/* The caller must have search access to the directory. Root always does. */
|
|
||||||
if (uid == 0) return OK;
|
|
||||||
|
|
||||||
mode = get_mode(ino, attr->a_mode);
|
|
||||||
|
|
||||||
return (mode & mask) ? OK : EACCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* next_name *
|
|
||||||
*===========================================================================*/
|
|
||||||
static int next_name(
|
|
||||||
char **ptr, /* cursor pointer into path (in, out) */
|
|
||||||
char **start, /* place to store start of name */
|
|
||||||
char name[NAME_MAX+1] /* place to store name */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
/* 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 <= NAME_MAX; p++, i++)
|
|
||||||
name[i] = *p;
|
|
||||||
|
|
||||||
if (i > NAME_MAX)
|
|
||||||
return ENAMETOOLONG;
|
|
||||||
|
|
||||||
name[i] = 0;
|
|
||||||
} else {
|
|
||||||
strcpy(name, ".");
|
|
||||||
}
|
|
||||||
|
|
||||||
*ptr = p;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* go_up *
|
* go_up *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -199,142 +102,49 @@ static int go_down(
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_lookup *
|
* do_lookup *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_lookup(void)
|
int do_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
|
||||||
|
int *is_mountpt)
|
||||||
{
|
{
|
||||||
/* Resolve a path string to an inode.
|
/* Resolve a path string to an inode.
|
||||||
*/
|
*/
|
||||||
ino_t dir_ino_nr, root_ino_nr;
|
struct inode *dir_ino, *ino;
|
||||||
struct inode *cur_ino, *root_ino;
|
|
||||||
struct inode *next_ino = NULL;
|
|
||||||
struct sffs_attr attr;
|
struct sffs_attr attr;
|
||||||
char buf[PATH_MAX], path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
char name[NAME_MAX+1];
|
|
||||||
char *ptr, *last;
|
|
||||||
vfs_ucred_t ucred;
|
|
||||||
mode_t mask;
|
|
||||||
size_t len;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
dir_ino_nr = m_in.m_vfs_fs_lookup.dir_ino;
|
dprintf(("%s: lookup: got query for %"PRIu64", '%s'\n",
|
||||||
root_ino_nr = m_in.m_vfs_fs_lookup.root_ino;
|
sffs_name, dir_nr, name));
|
||||||
len = m_in.m_vfs_fs_lookup.path_len;
|
|
||||||
|
|
||||||
/* Fetch the path name. */
|
if ((dir_ino = find_inode(dir_nr)) == NULL)
|
||||||
if (len < 1 || len > PATH_MAX)
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
r = sys_safecopyfrom(m_in.m_source, m_in.m_vfs_fs_lookup.grant_path, 0,
|
|
||||||
(vir_bytes) buf, len);
|
|
||||||
|
|
||||||
if (r != OK)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (buf[len-1] != 0) {
|
|
||||||
printf("%s: VFS did not zero-terminate path!\n", sffs_name);
|
|
||||||
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fetch the credentials, and generate a search access mask to test against
|
|
||||||
* directory modes.
|
|
||||||
*/
|
|
||||||
if (m_in.m_vfs_fs_lookup.flags & PATH_GET_UCRED) {
|
|
||||||
if (m_in.m_vfs_fs_lookup.ucred_size != sizeof(ucred)) {
|
|
||||||
printf("%s: bad credential structure size\n", sffs_name);
|
|
||||||
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sys_safecopyfrom(m_in.m_source, m_in.m_vfs_fs_lookup.grant_ucred, 0,
|
|
||||||
(vir_bytes) &ucred, m_in.m_vfs_fs_lookup.ucred_size);
|
|
||||||
|
|
||||||
if (r != OK)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ucred.vu_uid = m_in.m_vfs_fs_lookup.uid;
|
|
||||||
ucred.vu_gid = m_in.m_vfs_fs_lookup.gid;
|
|
||||||
ucred.vu_ngroups = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mask = get_mask(&ucred);
|
|
||||||
|
|
||||||
/* Start the actual lookup. */
|
|
||||||
dprintf(("%s: lookup: got query '%s'\n", sffs_name, buf));
|
|
||||||
|
|
||||||
if ((cur_ino = find_inode(dir_ino_nr)) == NULL)
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
attr.a_mask = SFFS_ATTR_MODE | SFFS_ATTR_SIZE;
|
attr.a_mask = SFFS_ATTR_MODE | SFFS_ATTR_SIZE;
|
||||||
|
|
||||||
if ((r = verify_inode(cur_ino, path, &attr)) != OK)
|
if ((r = verify_inode(dir_ino, path, &attr)) != OK)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
get_inode(cur_ino);
|
if (!IS_DIR(dir_ino))
|
||||||
|
return ENOTDIR;
|
||||||
|
|
||||||
if (root_ino_nr > 0)
|
r = OK;
|
||||||
root_ino = find_inode(root_ino_nr);
|
if (!strcmp(name, "."))
|
||||||
|
get_inode(ino = dir_ino);
|
||||||
|
else if (!strcmp(name, ".."))
|
||||||
|
r = go_up(path, dir_ino, &ino, &attr);
|
||||||
else
|
else
|
||||||
root_ino = NULL;
|
r = go_down(path, dir_ino, name, &ino, &attr);
|
||||||
|
|
||||||
/* One possible optimization would be to check a path only right before the
|
|
||||||
* first ".." in a row, and at the very end (if still necessary). This would
|
|
||||||
* have consequences for inode validation, though.
|
|
||||||
*/
|
|
||||||
for (ptr = last = buf; *ptr != 0; ) {
|
|
||||||
if ((r = access_as_dir(cur_ino, &attr, ucred.vu_uid, mask)) != OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if ((r = next_name(&ptr, &last, name)) != OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
dprintf(("%s: lookup: next name '%s'\n", sffs_name, name));
|
|
||||||
|
|
||||||
if (!strcmp(name, ".") ||
|
|
||||||
(cur_ino == root_ino && !strcmp(name, "..")))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!strcmp(name, "..")) {
|
|
||||||
if (IS_ROOT(cur_ino))
|
|
||||||
r = ELEAVEMOUNT;
|
|
||||||
else
|
|
||||||
r = go_up(path, cur_ino, &next_ino, &attr);
|
|
||||||
} else {
|
|
||||||
r = go_down(path, cur_ino, name, &next_ino, &attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r != OK)
|
if (r != OK)
|
||||||
break;
|
|
||||||
|
|
||||||
assert(next_ino != NULL);
|
|
||||||
|
|
||||||
put_inode(cur_ino);
|
|
||||||
|
|
||||||
cur_ino = next_ino;
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf(("%s: lookup: result %d\n", sffs_name, r));
|
|
||||||
|
|
||||||
if (r != OK) {
|
|
||||||
put_inode(cur_ino);
|
|
||||||
|
|
||||||
/* We'd need support for these here. We don't have such support. */
|
|
||||||
assert(r != EENTERMOUNT && r != ESYMLINK);
|
|
||||||
|
|
||||||
if (r == ELEAVEMOUNT) {
|
|
||||||
m_out.m_fs_vfs_lookup.offset = (last - buf);
|
|
||||||
m_out.m_fs_vfs_lookup.symloop = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
|
||||||
|
|
||||||
m_out.m_fs_vfs_lookup.inode = INODE_NR(cur_ino);
|
node->fn_ino_nr = INODE_NR(ino);
|
||||||
m_out.m_fs_vfs_lookup.mode = get_mode(cur_ino, attr.a_mode);
|
node->fn_mode = get_mode(ino, attr.a_mode);
|
||||||
m_out.m_fs_vfs_lookup.file_size = attr.a_size;
|
node->fn_size = attr.a_size;
|
||||||
m_out.m_fs_vfs_lookup.uid = sffs_params->p_uid;
|
node->fn_uid = sffs_params->p_uid;
|
||||||
m_out.m_fs_vfs_lookup.gid = sffs_params->p_gid;
|
node->fn_gid = sffs_params->p_gid;
|
||||||
m_out.m_fs_vfs_lookup.device = NO_DEV;
|
node->fn_dev = NO_DEV;
|
||||||
|
|
||||||
|
*is_mountpt = FALSE;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,6 @@ int sffs_init(char *name, const struct sffs_table *table,
|
||||||
while (i > 0 && params->p_prefix[i - 1] == '/') i--;
|
while (i > 0 && params->p_prefix[i - 1] == '/') i--;
|
||||||
params->p_prefix[i] = 0;
|
params->p_prefix[i] = 0;
|
||||||
|
|
||||||
state.s_mounted = FALSE;
|
|
||||||
state.s_signaled = FALSE;
|
|
||||||
|
|
||||||
sffs_name = name;
|
sffs_name = name;
|
||||||
sffs_table = table;
|
sffs_table = table;
|
||||||
sffs_params = params;
|
sffs_params = params;
|
||||||
|
@ -45,62 +42,9 @@ void sffs_signal(int signo)
|
||||||
/* Only check for termination signal, ignore anything else. */
|
/* Only check for termination signal, ignore anything else. */
|
||||||
if (signo != SIGTERM) return;
|
if (signo != SIGTERM) return;
|
||||||
|
|
||||||
/* We can now terminate if we have also been unmounted. */
|
dprintf(("%s: got SIGTERM\n", sffs_name));
|
||||||
state.s_signaled = TRUE;
|
|
||||||
|
|
||||||
if (state.s_mounted) {
|
fsdriver_terminate();
|
||||||
dprintf(("%s: got SIGTERM, still mounted\n", sffs_name));
|
|
||||||
} else {
|
|
||||||
dprintf(("%s: got SIGTERM, shutting down\n", sffs_name));
|
|
||||||
|
|
||||||
/* Break out of the main loop, giving the main program the chance to
|
|
||||||
* perform further cleanup. This causes sef_receive() to return with
|
|
||||||
* an EINTR error code.
|
|
||||||
*/
|
|
||||||
sef_cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* get_work *
|
|
||||||
*===========================================================================*/
|
|
||||||
static int get_work(endpoint_t *who_e)
|
|
||||||
{
|
|
||||||
/* Receive a request message from VFS. Return TRUE if a new message is ready
|
|
||||||
* to be processed, or FALSE if sef_stop() was called from the signal handler.
|
|
||||||
*/
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if ((r = sef_receive(ANY, &m_in)) != OK) {
|
|
||||||
if (r != EINTR)
|
|
||||||
panic("receive failed: %d", r);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*who_e = m_in.m_source;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* send_reply *
|
|
||||||
*===========================================================================*/
|
|
||||||
static void send_reply(
|
|
||||||
int err, /* resulting error code */
|
|
||||||
int transid
|
|
||||||
)
|
|
||||||
{
|
|
||||||
/* Send a reply message to the requesting party, with the given error code.
|
|
||||||
*/
|
|
||||||
int r;
|
|
||||||
|
|
||||||
m_out.m_type = err;
|
|
||||||
if (IS_VFS_FS_TRANSID(transid)) {
|
|
||||||
/* If a transaction ID was set, reset it */
|
|
||||||
m_out.m_type = TRNS_ADD_ID(m_out.m_type, transid);
|
|
||||||
}
|
|
||||||
if ((r = ipc_send(m_in.m_source, &m_out)) != OK)
|
|
||||||
printf("%s: ipc_send failed (%d)\n", sffs_name, r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -108,47 +52,8 @@ static void send_reply(
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
void sffs_loop(void)
|
void sffs_loop(void)
|
||||||
{
|
{
|
||||||
/* The main function of this file server. After initializing, loop, receiving
|
/* The main function of this file server. Libfsdriver does the real work.
|
||||||
* one request from VFS at a time, processing it, and sending a reply back to
|
|
||||||
* VFS. Termination occurs when we both have been unmounted and have received
|
|
||||||
* a termination signal.
|
|
||||||
*/
|
*/
|
||||||
endpoint_t who_e;
|
|
||||||
int call_nr, err, transid;
|
|
||||||
|
|
||||||
while (state.s_mounted || !state.s_signaled) {
|
fsdriver_task(&sffs_dtable);
|
||||||
if (!get_work(&who_e))
|
|
||||||
continue; /* Recheck running conditions */
|
|
||||||
|
|
||||||
transid = TRNS_GET_ID(m_in.m_type);
|
|
||||||
m_in.m_type = TRNS_DEL_ID(m_in.m_type);
|
|
||||||
if (m_in.m_type == 0) {
|
|
||||||
assert(!IS_VFS_FS_TRANSID(transid));
|
|
||||||
m_in.m_type = transid; /* Backwards compat. */
|
|
||||||
transid = 0;
|
|
||||||
} else
|
|
||||||
assert(IS_VFS_FS_TRANSID(transid));
|
|
||||||
|
|
||||||
call_nr = m_in.m_type;
|
|
||||||
if (who_e != VFS_PROC_NR) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.s_mounted || call_nr == REQ_READSUPER) {
|
|
||||||
call_nr -= FS_BASE;
|
|
||||||
|
|
||||||
dprintf(("%s: call %d\n", sffs_name, call_nr));
|
|
||||||
|
|
||||||
if (call_nr >= 0 && call_nr < NREQS) {
|
|
||||||
err = (*call_vec[call_nr])();
|
|
||||||
} else {
|
|
||||||
err = ENOSYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf(("%s: call %d result %d\n", sffs_name, call_nr, err));
|
|
||||||
}
|
|
||||||
else err = EINVAL;
|
|
||||||
|
|
||||||
send_reply(err, transid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,10 @@
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_statvfs *
|
* do_statvfs *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_statvfs(void)
|
int do_statvfs(struct statvfs *statvfs)
|
||||||
{
|
{
|
||||||
/* Retrieve file system statistics.
|
/* Retrieve file system statistics.
|
||||||
*/
|
*/
|
||||||
struct statvfs statvfs;
|
|
||||||
struct inode *ino;
|
struct inode *ino;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
u64_t free, total;
|
u64_t free, total;
|
||||||
|
@ -38,20 +37,17 @@ int do_statvfs(void)
|
||||||
if ((r = sffs_table->t_queryvol(path, &free, &total)) != OK)
|
if ((r = sffs_table->t_queryvol(path, &free, &total)) != OK)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
memset(&statvfs, 0, sizeof(statvfs));
|
|
||||||
|
|
||||||
/* Returning zero for unknown values seems to be the convention. However, we
|
/* Returning zero for unknown values seems to be the convention. However, we
|
||||||
* do have to use a nonzero block size, even though it is entirely arbitrary.
|
* do have to use a nonzero block size, even though it is entirely arbitrary.
|
||||||
*/
|
*/
|
||||||
statvfs.f_flag = ST_NOTRUNC;
|
statvfs->f_flag = ST_NOTRUNC;
|
||||||
statvfs.f_bsize = BLOCK_SIZE;
|
statvfs->f_bsize = BLOCK_SIZE;
|
||||||
statvfs.f_frsize = BLOCK_SIZE;
|
statvfs->f_frsize = BLOCK_SIZE;
|
||||||
statvfs.f_iosize = BLOCK_SIZE;
|
statvfs->f_iosize = BLOCK_SIZE;
|
||||||
statvfs.f_blocks = (unsigned long)(total / BLOCK_SIZE);
|
statvfs->f_blocks = (fsblkcnt_t)(total / BLOCK_SIZE);
|
||||||
statvfs.f_bfree = (unsigned long)(free / BLOCK_SIZE);
|
statvfs->f_bfree = (fsblkcnt_t)(free / BLOCK_SIZE);
|
||||||
statvfs.f_bavail = statvfs.f_bfree;
|
statvfs->f_bavail = statvfs->f_bfree;
|
||||||
statvfs.f_namemax = NAME_MAX;
|
statvfs->f_namemax = NAME_MAX;
|
||||||
|
|
||||||
return sys_safecopyto(m_in.m_source, m_in.m_vfs_fs_statvfs.grant, 0,
|
return OK;
|
||||||
(vir_bytes) &statvfs, sizeof(statvfs));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* This file contains mount and unmount functionality.
|
/* This file contains mount and unmount functionality.
|
||||||
*
|
*
|
||||||
* The entry points into this file are:
|
* The entry points into this file are:
|
||||||
* do_readsuper perform the READSUPER file system call
|
* do_mount perform the READSUPER file system call
|
||||||
* do_unmount perform the UNMOUNT file system call
|
* do_unmount perform the UNMOUNT file system call
|
||||||
*
|
*
|
||||||
* Created:
|
* Created:
|
||||||
|
@ -11,9 +11,10 @@
|
||||||
#include "inc.h"
|
#include "inc.h"
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_readsuper *
|
* do_mount *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_readsuper(void)
|
int do_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node,
|
||||||
|
unsigned int *res_flags)
|
||||||
{
|
{
|
||||||
/* Mount the file system.
|
/* Mount the file system.
|
||||||
*/
|
*/
|
||||||
|
@ -22,17 +23,16 @@ int do_readsuper(void)
|
||||||
struct sffs_attr attr;
|
struct sffs_attr attr;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
dprintf(("%s: readsuper (dev %x, flags %x)\n",
|
dprintf(("%s: mount (dev %"PRIx64", flags %x)\n", sffs_name, dev, flags));
|
||||||
sffs_name, m_in.m_vfs_fs_readsuper.device, m_in.vfs_fs_readsuper.flags));
|
|
||||||
|
|
||||||
if (m_in.m_vfs_fs_readsuper.flags & REQ_ISROOT) {
|
if (flags & REQ_ISROOT) {
|
||||||
printf("%s: attempt to mount as root device\n", sffs_name);
|
printf("%s: attempt to mount as root device\n", sffs_name);
|
||||||
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.s_read_only = !!(m_in.m_vfs_fs_readsuper.flags & REQ_RDONLY);
|
state.s_read_only = !!(flags & REQ_RDONLY);
|
||||||
state.s_dev = m_in.m_vfs_fs_readsuper.device;
|
state.s_dev = dev;
|
||||||
|
|
||||||
init_dentry();
|
init_dentry();
|
||||||
ino = init_inode();
|
ino = init_inode();
|
||||||
|
@ -55,15 +55,14 @@ int do_readsuper(void)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_out.m_fs_vfs_readsuper.inode = INODE_NR(ino);
|
root_node->fn_ino_nr = INODE_NR(ino);
|
||||||
m_out.m_fs_vfs_readsuper.mode = get_mode(ino, attr.a_mode);
|
root_node->fn_mode = get_mode(ino, attr.a_mode);
|
||||||
m_out.m_fs_vfs_readsuper.file_size = attr.a_size;
|
root_node->fn_size = attr.a_size;
|
||||||
m_out.m_fs_vfs_readsuper.uid = sffs_params->p_uid;
|
root_node->fn_uid = sffs_params->p_uid;
|
||||||
m_out.m_fs_vfs_readsuper.gid = sffs_params->p_gid;
|
root_node->fn_gid = sffs_params->p_gid;
|
||||||
m_out.m_fs_vfs_readsuper.device = NO_DEV;
|
root_node->fn_dev = NO_DEV;
|
||||||
m_out.m_fs_vfs_readsuper.flags = RES_64BIT;
|
|
||||||
|
|
||||||
state.s_mounted = TRUE;
|
*res_flags = RES_64BIT;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -71,25 +70,21 @@ int do_readsuper(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_unmount *
|
* do_unmount *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_unmount(void)
|
void do_unmount(void)
|
||||||
{
|
{
|
||||||
/* Unmount the file system.
|
/* Unmount the file system.
|
||||||
*/
|
*/
|
||||||
struct inode *ino;
|
struct inode *ino;
|
||||||
|
|
||||||
dprintf(("%s: do_unmount\n", sffs_name));
|
dprintf(("%s: unmount\n", sffs_name));
|
||||||
|
|
||||||
/* Decrease the reference count of the root inode. */
|
/* Decrease the reference count of the root inode. */
|
||||||
if ((ino = find_inode(ROOT_INODE_NR)) == NULL)
|
if ((ino = find_inode(ROOT_INODE_NR)) == NULL)
|
||||||
return EINVAL;
|
return;
|
||||||
|
|
||||||
put_inode(ino);
|
put_inode(ino);
|
||||||
|
|
||||||
/* There should not be any referenced inodes anymore now. */
|
/* There should not be any referenced inodes anymore now. */
|
||||||
if (have_used_inode())
|
if (have_used_inode())
|
||||||
printf("%s: in-use inodes left at unmount time!\n", sffs_name);
|
printf("%s: in-use inodes left at unmount time!\n", sffs_name);
|
||||||
|
|
||||||
state.s_mounted = FALSE;
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ void normalize_name(char dst[NAME_MAX+1], char *src)
|
||||||
|
|
||||||
if (sffs_params->p_case_insens) {
|
if (sffs_params->p_case_insens) {
|
||||||
for (i = 0; i < size; i++)
|
for (i = 0; i < size; i++)
|
||||||
*dst++ = tolower(*src++);
|
*dst++ = tolower((int)*src++);
|
||||||
}
|
}
|
||||||
else memcpy(dst, src, size);
|
else memcpy(dst, src, size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,27 +21,31 @@ void unlink_inode(struct inode *ino);
|
||||||
struct inode *get_free_inode(void);
|
struct inode *get_free_inode(void);
|
||||||
int have_free_inode(void);
|
int have_free_inode(void);
|
||||||
int have_used_inode(void);
|
int have_used_inode(void);
|
||||||
int do_putnode(void);
|
int do_putnode(ino_t ino_nr, unsigned int count);
|
||||||
|
|
||||||
/* link.c */
|
/* link.c */
|
||||||
int do_create(void);
|
int do_create(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
|
||||||
int do_mkdir(void);
|
struct fsdriver_node *node);
|
||||||
int do_unlink(void);
|
int do_mkdir(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid);
|
||||||
int do_rmdir(void);
|
int do_unlink(ino_t dir_nr, char *name, int call);
|
||||||
int do_rename(void);
|
int do_rmdir(ino_t dir_nr, char *name, int call);
|
||||||
|
int do_rename(ino_t old_dir_nr, char *old_name, ino_t new_dir_nr,
|
||||||
|
char *new_name);
|
||||||
|
|
||||||
/* lookup.c */
|
/* lookup.c */
|
||||||
int do_lookup(void);
|
int do_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
|
||||||
|
int *is_mountpt);
|
||||||
|
|
||||||
/* main.c */
|
/* main.c */
|
||||||
int main(int argc, char *argv[]);
|
int main(int argc, char *argv[]);
|
||||||
|
|
||||||
/* misc.c */
|
/* misc.c */
|
||||||
int do_statvfs(void);
|
int do_statvfs(struct statvfs *statvfs);
|
||||||
|
|
||||||
/* mount.c */
|
/* mount.c */
|
||||||
int do_readsuper(void);
|
int do_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node,
|
||||||
int do_unmount(void);
|
unsigned int *res_flags);
|
||||||
|
void do_unmount(void);
|
||||||
|
|
||||||
/* name.c */
|
/* name.c */
|
||||||
void normalize_name(char dst[NAME_MAX+1], char *src);
|
void normalize_name(char dst[NAME_MAX+1], char *src);
|
||||||
|
@ -53,19 +57,16 @@ int push_path(char path[PATH_MAX], char *name);
|
||||||
void pop_path(char path[PATH_MAX]);
|
void pop_path(char path[PATH_MAX]);
|
||||||
|
|
||||||
/* read.c */
|
/* read.c */
|
||||||
int do_read(void);
|
ssize_t do_read(ino_t ino_nr, struct fsdriver_data *data, size_t count,
|
||||||
int do_getdents(void);
|
off_t pos, int call);
|
||||||
|
ssize_t do_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
|
||||||
|
off_t *pos);
|
||||||
|
|
||||||
/* stat.c */
|
/* stat.c */
|
||||||
mode_t get_mode(struct inode *ino, int mode);
|
mode_t get_mode(struct inode *ino, int mode);
|
||||||
int do_stat(void);
|
int do_stat(ino_t ino_nr, struct stat *stat);
|
||||||
int do_chmod(void);
|
int do_chmod(ino_t ino_nr, mode_t *mode);
|
||||||
int do_utime(void);
|
int do_utime(ino_t ino_nr, struct timespec *atime, struct timespec *mtime);
|
||||||
|
|
||||||
/* util.c */
|
|
||||||
int get_name(cp_grant_id_t grant, size_t len, char name[NAME_MAX+1]);
|
|
||||||
int do_noop(void);
|
|
||||||
int no_sys(void);
|
|
||||||
|
|
||||||
/* verify.c */
|
/* verify.c */
|
||||||
int verify_path(char *path, struct inode *ino, struct sffs_attr *attr,
|
int verify_path(char *path, struct inode *ino, struct sffs_attr *attr,
|
||||||
|
@ -76,7 +77,8 @@ int verify_dentry(struct inode *parent, char name[NAME_MAX+1],
|
||||||
char path[PATH_MAX], struct inode **res_ino);
|
char path[PATH_MAX], struct inode **res_ino);
|
||||||
|
|
||||||
/* write.c */
|
/* write.c */
|
||||||
int do_write(void);
|
ssize_t do_write(ino_t ino_nr, struct fsdriver_data *data, size_t count,
|
||||||
int do_ftrunc(void);
|
off_t pos, int call);
|
||||||
|
int do_trunc(ino_t ino_nr, off_t start, off_t end);
|
||||||
|
|
||||||
#endif /* _SFFS_PROTO_H */
|
#endif /* _SFFS_PROTO_H */
|
||||||
|
|
|
@ -12,23 +12,20 @@
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
#define DWORD_ALIGN(len) (((len) + sizeof(long) - 1) & ~(sizeof(long) - 1))
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_read *
|
* do_read *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_read(void)
|
ssize_t do_read(ino_t ino_nr, struct fsdriver_data *data, size_t count,
|
||||||
|
off_t pos, int call)
|
||||||
{
|
{
|
||||||
/* Read data from a file.
|
/* Read data from a file.
|
||||||
*/
|
*/
|
||||||
struct inode *ino;
|
struct inode *ino;
|
||||||
off_t pos;
|
size_t size, off;
|
||||||
size_t count, size;
|
|
||||||
vir_bytes off;
|
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int r, chunk;
|
int r, chunk;
|
||||||
|
|
||||||
if ((ino = find_inode(m_in.m_vfs_fs_readwrite.inode)) == NULL)
|
if ((ino = find_inode(ino_nr)) == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if (IS_DIR(ino)) return EISDIR;
|
if (IS_DIR(ino)) return EISDIR;
|
||||||
|
@ -36,9 +33,6 @@ int do_read(void)
|
||||||
if ((r = get_handle(ino)) != OK)
|
if ((r = get_handle(ino)) != OK)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
pos = m_in.m_vfs_fs_readwrite.seek_pos;
|
|
||||||
count = m_in.m_vfs_fs_readwrite.nbytes;
|
|
||||||
|
|
||||||
assert(count > 0);
|
assert(count > 0);
|
||||||
|
|
||||||
/* Use the buffer from below to eliminate extra copying. */
|
/* Use the buffer from below to eliminate extra copying. */
|
||||||
|
@ -53,10 +47,7 @@ int do_read(void)
|
||||||
|
|
||||||
chunk = r;
|
chunk = r;
|
||||||
|
|
||||||
r = sys_safecopyto(m_in.m_source, m_in.m_vfs_fs_readwrite.grant, off,
|
if ((r = fsdriver_copyout(data, off, ptr, chunk)) != OK)
|
||||||
(vir_bytes) ptr, chunk);
|
|
||||||
|
|
||||||
if (r != OK)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
count -= chunk;
|
count -= chunk;
|
||||||
|
@ -67,38 +58,33 @@ int do_read(void)
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
m_out.m_fs_vfs_readwrite.seek_pos = pos;
|
return off;
|
||||||
m_out.m_fs_vfs_readwrite.nbytes = off;
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_getdents *
|
* do_getdents *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_getdents(void)
|
ssize_t do_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
|
||||||
|
off_t *posp)
|
||||||
{
|
{
|
||||||
/* Retrieve directory entries.
|
/* Retrieve directory entries.
|
||||||
*/
|
*/
|
||||||
|
struct fsdriver_dentry fsdentry;
|
||||||
char name[NAME_MAX+1];
|
char name[NAME_MAX+1];
|
||||||
struct inode *ino, *child;
|
struct inode *ino, *child;
|
||||||
struct dirent *dent;
|
|
||||||
struct sffs_attr attr;
|
struct sffs_attr attr;
|
||||||
size_t len, off, user_off, user_left;
|
|
||||||
off_t pos;
|
off_t pos;
|
||||||
int r, namelen;
|
int r;
|
||||||
/* must be at least sizeof(struct dirent) + NAME_MAX */
|
/* must be at least sizeof(struct dirent) + NAME_MAX */
|
||||||
static char buf[BLOCK_SIZE];
|
static char buf[BLOCK_SIZE];
|
||||||
|
|
||||||
attr.a_mask = SFFS_ATTR_MODE;
|
if ((ino = find_inode(ino_nr)) == NULL)
|
||||||
|
|
||||||
if ((ino = find_inode(m_in.m_vfs_fs_getdents.inode)) == NULL)
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if(m_in.m_vfs_fs_getdents.seek_pos >= ULONG_MAX) return EINVAL;
|
|
||||||
|
|
||||||
if (!IS_DIR(ino)) return ENOTDIR;
|
if (!IS_DIR(ino)) return ENOTDIR;
|
||||||
|
|
||||||
|
if (*posp < 0 || *posp >= ULONG_MAX) return EINVAL;
|
||||||
|
|
||||||
/* We are going to need at least one free inode to store children in. */
|
/* We are going to need at least one free inode to store children in. */
|
||||||
if (!have_free_inode()) return ENFILE;
|
if (!have_free_inode()) return ENFILE;
|
||||||
|
|
||||||
|
@ -106,19 +92,19 @@ int do_getdents(void)
|
||||||
if ((r = get_handle(ino)) != OK)
|
if ((r = get_handle(ino)) != OK)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
off = 0;
|
fsdriver_dentry_init(&fsdentry, data, bytes, buf, sizeof(buf));
|
||||||
user_off = 0;
|
|
||||||
user_left = m_in.m_vfs_fs_getdents.mem_size;
|
|
||||||
|
|
||||||
/* We use the seek position as file index number. The first position is for
|
/* We use the seek position as file index number. The first position is for
|
||||||
* the "." entry, the second position is for the ".." entry, and the next
|
* the "." entry, the second position is for the ".." entry, and the next
|
||||||
* position numbers each represent a file in the directory.
|
* position numbers each represent a file in the directory.
|
||||||
*/
|
*/
|
||||||
for (pos = m_in.m_vfs_fs_getdents.seek_pos; ; pos++) {
|
do {
|
||||||
/* Determine which inode and name to use for this entry.
|
/* Determine which inode and name to use for this entry.
|
||||||
* We have no idea whether the host will give us "." and/or "..",
|
* We have no idea whether the host will give us "." and/or "..",
|
||||||
* so generate our own and skip those from the host.
|
* so generate our own and skip those from the host.
|
||||||
*/
|
*/
|
||||||
|
pos = (*posp)++;
|
||||||
|
|
||||||
if (pos == 0) {
|
if (pos == 0) {
|
||||||
/* Entry for ".". */
|
/* Entry for ".". */
|
||||||
child = ino;
|
child = ino;
|
||||||
|
@ -140,6 +126,8 @@ int do_getdents(void)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Any other entry, not being "." or "..". */
|
/* Any other entry, not being "." or "..". */
|
||||||
|
attr.a_mask = SFFS_ATTR_MODE;
|
||||||
|
|
||||||
r = sffs_table->t_readdir(ino->i_dir, pos - 2, name,
|
r = sffs_table->t_readdir(ino->i_dir, pos - 2, name,
|
||||||
sizeof(name), &attr);
|
sizeof(name), &attr);
|
||||||
|
|
||||||
|
@ -170,66 +158,14 @@ int do_getdents(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* record length incl. alignment. */
|
r = fsdriver_dentry_add(&fsdentry, INODE_NR(child), name, strlen(name),
|
||||||
namelen = strlen(name);
|
IS_DIR(child) ? DT_DIR : DT_REG);
|
||||||
len = _DIRENT_RECLEN(dent, namelen);
|
|
||||||
|
|
||||||
/* Is the user buffer too small to store another record?
|
|
||||||
* Note that we will be rerequesting the same dentry upon a subsequent
|
|
||||||
* getdents call this way, but we really need the name length for this.
|
|
||||||
*/
|
|
||||||
if (user_off + off + len > user_left) {
|
|
||||||
put_inode(child);
|
|
||||||
|
|
||||||
/* 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(m_in.m_source, m_in.m_vfs_fs_getdents.grant,
|
|
||||||
user_off, (vir_bytes) buf, off);
|
|
||||||
|
|
||||||
if (r != OK) {
|
|
||||||
put_inode(child);
|
put_inode(child);
|
||||||
|
|
||||||
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
} while (r > 0);
|
||||||
|
|
||||||
user_off += off;
|
return fsdriver_dentry_finish(&fsdentry);
|
||||||
user_left -= off;
|
|
||||||
off = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fill in the actual directory entry. */
|
|
||||||
dent = (struct dirent *) &buf[off];
|
|
||||||
dent->d_ino = INODE_NR(child);
|
|
||||||
dent->d_reclen = len;
|
|
||||||
dent->d_namlen = namelen;
|
|
||||||
dent->d_type = IS_DIR(child) ? DT_DIR : DT_REG;
|
|
||||||
strcpy(dent->d_name, name);
|
|
||||||
|
|
||||||
off += len;
|
|
||||||
|
|
||||||
put_inode(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there is anything left in our own buffer, copy that out now. */
|
|
||||||
if (off > 0) {
|
|
||||||
r = sys_safecopyto(m_in.m_source, m_in.m_vfs_fs_getdents.grant, user_off,
|
|
||||||
(vir_bytes) buf, off);
|
|
||||||
|
|
||||||
if (r != OK)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
user_off += off;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_out.m_fs_vfs_getdents.seek_pos = pos;
|
|
||||||
m_out.m_fs_vfs_getdents.nbytes = user_off;
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,19 +37,15 @@ mode_t get_mode(struct inode *ino, int mode)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_stat *
|
* do_stat *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_stat(void)
|
int do_stat(ino_t ino_nr, struct stat *stat)
|
||||||
{
|
{
|
||||||
/* Retrieve inode status.
|
/* Retrieve inode status.
|
||||||
*/
|
*/
|
||||||
struct inode *ino;
|
struct inode *ino;
|
||||||
struct sffs_attr attr;
|
struct sffs_attr attr;
|
||||||
struct stat stat;
|
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
ino_t ino_nr;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
ino_nr = m_in.m_vfs_fs_stat.inode;
|
|
||||||
|
|
||||||
/* Don't increase the inode refcount: it's already open anyway */
|
/* Don't increase the inode refcount: it's already open anyway */
|
||||||
if ((ino = find_inode(ino_nr)) == NULL)
|
if ((ino = find_inode(ino_nr)) == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
@ -60,45 +56,42 @@ int do_stat(void)
|
||||||
if ((r = verify_inode(ino, path, &attr)) != OK)
|
if ((r = verify_inode(ino, path, &attr)) != OK)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
memset(&stat, 0, sizeof(struct stat));
|
stat->st_dev = state.s_dev;
|
||||||
|
stat->st_ino = ino_nr;
|
||||||
|
stat->st_mode = get_mode(ino, attr.a_mode);
|
||||||
|
stat->st_uid = sffs_params->p_uid;
|
||||||
|
stat->st_gid = sffs_params->p_gid;
|
||||||
|
stat->st_rdev = NO_DEV;
|
||||||
|
stat->st_size = attr.a_size;
|
||||||
|
stat->st_atimespec = attr.a_atime;
|
||||||
|
stat->st_mtimespec = attr.a_mtime;
|
||||||
|
stat->st_ctimespec = attr.a_ctime;
|
||||||
|
stat->st_birthtimespec = attr.a_crtime;
|
||||||
|
|
||||||
stat.st_dev = state.s_dev;
|
stat->st_blocks = stat->st_size / S_BLKSIZE;
|
||||||
stat.st_ino = ino_nr;
|
if (stat->st_size % S_BLKSIZE != 0)
|
||||||
stat.st_mode = get_mode(ino, attr.a_mode);
|
stat->st_blocks += 1;
|
||||||
stat.st_uid = sffs_params->p_uid;
|
|
||||||
stat.st_gid = sffs_params->p_gid;
|
|
||||||
stat.st_rdev = NO_DEV;
|
|
||||||
stat.st_size = attr.a_size;
|
|
||||||
stat.st_atimespec = attr.a_atime;
|
|
||||||
stat.st_mtimespec = attr.a_mtime;
|
|
||||||
stat.st_ctimespec = attr.a_ctime;
|
|
||||||
stat.st_birthtimespec = attr.a_crtime;
|
|
||||||
|
|
||||||
stat.st_blocks = stat.st_size / S_BLKSIZE;
|
stat->st_blksize = BLOCK_SIZE;
|
||||||
if (stat.st_size % S_BLKSIZE != 0)
|
|
||||||
stat.st_blocks += 1;
|
|
||||||
|
|
||||||
stat.st_blksize = BLOCK_SIZE;
|
|
||||||
|
|
||||||
/* We could make this more accurate by iterating over directory inodes'
|
/* We could make this more accurate by iterating over directory inodes'
|
||||||
* children, counting how many of those are directories as well.
|
* children, counting how many of those are directories as well.
|
||||||
* It's just not worth it.
|
* It's just not worth it.
|
||||||
*/
|
*/
|
||||||
stat.st_nlink = 0;
|
stat->st_nlink = 0;
|
||||||
if (ino->i_parent != NULL) stat.st_nlink++;
|
if (ino->i_parent != NULL) stat->st_nlink++;
|
||||||
if (IS_DIR(ino)) {
|
if (IS_DIR(ino)) {
|
||||||
stat.st_nlink++;
|
stat->st_nlink++;
|
||||||
if (HAS_CHILDREN(ino)) stat.st_nlink++;
|
if (HAS_CHILDREN(ino)) stat->st_nlink++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sys_safecopyto(m_in.m_source, m_in.m_vfs_fs_stat.grant, 0,
|
return OK;
|
||||||
(vir_bytes) &stat, sizeof(stat));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_chmod *
|
* do_chmod *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_chmod(void)
|
int do_chmod(ino_t ino_nr, mode_t *mode)
|
||||||
{
|
{
|
||||||
/* Change file mode.
|
/* Change file mode.
|
||||||
*/
|
*/
|
||||||
|
@ -110,7 +103,7 @@ int do_chmod(void)
|
||||||
if (state.s_read_only)
|
if (state.s_read_only)
|
||||||
return EROFS;
|
return EROFS;
|
||||||
|
|
||||||
if ((ino = find_inode(m_in.m_vfs_fs_chmod.inode)) == NULL)
|
if ((ino = find_inode(ino_nr)) == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if ((r = verify_inode(ino, path, NULL)) != OK)
|
if ((r = verify_inode(ino, path, NULL)) != OK)
|
||||||
|
@ -118,7 +111,7 @@ int do_chmod(void)
|
||||||
|
|
||||||
/* Set the new file mode. */
|
/* Set the new file mode. */
|
||||||
attr.a_mask = SFFS_ATTR_MODE;
|
attr.a_mask = SFFS_ATTR_MODE;
|
||||||
attr.a_mode = m_in.m_vfs_fs_chmod.mode; /* no need to convert in this direction */
|
attr.a_mode = *mode; /* no need to convert in this direction */
|
||||||
|
|
||||||
if ((r = sffs_table->t_setattr(path, &attr)) != OK)
|
if ((r = sffs_table->t_setattr(path, &attr)) != OK)
|
||||||
return r;
|
return r;
|
||||||
|
@ -127,7 +120,7 @@ int do_chmod(void)
|
||||||
if ((r = verify_path(path, ino, &attr, NULL)) != OK)
|
if ((r = verify_path(path, ino, &attr, NULL)) != OK)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
m_out.m_fs_vfs_chmod.mode = get_mode(ino, attr.a_mode);
|
*mode = get_mode(ino, attr.a_mode);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -135,7 +128,7 @@ int do_chmod(void)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_utime *
|
* do_utime *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_utime(void)
|
int do_utime(ino_t ino_nr, struct timespec *atime, struct timespec *mtime)
|
||||||
{
|
{
|
||||||
/* Set file times.
|
/* Set file times.
|
||||||
*/
|
*/
|
||||||
|
@ -147,7 +140,7 @@ int do_utime(void)
|
||||||
if (state.s_read_only)
|
if (state.s_read_only)
|
||||||
return EROFS;
|
return EROFS;
|
||||||
|
|
||||||
if ((ino = find_inode(m_in.m_vfs_fs_utime.inode)) == NULL)
|
if ((ino = find_inode(ino_nr)) == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if ((r = verify_inode(ino, path, NULL)) != OK)
|
if ((r = verify_inode(ino, path, NULL)) != OK)
|
||||||
|
@ -155,37 +148,31 @@ int do_utime(void)
|
||||||
|
|
||||||
attr.a_mask = 0;
|
attr.a_mask = 0;
|
||||||
|
|
||||||
switch(m_in.m_vfs_fs_utime.acnsec) {
|
switch (atime->tv_nsec) {
|
||||||
case UTIME_OMIT: /* do not touch */
|
case UTIME_OMIT: /* do not touch */
|
||||||
break;
|
break;
|
||||||
case UTIME_NOW:
|
case UTIME_NOW:
|
||||||
/* XXX VFS should have time() into ACTIME, for compat; we trust it! */
|
/* XXX VFS should have time() into ACTIME, for compat; we trust it! */
|
||||||
m_in.m_vfs_fs_utime.acnsec = 0;
|
atime->tv_nsec = 0;
|
||||||
/*FALLTHROUGH*/
|
/*FALLTHROUGH*/
|
||||||
default:
|
default:
|
||||||
/* cases m_in.m_vfs_fs_utime.acnsec < 0 || m_in.m_vfs_fs_utime.acnsec >= 1E9
|
attr.a_atime = *atime;
|
||||||
* are caught by VFS to cooperate with old instances of EXT2
|
|
||||||
*/
|
|
||||||
attr.a_atime.tv_sec = m_in.m_vfs_fs_utime.actime;
|
|
||||||
attr.a_atime.tv_nsec = m_in.m_vfs_fs_utime.acnsec;
|
|
||||||
attr.a_mask |= SFFS_ATTR_ATIME;
|
attr.a_mask |= SFFS_ATTR_ATIME;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch(m_in.m_vfs_fs_utime.modnsec) {
|
|
||||||
|
switch (mtime->tv_nsec) {
|
||||||
case UTIME_OMIT: /* do not touch */
|
case UTIME_OMIT: /* do not touch */
|
||||||
break;
|
break;
|
||||||
case UTIME_NOW:
|
case UTIME_NOW:
|
||||||
/* XXX VFS should have time() into MODTIME, for compat; we trust it! */
|
/* XXX VFS should have time() into MODTIME, for compat; we trust it! */
|
||||||
m_in.m_vfs_fs_utime.modnsec = 0;
|
mtime->tv_nsec = 0;
|
||||||
/*FALLTHROUGH*/
|
/*FALLTHROUGH*/
|
||||||
default:
|
default:
|
||||||
/* cases m_in.m_vfs_fs_utime.modnsec < 0 || m_in.m_vfs_fs_utime.modnsec >= 1E9
|
attr.a_mtime = *mtime;
|
||||||
* are caught by VFS to cooperate with old instances
|
|
||||||
*/
|
|
||||||
attr.a_mtime.tv_sec = m_in.m_vfs_fs_utime.modtime;
|
|
||||||
attr.a_mtime.tv_nsec = m_in.m_vfs_fs_utime.modnsec;
|
|
||||||
attr.a_mask |= SFFS_ATTR_MTIME;
|
attr.a_mask |= SFFS_ATTR_MTIME;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sffs_table->t_setattr(path, &attr);
|
return sffs_table->t_setattr(path, &attr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,42 +7,22 @@
|
||||||
#define _TABLE
|
#define _TABLE
|
||||||
#include "inc.h"
|
#include "inc.h"
|
||||||
|
|
||||||
int (*call_vec[])(void) = {
|
struct fsdriver sffs_dtable = {
|
||||||
no_sys, /* 0 */
|
.fdr_mount = do_mount,
|
||||||
no_sys, /* 1 getnode */
|
.fdr_unmount = do_unmount,
|
||||||
do_putnode, /* 2 putnode */
|
.fdr_lookup = do_lookup,
|
||||||
no_sys, /* 3 slink */
|
.fdr_putnode = do_putnode,
|
||||||
do_ftrunc, /* 4 ftrunc */
|
.fdr_read = do_read,
|
||||||
no_sys, /* 5 chown */
|
.fdr_write = do_write,
|
||||||
do_chmod, /* 6 chmod */
|
.fdr_getdents = do_getdents,
|
||||||
do_noop, /* 7 inhibread */
|
.fdr_trunc = do_trunc,
|
||||||
do_stat, /* 8 stat */
|
.fdr_create = do_create,
|
||||||
do_utime, /* 9 utime */
|
.fdr_mkdir = do_mkdir,
|
||||||
do_statvfs, /* 10 statvfs */
|
.fdr_unlink = do_unlink,
|
||||||
no_sys, /* 11 bread */
|
.fdr_rmdir = do_rmdir,
|
||||||
no_sys, /* 12 bwrite */
|
.fdr_rename = do_rename,
|
||||||
do_unlink, /* 13 unlink */
|
.fdr_stat = do_stat,
|
||||||
do_rmdir, /* 14 rmdir */
|
.fdr_chmod = do_chmod,
|
||||||
do_unmount, /* 15 unmount */
|
.fdr_utime = do_utime,
|
||||||
do_noop, /* 16 sync */
|
.fdr_statvfs = do_statvfs
|
||||||
do_noop, /* 17 new_driver */
|
|
||||||
do_noop, /* 18 flush */
|
|
||||||
do_read, /* 19 read */
|
|
||||||
do_write, /* 20 write */
|
|
||||||
no_sys, /* 21 mknod */
|
|
||||||
do_mkdir, /* 22 mkdir */
|
|
||||||
do_create, /* 23 create */
|
|
||||||
no_sys, /* 24 link */
|
|
||||||
do_rename, /* 25 rename */
|
|
||||||
do_lookup, /* 26 lookup */
|
|
||||||
no_sys, /* 27 mountpoint */
|
|
||||||
do_readsuper, /* 28 readsuper */
|
|
||||||
no_sys, /* 29 newnode */
|
|
||||||
no_sys, /* 30 rdlink */
|
|
||||||
do_getdents, /* 31 getdents */
|
|
||||||
no_sys, /* 32 peek */
|
|
||||||
no_sys, /* 33 bpeek */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This should not fail with "array size is negative": */
|
|
||||||
extern int dummy[sizeof(call_vec) == NREQS * sizeof(call_vec[0]) ? 1 : -1];
|
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
/* Structure with global file system state. */
|
/* Structure with global file system state. */
|
||||||
struct state {
|
struct state {
|
||||||
int s_mounted; /* is the file system mounted? */
|
|
||||||
int s_signaled; /* have we received a SIGTERM? */
|
|
||||||
int s_read_only; /* is the file system mounted read-only? note,
|
int s_read_only; /* is the file system mounted read-only? note,
|
||||||
* has no relation to the shared folder mode */
|
* has no relation to the shared folder mode */
|
||||||
dev_t s_dev; /* device the file system is mounted on */
|
dev_t s_dev; /* device the file system is mounted on */
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
/* This file contains various utility functions.
|
|
||||||
*
|
|
||||||
* The entry points into this file are:
|
|
||||||
* get_name retrieve a path component string from VFS
|
|
||||||
* do_noop handle file system calls that do nothing and succeed
|
|
||||||
* no_sys handle file system calls that are not implemented
|
|
||||||
*
|
|
||||||
* Created:
|
|
||||||
* April 2009 (D.C. van Moolenbroek)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "inc.h"
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* get_name *
|
|
||||||
*===========================================================================*/
|
|
||||||
int get_name(
|
|
||||||
cp_grant_id_t grant, /* memory grant for the path component */
|
|
||||||
size_t len, /* length of the name, including '\0' */
|
|
||||||
char name[NAME_MAX+1] /* buffer in which store the result */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
/* Retrieve a path component from the caller, using a given grant.
|
|
||||||
*/
|
|
||||||
int r;
|
|
||||||
|
|
||||||
/* Copy in the name of the directory entry. */
|
|
||||||
if (len <= 1) return EINVAL;
|
|
||||||
if (len > NAME_MAX+1) return ENAMETOOLONG;
|
|
||||||
|
|
||||||
r = sys_safecopyfrom(m_in.m_source, grant, 0, (vir_bytes) name, len);
|
|
||||||
|
|
||||||
if (r != OK) return r;
|
|
||||||
|
|
||||||
if (name[len-1] != 0) {
|
|
||||||
printf("%s: VFS did not zero-terminate path component!\n", sffs_name);
|
|
||||||
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_noop *
|
|
||||||
*===========================================================================*/
|
|
||||||
int do_noop(void)
|
|
||||||
{
|
|
||||||
/* Generic handler for no-op system calls.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* no_sys *
|
|
||||||
*===========================================================================*/
|
|
||||||
int no_sys(void)
|
|
||||||
{
|
|
||||||
/* Generic handler for unimplemented system calls.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return ENOSYS;
|
|
||||||
}
|
|
|
@ -2,7 +2,7 @@
|
||||||
*
|
*
|
||||||
* The entry points into this file are:
|
* The entry points into this file are:
|
||||||
* do_write perform the WRITE file system call
|
* do_write perform the WRITE file system call
|
||||||
* do_ftrunc perform the FTRUNC file system call
|
* do_trunc perform the TRUNC file system call
|
||||||
*
|
*
|
||||||
* Created:
|
* Created:
|
||||||
* April 2009 (D.C. van Moolenbroek)
|
* April 2009 (D.C. van Moolenbroek)
|
||||||
|
@ -10,32 +10,27 @@
|
||||||
|
|
||||||
#include "inc.h"
|
#include "inc.h"
|
||||||
|
|
||||||
static int write_file(struct inode *ino, u64_t *posp, size_t *countp,
|
|
||||||
cp_grant_id_t *grantp);
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* write_file *
|
* write_file *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static int write_file(struct inode *ino, u64_t *posp, size_t *countp,
|
static ssize_t write_file(struct inode *ino, off_t pos, size_t count,
|
||||||
cp_grant_id_t *grantp)
|
struct fsdriver_data *data)
|
||||||
{
|
{
|
||||||
/* Write data or zeroes to a file, depending on whether a valid pointer to
|
/* Write data or zeroes to a file, depending on whether a valid pointer to
|
||||||
* a data grant was provided.
|
* a data grant was provided.
|
||||||
*/
|
*/
|
||||||
u64_t pos;
|
size_t size, off, chunk;
|
||||||
size_t count, size;
|
|
||||||
vir_bytes off;
|
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int r, chunk;
|
int r;
|
||||||
|
|
||||||
|
if (pos < 0)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
assert(!IS_DIR(ino));
|
assert(!IS_DIR(ino));
|
||||||
|
|
||||||
if ((r = get_handle(ino)) != OK)
|
if ((r = get_handle(ino)) != OK)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
pos = *posp;
|
|
||||||
count = *countp;
|
|
||||||
|
|
||||||
assert(count > 0);
|
assert(count > 0);
|
||||||
|
|
||||||
/* Use the buffer from below to eliminate extra copying. */
|
/* Use the buffer from below to eliminate extra copying. */
|
||||||
|
@ -45,11 +40,8 @@ static int write_file(struct inode *ino, u64_t *posp, size_t *countp,
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
chunk = MIN(count, size);
|
chunk = MIN(count, size);
|
||||||
|
|
||||||
if (grantp != NULL) {
|
if (data != NULL) {
|
||||||
r = sys_safecopyfrom(m_in.m_source, *grantp,
|
if ((r = fsdriver_copyin(data, off, ptr, chunk)) != OK)
|
||||||
off, (vir_bytes) ptr, chunk);
|
|
||||||
|
|
||||||
if (r != OK)
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
/* Do this every time. We don't know what happens below. */
|
/* Do this every time. We don't know what happens below. */
|
||||||
|
@ -67,73 +59,53 @@ static int write_file(struct inode *ino, u64_t *posp, size_t *countp,
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
*posp = pos;
|
return off;
|
||||||
*countp = off;
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_write *
|
* do_write *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_write(void)
|
ssize_t do_write(ino_t ino_nr, struct fsdriver_data *data, size_t count,
|
||||||
|
off_t pos, int call)
|
||||||
{
|
{
|
||||||
/* Write data to a file.
|
/* Write data to a file.
|
||||||
*/
|
*/
|
||||||
struct inode *ino;
|
struct inode *ino;
|
||||||
off_t pos;
|
|
||||||
size_t count;
|
|
||||||
cp_grant_id_t grant;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (state.s_read_only)
|
if (state.s_read_only)
|
||||||
return EROFS;
|
return EROFS;
|
||||||
|
|
||||||
if ((ino = find_inode(m_in.m_vfs_fs_readwrite.inode)) == NULL)
|
if ((ino = find_inode(ino_nr)) == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if (IS_DIR(ino)) return EISDIR;
|
if (IS_DIR(ino)) return EISDIR;
|
||||||
|
|
||||||
pos = m_in.m_vfs_fs_readwrite.seek_pos;
|
if (count == 0) return 0;
|
||||||
count = m_in.m_vfs_fs_readwrite.nbytes;
|
|
||||||
grant = m_in.m_vfs_fs_readwrite.grant;
|
|
||||||
|
|
||||||
if (count == 0) return EINVAL;
|
return write_file(ino, pos, count, data);
|
||||||
|
|
||||||
if ((r = write_file(ino, &pos, &count, &grant)) != OK)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
m_out.m_fs_vfs_readwrite.seek_pos = pos;
|
|
||||||
m_out.m_fs_vfs_readwrite.nbytes = count;
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_ftrunc *
|
* do_trunc *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_ftrunc(void)
|
int do_trunc(ino_t ino_nr, off_t start, off_t end)
|
||||||
{
|
{
|
||||||
/* Change file size or create file holes.
|
/* Change file size or create file holes.
|
||||||
*/
|
*/
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
struct inode *ino;
|
struct inode *ino;
|
||||||
struct sffs_attr attr;
|
struct sffs_attr attr;
|
||||||
u64_t start, end, delta;
|
uint64_t delta;
|
||||||
size_t count;
|
ssize_t r;
|
||||||
int r;
|
|
||||||
|
|
||||||
if (state.s_read_only)
|
if (state.s_read_only)
|
||||||
return EROFS;
|
return EROFS;
|
||||||
|
|
||||||
if ((ino = find_inode(m_in.m_vfs_fs_ftrunc.inode)) == NULL)
|
if ((ino = find_inode(ino_nr)) == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if (IS_DIR(ino)) return EISDIR;
|
if (IS_DIR(ino)) return EISDIR;
|
||||||
|
|
||||||
start = m_in.m_vfs_fs_ftrunc.trc_start;
|
|
||||||
end = m_in.m_vfs_fs_ftrunc.trc_end;
|
|
||||||
|
|
||||||
if (end == 0) {
|
if (end == 0) {
|
||||||
/* Truncate or expand the file. */
|
/* Truncate or expand the file. */
|
||||||
if ((r = verify_inode(ino, path, NULL)) != OK)
|
if ((r = verify_inode(ino, path, NULL)) != OK)
|
||||||
|
@ -147,13 +119,12 @@ int do_ftrunc(void)
|
||||||
/* Write zeroes to the file. We can't create holes. */
|
/* Write zeroes to the file. We can't create holes. */
|
||||||
if (end <= start) return EINVAL;
|
if (end <= start) return EINVAL;
|
||||||
|
|
||||||
delta = end - start;
|
delta = (uint64_t)end - (uint64_t)start;
|
||||||
|
|
||||||
if (ex64hi(delta) != 0) return EINVAL;
|
if (delta > SSIZE_MAX) return EINVAL;
|
||||||
|
|
||||||
count = ex64lo(delta);
|
if ((r = write_file(ino, start, (size_t)delta, NULL)) >= 0)
|
||||||
|
r = OK;
|
||||||
r = write_file(ino, &start, &count, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|
Loading…
Reference in a new issue