Example #1
0
static int
buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
{
	struct file *fp = (struct file *)f->f_fsdata;
	daddr_t blkno, blkoff;
	int rc = 0;
	size_t read;

	blkno = fp->f_off / ISO_DEFAULT_BLOCK_SIZE + fp->f_bno;
	blkoff = fp->f_off % ISO_DEFAULT_BLOCK_SIZE;

	if (blkno != fp->f_buf_blkno) {
		if (fp->f_buf == (char *)0)
			fp->f_buf = malloc(ISO_DEFAULT_BLOCK_SIZE);

		twiddle(16);
		rc = f->f_dev->dv_strategy(f->f_devdata, F_READ,
		    cdb2devb(blkno), ISO_DEFAULT_BLOCK_SIZE,
		    fp->f_buf, &read);
		if (rc)
			return (rc);
		if (read != ISO_DEFAULT_BLOCK_SIZE)
			return (EIO);

		fp->f_buf_blkno = blkno;
	}

	*buf_p = fp->f_buf + blkoff;
	*size_p = ISO_DEFAULT_BLOCK_SIZE - blkoff;

	if (*size_p > fp->f_size - fp->f_off)
		*size_p = fp->f_size - fp->f_off;
	return (rc);
}
Example #2
0
int
cd9660_read(struct open_file *f, void *start, size_t size, size_t *resid)
{
	struct file *fp = (struct file *)f->f_fsdata;
	int rc = 0;
	daddr_t bno;
	char buf[ISO_DEFAULT_BLOCK_SIZE];
	char *dp;
	size_t nread, off;

	while (size) {
		if (fp->off < 0 || fp->off >= fp->size)
			break;
		bno = fp->off / ISO_DEFAULT_BLOCK_SIZE + fp->bno;
		if (fp->off & (ISO_DEFAULT_BLOCK_SIZE - 1)
		    || size < ISO_DEFAULT_BLOCK_SIZE)
			dp = buf;
		else
			dp = start;
#if !defined(LIBSA_NO_TWIDDLE)
		twiddle();
#endif
		rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno),
		                            ISO_DEFAULT_BLOCK_SIZE, dp, &nread);
		if (rc)
			return rc;
		if (nread != ISO_DEFAULT_BLOCK_SIZE)
			return EIO;
		if (dp == buf) {
			off = fp->off & (ISO_DEFAULT_BLOCK_SIZE - 1);
			if (nread > off + size)
				nread = off + size;
			nread -= off;
			memcpy(start, buf + off, nread);
			start = (char *)start + nread;
			fp->off += nread;
			size -= nread;
		} else {
			start = (char *)start + ISO_DEFAULT_BLOCK_SIZE;
			fp->off += ISO_DEFAULT_BLOCK_SIZE;
			size -= ISO_DEFAULT_BLOCK_SIZE;
		}
	}
	if (resid)
		*resid = size;
	return rc;
}
Example #3
0
static ISO_SUSP_HEADER *
susp_lookup_record(struct open_file *f, const char *identifier,
    struct iso_directory_record *dp, int lenskip)
{
	static char susp_buffer[ISO_DEFAULT_BLOCK_SIZE];
	ISO_SUSP_HEADER *sh;
	ISO_RRIP_CONT *shc;
	char *p, *end;
	int error;
	size_t read;

