예제 #1
0
파일: ext2fs.c 프로젝트: ryo/netbsd-src
int
read_gdblock(struct open_file *f, struct m_ext2fs *fs)
{
	struct file *fp = (struct file *)f->f_fsdata;
	size_t rsize;
	uint gdpb;
	int i, rc;

	gdpb = fs->e2fs_bsize / sizeof(struct ext2_gd);

	for (i = 0; i < fs->e2fs_ngdb; i++) {
		rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
		    FSBTODB(fs, fs->e2fs.e2fs_first_dblock +
		    1 /* superblock */ + i),
		    fs->e2fs_bsize, fp->f_buf, &rsize);
		if (rc)
			return rc;
		if (rsize != fs->e2fs_bsize)
			return EIO;

		e2fs_cgload((struct ext2_gd *)fp->f_buf,
		    &fs->e2fs_gd[i * gdpb],
		    (i == (fs->e2fs_ngdb - 1)) ?
		    (fs->e2fs_ncg - gdpb * i) * sizeof(struct ext2_gd):
		    fs->e2fs_bsize);
	}

	return 0;
}
예제 #2
0
파일: read.c 프로젝트: AgamAgarwal/minix
oread(int fd, void *dest, size_t bcount)
#endif
{
	struct open_file *f = &files[fd];
	size_t resid;

#if !defined(LIBSA_NO_FD_CHECKING)
	if ((unsigned int)fd >= SOPEN_MAX || !(f->f_flags & F_READ)) {
		errno = EBADF;
		return -1;
	}
#endif
#if !defined(LIBSA_NO_RAW_ACCESS)
	if (f->f_flags & F_RAW) {
#if !defined(LIBSA_NO_TWIDDLE)
		twiddle();
#endif
		errno = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
			btodb(f->f_offset), bcount, dest, &resid);
		if (errno)
			return -1;
		f->f_offset += resid;
		return resid;
	}
#endif
	resid = bcount;
	if ((errno = FS_READ(f->f_ops)(f, dest, bcount, &resid)))
		return -1;
	return (ssize_t)(bcount - resid);
}
예제 #3
0
/*
 * Read a portion of a file into an internal buffer.
 * Return the location in the buffer and the amount in the buffer.
 */
static int
buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
{
	struct file *fp = (struct file *)f->f_fsdata;
	struct fs *fs = fp->f_fs;
	long off;
	indp_t file_block;
	size_t block_size;
	int rc;

	off = ufs_blkoff(fs, fp->f_seekp);
	file_block = ufs_lblkno(fs, fp->f_seekp);
#ifdef LIBSA_LFS
	block_size = dblksize(fs, &fp->f_di, file_block);
#else
	block_size = ffs_sblksize(fs, (int64_t)fp->f_di.di_size, file_block);
#endif

	if (file_block != fp->f_buf_blkno) {
		indp_t disk_block = 0; /* XXX: gcc */
		rc = block_map(f, file_block, &disk_block);
		if (rc)
			return rc;

		if (disk_block == 0) {
			memset(fp->f_buf, 0, block_size);
			fp->f_buf_size = block_size;
		} else {
			twiddle();
			rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
				FSBTODB(fs, disk_block),
				block_size, fp->f_buf, &fp->f_buf_size);
			if (rc)
				return rc;
		}

		fp->f_buf_blkno = file_block;
	}

	/*
	 * Return address of byte in buffer corresponding to
	 * offset, and size of remainder of buffer after that
	 * byte.
	 */
	*buf_p = fp->f_buf + off;
	*size_p = block_size - off;

	/*
	 * But truncate buffer at end of file.
	 */
	if (*size_p > fp->f_di.di_size - fp->f_seekp)
		*size_p = fp->f_di.di_size - fp->f_seekp;

	return 0;
}
예제 #4
0
/*
 * Read a new inode into a file structure.
 */
