Ejemplo n.º 1
0
/*===========================================================================*
 *				verify_dentry				     *
 *===========================================================================*/
int verify_dentry(
	struct inode *parent, 	/* parent inode: the inode to verify */
	char name[NAME_MAX+1],	/* the given directory entry path component */
	char path[PATH_MAX],  	/* buffer to store the resulting path in */
	struct inode **res_ino	/* pointer for addressed inode (or NULL) */
)
{
/* Given a directory inode and a name, construct a path identifying that
 * directory entry, check whether the path to the parent is still valid, and
 * check whether there is an inode pointed to by the full path. Upon success,
 * res_ino will contain either the inode for the full path, with increased
 * refcount, or NULL if no such inode exists.
 */
  int r;

  if ((r = verify_inode(parent, path, NULL)) != OK)
	return r;

  dprintf(("%s: verify_dentry: given path is '%s', name '%s'\n",
	sffs_name, path, name));

  if ((r = push_path(path, name)) != OK)
	return r;

  dprintf(("%s: verify_dentry: path now '%s'\n", sffs_name, path));

  *res_ino = lookup_dentry(parent, name);

  return OK;
}
Ejemplo n.º 2
0
static struct dentry *snd_info_card_followlink(struct dentry *dentry,
					       struct dentry *base,
					       unsigned int follow)
{
	char *s = ((struct proc_dir_entry *) dentry->d_inode->u.generic_ip)->data;
	return lookup_dentry(s, base, follow);
}
Ejemplo n.º 3
0
static struct dentry * autofs_follow_link(struct dentry *dentry,
					struct dentry *base,
					unsigned int follow)
{
	struct autofs_symlink *sl;

	sl = (struct autofs_symlink *)dentry->d_inode->u.generic_ip;
	return lookup_dentry(sl->data, base, follow);
}
Ejemplo n.º 4
0
/*===========================================================================*
 *				go_down					     *
 *===========================================================================*/
static int go_down(
	char path[PATH_MAX],    /* path to add the name to */
	struct inode *parent,   /* inode of the current directory */
	char *name,             /* name of the directory entry */
	struct inode **res_ino, /* place to store resulting inode */
	struct sffs_attr *attr  /* place to store inode attributes */
)
{
/* Given a directory inode and a name, progress into a directory entry.
 */
  struct inode *ino;
  int r, stale = 0;

  if ((r = push_path(path, name)) != OK)
	return r;

  dprintf(("%s: go_down: name '%s', path now '%s'\n", sffs_name, name, path));

  ino = lookup_dentry(parent, name);

  dprintf(("%s: lookup_dentry('%s') returned %p\n", sffs_name, name, ino));

  if (ino != NULL)
	r = verify_path(path, ino, attr, &stale);
  else
	r = sffs_table->t_getattr(path, attr);

  dprintf(("%s: path query returned %d\n", sffs_name, r));

  if (r != OK) {
	if (ino != NULL) {
		put_inode(ino);

		ino = NULL;
	}

	if (!stale)
		return r;
  }

  dprintf(("%s: name '%s'\n", sffs_name, name));

  if (ino == NULL) {
	if ((ino = get_free_inode()) == NULL)
		return ENFILE;

	dprintf(("%s: inode %p ref %d\n", sffs_name, ino, ino->i_ref));

	ino->i_flags = MODE_TO_DIRFLAG(attr->a_mode);

	add_dentry(parent, name, ino);
  }

  *res_ino = ino;
  return OK;
}
Ejemplo n.º 5
0
static struct dentry *devtree_follow_link(struct dentry *dentry,
					  struct dentry *base,
					  unsigned int follow)
{
	struct inode *inode = dentry->d_inode;
	struct proc_dir_entry * de;
	char *link;

	de = (struct proc_dir_entry *) inode->u.generic_ip;
	link = (char *) de->data;
	return lookup_dentry(link, base, follow);
}
Ejemplo n.º 6
0
static struct dentry *efs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow) {
	char *name;
	struct inode *inode = dentry->d_inode;