	p = dp->name + isonum_711(dp->name_len) + lenskip;
	/* Names of even length have a padding byte after the name. */
	if ((isonum_711(dp->name_len) & 1) == 0)
		p++;
	end = (char *)dp + isonum_711(dp->length);
	while (p + 3 < end) {
		sh = (ISO_SUSP_HEADER *)p;
		if (bcmp(sh->type, identifier, 2) == 0)
			return (sh);
		if (bcmp(sh->type, SUSP_STOP, 2) == 0)
			return (NULL);
		if (bcmp(sh->type, SUSP_CONTINUATION, 2) == 0) {
			shc = (ISO_RRIP_CONT *)sh;
			error = f->f_dev->dv_strategy(f->f_devdata, F_READ,
			    cdb2devb(isonum_733(shc->location)),
			    ISO_DEFAULT_BLOCK_SIZE, susp_buffer, &read);

			/* Bail if it fails. */
			if (error != 0 || read != ISO_DEFAULT_BLOCK_SIZE)
				return (NULL);
			p = susp_buffer + isonum_733(shc->offset);
			end = p + isonum_733(shc->length);
		} else {
			/* Ignore this record and skip to the next. */
			p += isonum_711(sh->length);

			/* Avoid infinite loops with corrupted file systems */
			if (isonum_711(sh->length) == 0)
				return (NULL);
		}
	}
	return (NULL);
}
Example #4
0
static int
cd9660_open(const char *path, struct open_file *f)
{
	struct file *fp = NULL;
	void *buf;
	struct iso_primary_descriptor *vd;
	size_t buf_size, read, dsize, off;
	daddr_t bno, boff;
	struct iso_directory_record rec;
	struct iso_directory_record *dp = NULL;
	int rc, first, use_rrip, lenskip;

	/* First find the volume descriptor */
	buf = malloc(buf_size = ISO_DEFAULT_BLOCK_SIZE);
	vd = buf;
	for (bno = 16;; bno++) {
		twiddle(1);
		rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno),
		    ISO_DEFAULT_BLOCK_SIZE, buf, &read);
		if (rc)
			goto out;
		if (read != ISO_DEFAULT_BLOCK_SIZE) {
			rc = EIO;
			goto out;
		}
		rc = EINVAL;
		if (bcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0)
			goto out;
		if (isonum_711(vd->type) == ISO_VD_END)
			goto out;
		if (isonum_711(vd->type) == ISO_VD_PRIMARY)
			break;
	}
	if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE)
		goto out;

	rec = *(struct iso_directory_record *) vd->root_directory_record;
	if (*path == '/') path++; /* eat leading '/' */

	first = 1;
	use_rrip = 0;
	while (*path) {
		bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length);
		dsize = isonum_733(rec.size);
		off = 0;
		boff = 0;

		while (off < dsize) {
			if ((off % ISO_DEFAULT_BLOCK_SIZE) == 0) {
				twiddle(1);
				rc = f->f_dev->dv_strategy
					(f->f_devdata, F_READ,
					 cdb2devb(bno + boff),
					 ISO_DEFAULT_BLOCK_SIZE,
					 buf, &read);
				if (rc)
					goto out;
				if (read != ISO_DEFAULT_BLOCK_SIZE) {
					rc = EIO;
					goto out;
				}
				boff++;
				dp = (struct iso_directory_record *) buf;
			}
			if (isonum_711(dp->length) == 0) {
			    /* skip to next block, if any */
			    off = boff * ISO_DEFAULT_BLOCK_SIZE;
			    continue;
			}

			/* See if RRIP is in use. */
			if (first)
				use_rrip = rrip_check(f, dp, &lenskip);

			if (dirmatch(f, path, dp, use_rrip,
				first ? 0 : lenskip)) {
				first = 0;
				break;
			} else
				first = 0;

			dp = (struct iso_directory_record *)
				((char *) dp + isonum_711(dp->length));
			/* If the new block has zero length, it is padding. */
			if (isonum_711(dp->length) == 0) {
				/* Skip to next block, if any. */
				off = boff * ISO_DEFAULT_BLOCK_SIZE;
				continue;
			}
			off += isonum_711(dp->length);
		}
		if (off >= dsize) {
			rc = ENOENT;
			goto out;
		}

		rec = *dp;
		while (*path && *path != '/') /* look for next component */
			path++;
		if (*path) path++; /* skip '/' */
	}

	/* allocate file system specific data structure */
	fp = malloc(sizeof(struct file));
	bzero(fp, sizeof(struct file));
	f->f_fsdata = (void *)fp;

	if ((isonum_711(rec.flags) & 2) != 0) {
		fp->f_flags = F_ISDIR;
	}
	if (first) {
		fp->f_flags |= F_ROOTDIR;

		/* Check for Rock Ridge since we didn't in the loop above. */
		bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length);
		twiddle(1);
		rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno),
		    ISO_DEFAULT_BLOCK_SIZE, buf, &read);
		if (rc)
			goto out;
		if (read != ISO_DEFAULT_BLOCK_SIZE) {
			rc = EIO;
			goto out;
		}
		dp = (struct iso_directory_record *)buf;
		use_rrip = rrip_check(f, dp, &lenskip);
	}
	if (use_rrip) {
		fp->f_flags |= F_RR;
		fp->f_susp_skip = lenskip;
	}
	fp->f_off = 0;
	fp->f_bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length);
	fp->f_size = isonum_733(rec.size);
	free(buf);

	return 0;