static int
read_inode(ino32_t inumber, struct open_file *f)
{
	struct file *fp = (struct file *)f->f_fsdata;
	struct fs *fs = fp->f_fs;
	char *buf;
	size_t rsize;
	int rc;
	daddr_t inode_sector = 0; /* XXX: gcc */
#ifdef LIBSA_LFS
	struct ufs_dinode *dip;
	int cnt;
#endif

#ifdef LIBSA_LFS
	if (inumber == fs->lfs_ifile)
		inode_sector = FSBTODB(fs, fs->lfs_idaddr);
	else if ((rc = find_inode_sector(inumber, f, &inode_sector)) != 0)
		return rc;
#else
	inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber));
#endif

	/*
	 * Read inode and save it.
	 */
	buf = fp->f_buf;
	twiddle();
	rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
	    inode_sector, fs->fs_bsize, buf, &rsize);
	if (rc)
		return rc;
	if (rsize != fs->fs_bsize)
		return EIO;

#ifdef LIBSA_LFS
	cnt = INOPBx(fs);
	dip = (struct ufs_dinode *)buf + (cnt - 1);
	for (; dip->di_inumber != inumber; --dip) {
		/* kernel code panics, but boot blocks which panic are Bad. */
		if (--cnt == 0)
			return EINVAL;
	}
	fp->f_di = *dip;
#else
	fp->f_di = ((struct ufs_dinode *)buf)[ino_to_fsbo(fs, inumber)];
#endif

	/*
	 * Clear out the old buffers
	 */
	fp->f_ind_cache_block = ~0;
	fp->f_buf_blkno = -1;
	return rc;
}
예제 #5
0
파일: ext2fs.c 프로젝트: ryo/netbsd-src
/*
 * Read a portion of a file into an internal buffer.
 * Return the location in the buffer and the amount in the buffer.
 */
static int
buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
{
	struct file *fp = (struct file *)f->f_fsdata;
	struct m_ext2fs *fs = fp->f_fs;
	long off;
	indp_t file_block;
	indp_t disk_block = 0;	/* XXX: gcc */
	size_t block_size;
	int rc;

	off = ext2_blkoff(fs, fp->f_seekp);
	file_block = ext2_lblkno(fs, fp->f_seekp);
	block_size = fs->e2fs_bsize;	/* no fragment */

	if (file_block != fp->f_buf_blkno) {
		rc = block_map(f, file_block, &disk_block);
		if (rc)
			return rc;

		if (disk_block == 0) {
			memset(fp->f_buf, 0, block_size);
			fp->f_buf_size = block_size;
		} else {
			twiddle();
			rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
				FSBTODB(fs, disk_block),
				block_size, fp->f_buf, &fp->f_buf_size);
			if (rc)
				return rc;
		}

		fp->f_buf_blkno = file_block;
	}

	/*
	 * Return address of byte in buffer corresponding to
	 * offset, and size of remainder of buffer after that
	 * byte.
	 */
	*buf_p = fp->f_buf + off;
	*size_p = block_size - off;

	/*
	 * But truncate buffer at end of file.
	 */
	/* XXX should handle LARGEFILE */
	if (*size_p > fp->f_di.e2di_size - fp->f_seekp)
		*size_p = fp->f_di.e2di_size - fp->f_seekp;

	return 0;
}
예제 #6
0
/*
 * Read a portion of a file into an internal buffer.
 * Return the location in the buffer and the amount in the buffer.
 */
