Пример #1
0
int
smbfs_smb_lookup(struct smbnode *dnp, const char *name, int nmlen,
	struct smbfattr *fap, struct smb_cred *scred)
{
	struct smbfs_fctx *ctx;
	int error;

	if (dnp == NULL || (dnp->n_ino == 2 && name == NULL)) {
		memset(fap, 0, sizeof(*fap));
		fap->fa_attr = SMB_FA_DIR;
		fap->fa_ino = 2;
		return 0;
	}
	if (nmlen == 1 && name[0] == '.') {
		error = smbfs_smb_lookup(dnp, NULL, 0, fap, scred);
		return error;
	} else if (nmlen == 2 && name[0] == '.' && name[1] == '.') {
		error = smbfs_smb_lookup(VTOSMB(dnp->n_parent), NULL, 0,
		    fap, scred);
		printf("%s: knows NOTHING about '..'\n", __func__);
		return error;
	}
	error = smbfs_findopen(dnp, name, nmlen,
	    SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scred, &ctx);
	if (error)
		return error;
	ctx->f_flags |= SMBFS_RDD_FINDSINGLE;
	error = smbfs_findnext(ctx, 1, scred);
	if (error == 0) {
		*fap = ctx->f_attr;
		if (name == NULL)
			fap->fa_ino = dnp->n_ino;

		/*
		 * Check the returned file name case exactly
		 * matches requested file name. ctx->f_nmlen is
		 * guaranteed to always match nmlen.
		 */
		if (nmlen > 0 && strncmp(name, ctx->f_name, nmlen) != 0)
			error = ENOENT;
	}
	smbfs_findclose(ctx, scred);
	return error;
}
Пример #2
0
int
smbfs_smb_lookup(struct smbnode *dnp, const char *name, int nmlen,
	struct smbfattr *fap, struct smb_cred *scred)
{
	struct smbfs_fctx *ctx;
	int error;

	if (dnp == NULL || (dnp->n_ino == 2 && name == NULL)) {
		bzero(fap, sizeof(*fap));
		fap->fa_attr = SMB_FA_DIR;
		fap->fa_ino = 2;
		return 0;
	}
	if (nmlen == 1 && name[0] == '.') {
		error = smbfs_smb_lookup(dnp, NULL, 0, fap, scred);
		return error;
	} else if (nmlen == 2 && name[0] == '.' && name[1] == '.') {
		error = smbfs_smb_lookup(VTOSMB(dnp->n_parent), NULL, 0, fap,
		    scred);
		kprintf("%s: knows NOTHING about '..'\n", __func__);
		return error;
	}
	error = smbfs_findopen(dnp, name, nmlen,
	    SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scred, &ctx);
	if (error)
		return error;
	ctx->f_flags |= SMBFS_RDD_FINDSINGLE;
	error = smbfs_findnext(ctx, 1, scred);
	if (error == 0) {
		*fap = ctx->f_attr;
		if (name == NULL)
			fap->fa_ino = dnp->n_ino;
	}
	smbfs_findclose(ctx, scred);
	return error;
}
Пример #3
0
int
smbfs_mkdir(void *v)
{
	struct vop_mkdir_v3_args /* {
		struct vnode *a_dvp;
		struct vnode **a_vpp;
		struct componentname *a_cnp;
		struct vattr *a_vap;
	} */ *ap = v;
	struct vnode *dvp = ap->a_dvp;
/*	struct vattr *vap = ap->a_vap;*/
	struct vnode *vp;
	struct componentname *cnp = ap->a_cnp;
	struct smbnode *dnp = VTOSMB(dvp);
	struct smb_cred scred;
	struct smbfattr fattr;
	const char *name = cnp->cn_nameptr;
	int len = cnp->cn_namelen;
	int error;

	if ((name[0] == '.') && ((len == 1) || ((len == 2) && (name[1] == '.')))){
		error = EEXIST;
		goto out;
	}

	smb_makescred(&scred, curlwp, cnp->cn_cred);
	error = smbfs_smb_mkdir(dnp, name, len, &scred);
	if (error)
		goto out;
	error = smbfs_smb_lookup(dnp, name, len, &fattr, &scred);
	if (error)
		goto out;
	error = smbfs_nget(VTOVFS(dvp), dvp, name, len, &fattr, &vp);
	if (error)
		goto out;
	VOP_UNLOCK(vp);
	*ap->a_vpp = vp;

 out:
	VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);

	return (error);
}
Пример #4
0
/*
 * smbfs_create call
 * Create a regular file. On entry the directory to contain the file being
 * created is locked.  We must release before we return.
 */
int
smbfs_create(void *v)
{
	struct vop_create_v3_args /* {
		struct vnode *a_dvp;
		struct vnode **a_vpp;
		struct componentname *a_cnp;
		struct vattr *a_vap;
	} */ *ap = v;
	struct vnode *dvp = ap->a_dvp;
	struct vattr *vap = ap->a_vap;
	struct componentname *cnp = ap->a_cnp;
	struct smbnode *dnp = VTOSMB(dvp);
	struct smbfattr fattr;
	struct smb_cred scred;
	const char *name = cnp->cn_nameptr;
	int nmlen = cnp->cn_namelen;
	int error = EINVAL;


	if (vap->va_type != VREG)
		goto out;

	smb_makescred(&scred, curlwp, cnp->cn_cred);
	error = smbfs_smb_create(dnp, name, nmlen, &scred);
	if (error)
		goto out;

	error = smbfs_smb_lookup(dnp, name, nmlen, &fattr, &scred);
	if (error)
		goto out;
	error = smbfs_nget(VTOVFS(dvp), dvp, name, nmlen, &fattr, ap->a_vpp);
	if (error)
		goto out;
	VOP_UNLOCK(*ap->a_vpp);

	cache_enter(dvp, *ap->a_vpp, cnp->cn_nameptr, cnp->cn_namelen,
		    cnp->cn_flags);

  out:
	VN_KNOTE(dvp, NOTE_WRITE);
	return (error);
}
Пример #5
0
/* 
 * Return locked root vnode of a filesystem
 */
