Beispiel #1
0
static void
cd9660_rrip_defname(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana)
{
        isofntrans(isodir->name,isonum_711(isodir->name_len),
                   ana->outbuf,ana->outlen,
                   1,isonum_711(isodir->flags)&4, ana->imp->joliet_level,
                   ana->imp->im_flags, ana->imp->im_d2l);
	switch (*ana->outbuf) {
	default:
		break;
	case 1:
		*ana->outlen = 2;
		/* FALL THROUGH */
	case 0:
		/* outlen is 1 already */
		strcpy(ana->outbuf,"..");
		break;
	}
}
Beispiel #2
0
static void
cd9660_rrip_defname(void *v, ISO_RRIP_ANALYZE *ana)
{
	struct iso_directory_record *isodir = v;

	isofntrans(isodir->name, isonum_711(isodir->name_len),
		   ana->outbuf, ana->outlen,
		   1, 0, isonum_711(isodir->flags) & 4,
		   ana->imp->im_joliet_level);
	switch (ana->outbuf[0]) {
	default:
		break;
	case 0:
		ana->outbuf[0] = '.';
		*ana->outlen = 1;
		break;
	case 1:
		strlcpy(ana->outbuf, "..", ana->maxlen - *ana->outlen);
		*ana->outlen = 2;
		break;
	}
}
Beispiel #3
0
/*
 * Vnode op for readdir
 */
int
cd9660_readdir(void *v)
{
	struct vop_readdir_args /* {
		struct vnode *a_vp;
		struct uio *a_uio;
		kauth_cred_t a_cred;
		int *a_eofflag;
		off_t **a_cookies;
		int *a_ncookies;
	} */ *ap = v;
	struct uio *uio = ap->a_uio;
	struct isoreaddir *idp;
	struct vnode *vdp = ap->a_vp;
	struct iso_node *dp;
	struct iso_mnt *imp;
	struct buf *bp = NULL;
	struct iso_directory_record *ep;
	int entryoffsetinblock;
	doff_t endsearch;
	u_long bmask;
	int error = 0;
	int reclen;
	u_short namelen;
	off_t *cookies = NULL;
	int ncookies = 0;

	if (vdp->v_type != VDIR)
		return (ENOTDIR);

	dp = VTOI(vdp);
	imp = dp->i_mnt;
	bmask = imp->im_bmask;

	idp = (struct isoreaddir *)malloc(sizeof(*idp), M_TEMP, M_WAITOK);
	idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
	/*
	 * XXX
	 * Is it worth trying to figure out the type?
	 */
	idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
	    DT_UNKNOWN;
	idp->uio = uio;
	if (ap->a_ncookies == NULL)
		idp->cookies = NULL;
	else {
		ncookies = uio->uio_resid / _DIRENT_MINSIZE((struct dirent *)0);
		cookies = malloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK);
		idp->cookies = cookies;
		idp->ncookies = ncookies;
	}
	idp->eofflag = 1;
	idp->curroff = uio->uio_offset;

	if ((entryoffsetinblock = idp->curroff & bmask) &&
	    (error = cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) {
		free(idp, M_TEMP);
		return (error);
	}
	endsearch = dp->i_size;

	while (idp->curroff < endsearch) {
		/*
		 * If offset is on a block boundary,
		 * read the next directory block.
		 * Release previous if it exists.
		 */
		if ((idp->curroff & bmask) == 0) {
			if (bp != NULL)
				brelse(bp, 0);
			error = cd9660_blkatoff(vdp, (off_t)idp->curroff,
					     NULL, &bp);
			if (error)
				break;
			entryoffsetinblock = 0;
		}
		/*
		 * Get pointer to next entry.
		 */
		KASSERT(bp != NULL);
		ep = (struct iso_directory_record *)
			((char *)bp->b_data + entryoffsetinblock);

		reclen = isonum_711(ep->length);
		if (reclen == 0) {
			/* skip to next block, if any */
			idp->curroff =
			    (idp->curroff & ~bmask) + imp->logical_block_size;
			continue;
		}

		if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
			error = EINVAL;
			/* illegal entry, stop */
			break;
		}

		if (entryoffsetinblock + reclen > imp->logical_block_size) {
			error = EINVAL;
			/* illegal directory, so stop looking */
			break;
		}

		idp->current.d_namlen = isonum_711(ep->name_len);

		if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
			error = EINVAL;
			/* illegal entry, stop */
			break;
		}

		if (isonum_711(ep->flags)&2)
			idp->current.d_fileno = isodirino(ep, imp);
		else
			idp->current.d_fileno = dbtob(bp->b_blkno) +
				entryoffsetinblock;

		idp->curroff += reclen;

		switch (imp->iso_ftype) {
		case ISO_FTYPE_RRIP:
			cd9660_rrip_getname(ep, idp->current.d_name, &namelen,
			    &idp->current.d_fileno, imp);
			idp->current.d_namlen = (u_char)namelen;
			if (idp->current.d_namlen)
				error = iso_uiodir(idp, &idp->current,
				    idp->curroff);
			break;
		default:	/* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
			isofntrans(ep->name, idp->current.d_namlen,
				   idp->current.d_name, &namelen,
				   imp->iso_ftype == ISO_FTYPE_9660,
				   (imp->im_flags & ISOFSMNT_NOCASETRANS) == 0,
				   isonum_711(ep->flags)&4,
				   imp->im_joliet_level);
			switch (idp->current.d_name[0]) {
			case 0:
				idp->current.d_name[0] = '.';
				idp->current.d_namlen = 1;
				error = iso_uiodir(idp, &idp->current,
				    idp->curroff);
				break;
			case 1:
				strlcpy(idp->current.d_name, "..",
				    sizeof(idp->current.d_name));
				idp->current.d_namlen = 2;
				error = iso_uiodir(idp, &idp->current,
				    idp->curroff);
				break;
			default:
				idp->current.d_namlen = (u_char)namelen;
				if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
					error = iso_shipdir(idp);
				else
					error = iso_uiodir(idp, &idp->current,
					    idp->curroff);
				break;
			}
		}
		if (error)
			break;

		entryoffsetinblock += reclen;
	}

	if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
		idp->current.d_namlen = 0;
		error = iso_shipdir(idp);
	}
	if (error < 0)
		error = 0;

	if (ap->a_ncookies != NULL) {
		if (error)
			free(cookies, M_TEMP);
		else {
			/*
			 * Work out the number of cookies actually used.
			 */
			*ap->a_ncookies = ncookies - idp->ncookies;
			*ap->a_cookies = cookies;
		}
	}

	if (bp)
		brelse(bp, 0);

	uio->uio_offset = idp->uio_off;
	*ap->a_eofflag = idp->eofflag;

	free(idp, M_TEMP);

	return (error);
}