libsffs: use libfsdriver
Change-Id: Id8377873455771c614371e115643cd906d05f12c
This commit is contained in:
		
							parent
							
								
									ebd3c0673d
								
							
						
					
					
						commit
						a99c939dee
					
				@ -2,7 +2,7 @@
 | 
			
		||||
PROG=	hgfs
 | 
			
		||||
SRCS=	hgfs.c
 | 
			
		||||
 | 
			
		||||
DPADD+=	${LIBSFFS} ${LIBHGFS} ${LIBSYS}
 | 
			
		||||
LDADD+=	-lsffs -lhgfs -lsys
 | 
			
		||||
DPADD+=	${LIBSFFS} ${LIBHGFS} ${LIBFSDRIVER} ${LIBSYS}
 | 
			
		||||
LDADD+=	-lsffs -lhgfs -lfsdriver -lsys
 | 
			
		||||
 | 
			
		||||
.include <minix.service.mk>
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
PROG=	vbfs
 | 
			
		||||
SRCS=	vbfs.c
 | 
			
		||||
 | 
			
		||||
DPADD+=	${LIBSFFS} ${LIBVBOXFS} ${LIBSYS}
 | 
			
		||||
LDADD+=	-lsffs -lvboxfs -lsys
 | 
			
		||||
DPADD+=	${LIBSFFS} ${LIBVBOXFS} ${LIBFSDRIVER} ${LIBSYS}
 | 
			
		||||
LDADD+=	-lsffs -lvboxfs -lfsdriver -lsys
 | 
			
		||||
 | 
			
		||||
.include <minix.service.mk>
 | 
			
		||||
 | 
			
		||||
@ -1,13 +1,13 @@
 | 
			
		||||
NOGCCERROR=yes
 | 
			
		||||
NOCLANGERROR=yes
 | 
			
		||||
CPPFLAGS+= -D_MINIX_SYSTEM
 | 
			
		||||
 | 
			
		||||
# Makefile for libsffs
 | 
			
		||||
.include <bsd.own.mk>
 | 
			
		||||
 | 
			
		||||
NOGCCERROR=yes
 | 
			
		||||
 | 
			
		||||
CPPFLAGS+= -D_MINIX_SYSTEM
 | 
			
		||||
 | 
			
		||||
LIB=	sffs
 | 
			
		||||
 | 
			
		||||
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>
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,6 @@
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 | 
			
		||||
@ -10,10 +10,8 @@ EXTERN char *sffs_name;				/* file server name */
 | 
			
		||||
EXTERN const struct sffs_table *sffs_table;	/* call table */
 | 
			
		||||
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 int(*call_vec[]) (void);
 | 
			
		||||
extern struct fsdriver sffs_dtable;		/* driver table */
 | 
			
		||||
 | 
			
		||||
#endif /* _SFFS_GLO_H */
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@
 | 
			
		||||
#define _SFFS_INC_H
 | 
			
		||||
 | 
			
		||||
#include <minix/drivers.h>
 | 
			
		||||
#include <minix/fsdriver.h>
 | 
			
		||||
#include <minix/vfsif.h>
 | 
			
		||||
#include <minix/optset.h>
 | 
			
		||||
#include <minix/sffs.h>
 | 
			
		||||
 | 
			
		||||
@ -273,19 +273,16 @@ int have_used_inode(void)
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				do_putnode				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int do_putnode(void)
 | 
			
		||||