	if (!(name = efs_linktarget(inode, NULL))) {
		dput(base);
		return ERR_PTR(-ELOOP);
	}
	base = lookup_dentry(name, base, follow);
	kfree(name);
  
	return base;
}
Ejemplo n.º 7
0
static struct dentry *ncp_follow_link(struct dentry *dentry,
				      struct dentry *base,
				      unsigned int follow)
{
	struct inode *inode=dentry->d_inode;
	int error, length, cnt;
	char *link;

#ifdef DEBUG
	printk("ncp_follow_link(dentry=%p,base=%p,follow=%u)\n",dentry,base,follow);
#endif

	if(!S_ISLNK(inode->i_mode)) {
		dput(base);
		return ERR_PTR(-EINVAL);
	}

	if(ncp_make_open(inode,O_RDONLY)) {
		dput(base);
		return ERR_PTR(-EIO);
	}

	for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1, GFP_NFS))==NULL; cnt++) {
		if (cnt > 10) {
			dput(base);
			return ERR_PTR(-EAGAIN); /* -ENOMEM? */
		}
		schedule();
	}

	error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
                         0,NCP_MAX_SYMLINK_SIZE,link,&length);

	if (error!=0 || length<NCP_MIN_SYMLINK_SIZE || 
	   ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 || ((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
		dput(base);
		kfree(link);
		return ERR_PTR(-EIO);
	}
 
	link[length]=0;

	vol2io(NCP_SERVER(inode), link+8, 0);
	
	/* UPDATE_ATIME(inode); */
	base=lookup_dentry(link+8, base, follow);
	kfree(link);

	return base;
}
Ejemplo n.º 8
0
static struct dir_entry *path_to_dentry(struct vmm_blockdev *mdev,
					const char *path,
					struct dir_entry *pdentry)
{
	char dirname[VFS_MAX_NAME] = { 0 };
	struct dir_entry *dentry, *d_root;
	int i = 0, rd;
	int len = 0;
	char rpath[VFS_MAX_NAME];

	len = strlen(path);

	if (!len) return NULL;

	vmm_snprintf(rpath, len, "%s", path);
	if (rpath[len - 1] != '/') {
		rpath[len] = '/';
		rpath[len+1] = 0;
	}

	path = rpath;

	if (*path == '/') {
		path++;
		if (!*path) return pdentry;
	}

	while (*path && *path != '/') {
		dirname[i] = *path;
		path++;
		i++;
	}

	dentry = lookup_dentry(dirname, pdentry);
	if (dentry) {
		d_root = vmm_zalloc(dentry->dlen.lsb);
		rd = vmm_blockdev_read(mdev, (u8 *)d_root,
				       (dentry->start_lba.lsb * 2048),
				       dentry->dlen.lsb);
		if (rd != dentry->dlen.lsb) {
			vmm_free(d_root);
			return NULL;
		}
		dentry = path_to_dentry(mdev, path, d_root);
	}

	return dentry;
}
Ejemplo n.º 9
0
static struct dentry *qnx4_follow_link(struct dentry *dentry,
				       struct dentry *base, unsigned int follow)
{
	struct inode *inode = dentry->d_inode;
	struct buffer_head *bh;

	if ( !inode ) {
		return ERR_PTR(-ENOENT);
	}
	if ( !( bh = qnx4_bread( inode, 0, 0 ) ) ) {
		dput( base );
		return ERR_PTR(-EIO);
	}
	UPDATE_ATIME( inode );
	base = lookup_dentry( bh->b_data, base, follow );
	brelse( bh );
	return base;
}
Ejemplo n.º 10
0
void devfs_init(void)
{
	int mode;
	/* Make sure there is a dev directory */
	struct dentry *dentry = lookup_dentry("/dev/", 0);	
	if (!dentry) {
		assert(!do_mkdir("/dev/", S_IRWXU | S_IRWXG | S_IRWXO));
	} else {
		kref_put(&dentry->d_kref);
	}
	/* Notice we don't kref_put().  We're storing the refs globally */
	dev_stdin = make_device("/dev/stdin", S_IRUSR | S_IRGRP | S_IROTH,
	                        __S_IFCHR, &dev_f_op_stdin);
	dev_stdout = make_device("/dev/stdout", S_IWUSR | S_IWGRP | S_IWOTH,
	                         __S_IFCHR, &dev_f_op_stdout);
	/* Note stderr uses the same f_op as stdout */
	dev_stderr = make_device("/dev/stderr", S_IWUSR | S_IWGRP | S_IWOTH,
	                         __S_IFCHR, &dev_f_op_stdout);
	dev_null = make_device("/dev/null", S_IWUSR | S_IWGRP | S_IWOTH,
	                       __S_IFCHR, &dev_f_op_null);
}
Ejemplo n.º 11
0
int
osi_lookupname(char *aname, uio_seg_t seg, int followlink, struct dentry **dpp)
{
    struct dentry *dp = NULL;
    int code;

    code = ENOENT;
    if (seg == AFS_UIOUSER) {
        dp = followlink ? namei(aname) : lnamei(aname);
    } else {
        dp = lookup_dentry(aname, NULL, followlink ? 1 : 0);
    }

    if (dp && !IS_ERR(dp)) {
        if (dp->d_inode) {
            *dpp = dp;
            code = 0;
        } else
            dput(dp);
    }

    return code;
}
Ejemplo n.º 12
0
/*
 * Look up one component of a pathname.
 * N.B. After this call _both_ fhp and resfh need an fh_put
 */
int
nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
					int len, struct svc_fh *resfh)
{
	struct svc_export	*exp;
	struct dentry		*dparent, *dchild;
	int			err;

	dprintk("nfsd: nfsd_lookup(fh %p, %s)\n", SVCFH_DENTRY(fhp), name);

	/* Obtain dentry and export. */
	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_EXEC);
	if (err)
		goto out;

	dparent = fhp->fh_dentry;
	exp  = fhp->fh_export;

