⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iso9660fs.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
字号:
/* $Id: iso9660fs.c,v 1.2 2002/08/19 08:02:05 pefo Exp $ *//*	$OpenBSD: cd9660.c,v 1.7 1998/05/30 02:29:56 mickey Exp $	*//*	$NetBSD: cd9660.c,v 1.1 1996/09/30 16:01:19 ws Exp $	*//* * Copyright (C) 1996 Wolfgang Solfrank. * Copyright (C) 1996 TooLs GmbH. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by TooLs GmbH. * 4. The name of TooLs GmbH may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *//* * Stand-alone ISO9660 file reading package. * * Note: This doesn't support Rock Ridge extensions, extended attributes, * blocksizes other than 2048 bytes, multi-extent files, etc. */#include <sys/param.h>#include <sys/systm.h>#include <sys/stat.h>#include <sys/unistd.h>#include <sys/device.h>#include <stdlib.h>#include <ctype.h>#include <pmon.h>#include <file.h>/* THIS IS AN UGLY HACK!!!			XXX */struct fid;struct mbuf;struct nameidata;struct netexport { int x; };struct proc;struct statfs;struct ucred;#include "iso9660.h"/* *  ISO9660 uses disk devio for physical access */extern int   devio_open (int, const char *, int, int);extern int   devio_close (int);extern int   devio_read (int, void *, size_t);extern int   devio_write (int, const void *, size_t);extern off_t devio_lseek (int, off_t, int);extern int errno;struct ptable_ent {	char namlen	[ISODCL( 1, 1)];	/* 711 */	char extlen	[ISODCL( 2, 2)];	/* 711 */	char block	[ISODCL( 3, 6)];	/* 732 */	char parent	[ISODCL( 7, 8)];	/* 722 */	char name	[1];};#define	PTFIXSZ		8#define	PTSIZE(pp)	roundup(PTFIXSZ + isonum_711((pp)->namlen), 2)static struct iso9660dev {        int   offs;        int   bno;        int   size;} openfile[OPEN_MAX];#define	cdb2devb(bno)	((off_t)(bno) * ISO_DEFAULT_BLOCK_SIZE)int   iso9660_open (int, const char *, int, int);int   iso9660_close (int);int   iso9660_read (int, void *, size_t);int   iso9660_write (int, const void *, size_t);off_t iso9660_lseek (int, off_t, int);static int pnmatch(const char *path, struct ptable_ent *pp);static int dirmatch(const char *path, struct iso_directory_record *dp);static intpnmatch(const char *path, struct ptable_ent *pp){	char *cp;	int i;		cp = pp->name;	for (i = isonum_711(pp->namlen); --i >= 0; path++, cp++) {		if (toupper(*path) == *cp)			continue;		return 0;	}	if (*path != '/')		return 0;	return 1;}static intdirmatch(const char *path, struct iso_directory_record *dp){	char *cp;	int i;	/* This needs to be a regular file */	if (dp->flags[0] & 6)		return 0;	cp = dp->name;	for (i = isonum_711(dp->name_len); --i >= 0; path++, cp++) {		if (!*path)			break;		if (toupper(*path) == *cp)			continue;		return 0;	}	if (*path)		return 0;	/*	 * Allow stripping of trailing dots and the version number.	 * Note that this will find the first instead of the last version	 * of a file.	 */	if (i >= 0 && (*cp == ';' || *cp == '.')) {		/* This is to prevent matching of numeric extensions */		if (*cp == '.' && cp[1] != ';')			return 0;		while (--i >= 0)			if (*++cp != ';' && (*cp < '0' || *cp > '9'))				return 0;	}	return 1;}intiso9660_open(int fd, const char *path, int flags, int mode){	char dpath[64];	void *buf;	const char *opath;	struct iso_primary_descriptor *vd;	size_t buf_size, psize, dsize;	daddr_t bno;	int parent, ent;	struct ptable_ent *pp;	struct iso_directory_record *dp;	int rc;		/*  Try to get to the physical device */	opath = path;	if (strncmp(opath, "/dev/", 5) == 0)		opath += 5;	if (strncmp(opath, "iso9660/", 8) == 0)		opath += 8;	/* There has to be at least one more component after the devicename */	if (strchr(opath, '/') == NULL) {		errno = ENOENT;		return -1;	}	/* Dig out the device name */	strncpy(dpath, opath, sizeof(dpath));	*(strchr(dpath, '/')) = '\0';	/* Set opath to point at the isolated filname path */	opath = strchr(opath, '/') + 1;	/* Try to open the physical device */	rc = devio_open(fd, dpath, flags, mode);	if (rc < 0)		return rc;	/* First find the volume descriptor */	buf = malloc(buf_size = ISO_DEFAULT_BLOCK_SIZE);	dp = (struct iso_directory_record *)buf;	vd = buf;	for (bno = 16;; bno++) {		devio_lseek(fd, cdb2devb(bno), SEEK_SET);		rc = devio_read(fd, buf, ISO_DEFAULT_BLOCK_SIZE);		if (rc != ISO_DEFAULT_BLOCK_SIZE) {			goto out;		}		errno = ENOENT;		/* In case of error */		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;		/* 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) {		free(buf);		buf = malloc(buf_size = roundup(psize, ISO_DEFAULT_BLOCK_SIZE));	}	devio_lseek(fd, cdb2devb(bno), SEEK_SET);	rc = devio_read(fd, buf, buf_size);	if (rc != buf_size) {		goto out;	}		parent = 1;	pp = (struct ptable_ent *)buf;	ent = 1;	bno = isonum_732(pp->block) + isonum_711(pp->extlen);		while (*opath) {		if ((void *)pp >= buf + psize)			break;		if (isonum_722(pp->parent) != parent)			break;		if (!pnmatch(opath, pp)) {			pp = (struct ptable_ent *)((void *)pp + PTSIZE(pp));			ent++;			continue;		}		opath += isonum_711(pp->namlen) + 1;		parent = ent;		bno = isonum_732(pp->block) + isonum_711(pp->extlen);		while ((void *)pp < buf + psize) {			if (isonum_722(pp->parent) == parent)				break;			pp = (struct ptable_ent *)((void *)pp + PTSIZE(pp));			ent++;		}	}	/* Now bno has the start of the dir 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++;			devio_lseek(fd, cdb2devb(bno), SEEK_SET);			rc = devio_read(fd, buf, ISO_DEFAULT_BLOCK_SIZE);			if (rc != ISO_DEFAULT_BLOCK_SIZE) {				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(opath, dp))			break;		psize += isonum_711(dp->length);		dp = (struct iso_directory_record *)((void *)dp + isonum_711(dp->length));	}	if (psize >= dsize) {		errno = ENOENT;		goto out;	}		/* allocate file system specific data structure */	openfile[fd].offs = 0;	openfile[fd].bno = isonum_733(dp->extent);	openfile[fd].size = isonum_733(dp->size);	free(buf);	return fd;	out:	free(buf);	rc = errno;	(void)devio_close(fd);	errno = rc;		/* Return real reason! */	return -1;}intiso9660_close(int fd){	return devio_close(fd);}intiso9660_read(int fd, void *start, size_t size){	int rc = 0;	daddr_t bno;	char buf[ISO_DEFAULT_BLOCK_SIZE];	char *dp;	size_t asked, offs;		asked = size;	while (size) {		if (openfile[fd].offs < 0 ||		    openfile[fd].offs >= openfile[fd].size)			break;		bno = (openfile[fd].offs >> ISO_DEFAULT_BLOCK_SHIFT);		bno += openfile[fd].bno;		if (openfile[fd].offs & (ISO_DEFAULT_BLOCK_SIZE - 1)		    || size < ISO_DEFAULT_BLOCK_SIZE)			dp = buf;		else			dp = start;		devio_lseek(fd, cdb2devb(bno), SEEK_SET);		rc = devio_read(fd, dp, ISO_DEFAULT_BLOCK_SIZE);		if (rc != ISO_DEFAULT_BLOCK_SIZE) {			errno = EIO;			return -1;		}		if (dp == buf) {			offs = openfile[fd].offs & (ISO_DEFAULT_BLOCK_SIZE - 1);			if (rc > offs + size)				rc = offs + size;			rc -= offs;			bcopy(buf + offs, start, rc);			start += rc;			openfile[fd].offs += rc;			size -= rc;		} else {			start += ISO_DEFAULT_BLOCK_SIZE;			openfile[fd].offs += ISO_DEFAULT_BLOCK_SIZE;			size -= ISO_DEFAULT_BLOCK_SIZE;		}	}	return asked - size;}intiso9660_write(int fd, const void *start, size_t size){	return EROFS;}off_tiso9660_lseek(int fd, off_t offset, int where){	switch (where) {	case SEEK_SET:		openfile[fd].offs = offset;		break;	case SEEK_CUR:		openfile[fd].offs += offset;		break;	case SEEK_END:		openfile[fd].offs = openfile[fd].size - offset;		break;	default:		return -1;	}	return openfile[fd].offs;}/* *  File system registration info. */static FileSystem iso9660fs = {        "iso9660", FS_FILE,        iso9660_open,        iso9660_read,        iso9660_write,        iso9660_lseek,        iso9660_close,	NULL};static void init_fs(void) __attribute__ ((constructor));static voidinit_fs(){	filefs_init(&iso9660fs);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -