示例#1
0
int
readliflabel(struct buf *bp, void (*strat)(struct buf *),
    struct disklabel *lp, int *partoffp, int spoofonly)
{
	struct buf *dbp = NULL;
	struct lifdir *p;
	struct lifvol *lvp;
	int error = 0;
	int fsoff = 0, openbsdstart = MAXLIFSPACE, i;

	/* read LIF volume header */
	bp->b_blkno = btodb(LIF_VOLSTART);
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if (biowait(bp))
		return (bp->b_error);

	lvp = (struct lifvol *)bp->b_data;
	if (lvp->vol_id != LIF_VOL_ID) {
		error = EINVAL;		/* no LIF volume header */
		goto done;
	}

	dbp = geteblk(LIF_DIRSIZE);
	dbp->b_dev = bp->b_dev;

	/* read LIF directory */
	dbp->b_blkno = lifstodb(lvp->vol_addr);
	dbp->b_bcount = lp->d_secsize;
	CLR(dbp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(dbp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(dbp);
	if (biowait(dbp)) {
		error = dbp->b_error;
		goto done;
	}

	/* scan for LIF_DIR_FS dir entry */
	for (i=0, p=(struct lifdir *)dbp->b_data; i < LIF_NUMDIR; p++, i++) {
		if (p->dir_type == LIF_DIR_FS || p->dir_type == LIF_DIR_HPLBL)
			break;
	}

	if (p->dir_type == LIF_DIR_FS) {
		fsoff = lifstodb(p->dir_addr);
		openbsdstart = 0;
		goto finished;
	}

	/* Only came here to find the offset... */
	if (partoffp)
		goto finished;

	if (p->dir_type == LIF_DIR_HPLBL) {
		struct hpux_label *hl;
		struct partition *pp;
		u_int8_t fstype;
		int i;

		/* read LIF directory */
		dbp->b_blkno = lifstodb(p->dir_addr);
		dbp->b_bcount = lp->d_secsize;
		CLR(dbp->b_flags, B_READ | B_WRITE | B_DONE);
		SET(dbp->b_flags, B_BUSY | B_READ | B_RAW);
		(*strat)(dbp);

		if (biowait(dbp)) {
			error = dbp->b_error;
			goto done;
		}

		hl = (struct hpux_label *)dbp->b_data;
		if (hl->hl_magic1 != hl->hl_magic2 ||
		    hl->hl_magic != HPUX_MAGIC || hl->hl_version != 1) {
			error = EINVAL;	 /* HPUX label magic mismatch */
			goto done;
		}

		lp->d_bbsize = 8192;
		lp->d_sbsize = 8192;
		for (i = 0; i < MAXPARTITIONS; i++) {
			DL_SETPSIZE(&lp->d_partitions[i], 0);
			DL_SETPOFFSET(&lp->d_partitions[i], 0);
			lp->d_partitions[i].p_fstype = 0;
		}

		for (i = 0; i < HPUX_MAXPART; i++) {
			if (!hl->hl_flags[i])
				continue;
			if (hl->hl_flags[i] == HPUX_PART_ROOT) {
				pp = &lp->d_partitions[0];
				fstype = FS_BSDFFS;
			} else if (hl->hl_flags[i] == HPUX_PART_SWAP) {
				pp = &lp->d_partitions[1];
				fstype = FS_SWAP;
			} else if (hl->hl_flags[i] == HPUX_PART_BOOT) {
				pp = &lp->d_partitions[RAW_PART + 1];
				fstype = FS_BSDFFS;
			} else
				continue;

			DL_SETPSIZE(pp, hl->hl_parts[i].hlp_length * 2);
			DL_SETPOFFSET(pp, hl->hl_parts[i].hlp_start * 2);
			pp->p_fstype = fstype;
		}

		DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
		DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
		lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
		lp->d_npartitions = MAXPARTITIONS;
		lp->d_magic = DISKMAGIC;
		lp->d_magic2 = DISKMAGIC;
		lp->d_version = 1;
		lp->d_checksum = 0;
		lp->d_checksum = dkcksum(lp);
		/* drop through */
	}

finished:
	/* record the OpenBSD partition's placement for the caller */
	if (partoffp)
		*partoffp = fsoff;
	else {
		DL_SETBSTART(lp, openbsdstart);
		DL_SETBEND(lp, DL_GETDSIZE(lp));	/* XXX */
	}

	/* don't read the on-disk label if we are in spoofed-only mode */
	if (spoofonly)
		goto done;

	bp->b_blkno = fsoff + LABELSECTOR;
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if (biowait(bp)) {
		error = bp->b_error;
		goto done;
	}

	/*
	 * Do OpenBSD disklabel validation/adjustment.
	 *
	 * N.B: No matter what the bits are on the disk, we now have the
	 * OpenBSD disklabel for this lif disk. DO NOT proceed to
	 * readdoslabel(), iso_spooflabel(), etc.
	 */
	checkdisklabel(bp->b_data, lp, openbsdstart, DL_GETDSIZE(lp));
	error = 0;

done:
	if (dbp) {
		dbp->b_flags |= B_INVAL;
		brelse(dbp);
	}
	return (error);
}
示例#2
0
文件: lif.c 项目: MarginC/kame
int
lif_open(const char *path, struct open_file *f)
{
	struct file *fp;
	struct lifdir *dp;
	const char *p, *q;
	struct lif_load load;
	int err, l;
	size_t buf_size;

#ifdef LIFDEBUG
	if (debug)
		printf("lif_open(%s, %p)\n", path, f);
#endif

	fp = alloc(sizeof(*fp));
	/* XXX we're assuming here that sizeof(fp->f_buf) >= LIF_FILESTART */

	err = (*f->f_dev->dv_strategy)(f->f_devdata, F_READ, 0,
	    sizeof(fp->f_buf), &fp->f_buf, &buf_size);
	if (err || buf_size != sizeof(fp->f_buf)) {
#ifdef LIFDEBUG
		if (debug)
			printf("lif_open: unable to read LIF header (%d)\n", err);
#endif
	} else if ((fp->f_lp = (struct lifvol *)fp->f_buf)->vol_id ==
		   LIF_VOL_ID) {
		f->f_fsdata = fp;
		fp->f_ld = (struct lifdir *)(fp->f_buf + LIF_DIRSTART);
		fp->f_seek = 0;
		fp->f_rd = fp->f_ld;
		fp->f_nfiles = lifstob(fp->f_lp->vol_dirsize) /
			sizeof(struct lifdir);

		/* no dirs on the lif */
		for (p = path + (l = strlen(path)); p >= path; p--)
			if (*p == '/') {
				p++;
				break;
			}
		if (p > path)
			path = p;
	} else
		err = EINVAL;

	if (!err && *path != '.') {
		fp->f_isdir = 0;
		err = ENOENT;
		for (dp = fp->f_ld; dp < &fp->f_ld[fp->f_nfiles]; dp++) {
#ifdef LIFDEBUG
			if (debug)
				printf("lif_open: "
				       "%s <--> '%c%c%c%c%c%c%c%c%c%c'\n",
				       path, dp->dir_name[0], dp->dir_name[1],
				       dp->dir_name[2], dp->dir_name[3],
				       dp->dir_name[4], dp->dir_name[5],
				       dp->dir_name[6], dp->dir_name[7],
				       dp->dir_name[8], dp->dir_name[9]);
#endif
			for (p = path, q = dp->dir_name;
			     *q && *q != ' '; q++, p++)
				if (tolower(*q) != tolower(*p))
					break;
			if ((!*q || *q == ' ') && !*p) {
				err = 0;
				break;
			}
		}
		if (!err) {
			fp->f_off = lifstodb(dp->dir_addr);
			if (!(err =(f->f_dev->dv_strategy)(f->f_devdata, F_READ,
			      fp->f_off, sizeof(load), &load, &buf_size)) &&
			    buf_size == sizeof(load)) {
				/* no checksum */
				fp->f_count = load.count - sizeof(int);
				fp->f_off = dbtob(fp->f_off) + sizeof(load);
#ifdef LIFDEBUG
				if (debug)
					printf("lif_open: %u @ %u [%x]\n",
					       fp->f_count, fp->f_off,
					       load.address);
#endif
			} else if (!err)
				err = EIO;
		}
	} else
		fp->f_isdir = 1;

	if (err) {
		free (fp, sizeof(*fp));
		f->f_fsdata = NULL;
	}
#ifdef LIFDEBUG
	if (debug)
		printf("ret(%d)\n", err);
#endif
	return err;
}