static int
buf_read_file(struct open_file *f, void *v, size_t *size_p)
{
	char **buf_p = v;
	struct file *fp = (struct file *)f->f_fsdata;
	struct mfs_sblock *fs = fp->f_fs;
	long off;
	block_t file_block;
	block_t disk_block;
	size_t block_size;
	int rc;

	off = mfs_blkoff(fs, fp->f_seekp);
	file_block = mfs_lblkno(fs, fp->f_seekp);
	block_size = fs->mfs_block_size;

	if (file_block != fp->f_buf_blkno) {
		rc = block_map(f, file_block, &disk_block);
		if (rc)
			return rc;

		if (disk_block == 0) {
			memset(fp->f_buf, 0, block_size);
			fp->f_buf_size = block_size;
		} else {
			twiddle();
			rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
				FSBTODB(fs, disk_block),
				block_size, fp->f_buf, &fp->f_buf_size);
			if (rc)
				return rc;
		}

		fp->f_buf_blkno = file_block;
	}

	/*
	 * Return address of byte in buffer corresponding to
	 * offset, and size of remainder of buffer after that
	 * byte.
	 */
	*buf_p = fp->f_buf + off;
	*size_p = block_size - off;

	/*
	 * But truncate buffer at end of file.
	 */
	if (*size_p > fp->f_di.mdi_size - fp->f_seekp)
		*size_p = fp->f_di.mdi_size - fp->f_seekp;

	return 0;
}
예제 #7
0
int
read_sblock(struct open_file *f, struct mfs_sblock *fs)
{
	static uint8_t sbbuf[MINBSIZE];
	size_t buf_size;
	int rc;

	/* We must read amount multiple of sector size, hence we can't
	 * read SBSIZE and read MINBSIZE.
	 */
	if (SBSIZE > MINBSIZE)
		return EINVAL;

	rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
	    SUPER_BLOCK_OFF / DEV_BSIZE, MINBSIZE, sbbuf, &buf_size);
	if (rc)
		return rc;

	if (buf_size != MINBSIZE)
		return EIO;

	mfs_sbload((void *)sbbuf, fs);

	if (fs->mfs_magic != SUPER_MAGIC)
		return EINVAL;
	if (fs->mfs_block_size < MINBSIZE)
		return EINVAL;
	if ((fs->mfs_block_size % 512) != 0)
		return EINVAL;
	if (SBSIZE > fs->mfs_block_size)
		return EINVAL;
	if ((fs->mfs_block_size % INODE_SIZE) != 0)
		return EINVAL;

	/* For even larger disks, a similar problem occurs with s_firstdatazone.
	 * If the on-disk field contains zero, we assume that the value was too
	 * large to fit, and compute it on the fly.
	 */
	if (fs->mfs_firstdatazone_old == 0) {
		block_t offset;
		offset = START_BLOCK + fs->mfs_imap_blocks + fs->mfs_zmap_blocks;
		offset += (fs->mfs_ninodes + fs->mfs_inodes_per_block - 1) /
				fs->mfs_inodes_per_block;

		fs->mfs_firstdatazone =
			(offset + (1 << fs->mfs_log_zone_size) - 1) >>
				fs->mfs_log_zone_size;
	} else {
예제 #8
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;
}
예제 #9
0
파일: ext2fs.c 프로젝트: ryo/netbsd-src
int
read_sblock(struct open_file *f, struct m_ext2fs *fs)
{
	static uint8_t sbbuf[SBSIZE];
	struct ext2fs ext2fs;
	size_t buf_size;
	int rc;

	rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
	    SBOFF / DEV_BSIZE, SBSIZE, sbbuf, &buf_size);
	if (rc)
		return rc;

	if (buf_size != SBSIZE)
		return EIO;

	e2fs_sbload((void *)sbbuf, &ext2fs);
	if (ext2fs.e2fs_magic != E2FS_MAGIC)
		return EINVAL;
	if (ext2fs.e2fs_rev > E2FS_REV1 ||
	    (ext2fs.e2fs_rev == E2FS_REV1 &&
	     (ext2fs.e2fs_first_ino != EXT2_FIRSTINO ||
	     (ext2fs.e2fs_inode_size != 128 && ext2fs.e2fs_inode_size != 256) ||
	      ext2fs.e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP))) {
		return ENODEV;
	}

	e2fs_sbload((void *)sbbuf, &fs->e2fs);
	/* compute in-memory m_ext2fs values */
	fs->e2fs_ncg =
	    howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
	    fs->e2fs.e2fs_bpg);
	/* XXX assume hw bsize = 512 */
	fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1;
	fs->e2fs_bsize = MINBSIZE << fs->e2fs.e2fs_log_bsize;
	fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize;
	fs->e2fs_qbmask = fs->e2fs_bsize - 1;
	fs->e2fs_bmask = ~fs->e2fs_qbmask;
	fs->e2fs_ngdb =
	    howmany(fs->e2fs_ncg, fs->e2fs_bsize / sizeof(struct ext2_gd));
	fs->e2fs_ipb = fs->e2fs_bsize / ext2fs.e2fs_inode_size;
	fs->e2fs_itpg = fs->e2fs.e2fs_ipg / fs->e2fs_ipb;

	return 0;
}
예제 #10
0
static int
ffs_find_superblock(struct open_file *f, struct fs *fs)
{
	int i, rc;
	size_t buf_size;

	for (i = 0; sblock_try[i] != -1; i++) {
		rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
		    sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size);
		if (rc != 0 || buf_size != SBLOCKSIZE)
			return rc;
		if (fs->fs_sblockloc != sblock_try[i])
			/* an alternate superblock - try again */
			continue;
		if (fs->fs_magic == FS_UFS2_MAGIC) {
			return 0;
		}
	}
	return EINVAL;
}
예제 #11
0
파일: ext2fs.c 프로젝트: ryo/netbsd-src
/*
 * Read a new inode into a file structure.
 */