#if 0
	err = nfsd_permission(exp, dparent, MAY_EXEC);
	if (err)
		goto out;
#endif
	err = nfserr_noent;
	if (fs_off_limits(dparent->d_sb))
		goto out;
	err = nfserr_acces;
	if (nfsd_iscovered(dparent, exp))
		goto out;

	/* Lookup the name, but don't follow links */
	dchild = lookup_dentry(name, dget(dparent), 0);
	if (IS_ERR(dchild))
		goto out_nfserr;
	/*
	 * check if we have crossed a mount point ...
	 */
	if (dchild->d_sb != dparent->d_sb) {
		struct dentry *tdentry;
		tdentry = dchild->d_covers;
		if (tdentry == dchild)
			goto out_dput;
	        dput(dchild);
		dchild = dget(tdentry);
	        if (dchild->d_sb != dparent->d_sb) {
printk("nfsd_lookup: %s/%s crossed mount point!\n", dparent->d_name.name, dchild->d_name.name);
			goto out_dput;
		}
	}

	/*
	 * Note: we compose the file handle now, but as the
	 * dentry may be negative, it may need to be updated.
	 */
	fh_compose(resfh, exp, dchild);
	err = nfserr_noent;
	if (dchild->d_inode)
		err = 0;
out:
	return err;

out_nfserr:
	err = nfserrno(-PTR_ERR(dchild));
	goto out;