int do_putnode(ino_t ino_nr, unsigned int count)
 | 
			
		||||
{
 | 
			
		||||
/* Decrease an inode's reference count.
 | 
			
		||||
 */
 | 
			
		||||
  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;
 | 
			
		||||
 | 
			
		||||
  count = m_in.m_vfs_fs_putnode.count;
 | 
			
		||||
 | 
			
		||||
  if (count <= 0 || count > ino->i_ref) return EINVAL;
 | 
			
		||||
  if (count > ino->i_ref) return EINVAL;
 | 
			
		||||
 | 
			
		||||
  ino->i_ref -= count - 1;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -15,16 +15,15 @@
 | 
			
		||||
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
static int force_remove(char *path, int dir);
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				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.
 | 
			
		||||
 */
 | 
			
		||||
  char path[PATH_MAX], name[NAME_MAX+1];
 | 
			
		||||
  char path[PATH_MAX];
 | 
			
		||||
  struct inode *parent, *ino;
 | 
			
		||||
  struct sffs_attr attr;
 | 
			
		||||
  sffs_file_t handle;
 | 
			
		||||
@ -34,13 +33,7 @@ int do_create(void)
 | 
			
		||||
  if (state.s_read_only)
 | 
			
		||||
	return EROFS;
 | 
			
		||||
 | 
			
		||||
  /* Get path, name, parent inode and possibly inode for the given path. */
 | 
			
		||||
  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)
 | 
			
		||||
  if ((parent = find_inode(dir_nr)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
 | 
			
		||||
  if ((r = verify_dentry(parent, name, path, &ino)) != OK)
 | 
			
		||||
@ -59,8 +52,7 @@ int do_create(void)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Perform the actual create call. */
 | 
			
		||||
  r = sffs_table->t_open(path, O_CREAT | O_EXCL | O_RDWR, m_in.m_vfs_fs_create.mode,
 | 
			
		||||
	&handle);
 | 
			
		||||
  r = sffs_table->t_open(path, O_CREAT | O_EXCL | O_RDWR, mode, &handle);
 | 
			
		||||
 | 
			
		||||
  if (r != OK) {
 | 
			
		||||
	/* 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);
 | 
			
		||||
 | 
			
		||||
  m_out.m_fs_vfs_create.inode = INODE_NR(ino);
 | 
			
		||||
  m_out.m_fs_vfs_create.mode = get_mode(ino, attr.a_mode);
 | 
			
		||||
  m_out.m_fs_vfs_create.file_size = attr.a_size;
 | 
			
		||||
  m_out.m_fs_vfs_create.uid = sffs_params->p_uid;
 | 
			
		||||
  m_out.m_fs_vfs_create.gid = sffs_params->p_gid;
 | 
			
		||||
  node->fn_ino_nr = INODE_NR(ino);
 | 
			
		||||
  node->fn_mode = get_mode(ino, attr.a_mode);
 | 
			
		||||
  node->fn_size = attr.a_size;
 | 
			
		||||
  node->fn_uid = sffs_params->p_uid;
 | 
			
		||||
  node->fn_gid = sffs_params->p_gid;
 | 
			
		||||
  node->fn_dev = NO_DEV;
 | 
			
		||||
 | 
			
		||||
  return OK;
 | 
			
		||||
}
 | 
			
		||||
@ -127,11 +120,11 @@ int do_create(void)
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				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.
 | 
			
		||||
 */
 | 
			
		||||
  char path[PATH_MAX], name[NAME_MAX+1];
 | 
			
		||||
  char path[PATH_MAX];
 | 
			
		||||
  struct inode *parent, *ino;
 | 
			
		||||
  int r;
 | 
			
		||||
 | 
			
		||||
@ -139,20 +132,14 @@ int do_mkdir(void)
 | 
			
		||||
  if (state.s_read_only)
 | 
			
		||||
	return EROFS;
 | 
			
		||||
 | 
			
		||||
  /* Get the path string and possibly an inode for the given path. */
 | 
			
		||||
  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)
 | 
			
		||||
  if ((parent = find_inode(dir_nr)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
 | 
			
		||||
  if ((r = verify_dentry(parent, name, path, &ino)) != OK)
 | 
			
		||||
	return r;
 | 
			
		||||
 | 
			
		||||
  /* 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 (ino != NULL)
 | 
			
		||||
@ -232,11 +219,11 @@ static int force_remove(
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				do_unlink				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int do_unlink(void)
 | 
			
		||||
int do_unlink(ino_t dir_nr, char *name, int call)
 | 
			
		||||
{
 | 
			
		||||
/* Delete a file.
 | 
			
		||||
 */
 | 
			
		||||
  char path[PATH_MAX], name[NAME_MAX+1];
 | 
			
		||||
  char path[PATH_MAX];
 | 
			
		||||
  struct inode *parent, *ino;
 | 
			
		||||
  int r;
 | 
			
		||||
 | 
			
		||||
@ -244,13 +231,7 @@ int do_unlink(void)
 | 
			
		||||
  if (state.s_read_only)
 | 
			
		||||
	return EROFS;
 | 
			
		||||
 | 
			
		||||
  /* Get the path string and possibly preexisting inode for the given path. */
 | 
			
		||||
  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)
 | 
			
		||||
  if ((parent = find_inode(dir_nr)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
 | 
			
		||||
  if ((r = verify_dentry(parent, name, path, &ino)) != OK)
 | 
			
		||||
@ -279,11 +260,11 @@ int do_unlink(void)
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				do_rmdir				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int do_rmdir(void)
 | 
			
		||||
int do_rmdir(ino_t dir_nr, char *name, int call)
 | 
			
		||||
{
 | 
			
		||||
/* Remove an empty directory.
 | 
			
		||||
 */
 | 
			
		||||
  char path[PATH_MAX], name[NAME_MAX+1];
 | 
			
		||||
  char path[PATH_MAX];
 | 
			
		||||
  struct inode *parent, *ino;
 | 
			
		||||
  int r;
 | 
			
		||||
 | 
			
		||||
@ -291,14 +272,7 @@ int do_rmdir(void)
 | 
			
		||||
  if (state.s_read_only)
 | 
			
		||||
	return EROFS;
 | 
			
		||||
 | 
			
		||||
  /* Get the path string and possibly preexisting inode for the given path. */
 | 
			
		||||
  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)
 | 
			
		||||
  if ((parent = find_inode(dir_nr)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
 | 
			
		||||
  if ((r = verify_dentry(parent, name, path, &ino)) != OK)
 | 
			
		||||
@ -327,12 +301,12 @@ int do_rmdir(void)
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				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.
 | 
			
		||||
 */
 | 
			
		||||
  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_ino, *new_ino;
 | 
			
		||||
  int r;
 | 
			
		||||
@ -341,20 +315,9 @@ int do_rename(void)
 | 
			
		||||
  if (state.s_read_only)
 | 
			
		||||
	return EROFS;
 | 
			
		||||
 | 
			
		||||
  /* Get path strings, names, directory inodes and possibly preexisting inodes
 | 
			
		||||
   * for the old and new paths.
 | 
			
		||||
   */
 | 
			
		||||
  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)
 | 
			
		||||
  /* Get possibly preexisting inodes for the old and new paths. */
 | 
			
		||||
  if ((old_parent = find_inode(old_dir_nr)) == NULL ||
 | 
			
		||||
	(new_parent = find_inode(new_dir_nr)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
 | 
			
		||||
  if ((r = verify_dentry(old_parent, old_name, old_path, &old_ino)) != OK)
 | 
			
		||||
 | 
			
		||||
@ -9,103 +9,6 @@
 | 
			
		||||
 | 
			
		||||
#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					     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
@ -199,142 +102,49 @@ static int go_down(
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				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.
 | 
			
		||||
 */
 | 
			
		||||
  ino_t dir_ino_nr, root_ino_nr;
 | 
			
		||||
  struct inode *cur_ino, *root_ino;
 | 
			
		||||
  struct inode *next_ino = NULL;
 | 
			
		||||
  struct inode *dir_ino, *ino;
 | 
			
		||||
  struct sffs_attr attr;
 | 
			
		||||
  char buf[PATH_MAX], path[PATH_MAX];
 | 
			
		||||
  char name[NAME_MAX+1];
 | 
			
		||||
  char *ptr, *last;
 | 
			
		||||
  vfs_ucred_t ucred;
 | 
			
		||||
  mode_t mask;
 | 
			
		||||
  size_t len;
 | 
			
		||||
  char path[PATH_MAX];
 | 
			
		||||
  int r;
 | 
			
		||||
 | 
			
		||||
  dir_ino_nr = m_in.m_vfs_fs_lookup.dir_ino;
 | 
			
		||||
  root_ino_nr = m_in.m_vfs_fs_lookup.root_ino;
 | 
			
		||||
  len = m_in.m_vfs_fs_lookup.path_len;
 | 
			
		||||
  dprintf(("%s: lookup: got query for %"PRIu64", '%s'\n",
 | 
			
		||||
	sffs_name, dir_nr, name));
 | 
			
		||||
 | 
			
		||||
  /* Fetch the path name. */
 | 
			
		||||
  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)
 | 
			
		||||
  if ((dir_ino = find_inode(dir_nr)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
 | 
			
		||||
  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;
 | 
			
		||||
 | 
			
		||||
  get_inode(cur_ino);
 | 
			
		||||
  if (!IS_DIR(dir_ino))
 | 
			
		||||
	return ENOTDIR;
 | 
			
		||||
 | 
			
		||||
  if (root_ino_nr > 0)
 | 
			
		||||
	root_ino = find_inode(root_ino_nr);
 | 
			
		||||
  r = OK;
 | 
			
		||||
  if (!strcmp(name, "."))
 | 
			
		||||
	get_inode(ino = dir_ino);
 | 
			
		||||
  else if (!strcmp(name, ".."))
 | 
			
		||||
	r = go_up(path, dir_ino, &ino, &attr);
 | 
			
		||||
  else
 | 
			
		||||
	root_ino = NULL;
 | 
			
		||||
 | 
			
		||||
  /* 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)
 | 
			
		||||
		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;
 | 
			
		||||
	}
 | 
			
		||||
	r = go_down(path, dir_ino, name, &ino, &attr);
 | 
			
		||||
 | 
			
		||||
  if (r != OK)
 | 
			
		||||
	return r;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  m_out.m_fs_vfs_lookup.inode = INODE_NR(cur_ino);
 | 
			
		||||
  m_out.m_fs_vfs_lookup.mode = get_mode(cur_ino, attr.a_mode);
 | 
			
		||||
  m_out.m_fs_vfs_lookup.file_size = attr.a_size;
 | 
			
		||||
  m_out.m_fs_vfs_lookup.uid = sffs_params->p_uid;
 | 
			
		||||
  m_out.m_fs_vfs_lookup.gid = sffs_params->p_gid;
 | 
			
		||||
  m_out.m_fs_vfs_lookup.device = NO_DEV;
 | 
			
		||||
  node->fn_ino_nr = INODE_NR(ino);
 | 
			
		||||
  node->fn_mode = get_mode(ino, attr.a_mode);
 | 
			
		||||
  node->fn_size = attr.a_size;
 | 
			
		||||
  node->fn_uid = sffs_params->p_uid;
 | 
			
		||||
  node->fn_gid = sffs_params->p_gid;
 | 
			
		||||
  node->fn_dev = NO_DEV;
 | 
			
		||||
 | 
			
		||||
  *is_mountpt = FALSE;
 | 
			
		||||
 | 
			
		||||
  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--;
 | 
			
		||||
  params->p_prefix[i] = 0;
 | 
			
		||||
 | 
			
		||||
  state.s_mounted = FALSE;
 | 
			
		||||
  state.s_signaled = FALSE;
 | 
			
		||||
 | 
			
		||||
  sffs_name = name;
 | 
			
		||||
  sffs_table = table;
 | 
			
		||||
  sffs_params = params;
 | 
			
		||||
@ -45,62 +42,9 @@ void sffs_signal(int signo)
 | 
			
		||||
  /* Only check for termination signal, ignore anything else. */
 | 
			
		||||
  if (signo != SIGTERM) return;
 | 
			
		||||
 | 
			
		||||
  /* We can now terminate if we have also been unmounted. */
 | 
			
		||||
  state.s_signaled = TRUE;
 | 
			
		||||
  dprintf(("%s: got SIGTERM\n", sffs_name));
 | 
			
		||||
 | 
			
		||||
  if (state.s_mounted) {
 | 
			
		||||
	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);
 | 
			
		||||
  fsdriver_terminate();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
@ -108,47 +52,8 @@ static void send_reply(
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
void sffs_loop(void)
 | 
			
		||||
{
 | 
			
		||||
/* The main function of this file server. After initializing, loop, receiving
 | 
			
		||||
 * 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.
 | 
			
		||||
/* The main function of this file server. Libfsdriver does the real work.
 | 
			
		||||
 */
 | 
			
		||||
  endpoint_t who_e;
 | 
			
		||||
  int call_nr, err, transid;
 | 
			
		||||
 | 
			
		||||
  while (state.s_mounted || !state.s_signaled) {
 | 
			
		||||
	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);
 | 
			
		||||
  }
 | 
			
		||||
  fsdriver_task(&sffs_dtable);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,11 +14,10 @@
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				do_statvfs				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int do_statvfs(void)
 | 
			
		||||
int do_statvfs(struct statvfs *statvfs)
 | 
			
		||||
{
 | 
			
		||||
/* Retrieve file system statistics.
 | 
			
		||||
 */
 | 
			
		||||
  struct statvfs statvfs;
 | 
			
		||||
  struct inode *ino;
 | 
			
		||||
  char path[PATH_MAX];
 | 
			
		||||
  u64_t free, total;
 | 
			
		||||
@ -38,20 +37,17 @@ int do_statvfs(void)
 | 
			
		||||
  if ((r = sffs_table->t_queryvol(path, &free, &total)) != OK)
 | 
			
		||||
	return r;
 | 
			
		||||
 | 
			
		||||
  memset(&statvfs, 0, sizeof(statvfs));
 | 
			
		||||
 | 
			
		||||
  /* 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.
 | 
			
		||||
   */
 | 
			
		||||
  statvfs.f_flag = ST_NOTRUNC;
 | 
			
		||||
  statvfs.f_bsize = BLOCK_SIZE;
 | 
			
		||||
  statvfs.f_frsize = BLOCK_SIZE;
 | 
			
		||||
  statvfs.f_iosize = BLOCK_SIZE;
 | 
			
		||||
  statvfs.f_blocks = (unsigned long)(total / BLOCK_SIZE);
 | 
			
		||||
  statvfs.f_bfree = (unsigned long)(free / BLOCK_SIZE);
 | 
			
		||||
  statvfs.f_bavail = statvfs.f_bfree;
 | 
			
		||||
  statvfs.f_namemax = NAME_MAX;
 | 
			
		||||
  statvfs->f_flag = ST_NOTRUNC;
 | 
			
		||||
  statvfs->f_bsize = BLOCK_SIZE;
 | 
			
		||||
  statvfs->f_frsize = BLOCK_SIZE;
 | 
			
		||||
  statvfs->f_iosize = BLOCK_SIZE;
 | 
			
		||||
  statvfs->f_blocks = (fsblkcnt_t)(total / BLOCK_SIZE);
 | 
			
		||||
  statvfs->f_bfree = (fsblkcnt_t)(free / BLOCK_SIZE);
 | 
			
		||||
  statvfs->f_bavail = statvfs->f_bfree;
 | 
			
		||||
  statvfs->f_namemax = NAME_MAX;
 | 
			
		||||
 | 
			
		||||
  return sys_safecopyto(m_in.m_source, m_in.m_vfs_fs_statvfs.grant, 0,
 | 
			
		||||
			(vir_bytes) &statvfs, sizeof(statvfs));
 | 
			
		||||
  return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
/* This file contains mount and unmount functionality.
 | 
			
		||||
 *
 | 
			
		||||
 * 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
 | 
			
		||||
 *
 | 
			
		||||
 * Created:
 | 
			
		||||
@ -11,9 +11,10 @@
 | 
			
		||||
#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.
 | 
			
		||||
 */
 | 
			
		||||
@ -22,17 +23,16 @@ int do_readsuper(void)
 | 
			
		||||
  struct sffs_attr attr;
 | 
			
		||||
  int r;
 | 
			
		||||
 | 
			
		||||
  dprintf(("%s: readsuper (dev %x, flags %x)\n",
 | 
			
		||||
	sffs_name, m_in.m_vfs_fs_readsuper.device, m_in.vfs_fs_readsuper.flags));
 | 
			
		||||
  dprintf(("%s: mount (dev %"PRIx64", flags %x)\n", sffs_name, dev, 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);
 | 
			
		||||
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  state.s_read_only = !!(m_in.m_vfs_fs_readsuper.flags & REQ_RDONLY);
 | 
			
		||||
  state.s_dev = m_in.m_vfs_fs_readsuper.device;
 | 
			
		||||
  state.s_read_only = !!(flags & REQ_RDONLY);
 | 
			
		||||
  state.s_dev = dev;
 | 
			
		||||
 | 
			
		||||
  init_dentry();
 | 
			
		||||
  ino = init_inode();
 | 
			
		||||
@ -55,15 +55,14 @@ int do_readsuper(void)
 | 
			
		||||
	return r;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  m_out.m_fs_vfs_readsuper.inode = INODE_NR(ino);
 | 
			
		||||
  m_out.m_fs_vfs_readsuper.mode = get_mode(ino, attr.a_mode);
 | 
			
		||||
  m_out.m_fs_vfs_readsuper.file_size = attr.a_size;
 | 
			
		||||
  m_out.m_fs_vfs_readsuper.uid = sffs_params->p_uid;
 | 
			
		||||
  m_out.m_fs_vfs_readsuper.gid = sffs_params->p_gid;
 | 
			
		||||
  m_out.m_fs_vfs_readsuper.device = NO_DEV;
 | 
			
		||||
  m_out.m_fs_vfs_readsuper.flags = RES_64BIT;
 | 
			
		||||
  root_node->fn_ino_nr = INODE_NR(ino);
 | 
			
		||||
  root_node->fn_mode = get_mode(ino, attr.a_mode);
 | 
			
		||||
  root_node->fn_size = attr.a_size;
 | 
			
		||||
  root_node->fn_uid = sffs_params->p_uid;
 | 
			
		||||
  root_node->fn_gid = sffs_params->p_gid;
 | 
			
		||||
  root_node->fn_dev = NO_DEV;
 | 
			
		||||
 | 
			
		||||
  state.s_mounted = TRUE;
 | 
			
		||||
  *res_flags = RES_64BIT;
 | 
			
		||||
 | 
			
		||||
  return OK;
 | 
			
		||||
}
 | 
			
		||||
@ -71,25 +70,21 @@ int do_readsuper(void)
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				do_unmount				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int do_unmount(void)
 | 
			
		||||
void do_unmount(void)
 | 
			
		||||
{
 | 
			
		||||
/* Unmount the file system.
 | 
			
		||||
 */
 | 
			
		||||
  struct inode *ino;
 | 
			
		||||
 | 
			
		||||
  dprintf(("%s: do_unmount\n", sffs_name));
 | 
			
		||||
  dprintf(("%s: unmount\n", sffs_name));
 | 
			
		||||
 | 
			
		||||
  /* Decrease the reference count of the root inode. */
 | 
			
		||||
  if ((ino = find_inode(ROOT_INODE_NR)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
  put_inode(ino);
 | 
			
		||||
 | 
			
		||||
  /* There should not be any referenced inodes anymore now. */
 | 
			
		||||
  if (have_used_inode())
 | 
			
		||||
	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) {
 | 
			
		||||
	for (i = 0; i < size; i++)
 | 
			
		||||
		*dst++ = tolower(*src++);
 | 
			
		||||
		*dst++ = tolower((int)*src++);
 | 
			
		||||
  }
 | 
			
		||||
  else memcpy(dst, src, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,27 +21,31 @@ void unlink_inode(struct inode *ino);
 | 
			
		||||
struct inode *get_free_inode(void);
 | 
			
		||||
int have_free_inode(void);
 | 
			
		||||
int have_used_inode(void);
 | 
			
		||||
int do_putnode(void);
 | 
			
		||||
int do_putnode(ino_t ino_nr, unsigned int count);
 | 
			
		||||
 | 
			
		||||
/* link.c */
 | 
			
		||||
int do_create(void);
 | 
			
		||||
int do_mkdir(void);
 | 
			
		||||
int do_unlink(void);
 | 
			
		||||
int do_rmdir(void);
 | 
			
		||||
int do_rename(void);
 | 
			
		||||
int do_create(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
 | 
			
		||||
	struct fsdriver_node *node);
 | 
			
		||||
int do_mkdir(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid);
 | 
			
		||||
int do_unlink(ino_t dir_nr, char *name, int call);
 | 
			
		||||
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 */
 | 
			
		||||
int do_lookup(void);
 | 
			
		||||
int do_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
 | 
			
		||||
	int *is_mountpt);
 | 
			
		||||
 | 
			
		||||
/* main.c */
 | 
			
		||||
int main(int argc, char *argv[]);
 | 
			
		||||
 | 
			
		||||
/* misc.c */
 | 
			
		||||
int do_statvfs(void);
 | 
			
		||||
int do_statvfs(struct statvfs *statvfs);
 | 
			
		||||
 | 
			
		||||
/* mount.c */
 | 
			
		||||
int do_readsuper(void);
 | 
			
		||||
int do_unmount(void);
 | 
			
		||||
int do_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node,
 | 
			
		||||
	unsigned int *res_flags);
 | 
			
		||||
void do_unmount(void);
 | 
			
		||||
 | 
			
		||||
/* name.c */
 | 
			
		||||
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]);
 | 
			
		||||
 | 
			
		||||
/* read.c */
 | 
			
		||||
int do_read(void);
 | 
			
		||||
int do_getdents(void);
 | 
			
		||||
ssize_t do_read(ino_t ino_nr, struct fsdriver_data *data, size_t count,
 | 
			
		||||
	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 */
 | 
			
		||||
mode_t get_mode(struct inode *ino, int mode);
 | 
			
		||||
int do_stat(void);
 | 
			
		||||
int do_chmod(void);
 | 
			
		||||
int do_utime(void);
 | 
			
		||||
 | 
			
		||||
/* 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);
 | 
			
		||||
int do_stat(ino_t ino_nr, struct stat *stat);
 | 
			
		||||
int do_chmod(ino_t ino_nr, mode_t *mode);
 | 
			
		||||
int do_utime(ino_t ino_nr, struct timespec *atime, struct timespec *mtime);
 | 
			
		||||
 | 
			
		||||
/* verify.c */
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
/* write.c */
 | 
			
		||||
int do_write(void);
 | 
			
		||||
int do_ftrunc(void);
 | 
			
		||||
ssize_t do_write(ino_t ino_nr, struct fsdriver_data *data, size_t count,
 | 
			
		||||
	off_t pos, int call);
 | 
			
		||||
int do_trunc(ino_t ino_nr, off_t start, off_t end);
 | 
			
		||||
 | 
			
		||||
#endif /* _SFFS_PROTO_H */
 | 
			
		||||
 | 
			
		||||
@ -12,23 +12,20 @@
 | 
			
		||||
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
 | 
			
		||||
#define DWORD_ALIGN(len) (((len) + sizeof(long) - 1) & ~(sizeof(long) - 1))
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				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.
 | 
			
		||||
 */
 | 
			
		||||
  struct inode *ino;
 | 
			
		||||
  off_t pos;
 | 
			
		||||
  size_t count, size;
 | 
			
		||||
  vir_bytes off;
 | 
			
		||||
  size_t size, off;
 | 
			
		||||
  char *ptr;
 | 
			
		||||
  int r, chunk;
 | 
			
		||||
 | 
			
		||||
  if ((ino = find_inode(m_in.m_vfs_fs_readwrite.inode)) == NULL)
 | 
			
		||||
  if ((ino = find_inode(ino_nr)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
 | 
			
		||||
  if (IS_DIR(ino)) return EISDIR;
 | 
			
		||||
@ -36,9 +33,6 @@ int do_read(void)
 | 
			
		||||
  if ((r = get_handle(ino)) != OK)
 | 
			
		||||
	return r;
 | 
			
		||||
 | 
			
		||||
  pos = m_in.m_vfs_fs_readwrite.seek_pos;
 | 
			
		||||
  count = m_in.m_vfs_fs_readwrite.nbytes;
 | 
			
		||||
 | 
			
		||||
  assert(count > 0);
 | 
			
		||||
 | 
			
		||||
  /* Use the buffer from below to eliminate extra copying. */
 | 
			
		||||
@ -53,10 +47,7 @@ int do_read(void)
 | 
			
		||||
 | 
			
		||||
	chunk = r;
 | 
			
		||||
 | 
			
		||||
	r = sys_safecopyto(m_in.m_source, m_in.m_vfs_fs_readwrite.grant, off,
 | 
			
		||||
		(vir_bytes) ptr, chunk);
 | 
			
		||||
 | 
			
		||||
	if (r != OK)
 | 
			
		||||
	if ((r = fsdriver_copyout(data, off, ptr, chunk)) != OK)
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	count -= chunk;
 | 
			
		||||
@ -67,38 +58,33 @@ int do_read(void)
 | 
			
		||||
  if (r < 0)
 | 
			
		||||
	return r;
 | 
			
		||||
 | 
			
		||||
  m_out.m_fs_vfs_readwrite.seek_pos = pos;
 | 
			
		||||
  m_out.m_fs_vfs_readwrite.nbytes = off;
 | 
			
		||||
 | 
			
		||||
  return OK;
 | 
			
		||||
  return off;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				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.
 | 
			
		||||
 */
 | 
			
		||||
  struct fsdriver_dentry fsdentry;
 | 
			
		||||
  char name[NAME_MAX+1];
 | 
			
		||||
  struct inode *ino, *child;
 | 
			
		||||
  struct dirent *dent;
 | 
			
		||||
  struct sffs_attr attr;
 | 
			
		||||
  size_t len, off, user_off, user_left;
 | 
			
		||||
  off_t pos;
 | 
			
		||||
  int r, namelen;
 | 
			
		||||
  int r;
 | 
			
		||||
  /* must be at least sizeof(struct dirent) + NAME_MAX */
 | 
			
		||||
  static char buf[BLOCK_SIZE];
 | 
			
		||||
 | 
			
		||||
  attr.a_mask = SFFS_ATTR_MODE;
 | 
			
		||||
 | 
			
		||||
  if ((ino = find_inode(m_in.m_vfs_fs_getdents.inode)) == NULL)
 | 
			
		||||
  if ((ino = find_inode(ino_nr)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
 | 
			
		||||
  if(m_in.m_vfs_fs_getdents.seek_pos >= ULONG_MAX) return EINVAL;
 | 
			
		||||
 | 
			
		||||
  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. */
 | 
			
		||||
  if (!have_free_inode()) return ENFILE;
 | 
			
		||||
 | 
			
		||||
@ -106,19 +92,19 @@ int do_getdents(void)
 | 
			
		||||
  if ((r = get_handle(ino)) != OK)
 | 
			
		||||
	return r;
 | 
			
		||||
 | 
			
		||||
  off = 0;
 | 
			
		||||
  user_off = 0;
 | 
			
		||||
  user_left = m_in.m_vfs_fs_getdents.mem_size;
 | 
			
		||||
  fsdriver_dentry_init(&fsdentry, data, bytes, buf, sizeof(buf));
 | 
			
		||||
 | 
			
		||||
  /* 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
 | 
			
		||||
   * 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.
 | 
			
		||||
	 * We have no idea whether the host will give us "." and/or "..",
 | 
			
		||||
	 * so generate our own and skip those from the host.
 | 
			
		||||
	 */
 | 
			
		||||
	pos = (*posp)++;
 | 
			
		||||
 | 
			
		||||
	if (pos == 0) {
 | 
			
		||||
		/* Entry for ".". */
 | 
			
		||||
		child = ino;
 | 
			
		||||
@ -140,6 +126,8 @@ int do_getdents(void)
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		/* Any other entry, not being "." or "..". */
 | 
			
		||||
		attr.a_mask = SFFS_ATTR_MODE;
 | 
			
		||||
 | 
			
		||||
		r = sffs_table->t_readdir(ino->i_dir, pos - 2, name,
 | 
			
		||||
			sizeof(name), &attr);
 | 
			
		||||
 | 
			
		||||
@ -170,66 +158,14 @@ int do_getdents(void)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* record length incl. alignment. */
 | 
			
		||||
	namelen = strlen(name);
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
			return r;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		user_off += off;
 | 
			
		||||
		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;
 | 
			
		||||
	r = fsdriver_dentry_add(&fsdentry, INODE_NR(child), name, strlen(name),
 | 
			
		||||
		IS_DIR(child) ? DT_DIR : DT_REG);
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
	if (r < 0)
 | 
			
		||||
		return r;
 | 
			
		||||
  } while (r > 0);
 | 
			
		||||
 | 
			
		||||
	user_off += off;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  m_out.m_fs_vfs_getdents.seek_pos = pos;
 | 
			
		||||
  m_out.m_fs_vfs_getdents.nbytes = user_off;
 | 
			
		||||
 | 
			
		||||
  return OK;
 | 
			
		||||
  return fsdriver_dentry_finish(&fsdentry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -37,19 +37,15 @@ mode_t get_mode(struct inode *ino, int mode)
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				do_stat					     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int do_stat(void)
 | 
			
		||||
int do_stat(ino_t ino_nr, struct stat *stat)
 | 
			
		||||
{
 | 
			
		||||
/* Retrieve inode status.
 | 
			
		||||
 */
 | 
			
		||||
  struct inode *ino;
 | 
			
		||||
  struct sffs_attr attr;
 | 
			
		||||
  struct stat stat;
 | 
			
		||||
  char path[PATH_MAX];
 | 
			
		||||
  ino_t ino_nr;
 | 
			
		||||
  int r;
 | 
			
		||||
 | 
			
		||||
  ino_nr = m_in.m_vfs_fs_stat.inode;
 | 
			
		||||
 | 
			
		||||
  /* Don't increase the inode refcount: it's already open anyway */
 | 
			
		||||
  if ((ino = find_inode(ino_nr)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
@ -60,45 +56,42 @@ int do_stat(void)
 | 
			
		||||
  if ((r = verify_inode(ino, path, &attr)) != OK)
 | 
			
		||||
	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_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_blocks = stat->st_size / S_BLKSIZE;
 | 
			
		||||
  if (stat->st_size % S_BLKSIZE != 0)
 | 
			
		||||
	stat->st_blocks += 1;
 | 
			
		||||
 | 
			
		||||
  stat.st_blocks = stat.st_size / S_BLKSIZE;
 | 
			
		||||
  if (stat.st_size % S_BLKSIZE != 0)
 | 
			
		||||
	stat.st_blocks += 1;
 | 
			
		||||
 | 
			
		||||
  stat.st_blksize = BLOCK_SIZE;
 | 
			
		||||
  stat->st_blksize = BLOCK_SIZE;
 | 
			
		||||
 | 
			
		||||
  /* We could make this more accurate by iterating over directory inodes'
 | 
			
		||||
   * children, counting how many of those are directories as well.
 | 
			
		||||
   * It's just not worth it.
 | 
			
		||||
   */
 | 
			
		||||
  stat.st_nlink = 0;
 | 
			
		||||
  if (ino->i_parent != NULL) stat.st_nlink++;
 | 
			
		||||
  stat->st_nlink = 0;
 | 
			
		||||
  if (ino->i_parent != NULL) stat->st_nlink++;
 | 
			
		||||
  if (IS_DIR(ino)) {
 | 
			
		||||
	stat.st_nlink++;
 | 
			
		||||
	if (HAS_CHILDREN(ino)) stat.st_nlink++;
 | 
			
		||||
	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,
 | 
			
		||||
	(vir_bytes) &stat, sizeof(stat));
 | 
			
		||||
  return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				do_chmod				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int do_chmod(void)
 | 
			
		||||
int do_chmod(ino_t ino_nr, mode_t *mode)
 | 
			
		||||
{
 | 
			
		||||
/* Change file mode.
 | 
			
		||||
 */
 | 
			
		||||
@ -110,7 +103,7 @@ int do_chmod(void)
 | 
			
		||||
  if (state.s_read_only)
 | 
			
		||||
	return EROFS;
 | 
			
		||||
 | 
			
		||||
  if ((ino = find_inode(m_in.m_vfs_fs_chmod.inode)) == NULL)
 | 
			
		||||
  if ((ino = find_inode(ino_nr)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
 | 
			
		||||
  if ((r = verify_inode(ino, path, NULL)) != OK)
 | 
			
		||||
@ -118,7 +111,7 @@ int do_chmod(void)
 | 
			
		||||
 | 
			
		||||
  /* Set the new file 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)
 | 
			
		||||
	return r;
 | 
			
		||||
@ -127,7 +120,7 @@ int do_chmod(void)
 | 
			
		||||
  if ((r = verify_path(path, ino, &attr, NULL)) != OK)
 | 
			
		||||
	return r;
 | 
			
		||||
 | 
			
		||||
  m_out.m_fs_vfs_chmod.mode = get_mode(ino, attr.a_mode);
 | 
			
		||||
  *mode = get_mode(ino, attr.a_mode);
 | 
			
		||||
 | 
			
		||||
  return OK;
 | 
			
		||||
}
 | 
			
		||||
@ -135,7 +128,7 @@ int do_chmod(void)
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				do_utime				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
int do_utime(void)
 | 
			
		||||
int do_utime(ino_t ino_nr, struct timespec *atime, struct timespec *mtime)
 | 
			
		||||
{
 | 
			
		||||
/* Set file times.
 | 
			
		||||
 */
 | 
			
		||||
@ -147,7 +140,7 @@ int do_utime(void)
 | 
			
		||||
  if (state.s_read_only)
 | 
			
		||||
	return EROFS;
 | 
			
		||||
 | 
			
		||||
  if ((ino = find_inode(m_in.m_vfs_fs_utime.inode)) == NULL)
 | 
			
		||||
  if ((ino = find_inode(ino_nr)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
 | 
			
		||||
  if ((r = verify_inode(ino, path, NULL)) != OK)
 | 
			
		||||
@ -155,37 +148,31 @@ int do_utime(void)
 | 
			
		||||
 | 
			
		||||
  attr.a_mask = 0;
 | 
			
		||||
 | 
			
		||||
  switch(m_in.m_vfs_fs_utime.acnsec) {
 | 
			
		||||
  switch (atime->tv_nsec) {
 | 
			
		||||
  case UTIME_OMIT: /* do not touch */
 | 
			
		||||
	break;
 | 
			
		||||
  case UTIME_NOW:
 | 
			
		||||
	/* 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*/
 | 
			
		||||
  default:
 | 
			
		||||
	/* cases m_in.m_vfs_fs_utime.acnsec < 0 || m_in.m_vfs_fs_utime.acnsec >= 1E9
 | 
			
		||||
	 * 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_atime = *atime;
 | 
			
		||||
	attr.a_mask |= SFFS_ATTR_ATIME;
 | 
			
		||||
	break;
 | 
			
		||||
  }
 | 
			
		||||
  switch(m_in.m_vfs_fs_utime.modnsec) {
 | 
			
		||||
 | 
			
		||||
  switch (mtime->tv_nsec) {
 | 
			
		||||
  case UTIME_OMIT: /* do not touch */
 | 
			
		||||
	break;
 | 
			
		||||
  case UTIME_NOW:
 | 
			
		||||
	/* 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*/
 | 
			
		||||
  default:
 | 
			
		||||
	/* cases m_in.m_vfs_fs_utime.modnsec < 0 || m_in.m_vfs_fs_utime.modnsec >= 1E9
 | 
			
		||||
	 * 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_mtime = *mtime;
 | 
			
		||||
	attr.a_mask |= SFFS_ATTR_MTIME;
 | 
			
		||||
	break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return sffs_table->t_setattr(path, &attr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -7,42 +7,22 @@
 | 
			
		||||
#define _TABLE
 | 
			
		||||
#include "inc.h"
 | 
			
		||||
 | 
			
		||||
int (*call_vec[])(void) = {
 | 
			
		||||
	no_sys,		/*  0			*/
 | 
			
		||||
	no_sys,		/*  1 getnode		*/
 | 
			
		||||
	do_putnode,	/*  2 putnode		*/
 | 
			
		||||
	no_sys,		/*  3 slink		*/
 | 
			
		||||
	do_ftrunc,	/*  4 ftrunc		*/
 | 
			
		||||
	no_sys,		/*  5 chown		*/
 | 
			
		||||
	do_chmod,	/*  6 chmod		*/
 | 
			
		||||
	do_noop,	/*  7 inhibread		*/
 | 
			
		||||
	do_stat,	/*  8 stat		*/
 | 
			
		||||
	do_utime,	/*  9 utime		*/
 | 
			
		||||
	do_statvfs,	/* 10 statvfs		*/
 | 
			
		||||
	no_sys,		/* 11 bread		*/
 | 
			
		||||
	no_sys,		/* 12 bwrite		*/
 | 
			
		||||
	do_unlink,	/* 13 unlink		*/
 | 
			
		||||
	do_rmdir,	/* 14 rmdir		*/
 | 
			
		||||
	do_unmount,	/* 15 unmount		*/
 | 
			
		||||
	do_noop,	/* 16 sync		*/
 | 
			
		||||
	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		*/
 | 
			
		||||
struct fsdriver sffs_dtable = {
 | 
			
		||||
	.fdr_mount	= do_mount,
 | 
			
		||||
	.fdr_unmount	= do_unmount,
 | 
			
		||||
	.fdr_lookup	= do_lookup,
 | 
			
		||||
	.fdr_putnode	= do_putnode,
 | 
			
		||||
	.fdr_read	= do_read,
 | 
			
		||||
	.fdr_write	= do_write,
 | 
			
		||||
	.fdr_getdents	= do_getdents,
 | 
			
		||||
	.fdr_trunc	= do_trunc,
 | 
			
		||||
	.fdr_create	= do_create,
 | 
			
		||||
	.fdr_mkdir	= do_mkdir,
 | 
			
		||||
	.fdr_unlink	= do_unlink,
 | 
			
		||||
	.fdr_rmdir	= do_rmdir,
 | 
			
		||||
	.fdr_rename	= do_rename,
 | 
			
		||||
	.fdr_stat	= do_stat,
 | 
			
		||||
	.fdr_chmod	= do_chmod,
 | 
			
		||||
	.fdr_utime	= do_utime,
 | 
			
		||||
	.fdr_statvfs	= do_statvfs
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* 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. */
 | 
			
		||||
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,
 | 
			
		||||
				 * has no relation to the shared folder mode */
 | 
			
		||||
  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:
 | 
			
		||||
 *   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:
 | 
			
		||||
 *   April 2009 (D.C. van Moolenbroek)
 | 
			
		||||
@ -10,32 +10,27 @@
 | 
			
		||||
 | 
			
		||||
#include "inc.h"
 | 
			
		||||
 | 
			
		||||
static int write_file(struct inode *ino, u64_t *posp, size_t *countp,
 | 
			
		||||
	cp_grant_id_t *grantp);
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				write_file				     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
static int write_file(struct inode *ino, u64_t *posp, size_t *countp,
 | 
			
		||||
	cp_grant_id_t *grantp)
 | 
			
		||||
static ssize_t write_file(struct inode *ino, off_t pos, size_t count,
 | 
			
		||||
	struct fsdriver_data *data)
 | 
			
		||||
{
 | 
			
		||||
/* Write data or zeroes to a file, depending on whether a valid pointer to
 | 
			
		||||
 * a data grant was provided.
 | 
			
		||||
 */
 | 
			
		||||
  u64_t pos;
 | 
			
		||||
  size_t count, size;
 | 
			
		||||
  vir_bytes off;
 | 
			
		||||
  size_t size, off, chunk;
 | 
			
		||||
  char *ptr;
 | 
			
		||||
  int r, chunk;
 | 
			
		||||
  int r;
 | 
			
		||||
 | 
			
		||||
  if (pos < 0)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
 | 
			
		||||
  assert(!IS_DIR(ino));
 | 
			
		||||
 | 
			
		||||
  if ((r = get_handle(ino)) != OK)
 | 
			
		||||
	return r;
 | 
			
		||||
 | 
			
		||||
  pos = *posp;
 | 
			
		||||
  count = *countp;
 | 
			
		||||
 | 
			
		||||
  assert(count > 0);
 | 
			
		||||
 | 
			
		||||
  /* 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) {
 | 
			
		||||
	chunk = MIN(count, size);
 | 
			
		||||
 | 
			
		||||
	if (grantp != NULL) {
 | 
			
		||||
		r = sys_safecopyfrom(m_in.m_source, *grantp,
 | 
			
		||||
			off, (vir_bytes) ptr, chunk);
 | 
			
		||||
 | 
			
		||||
		if (r != OK)
 | 
			
		||||
	if (data != NULL) {
 | 
			
		||||
		if ((r = fsdriver_copyin(data, off, ptr, chunk)) != OK)
 | 
			
		||||
			break;
 | 
			
		||||
	} else {
 | 
			
		||||
		/* 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)
 | 
			
		||||
	return r;
 | 
			
		||||
 | 
			
		||||
  *posp = pos;
 | 
			
		||||
  *countp = off;
 | 
			
		||||
 | 
			
		||||
  return OK;
 | 
			
		||||
  return off;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				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.
 | 
			
		||||
 */
 | 
			
		||||
  struct inode *ino;
 | 
			
		||||
  off_t pos;
 | 
			
		||||
  size_t count;
 | 
			
		||||
  cp_grant_id_t grant;
 | 
			
		||||
  int r;
 | 
			
		||||
 | 
			
		||||
  if (state.s_read_only)
 | 
			
		||||
	return EROFS;
 | 
			
		||||
 | 
			
		||||
  if ((ino = find_inode(m_in.m_vfs_fs_readwrite.inode)) == NULL)
 | 
			
		||||
  if ((ino = find_inode(ino_nr)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
 | 
			
		||||
  if (IS_DIR(ino)) return EISDIR;
 | 
			
		||||
 | 
			
		||||
  pos = m_in.m_vfs_fs_readwrite.seek_pos;
 | 
			
		||||
  count = m_in.m_vfs_fs_readwrite.nbytes;
 | 
			
		||||
  grant = m_in.m_vfs_fs_readwrite.grant;
 | 
			
		||||
  if (count == 0) return 0;
 | 
			
		||||
 | 
			
		||||
  if (count == 0) return EINVAL;
 | 
			
		||||
 | 
			
		||||
  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;
 | 
			
		||||
  return write_file(ino, pos, count, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				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.
 | 
			
		||||
 */
 | 
			
		||||
  char path[PATH_MAX];
 | 
			
		||||
  struct inode *ino;
 | 
			
		||||
  struct sffs_attr attr;
 | 
			
		||||
  u64_t start, end, delta;
 | 
			
		||||
  size_t count;
 | 
			
		||||
  int r;
 | 
			
		||||
  uint64_t delta;
 | 
			
		||||
  ssize_t r;
 | 
			
		||||
 | 
			
		||||
  if (state.s_read_only)
 | 
			
		||||
	return EROFS;
 | 
			
		||||
 | 
			
		||||
  if ((ino = find_inode(m_in.m_vfs_fs_ftrunc.inode)) == NULL)
 | 
			
		||||
  if ((ino = find_inode(ino_nr)) == NULL)
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
 | 
			
		||||
  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) {
 | 
			
		||||
	/* Truncate or expand the file. */
 | 
			
		||||
	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. */
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	r = write_file(ino, &start, &count, NULL);
 | 
			
		||||
	if ((r = write_file(ino, start, (size_t)delta, NULL)) >= 0)
 | 
			
		||||
		r = OK;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return r;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user