static int
read_inode(ino32_t inumber, struct open_file *f)
{
	struct file *fp = (struct file *)f->f_fsdata;
	struct m_ext2fs *fs = fp->f_fs;
	char *buf;
	size_t rsize;
	int rc;
	daddr_t inode_sector;
	struct ext2fs_dinode *dip;

	inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber));

	/*
	 * Read inode and save it.
	 */
	buf = fp->f_buf;
	twiddle();
	rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
	    inode_sector, fs->e2fs_bsize, buf, &rsize);
	if (rc)
		return rc;
	if (rsize != fs->e2fs_bsize)
		return EIO;

	dip = (struct ext2fs_dinode *)(buf +
	    EXT2_DINODE_SIZE(fs) * ino_to_fsbo(fs, inumber));
	e2fs_iload(dip, &fp->f_di, EXT2_DINODE_SIZE(fs));

	/*
	 * Clear out the old buffers
	 */
	fp->f_ind_cache_block = ~0;
	fp->f_buf_blkno = -1;
	return rc;
}
예제 #12
0
/*
 * Open a file.
 */
__compactcall int
ufs_open(const char *path, struct open_file *f)
{
#ifndef LIBSA_FS_SINGLECOMPONENT
	const char *cp, *ncp;
	int c;
#endif
	ino32_t inumber;
	struct file *fp;
	struct fs *fs;
	int rc;
#ifndef LIBSA_NO_FS_SYMLINK
	ino32_t parent_inumber;
	int nlinks = 0;
	char namebuf[MAXPATHLEN+1];
	char *buf;
#endif

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

	/* allocate space and read super block */
	fs = alloc(SBLOCKSIZE);
	fp->f_fs = fs;
	twiddle();

#ifdef LIBSA_FFSv2
	rc = ffs_find_superblock(f, fs);
	if (rc)
		goto out;
#else
	{
		size_t buf_size;
		rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
			SBLOCKOFFSET / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size);
		if (rc)
			goto out;
		if (buf_size != SBLOCKSIZE ||
#ifdef LIBSA_FFS
		    fs->lfs_version != REQUIRED_LFS_VERSION ||
#endif
		    fs->fs_magic != FS_MAGIC) {
			rc = EINVAL;
			goto out;
		}
	}
#if defined(LIBSA_LFS) && REQUIRED_LFS_VERSION == 2
	/*
	 * XXX	We should check the second superblock and use the eldest
	 *	of the two.  See comments near the top of lfs_mountfs()
	 *	in sys/ufs/lfs/lfs_vfsops.c.
	 *      This may need a LIBSA_LFS_SMALL check as well.
	 */
#endif
#endif

#ifdef LIBSA_FFSv1
	ffs_oldfscompat(fs);
