Ejemplo n.º 1
0
int
smbfs_writevnode(struct vnode *vp, struct uio *uiop,
	struct ucred *cred, int ioflag)
{
	struct smbmount *smp = VTOSMBFS(vp);
	struct smbnode *np = VTOSMB(vp);
	struct smb_cred *scred;
	struct thread *td;
	int error = 0;

	if (vp->v_type != VREG) {
		SMBERROR("vn types other than VREG unsupported !\n");
		return EIO;
	}
	SMBVDEBUG("ofs=%jd,resid=%zd\n", (intmax_t)uiop->uio_offset, 
	    uiop->uio_resid);
	if (uiop->uio_offset < 0)
		return EINVAL;
/*	if (uiop->uio_offset + uiop->uio_resid > smp->nm_maxfilesize)
		return (EFBIG);*/
	td = uiop->uio_td;
	if (ioflag & (IO_APPEND | IO_SYNC)) {
		if (np->n_flag & NMODIFIED) {
			smbfs_attr_cacheremove(vp);
			error = smbfs_vinvalbuf(vp, td);
			if (error)
				return error;
		}
		if (ioflag & IO_APPEND) {
#ifdef notyet
			/*
			 * File size can be changed by another client
			 */
			smbfs_attr_cacheremove(vp);
			error = VOP_GETATTR(vp, &vattr, cred);
			if (error) return (error);
#endif
			uiop->uio_offset = np->n_size;
		}
	}
	if (uiop->uio_resid == 0)
		return 0;

	if (vn_rlimit_fsize(vp, uiop, td))
		return (EFBIG);
	
	scred = smbfs_malloc_scred();
	smb_makescred(scred, td, cred);
	error = smb_write(smp->sm_share, np->n_fid, uiop, scred);
	smbfs_free_scred(scred);
	SMBVDEBUG("after: ofs=%jd,resid=%zd\n", (intmax_t)uiop->uio_offset, 
	    uiop->uio_resid);
	if (!error) {
		if (uiop->uio_offset > np->n_size) {
			np->n_size = uiop->uio_offset;
			vnode_pager_setsize(vp, np->n_size);
		}
	}
	return error;
}
Ejemplo n.º 2
0
int
smbfs_readvnode(struct vnode *vp, struct uio *uiop, struct ucred *cred)
{
	struct smbmount *smp = VFSTOSMBFS(vp->v_mount);
	struct smbnode *np = VTOSMB(vp);
	struct thread *td;
	struct vattr vattr;
	struct smb_cred scred;
	int error, lks;

	/*
	 * Protect against method which is not supported for now
	 */
	if (uiop->uio_segflg == UIO_NOCOPY)
		return EOPNOTSUPP;

	if (vp->v_type != VREG && vp->v_type != VDIR) {
		SMBFSERR("vn types other than VREG or VDIR are unsupported !\n");
		return EIO;
	}
	if (uiop->uio_resid == 0)
		return 0;
	if (uiop->uio_offset < 0)
		return EINVAL;
/*	if (uiop->uio_offset + uiop->uio_resid > smp->nm_maxfilesize)
		return EFBIG;*/
	td = uiop->uio_td;
	if (vp->v_type == VDIR) {
		lks = LK_EXCLUSIVE;/*lockstatus(vp->v_vnlock, td);*/
		if (lks == LK_SHARED)
			vn_lock(vp, LK_UPGRADE | LK_RETRY, td);
		error = smbfs_readvdir(vp, uiop, cred);
		if (lks == LK_SHARED)
			vn_lock(vp, LK_DOWNGRADE | LK_RETRY, td);
		return error;
	}

/*	biosize = SSTOCN(smp->sm_share)->sc_txmax;*/
	if (np->n_flag & NMODIFIED) {
		smbfs_attr_cacheremove(vp);
		error = VOP_GETATTR(vp, &vattr, cred, td);
		if (error)
			return error;
		np->n_mtime.tv_sec = vattr.va_mtime.tv_sec;
	} else {
		error = VOP_GETATTR(vp, &vattr, cred, td);
		if (error)
			return error;
		if (np->n_mtime.tv_sec != vattr.va_mtime.tv_sec) {
			error = smbfs_vinvalbuf(vp, td);
			if (error)
				return error;
			np->n_mtime.tv_sec = vattr.va_mtime.tv_sec;
		}
	}
	smb_makescred(&scred, td, cred);
	return smb_read(smp->sm_share, np->n_fid, uiop, &scred);
}
Ejemplo n.º 3
0
int
smbfs_writevnode(struct vnode *vp, struct uio *uiop,
		 struct ucred *cred, int ioflag)
{
	struct thread *td;
	struct smbmount *smp = VTOSMBFS(vp);
	struct smbnode *np = VTOSMB(vp);
	struct smb_cred scred;
	int error = 0;

