FreeBSD/sys/fs/nfsserver/nfs_nfsdport.c
/*
 * Common code for creating a regular file (plus special files for V2).
 */
Common code for creating a regular file (plus special files for V2).
Common code for creating a regular file ( plus special files for V2 ) .
int
nfsvno_createsub(struct nfsrv_descript *nd, struct nameidata *ndp,
    struct vnode **vpp, struct nfsvattr *nvap, int *exclusive_flagp,
    int32_t *cverf, NFSDEV_T rdev, struct thread *p, struct nfsexstuff *exp)
{
	u_quad_t tempsize;
	int error;
	error = nd->nd_repstat;
	if (!error && ndp->ni_vp == NULL) {
		if (nvap->na_type == VREG || nvap->na_type == VSOCK) {
			vrele(ndp->ni_startdir);
			error = VOP_CREATE(ndp->ni_dvp,
			    &ndp->ni_vp, &ndp->ni_cnd, &nvap->na_vattr);
			vput(ndp->ni_dvp);
			nfsvno_relpathbuf(ndp);
			if (!error) {
				if (*exclusive_flagp) {
					*exclusive_flagp = 0;
					NFSVNO_ATTRINIT(nvap);
					nvap->na_atime.tv_sec = cverf[0];
					nvap->na_atime.tv_nsec = cverf[1];
					error = VOP_SETATTR(ndp->ni_vp,
					    &nvap->na_vattr, nd->nd_cred);
					if (error != 0) {
						vput(ndp->ni_vp);
						ndp->ni_vp = NULL;
						error = NFSERR_NOTSUPP;
					}
				}
			}
		} else if (nvap->na_type == VCHR || nvap->na_type == VBLK ||
			nvap->na_type == VFIFO) {
			if (nvap->na_type == VCHR && rdev == 0xffffffff)
				nvap->na_type = VFIFO;
                        if (nvap->na_type != VFIFO &&
			    (error = priv_check_cred(nd->nd_cred,
			     PRIV_VFS_MKNOD_DEV, 0))) {
				vrele(ndp->ni_startdir);
				nfsvno_relpathbuf(ndp);
				vput(ndp->ni_dvp);
				goto out;
			}
			nvap->na_rdev = rdev;
			error = VOP_MKNOD(ndp->ni_dvp, &ndp->ni_vp,
			    &ndp->ni_cnd, &nvap->na_vattr);
			vput(ndp->ni_dvp);
			nfsvno_relpathbuf(ndp);
			vrele(ndp->ni_startdir);
			if (error)
				goto out;
		} else {
			vrele(ndp->ni_startdir);
			nfsvno_relpathbuf(ndp);
			vput(ndp->ni_dvp);
			error = ENXIO;
			goto out;
		}
		*vpp = ndp->ni_vp;
	} else {
		vrele(ndp->ni_startdir);
		nfsvno_relpathbuf(ndp);
		*vpp = ndp->ni_vp;
		if (ndp->ni_dvp == *vpp)
			vrele(ndp->ni_dvp);
		else
			vput(ndp->ni_dvp);
		if (!error && nvap->na_size != VNOVAL) {
			error = nfsvno_accchk(*vpp, VWRITE,
			    nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE,
			    NFSACCCHK_VPISLOCKED, NULL);
			if (!error) {
				tempsize = nvap->na_size;
				NFSVNO_ATTRINIT(nvap);
				nvap->na_size = tempsize;
				error = VOP_SETATTR(*vpp,
				    &nvap->na_vattr, nd->nd_cred);
			}
		}
		if (error)
			vput(*vpp);
	}
out:
	NFSEXITCODE(error);
	return (error);
}
int nfsvno_createsub ( struct nfsrv_descript * nd , struct nameidata * ndp , struct vnode * * vpp , struct nfsvattr * nvap , int * exclusive_flagp , int32_t * cverf , NFSDEV_T rdev , struct thread * p , struct nfsexstuff * exp ) { u_quad_t tempsize ; int error ; error = nd -> nd_repstat ; if ( ! error && ndp -> ni_vp == NULL ) { if ( nvap -> na_type == VREG || nvap -> na_type == VSOCK ) { vrele ( ndp -> ni_startdir ) ; error = VOP_CREATE ( ndp -> ni_dvp , & ndp -> ni_vp , & ndp -> ni_cnd , & nvap -> na_vattr ) ; vput ( ndp -> ni_dvp ) ; nfsvno_relpathbuf ( ndp ) ; if ( ! error ) { if ( * exclusive_flagp ) { * exclusive_flagp = 0 ; NFSVNO_ATTRINIT ( nvap ) ; nvap -> na_atime . tv_sec = cverf [ 0 ] ; nvap -> na_atime . tv_nsec = cverf [ 1 ] ; error = VOP_SETATTR ( ndp -> ni_vp , & nvap -> na_vattr , nd -> nd_cred ) ; if ( error != 0 ) { vput ( ndp -> ni_vp ) ; ndp -> ni_vp = NULL ; error = NFSERR_NOTSUPP ; } } } } else if ( nvap -> na_type == VCHR || nvap -> na_type == VBLK || nvap -> na_type == VFIFO ) { if ( nvap -> na_type == VCHR && rdev == 0xffffffff ) nvap -> na_type = VFIFO ; if ( nvap -> na_type != VFIFO && ( error = priv_check_cred ( nd -> nd_cred , PRIV_VFS_MKNOD_DEV , 0 ) ) ) { vrele ( ndp -> ni_startdir ) ; nfsvno_relpathbuf ( ndp ) ; vput ( ndp -> ni_dvp ) ; goto out ; } nvap -> na_rdev = rdev ; error = VOP_MKNOD ( ndp -> ni_dvp , & ndp -> ni_vp , & ndp -> ni_cnd , & nvap -> na_vattr ) ; vput ( ndp -> ni_dvp ) ; nfsvno_relpathbuf ( ndp ) ; vrele ( ndp -> ni_startdir ) ; if ( error ) goto out ; } else { vrele ( ndp -> ni_startdir ) ; nfsvno_relpathbuf ( ndp ) ; vput ( ndp -> ni_dvp ) ; error = ENXIO ; goto out ; } * vpp = ndp -> ni_vp ; } else { vrele ( ndp -> ni_startdir ) ; nfsvno_relpathbuf ( ndp ) ; * vpp = ndp -> ni_vp ; if ( ndp -> ni_dvp == * vpp ) vrele ( ndp -> ni_dvp ) ; else vput ( ndp -> ni_dvp ) ; if ( ! error && nvap -> na_size != VNOVAL ) { error = nfsvno_accchk ( * vpp , VWRITE , nd -> nd_cred , exp , p , NFSACCCHK_NOOVERRIDE , NFSACCCHK_VPISLOCKED , NULL ) ; if ( ! error ) { tempsize = nvap -> na_size ; NFSVNO_ATTRINIT ( nvap ) ; nvap -> na_size = tempsize ; error = VOP_SETATTR ( * vpp , & nvap -> na_vattr , nd -> nd_cred ) ; } } if ( error ) vput ( * vpp ) ; } out : NFSEXITCODE ( error ) ; return ( error ) ; }
Common code for creating a regular file (plus special files for V2).
Common code for creating a regular file ( plus special files for V2 ) .
/*
		 * NFS V2 Only. nfsrvd_mknod() does this for V3.
		 * (This implies, just get out on an error.)
		 */ /*
		 * Handle cases where error is already set and/or
		 * the file exists.
		 * 1 - clean up the lookup
		 * 2 - iff !error and na_size set, truncate it
		 */