#endif

	if (fs->fs_bsize > MAXBSIZE ||
	    (size_t)fs->fs_bsize < sizeof(struct fs)) {
		rc = EINVAL;
		goto out;
	}

	/*
	 * Calculate indirect block levels.
	 */
	{
		indp_t mult;
		int ln2;

		/*
		 * We note that the number of indirect blocks is always
		 * a power of 2.  This lets us use shifts and masks instead
		 * of divide and remainder and avoinds pulling in the
		 * 64bit division routine into the boot code.
		 */
		mult = UFS_NINDIR(fs);
#ifdef DEBUG
		if (mult & (mult - 1)) {
			/* Hummm was't a power of 2 */
			rc = EINVAL;
			goto out;
		}
#endif
		for (ln2 = 0; mult != 1; ln2++)
			mult >>= 1;

		fp->f_nishift = ln2;
	}

	/* alloc a block sized buffer used for all fs transfers */
	fp->f_buf = alloc(fs->fs_bsize);
	inumber = UFS_ROOTINO;
	if ((rc = read_inode(inumber, f)) != 0)
		goto out;

#ifndef LIBSA_FS_SINGLECOMPONENT
	cp = path;
	while (*cp) {

		/*
		 * Remove extra separators
		 */
		while (*cp == '/')
			cp++;
		if (*cp == '\0')
			break;

		/*
		 * Check that current node is a directory.
		 */
		if ((fp->f_di.di_mode & IFMT) != IFDIR) {
			rc = ENOTDIR;
			goto out;
		}

		/*
		 * Get next component of path name.
		 */
		ncp = cp;
		while ((c = *cp) != '\0' && c != '/')
			cp++;

		/*
		 * Look up component in current directory.
		 * Save directory inumber in case we find a
		 * symbolic link.
		 */
#ifndef LIBSA_NO_FS_SYMLINK
		parent_inumber = inumber;
#endif
		rc = search_directory(ncp, cp - ncp, f, &inumber);
		if (rc)
			goto out;

		/*
		 * Open next component.
		 */
		if ((rc = read_inode(inumber, f)) != 0)
			goto out;

#ifndef LIBSA_NO_FS_SYMLINK
		/*
		 * Check for symbolic link.
		 */
		if ((fp->f_di.di_mode & IFMT) == IFLNK) {
			int link_len = fp->f_di.di_size;
			int len;

			len = strlen(cp);

			if (link_len + len > MAXPATHLEN ||
			    ++nlinks > MAXSYMLINKS) {
				rc = ENOENT;
				goto out;
			}

			memmove(&namebuf[link_len], cp, len + 1);

			if (link_len < fs->fs_maxsymlinklen) {
				memcpy(namebuf, fp->f_di.di_db, link_len);
			} else {
				/*
				 * Read file for symbolic link
				 */
				size_t buf_size;
				indp_t	disk_block;

				buf = fp->f_buf;
				rc = block_map(f, (indp_t)0, &disk_block);
				if (rc)
					goto out;

				twiddle();
				rc = DEV_STRATEGY(f->f_dev)(f->f_devdata,
					F_READ, FSBTODB(fs, disk_block),
					fs->fs_bsize, buf, &buf_size);
				if (rc)
					goto out;

				memcpy(namebuf, buf, link_len);
			}

			/*
			 * If relative pathname, restart at parent directory.
			 * If absolute pathname, restart at root.
			 */
			cp = namebuf;
			if (*cp != '/')
				inumber = parent_inumber;
			else
				inumber = (ino32_t)UFS_ROOTINO;

			if ((rc = read_inode(inumber, f)) != 0)
				goto out;
		}
#endif	/* !LIBSA_NO_FS_SYMLINK */
	}

	/*
	 * Found terminal component.
	 */
	rc = 0;

#else /* !LIBSA_FS_SINGLECOMPONENT */

	/* look up component in the current (root) directory */
	rc = search_directory(path, strlen(path), f, &inumber);
	if (rc)
		goto out;

	/* open it */
	rc = read_inode(inumber, f);

#endif /* !LIBSA_FS_SINGLECOMPONENT */

	fp->f_seekp = 0;		/* reset seek pointer */

out:
	if (rc)
		ufs_close(f);
#ifdef FSMOD		/* Only defined for lfs */
	else
		fsmod = FSMOD;
#endif
	return rc;
}
예제 #13
0
/*
 * Given an offset in a file, find the disk block number that
 * contains that block.
 */