static int
smbfs_root(struct mount *mp, struct vnode **vpp)
{
	struct thread *td = curthread;	/* XXX */
	struct smbmount *smp = VFSTOSMBFS(mp);
	struct vnode *vp;
	struct smbnode *np;
	struct smbfattr fattr;
	struct ucred *cred;
	struct smb_cred scred;
	int error;

	if (smp == NULL) {
		SMBERROR("smp == NULL (bug in umount)\n");
		return EINVAL;
	}
	if (smp->sm_root) {
		*vpp = SMBTOV(smp->sm_root);
		return vget(*vpp, LK_EXCLUSIVE | LK_RETRY);
	}
	if (td->td_proc)
		cred = td->td_proc->p_ucred;
	else
		cred = proc0.p_ucred;

	smb_makescred(&scred, td, cred);
	error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, &scred);
	if (error)
		return error;
	error = smbfs_nget(mp, NULL, "TheRooT", 7, &fattr, &vp);
	if (error)
		return error;
	vsetflags(vp, VROOT);
	np = VTOSMB(vp);
	smp->sm_root = np;
	*vpp = vp;
	return 0;
}
Пример #6
0
/*
 * Get root vnode of the smbfs filesystem, and store it in sm_root.
 */
static int
smbfs_setroot(struct mount *mp)
{
	struct smbmount *smp = VFSTOSMBFS(mp);
	struct vnode *vp;
	struct smbfattr fattr;
	struct lwp *l = curlwp;
	kauth_cred_t cred = l->l_cred;
	struct smb_cred scred;
	int error;

	KASSERT(smp->sm_root == NULL);

	smb_makescred(&scred, l, cred);
	error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, &scred);
	if (error)
		return error;
	error = smbfs_nget(mp, NULL, "TheRooT", 7, &fattr, &vp);
	if (error)
		return error;

	/*
	 * Someone might have already set sm_root while we slept
	 * in smb_lookup or malloc/getnewvnode.
	 */
	if (smp->sm_root)
		vput(vp);
	else {
		vp->v_vflag |= VV_ROOT;
		smp->sm_root = VTOSMB(vp);

		/* Keep reference, but unlock */
		VOP_UNLOCK(vp, 0);
	}

	return (0);
}
Пример #7
0
/*
 * smbfs_getattr call from vfs.
 */
int
smbfs_getattr(void *v)
{
	struct vop_getattr_args /* {
		struct vnode *a_vp;
		struct vattr *a_vap;
		kauth_cred_t a_cred;
	} */ *ap = v;
	struct vnode *vp = ap->a_vp;
	struct smbnode *np = VTOSMB(vp);
	struct vattr *va=ap->a_vap;
	struct smbfattr fattr;
	struct smb_cred scred;
	u_quad_t oldsize;
	int error;

	SMBVDEBUG("%p: '%.*s' isroot %d\n", vp,
		(int) np->n_nmlen, np->n_name, (vp->v_vflag & VV_ROOT) != 0);

	if ((error = smbfs_attr_cachelookup(vp, va)) == 0)
		return (0);

	SMBVDEBUG0("not in the cache\n");
	smb_makescred(&scred, curlwp, ap->a_cred);
	oldsize = np->n_size;
	error = smbfs_smb_lookup(np, NULL, 0, &fattr, &scred);
	if (error) {
		SMBVDEBUG("error %d\n", error);
		return error;
	}
	smbfs_attr_cacheenter(vp, &fattr);
	smbfs_attr_cachelookup(vp, va);
	if ((np->n_flag & NOPEN) != 0)
		np->n_size = oldsize;
	return 0;
}
Пример #8
0
/* 
 * Return locked root vnode of a filesystem
 */
static int
smbfs_root(struct mount *mp, int flags, struct vnode **vpp)
{
	struct smbmount *smp = VFSTOSMBFS(mp);
	struct vnode *vp;
	struct smbnode *np;
	struct smbfattr fattr;
	struct thread *td;
	struct ucred *cred;
	struct smb_cred *scred;
	int error;

	td = curthread;
	cred = td->td_ucred;

	if (smp->sm_root) {
		*vpp = SMBTOV(smp->sm_root);
		return vget(*vpp, LK_EXCLUSIVE | LK_RETRY, td);
	}
	scred = smbfs_malloc_scred();
	smb_makescred(scred, td, cred);
	error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, scred);
	if (error)
		goto out;
	error = smbfs_nget(mp, NULL, NULL, 0, &fattr, &vp);
	if (error)
		goto out;
	ASSERT_VOP_LOCKED(vp, "smbfs_root");
	vp->v_vflag |= VV_ROOT;
	np = VTOSMB(vp);
	smp->sm_root = np;
	*vpp = vp;
out:
	smbfs_free_scred(scred);
	return error;
}