if (sp->a_vp->v_type == VREG) { error = 0; while (uio->uio_resid > 0) { void *win; vsize_t bytelen = min(ap->fsize - uio->uio_offset, uio->uio_resid);  if (bytelen == 0) { break; } win = ubc_alloc(&sp->a_vp->v_uobj, uio->uio_offset, &bytelen, UBC_READ); error = uiomove(win, bytelen, uio); ubc_release(win, 0); if (error) { break; } } goto reterr; }
adosfs_read(v)	void *v;{	struct vop_read_args /* {		struct vnode *a_vp;		struct uio *a_uio;		int a_ioflag;		struct ucred *a_cred;	} */ *sp = v;	struct adosfsmount *amp;	struct anode *ap;	struct uio *uio;	struct buf *bp;	daddr_t lbn;	int size, error, n, on;	u_int32_t off;	int64_t diff;#ifdef ADOSFS_DIAGNOSTIC	advopprint(sp);#endif	error = 0;	uio = sp->a_uio;	ap = VTOA(sp->a_vp);	amp = ap->amp;		/*	 * Return EOF for character devices, EIO for others	 */	if (sp->a_vp->v_type != VREG) {		error = EIO;		goto reterr;	}	if (uio->uio_resid == 0)		goto reterr;	if (uio->uio_offset < 0 || uio->uio_offset > UINT_MAX) { /* XXX */		error = EINVAL;		goto reterr;	}	off = (u_int32_t)uio->uio_offset;	/*	 * to expensive to let general algorithm figure out that 	 * we are beyond the file.  Do it now.	 */	if (off >= ap->fsize)		goto reterr;	/*	 * taken from ufs_read()	 */	if (sp->a_vp->v_type == VREG) {		error = 0;		while (uio->uio_resid > 0) {			void *win;			vsize_t bytelen = min(ap->fsize - uio->uio_offset,					uio->uio_resid);			if (bytelen == 0) {				break;			}			win = ubc_alloc(&sp->a_vp->v_uobj, uio->uio_offset,					&bytelen, UBC_READ);			error = uiomove(win, bytelen, uio);			ubc_release(win, 0);			if (error) {				break;			}		}		goto reterr;	}	do {		/*		 * we are only supporting ADosFFS currently		 * (which have data blocks without headers)		 */		size = amp->dbsize;		lbn = off / size;		on = off % size;		n = min((u_int32_t)(size - on), uio->uio_resid);		diff = ap->fsize - off;		/* 		 * check for EOF		 */		if (diff <= 0)			return(0);		if (diff < n)			n = (int)diff;		/*		 * read ahead could possibly be worth something		 * but not much as ados makes little attempt to 		 * make things contigous		 */		error = bread(sp->a_vp, lbn * amp->secsperblk, amp->bsize,		    NOCRED, &bp);		if (!IS_FFS(amp)) {			if (bp->b_resid > 0)				error = EIO; /* OFS needs the complete block */			else if (adoswordn(bp, 0) != BPT_DATA) {#ifdef DIAGNOSTIC				printf("adosfs: bad primary type blk %ld\n",				    bp->b_blkno / amp->secsperblk);#endif				error=EINVAL;			}			else if (adoscksum(bp, ap->nwords)) {#ifdef DIAGNOSTIC				printf("adosfs: blk %u failed cksum.\n",				    bp->b_blkno / amp->secsperblk);#endif				error=EINVAL;			}		}		if (error) {			brelse(bp);			goto reterr;		}#ifdef ADOSFS_DIAGNOSTIC		printf(" %u+%u-%u+%u", lbn, on, lbn, n);#endif		n = min(n, size - bp->b_resid);	/* XXX check types */		error = uiomove(bp->b_un.b_addr + on + amp->bsize -		    amp->dbsize, n, uio);		brelse(bp);		off = (u_int32_t)uio->uio_offset;	} while (error == 0 && uio->uio_resid > 0 && n != 0);reterr:#ifdef ADOSFS_DIAGNOSTIC	printf(" %d)", error);#endif	return(error);}