out_dput:
	dput(dchild);
	err = nfserr_acces;
	goto out;
}
Ejemplo n.º 13
0
int __init change_root(kdev_t new_root_dev,const char *put_old)
{
	kdev_t old_root_dev;
	struct vfsmount *vfsmnt;
	struct dentry *old_root,*old_pwd,*dir_d = NULL;
	int error;

	old_root = current->fs->root;
	old_pwd = current->fs->pwd;
	old_root_dev = ROOT_DEV;
	if (!fs_may_mount(new_root_dev)) {
		printk(KERN_CRIT "New root is busy. Staying in initrd.\n");
		return -EBUSY;
	}
	ROOT_DEV = new_root_dev;
	mount_root();
	dput(old_root);
	dput(old_pwd);
#if 1
	shrink_dcache();
	printk("change_root: old root has d_count=%d\n", old_root->d_count);
#endif
	/*
	 * Get the new mount directory
	 */
	dir_d = lookup_dentry(put_old, NULL, 1);
	if (IS_ERR(dir_d)) {
		error = PTR_ERR(dir_d);
	} else if (!dir_d->d_inode) {
		dput(dir_d);
		error = -ENOENT;
	} else {
		error = 0;
	}
	if (!error && dir_d->d_covers != dir_d) {
		dput(dir_d);
		error = -EBUSY;
	}
	if (!error && !S_ISDIR(dir_d->d_inode->i_mode)) {
		dput(dir_d);
		error = -ENOTDIR;
	}
	if (error) {
		int umount_error;

		printk(KERN_NOTICE "Trying to unmount old root ... ");
		umount_error = do_umount(old_root_dev,1, 0);
		if (!umount_error) {
			printk("okay\n");
			/* special: the old device driver is going to be
			   a ramdisk and the point of this call is to free its
			   protected memory (even if dirty). */
			destroy_buffers(old_root_dev);
			return 0;
		}
		printk(KERN_ERR "error %d\n",umount_error);
		return error;
	}
	remove_vfsmnt(old_root_dev);
	vfsmnt = add_vfsmnt(old_root->d_sb, "/dev/root.old", put_old);
	if (vfsmnt) {
		d_mount(dir_d,old_root);
		return 0;
	}
	printk(KERN_CRIT "Trouble: add_vfsmnt failed\n");
	return -ENOMEM;
}
Ejemplo n.º 14
0
Archivo: read.c Proyecto: Sciumo/minix
/*===========================================================================*
 *				do_getdents				     *
 *===========================================================================*/
int do_getdents()
{
/* Retrieve directory entries.
 */
  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;
  /* 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.REQ_INODE_NR)) == NULL)
	return EINVAL;

  if (m_in.REQ_SEEK_POS_HI != 0) return EINVAL;

  if (!IS_DIR(ino)) return ENOTDIR;

  /* We are going to need at least one free inode to store children in. */
  if (!have_free_inode()) return ENFILE;

  /* If we don't have a directory handle yet, get one now. */
  if ((r = get_handle(ino)) != OK)
	return r;

  off = 0;
  user_off = 0;
  user_left = m_in.REQ_MEM_SIZE;

  /* 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.REQ_SEEK_POS_LO; ; pos++) {
	/* 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.
	 */
	if (pos == 0) {
		/* Entry for ".". */
		child = ino;

		strcpy(name, ".");

		get_inode(child);
	}
	else if (pos == 1) {
		/* Entry for "..", but only when there is a parent. */
		if (ino->i_parent == NULL)
			continue;

		child = ino->i_parent;

		strcpy(name, "..");

		get_inode(child);
	}
	else {
		/* Any other entry, not being "." or "..". */
		r = sffs_table->t_readdir(ino->i_dir, pos - 2, name,
			sizeof(name), &attr);

		if (r != OK) {
			/* No more entries? Then close the handle and stop. */
			if (r == ENOENT) {
				put_handle(ino);

				break;
			}

			/* FIXME: what if the error is ENAMETOOLONG? */
			return r;
		}

		if (!strcmp(name, ".") || !strcmp(name, ".."))
			continue;

		if ((child = lookup_dentry(ino, name)) == NULL) {
			child = get_free_inode();

			/* We were promised a free inode! */
			assert(child != NULL);

			child->i_flags = MODE_TO_DIRFLAG(attr.a_mode);

			add_dentry(ino, name, child);
		}
	}

	len = DWORD_ALIGN(sizeof(struct dirent) + strlen(name));

	/* 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.REQ_GRANT,
			user_off, (vir_bytes) buf, off, D);

		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_off = pos;
	dent->d_reclen = len;
	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.REQ_GRANT, user_off,
		(vir_bytes) buf, off, D);

	if (r != OK)
		return r;

	user_off += off;
  }

  m_out.RES_SEEK_POS_HI = 0;
  m_out.RES_SEEK_POS_LO = pos;
  m_out.RES_NBYTES = user_off;

  return OK;
}
Ejemplo n.º 15
0
/*
 * Create a hardlink
 * N.B. After this call _both_ ffhp and tfhp need an fh_put
 */
int
nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
				char *fname, int len, struct svc_fh *tfhp)
{
	struct dentry	*ddir, *dnew, *dold;
	struct inode	*dirp, *dest;
	int		err;

	err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE);
	if (err)
		goto out;
	err = fh_verify(rqstp, tfhp, S_IFREG, MAY_NOP);
	if (err)
		goto out;

	err = nfserr_perm;
	if (!len)
		goto out;

	ddir = ffhp->fh_dentry;
	dirp = ddir->d_inode;

	dnew = lookup_dentry(fname, dget(ddir), 0);
	err = PTR_ERR(dnew);
	if (IS_ERR(dnew))
		goto out_nfserr;
	/*
	 * Lock the parent before checking for existence
	 */
	err = fh_lock_parent(ffhp, dnew);
	if (err)
		goto out_dput;

	err = nfserr_exist;
	if (dnew->d_inode)
		goto out_unlock;

	dold = tfhp->fh_dentry;
	dest = dold->d_inode;

	err = nfserr_acces;
	if (nfsd_iscovered(ddir, ffhp->fh_export))
		goto out_unlock;
	/* FIXME: nxdev for NFSv3 */
	if (dirp->i_dev != dest->i_dev)
		goto out_unlock;

	err = nfserr_perm;
	if (IS_IMMUTABLE(dest) /* || IS_APPEND(dest) */ )
		goto out_unlock;
	if (!dirp->i_op || !dirp->i_op->link)
		goto out_unlock;

	DQUOT_INIT(dirp);
	err = dirp->i_op->link(dold, dirp, dnew);
	DQUOT_DROP(dirp);
	if (!err) {
		if (EX_ISSYNC(ffhp->fh_export)) {
			write_inode_now(dirp);
			write_inode_now(dest);
		}
	} else
		err = nfserrno(-err);