out:
	if (fp)
		free(fp);
	free(buf);

	return rc;
}
Example #5
0
int
cd9660_open(const char *path, struct open_file *f)
{
	struct file *fp = 0;
	void *buf;
	struct iso_primary_descriptor *vd;
	size_t buf_size, nread, psize, dsize;
	daddr_t bno;
	int parent, ent;
	struct ptable_ent *pp;
	struct iso_directory_record *dp = 0;
	int rc;

	/* First find the volume descriptor */
	buf_size = ISO_DEFAULT_BLOCK_SIZE;
	buf = alloc(buf_size);
	vd = buf;
	for (bno = 16;; bno++) {
#if !defined(LIBSA_NO_TWIDDLE)
		twiddle();
#endif
		rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno),
					   ISO_DEFAULT_BLOCK_SIZE, buf, &nread);
		if (rc)
			goto out;
		if (nread != ISO_DEFAULT_BLOCK_SIZE) {
			rc = EIO;
			goto out;
		}
		rc = EINVAL;
		if (memcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0)
			goto out;
		if (isonum_711(vd->type) == ISO_VD_END)
			goto out;
		if (isonum_711(vd->type) == ISO_VD_PRIMARY)
			break;
	}
	if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE)
		goto out;

	/* Now get the path table and lookup the directory of the file */
	bno = isonum_732(vd->type_m_path_table);
	psize = isonum_733(vd->path_table_size);

	if (psize > ISO_DEFAULT_BLOCK_SIZE) {
		dealloc(buf, ISO_DEFAULT_BLOCK_SIZE);
		buf = alloc(buf_size = roundup(psize, ISO_DEFAULT_BLOCK_SIZE));
	}

#if !defined(LIBSA_NO_TWIDDLE)
	twiddle();
#endif
	rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno),
	                           buf_size, buf, &nread);
	if (rc)
		goto out;
	if (nread != buf_size) {
		rc = EIO;
		goto out;
	}

	parent = 1;
	pp = (struct ptable_ent *)buf;
	ent = 1;
	bno = isonum_732(pp->block) + isonum_711(pp->extlen);

	rc = ENOENT;
	/*
	 * Remove extra separators
	 */
	while (*path == '/')
		path++;

	while (*path) {
		if ((char *)pp >= (char *)buf + psize)
			break;
		if (isonum_722(pp->parent) != parent)
			break;
		if (!pnmatch(path, pp)) {
			pp = (struct ptable_ent *)((char *)pp + PTSIZE(pp));
			ent++;
			continue;
		}
		path += isonum_711(pp->namlen) + 1;
		parent = ent;
		bno = isonum_732(pp->block) + isonum_711(pp->extlen);
		while ((char *)pp < (char *)buf + psize) {
			if (isonum_722(pp->parent) == parent)
				break;
			pp = (struct ptable_ent *)((char *)pp + PTSIZE(pp));
			ent++;
		}
	}

	/*
	 * Now bno has the start of the directory that supposedly
	 * contains the file
	 */
	bno--;
	dsize = 1;		/* Something stupid, but > 0 XXX */
	for (psize = 0; psize < dsize;) {
		if (!(psize % ISO_DEFAULT_BLOCK_SIZE)) {
			bno++;
#if !defined(LIBSA_NO_TWIDDLE)
			twiddle();
#endif
			rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
			                           cdb2devb(bno),
			                           ISO_DEFAULT_BLOCK_SIZE,
			                           buf, &nread);
			if (rc)
				goto out;
			if (nread != ISO_DEFAULT_BLOCK_SIZE) {
				rc = EIO;
				goto out;
			}
			dp = (struct iso_directory_record *)buf;
		}
		if (!isonum_711(dp->length)) {
			if ((void *)dp == buf)
				psize += ISO_DEFAULT_BLOCK_SIZE;
			else
				psize = roundup(psize, ISO_DEFAULT_BLOCK_SIZE);
			continue;
		}
		if (dsize == 1)
			dsize = isonum_733(dp->size);
		if (dirmatch(path, dp))
			break;
		psize += isonum_711(dp->length);
		dp = (struct iso_directory_record *)
			((char *)dp + isonum_711(dp->length));
	}

	if (psize >= dsize) {
		rc = ENOENT;
		goto out;
	}

	/* allocate file system specific data structure */
	fp = alloc(sizeof(struct file));
	memset(fp, 0, sizeof(struct file));
	f->f_fsdata = (void *)fp;

	fp->off = 0;
	fp->bno = isonum_733(dp->extent);
	fp->size = isonum_733(dp->size);
	dealloc(buf, buf_size);

	return 0;

out:
	if (fp)
		dealloc(fp, sizeof(struct file));
	dealloc(buf, buf_size);

	return rc;
}