static int
block_map(struct open_file *f, indp_t file_block, indp_t *disk_block_p)
{
	struct file *fp = (struct file *)f->f_fsdata;
	struct fs *fs = fp->f_fs;
	uint level;
	indp_t ind_cache;
	indp_t ind_block_num;
	size_t rsize;
	int rc;
	indp_t *buf = (void *)fp->f_buf;

	/*
	 * Index structure of an inode:
	 *
	 * di_db[0..UFS_NDADDR-1]	hold block numbers for blocks
	 *			0..UFS_NDADDR-1
	 *
	 * di_ib[0]		index block 0 is the single indirect block
	 *			holds block numbers for blocks
	 *			UFS_NDADDR .. UFS_NDADDR + UFS_NINDIR(fs)-1
	 *
	 * di_ib[1]		index block 1 is the double indirect block
	 *			holds block numbers for INDEX blocks for blocks
	 *			UFS_NDADDR + UFS_NINDIR(fs) ..
	 *			UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2 - 1
	 *
	 * di_ib[2]		index block 2 is the triple indirect block
	 *			holds block numbers for double-indirect
	 *			blocks for blocks
	 *			UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2 ..
	 *			UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2
	 *				+ UFS_NINDIR(fs)**3 - 1
	 */

	if (file_block < UFS_NDADDR) {
		/* Direct block. */
		*disk_block_p = fp->f_di.di_db[file_block];
		return 0;
	}

	file_block -= UFS_NDADDR;

	ind_cache = file_block >> LN2_IND_CACHE_SZ;
	if (ind_cache == fp->f_ind_cache_block) {
		*disk_block_p = fp->f_ind_cache[file_block & IND_CACHE_MASK];
		return 0;
	}

	for (level = 0;;) {
		level += fp->f_nishift;
		if (file_block < (indp_t)1 << level)
			break;
		if (level > UFS_NIADDR * fp->f_nishift)
			/* Block number too high */
			return EFBIG;
		file_block -= (indp_t)1 << level;
	}

	ind_block_num = fp->f_di.di_ib[level / fp->f_nishift - 1];

	for (;;) {
		level -= fp->f_nishift;
		if (ind_block_num == 0) {
			*disk_block_p = 0;	/* missing */
			return 0;
		}

		twiddle();
		/*
		 * If we were feeling brave, we could work out the number
		 * of the disk sector and read a single disk sector instead
		 * of a filesystem block.
		 * However we don't do this very often anyway...
		 */
		rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
			FSBTODB(fp->f_fs, ind_block_num), fs->fs_bsize,
			buf, &rsize);
		if (rc)
			return rc;
		if (rsize != fs->fs_bsize)
			return EIO;
		ind_block_num = buf[file_block >> level];
		if (level == 0)
			break;
		file_block &= (1 << level) - 1;
	}

	/* Save the part of the block that contains this sector */
	memcpy(fp->f_ind_cache, &buf[file_block & ~IND_CACHE_MASK],
	    IND_CACHE_SZ * sizeof fp->f_ind_cache[0]);
	fp->f_ind_cache_block = ind_cache;

	*disk_block_p = ind_block_num;

	return 0;
}
예제 #14
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;
}
예제 #15
0
파일: ext2fs.c 프로젝트: ryo/netbsd-src
/*
 * Open a file.
 */