out_unlock:
	fh_unlock(ffhp);
out_dput:
	dput(dnew);
out:
	return err;

out_nfserr:
	err = nfserrno(-err);
	goto out;
}
Ejemplo n.º 16
0
/*
 * Create a symlink and look up its inode
 * N.B. After this call _both_ fhp and resfhp need an fh_put
 */
int
nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
				char *fname, int flen,
				char *path,  int plen,
				struct svc_fh *resfhp)
{
	struct dentry	*dentry, *dnew;
	struct inode	*dirp;
	int		err;

	err = nfserr_noent;
	if (!flen || !plen)
		goto out;

	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
	if (err)
		goto out;
	dentry = fhp->fh_dentry;

	err = nfserr_perm;
	if (nfsd_iscovered(dentry, fhp->fh_export))
		goto out;
	dirp = dentry->d_inode;
	if (!dirp->i_op	|| !dirp->i_op->symlink)
		goto out;

	dnew = lookup_dentry(fname, dget(dentry), 0);
	err = PTR_ERR(dnew);
	if (IS_ERR(dnew))
		goto out_nfserr;

	/*
	 * Lock the parent before checking for existence
	 */
	err = fh_lock_parent(fhp, dnew);
	if (err)
		goto out_compose;

	err = nfserr_exist;
	if (!dnew->d_inode) {
		DQUOT_INIT(dirp);
		err = dirp->i_op->symlink(dirp, dnew, path);
		DQUOT_DROP(dirp);
		if (!err) {
			if (EX_ISSYNC(fhp->fh_export))
				write_inode_now(dirp);
		} else
			err = nfserrno(-err);
	}
	fh_unlock(fhp);

	/* Compose the fh so the dentry will be freed ... */
out_compose:
	fh_compose(resfhp, fhp->fh_export, dnew);
out:
	return err;

out_nfserr:
	err = nfserrno(-err);
	goto out;
}
Ejemplo n.º 17
0
/*
 * Create a file (regular, directory, device, fifo); UNIX sockets 
 * not yet implemented.
 * If the response fh has been verified, the parent directory should
 * already be locked. Note that the parent directory is left locked.
 *
 * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp
 */
