Example #1
0
/*
 * This routine traverse the b+ tree representing directory
 * looking for file named 'name'. Returns buf struct and hpfsdirent
 * pointer. Calling routine is supposed to brelse buffer.
 * name is supposed in Unix encodeing.
 */
int
hpfs_genlookupbyname (
	struct hpfsnode *dhp,
	char *name,
	int namelen,
	struct buf **bpp,
	struct hpfsdirent **depp)
{
	struct hpfsmount *hpmp = dhp->h_hpmp;
	struct buf *bp;
	struct dirblk *dp;
	struct hpfsdirent *dep;
	lsn_t lsn;
	int error, res;

	dprintf(("hpfs_genlookupbyname(0x%x, %s (%d)): \n", 
		dhp->h_no, name, namelen));

	lsn = ((alleaf_t *)dhp->h_fn.fn_abd)->al_lsn;
dive:
	error = hpfs_breaddirblk (hpmp, lsn, &bp);
	if (error)
		return (error);

	dp = (struct dirblk *) bp->b_data;
	dep = D_DIRENT(dp);

	while(!(dep->de_flag & DE_END)) {
		dprintf(("no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x\n",
			dep->de_fnode, dep->de_size, dep->de_namelen,
			dep->de_namelen, dep->de_name, dep->de_flag));

		res = hpfs_cmpfname(hpmp, name, namelen,
				dep->de_name, dep->de_namelen, dep->de_cpid);
		if (res == 0) {
			*bpp = bp;
			*depp = dep;
			return (0);
		} else if (res < 0)
			break;

		dep = (hpfsdirent_t *)(((caddr_t)dep) + dep->de_reclen);
	}

	if (dep->de_flag & DE_DOWN) {
		lsn = DE_DOWNLSN(dep);
		brelse(bp);
		goto dive;
	}

	brelse(bp);

	return (ENOENT);
}
Example #2
0
/*
 * hpfs_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred,
 *		int *a_ncookies, off_t **cookies)
 */
int
hpfs_readdir(struct vop_readdir_args *ap)
{
	struct vnode *vp = ap->a_vp;
	struct hpfsnode *hp = VTOHP(vp);
	struct hpfsmount *hpmp = hp->h_hpmp;
	struct uio *uio = ap->a_uio;
	int ncookies = 0, i, num, cnum;
	int error = 0;
	struct buf *bp;
	struct dirblk *dp;
	struct hpfsdirent *dep;
	lsn_t olsn;
	lsn_t lsn;
	int level;

	dprintf(("hpfs_readdir(0x%x, 0x%x, 0x%lx): ",
		hp->h_no, (u_int32_t)uio->uio_offset, uio->uio_resid));

	/*
	 * As we need to fake up . and .., and the remaining directory structure
	 * can't be expressed in one off_t as well, we just increment uio_offset
	 * by 1 for each entry.
	 *
	 * num is the entry we need to start reporting
	 * cnum is the current entry
	 */
	if (uio->uio_offset < 0 || uio->uio_offset > INT_MAX)
		return(EINVAL);
	if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0)
		return (error);

	num = uio->uio_offset;
	cnum = 0;

	if( num <= cnum ) {
		dprintf((". faked, "));
		if (vop_write_dirent(&error, uio, hp->h_no, DT_DIR, 1, "."))
			goto done;
		if (error)
			goto done;
		ncookies ++;
	}
	cnum++;

	if( num <= cnum ) {
		dprintf((".. faked, "));
		if (vop_write_dirent(&error, uio, hp->h_fn.fn_parent, DT_DIR, 2, ".."))
			goto readdone;
		if (error)
			goto done;
		ncookies ++;
	}
	cnum++;

	lsn = ((alleaf_t *)hp->h_fn.fn_abd)->al_lsn;

	olsn = 0;
	level = 1;

dive:
	dprintf(("[dive 0x%x] ", lsn));
	error = bread(hp->h_devvp, dbtodoff(lsn), D_BSIZE, &bp);
	if (error) {
		brelse(bp);
		goto done;
	}

	dp = (struct dirblk *) bp->b_data;
	if (dp->d_magic != D_MAGIC) {
		kprintf("hpfs_readdir: MAGIC DOESN'T MATCH\n");
		brelse(bp);
		error = EINVAL;
		goto done;
	}

	dep = D_DIRENT(dp);

	if (olsn) {
		dprintf(("[restore 0x%x] ", olsn));

		while(!(dep->de_flag & DE_END) ) {
			if((dep->de_flag & DE_DOWN) &&
			   (olsn == DE_DOWNLSN(dep)))
					 break;
			dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
		}

		if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) {
			if (dep->de_flag & DE_END)
				goto blockdone;

			if (!(dep->de_flag & DE_SPECIAL)) {
				if (num <= cnum) {
					if (hpfs_de_uiomove(&error, hpmp, dep, uio)) {
						brelse(bp);
						dprintf(("[resid] "));
						goto readdone;
					}
					if (error) {
						brelse (bp);
						goto done;
					}
					ncookies++;
				}
				cnum++;
			}

			dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
		} else {
			kprintf("hpfs_readdir: ERROR! oLSN not found\n");
			brelse(bp);
			error = EINVAL;
			goto done;
		}
	}

	olsn = 0;

	while(!(dep->de_flag & DE_END)) {
		if(dep->de_flag & DE_DOWN) {
			lsn = DE_DOWNLSN(dep);
			brelse(bp);
			level++;
			goto dive;
		}

		if (!(dep->de_flag & DE_SPECIAL)) {
			if (num <= cnum) {
				if (hpfs_de_uiomove(&error, hpmp, dep, uio)) {
					brelse(bp);
					dprintf(("[resid] "));
					goto readdone;
				}
				if (error) {
					brelse (bp);
					goto done;
				}
				ncookies++;
			}
			cnum++;
		}

		dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
	}

	if(dep->de_flag & DE_DOWN) {
		dprintf(("[enddive] "));
		lsn = DE_DOWNLSN(dep);
		brelse(bp);
		level++;
		goto dive;
	}

blockdone:
	dprintf(("[EOB] "));
	olsn = lsn;
	lsn = dp->d_parent;
	brelse(bp);
	level--;

	dprintf(("[level %d] ", level));

	if (level > 0)
		goto dive;	/* undive really */

	if (ap->a_eofflag) {
	    dprintf(("[EOF] "));
	    *ap->a_eofflag = 1;
	}

readdone:
	uio->uio_offset = cnum;
	dprintf(("[readdone]\n"));
	if (!error && ap->a_ncookies != NULL) {
		off_t *cookies;
		off_t *cookiep;

		dprintf(("%d cookies, ",ncookies));
		if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
			panic("hpfs_readdir: unexpected uio from NFS server");
		cookies = kmalloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK);
		for (cookiep = cookies, i=0; i < ncookies; i++)
			*cookiep++ = ++num;

		*ap->a_ncookies = ncookies;
		*ap->a_cookies = cookies;
	}

done:
	vn_unlock(ap->a_vp);
	return (error);
}