__compactcall int
ext2fs_open(const char *path, struct open_file *f)
{
#ifndef LIBSA_FS_SINGLECOMPONENT
	const char *cp, *ncp;
	int c;
#endif
	ino32_t inumber;
	struct file *fp;
	struct m_ext2fs *fs;
	int rc;
#ifndef LIBSA_NO_FS_SYMLINK
	ino32_t parent_inumber;
	int nlinks = 0;
	char namebuf[MAXPATHLEN+1];
	char *buf;
#endif

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

	/* allocate space and read super block */
	fs = alloc(sizeof(*fs));
	memset(fs, 0, sizeof(*fs));
	fp->f_fs = fs;
	twiddle();

	rc = read_sblock(f, fs);
	if (rc)
		goto out;

#ifdef EXT2FS_DEBUG
	dump_sblock(fs);
#endif

	/* alloc a block sized buffer used for all fs transfers */
	fp->f_buf = alloc(fs->e2fs_bsize);

	/* read group descriptor blocks */
	fs->e2fs_gd = alloc(sizeof(struct ext2_gd) * fs->e2fs_ncg);
	rc = read_gdblock(f, fs);
	if (rc)
		goto out;

	/*
	 * Calculate indirect block levels.
	 */
	{
		indp_t mult;
		int ln2;

		/*
		 * We note that the number of indirect blocks is always
		 * a power of 2.  This lets us use shifts and masks instead
		 * of divide and remainder and avoinds pulling in the
		 * 64bit division routine into the boot code.
		 */
		mult = EXT2_NINDIR(fs);
#ifdef DEBUG
		if (!powerof2(mult)) {
			/* Hummm was't a power of 2 */
			rc = EINVAL;
			goto out;
		}
#endif
		for (ln2 = 0; mult != 1; ln2++)
			mult >>= 1;

		fp->f_nishift = ln2;
	}

	inumber = EXT2_ROOTINO;
	if ((rc = read_inode(inumber, f)) != 0)
		goto out;

#ifndef LIBSA_FS_SINGLECOMPONENT
	cp = path;
	while (*cp) {

		/*
		 * Remove extra separators
		 */
		while (*cp == '/')
			cp++;
		if (*cp == '\0')
			break;

		/*
		 * Check that current node is a directory.
		 */
		if ((fp->f_di.e2di_mode & EXT2_IFMT) != EXT2_IFDIR) {
			rc = ENOTDIR;
			goto out;
		}

		/*
		 * Get next component of path name.
		 */
		ncp = cp;
		while ((c = *cp) != '\0' && c != '/')
			cp++;

		/*
		 * Look up component in current directory.
		 * Save directory inumber in case we find a
		 * symbolic link.
		 */
#ifndef LIBSA_NO_FS_SYMLINK
		parent_inumber = inumber;
#endif
		rc = search_directory(ncp, cp - ncp, f, &inumber);
		if (rc)
			goto out;

		/*
		 * Open next component.
		 */
		if ((rc = read_inode(inumber, f)) != 0)
			goto out;

#ifndef LIBSA_NO_FS_SYMLINK
		/*
		 * Check for symbolic link.
		 */
		if ((fp->f_di.e2di_mode & EXT2_IFMT) == EXT2_IFLNK) {
			/* XXX should handle LARGEFILE */
			int link_len = fp->f_di.e2di_size;
			int len;

			len = strlen(cp);

			if (link_len + len > MAXPATHLEN ||
			    ++nlinks > MAXSYMLINKS) {
				rc = ENOENT;
				goto out;
			}

			memmove(&namebuf[link_len], cp, len + 1);

			if (link_len < EXT2_MAXSYMLINKLEN) {
				memcpy(namebuf, fp->f_di.e2di_blocks, link_len);
			} else {
				/*
				 * Read file for symbolic link
				 */
				size_t buf_size;
				indp_t	disk_block;

				buf = fp->f_buf;
				rc = block_map(f, (indp_t)0, &disk_block);
				if (rc)
					goto out;

				twiddle();
				rc = DEV_STRATEGY(f->f_dev)(f->f_devdata,
					F_READ, FSBTODB(fs, disk_block),
					fs->e2fs_bsize, buf, &buf_size);
				if (rc)
					goto out;

				memcpy(namebuf, buf, link_len);
			}

			/*
			 * If relative pathname, restart at parent directory.
			 * If absolute pathname, restart at root.
			 */
			cp = namebuf;
			if (*cp != '/')
				inumber = parent_inumber;
			else
				inumber = (ino32_t)EXT2_ROOTINO;

			if ((rc = read_inode(inumber, f)) != 0)
				goto out;
		}
#endif	/* !LIBSA_NO_FS_SYMLINK */
	}

	/*
	 * Found terminal component.
	 */
	rc = 0;

#else /* !LIBSA_FS_SINGLECOMPONENT */

	/* look up component in the current (root) directory */
	rc = search_directory(path, strlen(path), f, &inumber);
	if (rc)
		goto out;

	/* open it */
	rc = read_inode(inumber, f);

#endif /* !LIBSA_FS_SINGLECOMPONENT */

	fp->f_seekp = 0;		/* reset seek pointer */

out:
	if (rc)
		ext2fs_close(f);
	else
		fsmod = "ext2fs";
	return rc;
}
예제 #16
0
/*
 * Given an offset in a file, find the disk block number (not zone!)
 * that contains that block.
 */