int
nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
		char *fname, int flen, struct iattr *iap,
		int type, dev_t rdev, struct svc_fh *resfhp)
{
	struct dentry	*dentry, *dchild;
	struct inode	*dirp;
	nfsd_dirop_t	opfunc = NULL;
	int		err;

	err = nfserr_perm;
	if (!flen)
		goto out;
	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
	if (err)
		goto out;

	dentry = fhp->fh_dentry;
	dirp = dentry->d_inode;

	err = nfserr_notdir;
	if(!dirp->i_op || !dirp->i_op->lookup)
		goto out;
	/*
	 * Check whether the response file handle has been verified yet.
	 * If it has, the parent directory should already be locked.
	 */
	if (!resfhp->fh_dverified) {
		dchild = lookup_dentry(fname, dget(dentry), 0);
		err = PTR_ERR(dchild);
		if (IS_ERR(dchild))
			goto out_nfserr;
		fh_compose(resfhp, fhp->fh_export, dchild);
		/* Lock the parent and check for errors ... */
		err = fh_lock_parent(fhp, dchild);
		if (err)
			goto out;
	} else {
		dchild = resfhp->fh_dentry;
		if (!fhp->fh_locked)
			printk(KERN_ERR
				"nfsd_create: parent %s/%s not locked!\n",
				dentry->d_parent->d_name.name,
				dentry->d_name.name);
	}
	/*
	 * Make sure the child dentry is still negative ...
	 */
	err = nfserr_exist;
	if (dchild->d_inode) {
		printk(KERN_WARNING
			"nfsd_create: dentry %s/%s not negative!\n",
			dentry->d_name.name, dchild->d_name.name);
		goto out; 
	}

	/*
	 * Get the dir op function pointer.
	 */
	err = nfserr_perm;
	switch (type) {
	case S_IFREG:
		opfunc = (nfsd_dirop_t) dirp->i_op->create;
		break;
	case S_IFDIR:
		opfunc = (nfsd_dirop_t) dirp->i_op->mkdir;
		break;
	case S_IFCHR:
	case S_IFBLK:
		/* The client is _NOT_ required to do security enforcement */
		if(!capable(CAP_SYS_ADMIN))
		{
			err = -EPERM;
			goto out;
		}
	case S_IFIFO:
	case S_IFSOCK:
		opfunc = dirp->i_op->mknod;
		break;
	}
	if (!opfunc)
		goto out;

	if (!(iap->ia_valid & ATTR_MODE))
		iap->ia_mode = 0;

	/*
	 * Call the dir op function to create the object.
	 */
	DQUOT_INIT(dirp);
	err = opfunc(dirp, dchild, iap->ia_mode, rdev);
	DQUOT_DROP(dirp);
	if (err < 0)
		goto out_nfserr;

	if (EX_ISSYNC(fhp->fh_export))
		write_inode_now(dirp);

	/*
	 * Update the file handle to get the new inode info.
	 */
	fh_update(resfhp);

	/* Set file attributes. Mode has already been set and
	 * setting uid/gid works only for root. Irix appears to
	 * send along the gid when it tries to implement setgid
	 * directories via NFS.
	 */
	err = 0;
	if ((iap->ia_valid &= (ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
		err = nfsd_setattr(rqstp, resfhp, iap);
out:
	return err;

out_nfserr:
	err = nfserrno(-err);
	goto out;
}
Ejemplo n.º 18
0
Archivo: redir.c Proyecto: lb1a/avfs
static char *resolv_virt(const char *pathname, int must_exist, int flags)
{
	struct dentry *root, *origroot;
	struct dentry *dentry;
	char *newpathname = NULL;
	char *page = NULL;
	char *path = NULL;
	int pathlen = 0;

	lock_kernel();

	DEB((KERN_INFO "resolve_virt pathname: '%s'\n", 
	     pathname ? pathname : "(null)"));

	root = lookup_dentry(OVERLAY_DIR, NULL, 1);
	if(IS_ERR(root))
		goto out;
	
	if(!root->d_inode) {
		dput(root);
		goto out;
	}

	origroot = current->fs->root;
	current->fs->root = root;
	
	dentry = lookup_dentry(pathname, NULL, flags);
	if(!IS_ERR(dentry)) {
		if((!must_exist || dentry->d_inode) && path_ok(dentry)) {
			page = (char *) __get_free_page(GFP_USER);
			if(page) {
				path = d_path(dentry, page, PAGE_SIZE);
				DEB((KERN_INFO "resolve_virt path = '%s'\n",
				     path));
				pathlen = (unsigned int) page + PAGE_SIZE - 
					(unsigned int) path;
			}
		}
		dput(dentry);
	}

	current->fs->root = origroot;
	dput(root);

	if(path) {
		int isvirtual;

		dentry = lookup_dentry(path, NULL, flags);

		if(!IS_ERR(dentry)) {
			if(dentry->d_inode)
				isvirtual = 0;
			else if(must_exist)
				isvirtual = 1;
			else if(strchr(path, AVFS_MAGIC_CHAR))
				isvirtual = 1;
			else 
				isvirtual = 0;

			dput(dentry);
		}
		else {
			isvirtual = 1;
		}

		if(!isvirtual) {
			newpathname = kmalloc(pathlen + 1, 
					      GFP_USER);
			if(newpathname)
				strncpy(newpathname, path, pathlen);
		}
		else {
			newpathname = kmalloc(OVERLAY_DIR_LEN + pathlen + 1,
					      GFP_USER);

			if(newpathname) {
				strcpy(newpathname, OVERLAY_DIR);
				strncat(newpathname, path, pathlen);
			}
		}
	}

	if(page)
		free_page((unsigned long) page);


	DEB((KERN_INFO "resolve_virt newpathname: '%s'\n", 
	     newpathname ? newpathname : "(null)"));

 out:
	unlock_kernel();
	return newpathname;
}
Ejemplo n.º 19
0
/*
 * Unlink a file or directory
 * N.B. After this call fhp needs an fh_put
 */
int
nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
				char *fname, int flen)
{
	struct dentry	*dentry, *rdentry;
	struct inode	*dirp;
	int		err;

	/* N.B. We shouldn't need this test ... handled by dentry layer */
	err = nfserr_acces;
	if (!flen || isdotent(fname, flen))
		goto out;
	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_REMOVE);
	if (err)
		goto out;

	dentry = fhp->fh_dentry;
	dirp = dentry->d_inode;

	rdentry = lookup_dentry(fname, dget(dentry), 0);
	err = PTR_ERR(rdentry);
	if (IS_ERR(rdentry))
		goto out_nfserr;

	if (!rdentry->d_inode) {
		dput(rdentry);
		err = nfserr_noent;
		goto out;
	}

	if (type != S_IFDIR) {
		/* It's UNLINK */
		err = fh_lock_parent(fhp, rdentry);
		if (err)
			goto out;

		err = vfs_unlink(dirp, rdentry);

		DQUOT_DROP(dirp);
		fh_unlock(fhp);

		dput(rdentry);

	} else {
		/* It's RMDIR */
		/* See comments in fs/namei.c:do_rmdir */
		rdentry->d_count++;
		nfsd_double_down(&dirp->i_sem, &rdentry->d_inode->i_sem);
		if (!fhp->fh_pre_mtime)
			fhp->fh_pre_mtime = dirp->i_mtime;
		fhp->fh_locked = 1;

		err = -ENOENT;
		if (check_parent(dirp, rdentry))
			err = vfs_rmdir(dirp, rdentry);

		rdentry->d_count--;
		DQUOT_DROP(dirp);
		if (!fhp->fh_post_version)
			fhp->fh_post_version = dirp->i_version;
		fhp->fh_locked = 0;
		nfsd_double_up(&dirp->i_sem, &rdentry->d_inode->i_sem);

		dput(rdentry);
	}

	if (err)
		goto out_nfserr;
	if (EX_ISSYNC(fhp->fh_export))
		write_inode_now(dirp);
out:
	return err;

out_nfserr:
	err = nfserrno(-err);
	goto out;
}
Ejemplo n.º 20
0
/*
 * Rename a file
 * N.B. After this call _both_ ffhp and tfhp need an fh_put
 */
int
nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
			    struct svc_fh *tfhp, char *tname, int tlen)
{
	struct dentry	*fdentry, *tdentry, *odentry, *ndentry;
	struct inode	*fdir, *tdir;
	int		err;