	if (vp->v_type != VREG) {
		SMBERROR("vn types other than VREG unsupported !\n");
		return EIO;
	}
	SMBVDEBUG("ofs=%d,resid=%d\n",(int)uiop->uio_offset, uiop->uio_resid);
	if (uiop->uio_offset < 0)
		return EINVAL;
	td = uiop->uio_td;
	if (ioflag & (IO_APPEND | IO_SYNC)) {
		if (np->n_flag & NMODIFIED) {
			smbfs_attr_cacheremove(vp);
			error = smbfs_vinvalbuf(vp, V_SAVE, 1);
			if (error)
				return error;
		}
		if (ioflag & IO_APPEND) {
#if 0 /* notyet */
			/*
			 * File size can be changed by another client
			 */
			smbfs_attr_cacheremove(vp);
			error = VOP_GETATTR(vp, &vattr);
			if (error) return (error);
#endif
			uiop->uio_offset = np->n_size;
		}
	}
	if (uiop->uio_resid == 0)
		return 0;
	if (td->td_proc &&
	    uiop->uio_offset + uiop->uio_resid >
	    td->td_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
		lwpsignal(td->td_proc, td->td_lwp, SIGXFSZ);
		return EFBIG;
	}
	smb_makescred(&scred, td, cred);
	error = smb_write(smp->sm_share, np->n_fid, uiop, &scred);
	SMBVDEBUG("after: ofs=%d,resid=%d\n",(int)uiop->uio_offset, uiop->uio_resid);
	if (!error) {
		if (uiop->uio_offset > np->n_size) {
			np->n_size = uiop->uio_offset;
			vnode_pager_setsize(vp, np->n_size);
		}
	}
	return error;
}
Ejemplo n.º 4
0
/*
 * Close called.
 */
int
smbfs_close(void *v)
{
	struct vop_close_args /* {
		struct vnodeop_desc *a_desc;
		struct vnode *a_vp;
		int  a_fflag;
		kauth_cred_t a_cred;
	} */ *ap = v;
	int error;
	struct lwp *l = curlwp;
	struct vnode *vp = ap->a_vp;
	struct smbnode *np = VTOSMB(vp);

	/* Flush all file data */
	error = smbfs_vinvalbuf(vp, V_SAVE, ap->a_cred, l, 1);
	if (error)
		return (error);

	/*
	 * We must close the directory lookup context now, so that
	 * later directory changes would be properly detected.
	 * Ideally, the lookup routines should handle such case, and
	 * the context would be removed only in smbfs_inactive().
	 */
	if (vp->v_type == VDIR && (np->n_flag & NOPEN) != 0) {
		struct smb_share *ssp = np->n_mount->sm_share;
		struct smb_cred scred;

		smb_makescred(&scred, l, ap->a_cred);

		if (np->n_dirseq != NULL) {
			smbfs_findclose(np->n_dirseq, &scred);
			np->n_dirseq = NULL;
		}

		if (SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_NT_SMBS)
			smbfs_smb_close(ssp, np->n_fid, &np->n_mtime, &scred);

		np->n_flag &= ~NOPEN;
		smbfs_attr_cacheremove(vp);
	}

	return (0);
}
Ejemplo n.º 5
0
/* ARGSUSED */
int
smbfs_open(void *v)
{
	struct vop_open_args /* {
		struct vnode *a_vp;
		int  a_mode;
		kauth_cred_t a_cred;
	} */ *ap = v;
	struct lwp *l = curlwp;
	struct vnode *vp = ap->a_vp;
	struct smbnode *np = VTOSMB(vp);
	struct smb_cred scred;
	struct vattr vattr;
	u_int32_t sv_caps = SMB_CAPS(SSTOVC(np->n_mount->sm_share));
	int error, accmode;

	SMBVDEBUG("%.*s,%d\n", (int) np->n_nmlen, np->n_name,
	    (np->n_flag & NOPEN) != 0);
	if (vp->v_type != VREG && vp->v_type != VDIR) {
		SMBFSERR("open eacces vtype=%d\n", vp->v_type);
		return EACCES;
	}
	if (vp->v_type == VDIR) {
		if ((sv_caps & SMB_CAP_NT_SMBS) == 0) {
			np->n_flag |= NOPEN;
			return 0;
		}
		goto do_open;	/* skip 'modified' check */
	}

	if (np->n_flag & NMODIFIED) {
		if ((error = smbfs_vinvalbuf(vp, V_SAVE, ap->a_cred, l, 1)) == EINTR)
			return error;
		smbfs_attr_cacheremove(vp);
		error = VOP_GETATTR(vp, &vattr, ap->a_cred);
		if (error)
			return error;
		np->n_mtime.tv_sec = vattr.va_mtime.tv_sec;
	} else {
		error = VOP_GETATTR(vp, &vattr, ap->a_cred);
		if (error)
			return error;
		if (np->n_mtime.tv_sec != vattr.va_mtime.tv_sec) {
			error = smbfs_vinvalbuf(vp, V_SAVE, ap->a_cred, l, 1);
			if (error == EINTR)
				return error;
			np->n_mtime.tv_sec = vattr.va_mtime.tv_sec;
		}
	}

do_open:
	if ((np->n_flag & NOPEN) != 0)
		return 0;

	smb_makescred(&scred, l, ap->a_cred);
	if (vp->v_type == VDIR)
		error = smbfs_smb_ntcreatex(np,
		    SMB_SM_DENYNONE|SMB_AM_OPENREAD, &scred);
	else {
		/*
		 * Use DENYNONE to give unixy semantics of permitting
		 * everything not forbidden by permissions.  Ie denial
		 * is up to server with clients/openers needing to use
		 * advisory locks for further control.
		 */
		accmode = SMB_SM_DENYNONE|SMB_AM_OPENREAD;
		if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
			accmode = SMB_SM_DENYNONE|SMB_AM_OPENRW;
		error = smbfs_smb_open(np, accmode, &scred);
		if (error) {
			if (ap->a_mode & FWRITE)
				return EACCES;

			error = smbfs_smb_open(np,
			    SMB_SM_DENYNONE|SMB_AM_OPENREAD, &scred);
		}
	}
	if (!error)
		np->n_flag |= NOPEN;
	smbfs_attr_cacheremove(vp);
	return error;
}