static int
block_map(struct open_file *f, block_t file_block, block_t *disk_block_p)
{
	struct file *fp = (struct file *)f->f_fsdata;
	struct mfs_sblock *fs = fp->f_fs;
	uint level;
	block_t ind_cache;
	block_t ind_block_num;
	zone_t zone;
	size_t rsize;
	int rc;
	int boff;
	int scale = fs->mfs_log_zone_size; /* for block-zone conversion */
	block_t *buf = (void *)fp->f_buf;

	/*
	 * Index structure of an inode:
	 *
	 * mdi_blocks[0..NR_DZONES-1]
	 *			hold zone numbers for zones
	 *			0..NR_DZONES-1
	 *
	 * mdi_blocks[NR_DZONES+0]
	 *			block NDADDR+0 is the single indirect block
	 *			holds zone numbers for zones
	 *			NR_DZONES .. NR_DZONES + MFS_NINDIR(fs)-1
	 *
	 * mdi_blocks[NR_DZONES+1]
	 *			block NDADDR+1 is the double indirect block
	 *			holds zone numbers for INDEX blocks for zones
	 *			NR_DZONES + MFS_NINDIR(fs) ..
	 *			NR_TZONES + MFS_NINDIR(fs) + MFS_NINDIR(fs)**2 - 1
	 */

	zone = file_block >> scale;
	boff = (int) (file_block - (zone << scale) ); /* relative blk in zone */

	if (zone < NR_DZONES) {
		/* Direct zone */
		zone_t z = fs2h32(fp->f_di.mdi_zone[zone]);
		if (z == NO_ZONE) {
			*disk_block_p = NO_BLOCK;
			return 0;
		}
		*disk_block_p = (block_t) ((z << scale) + boff);
		return 0;
	}

	zone -= NR_DZONES;

	ind_cache = zone >> LN2_IND_CACHE_SZ;
	if (ind_cache == fp->f_ind_cache_block) {
		*disk_block_p =
		    fs2h32(fp->f_ind_cache[zone & IND_CACHE_MASK]);
		return 0;
	}

	for (level = 0;;) {
		level += fp->f_nishift;

		if (zone < (block_t)1 << level)
			break;
		if (level > NIADDR * fp->f_nishift)
			/* Zone number too high */
			return EFBIG;
		zone -= (block_t)1 << level;
	}

	ind_block_num =
	    fs2h32(fp->f_di.mdi_zone[NR_DZONES + (level / fp->f_nishift - 1)]);

	for (;;) {
		level -= fp->f_nishift;
		if (ind_block_num == 0) {
			*disk_block_p = NO_BLOCK;	/* missing */
			return 0;
		}

		twiddle();
		/*
		 * If we were feeling brave, we could work out the number
		 * of the disk sector and read a single disk sector instead
		 * of a filesystem block.
		 * However we don't do this very often anyway...
		 */
		rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
			FSBTODB(fs, ind_block_num), fs->mfs_block_size,
			buf, &rsize);
		if (rc)
			return rc;
		if (rsize != fs->mfs_block_size)
			return EIO;

		ind_block_num = fs2h32(buf[zone >> level]);
		if (level == 0)
			break;
		zone &= (1 << level) - 1;
	}

	/* Save the part of the block that contains this sector */
	memcpy(fp->f_ind_cache, &buf[zone & ~IND_CACHE_MASK],
	    IND_CACHE_SZ * sizeof fp->f_ind_cache[0]);
	fp->f_ind_cache_block = ind_cache;

	zone = (zone_t)ind_block_num;
	*disk_block_p = (block_t)((zone << scale) + boff);
	return 0;
}