	err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE);
	if (err)
		goto out;
	err = fh_verify(rqstp, tfhp, S_IFDIR, MAY_CREATE);
	if (err)
		goto out;

	fdentry = ffhp->fh_dentry;
	fdir = fdentry->d_inode;

	tdentry = tfhp->fh_dentry;
	tdir = tdentry->d_inode;

	/* N.B. We shouldn't need this ... dentry layer handles it */
	err = nfserr_perm;
	if (!flen || (fname[0] == '.' && 
	    (flen == 1 || (flen == 2 && fname[1] == '.'))) ||
	    !tlen || (tname[0] == '.' && 
	    (tlen == 1 || (tlen == 2 && tname[1] == '.'))))
		goto out;

	odentry = lookup_dentry(fname, dget(fdentry), 0);
	err = PTR_ERR(odentry);
	if (IS_ERR(odentry))
		goto out_nfserr;

	err = -ENOENT;
	if (!odentry->d_inode)
		goto out_dput_old;

	ndentry = lookup_dentry(tname, dget(tdentry), 0);
	err = PTR_ERR(ndentry);
	if (IS_ERR(ndentry))
		goto out_dput_old;

	/*
	 * Lock the parent directories.
	 */
	nfsd_double_down(&tdir->i_sem, &fdir->i_sem);
	err = -ENOENT;
	/* GAM3 check for parent changes after locking. */
	if (check_parent(fdir, odentry) &&
	    check_parent(tdir, ndentry)) {

		err = vfs_rename(fdir, odentry, tdir, ndentry);
		if (!err && EX_ISSYNC(tfhp->fh_export)) {
			write_inode_now(fdir);
			write_inode_now(tdir);
		}
	} else
		dprintk("nfsd: Caught race in nfsd_rename");
	DQUOT_DROP(fdir);
	DQUOT_DROP(tdir);

	nfsd_double_up(&tdir->i_sem, &fdir->i_sem);
	dput(ndentry);

out_dput_old:
	dput(odentry);
	if (err)
		goto out_nfserr;
out:
	return err;

out_nfserr:
	err = nfserrno(-err);
	goto out;
}
Ejemplo n.º 21
0
Archivo: read.c Proyecto: Hooman3/minix
/*===========================================================================*
 *				do_getdents				     *
 *===========================================================================*/
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 sffs_attr attr;
  off_t pos;
  int r;
  /* must be at least sizeof(struct dirent) + NAME_MAX */
  static char buf[BLOCK_SIZE];

  if ((ino = find_inode(ino_nr)) == NULL)
	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;

  /* If we don't have a directory handle yet, get one now. */
  if ((r = get_handle(ino)) != OK)
	return r;

  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.
   */
  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;

		strcpy(name, ".");

		get_inode(child);
	}
	else if (pos == 1) {
		/* Entry for "..", but only when there is a parent. */
		if (ino->i_parent == NULL)
			continue;

		child = ino->i_parent;

		strcpy(name, "..");

		get_inode(child);
	}
	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);

		if (r != OK) {
			/* No more entries? Then close the handle and stop. */
			if (r == ENOENT) {
				put_handle(ino);

				break;
			}

			/* FIXME: what if the error is ENAMETOOLONG? */
			return r;
		}

		if (!strcmp(name, ".") || !strcmp(name, ".."))
			continue;

		if ((child = lookup_dentry(ino, name)) == NULL) {
			child = get_free_inode();

			/* We were promised a free inode! */
			assert(child != NULL);

			child->i_flags = MODE_TO_DIRFLAG(attr.a_mode);

			add_dentry(ino, name, child);
		}
	}

	r = fsdriver_dentry_add(&fsdentry, INODE_NR(child), name, strlen(name),
		IS_DIR(child) ? DT_DIR : DT_REG);

	put_inode(child);

	if (r < 0)
		return r;
  } while (r > 0);

  return fsdriver_dentry_finish(&fsdentry);
}