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

📄 arfs_vnops.c

📁 微内核软实时操作系统
💻 C
字号:
/* * Copyright (c) 2006-2007, Kohsuke Ohtani * 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. Neither the name of the author nor the names of any co-contributors  *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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. *//* * arfs_vnops.c - vnode operations for archive file system. */#include <prex/prex.h>#include <sys/stat.h>#include <sys/vnode.h>#include <sys/file.h>#include <sys/mount.h>#include <sys/param.h>#include <sys/dirent.h>#include <sys/buf.h>#include <ctype.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include <limits.h>#include <fcntl.h>#include "arfs.h"static char iobuf[BSIZE*2];static mutex_t arfs_lock = MUTEX_INITIALIZER;/* * Read two blocks. * iobuf is filled by read data. */static int arfs_readblk(mount_t mp, int blkno){	struct buf *bp;	int err;	/* Read two blocks for archive header */	if ((err = bread(mp->m_dev, blkno, &bp)) != 0)		return err;	memcpy(iobuf, bp->b_data, BSIZE);	brelse(bp);		if ((err = bread(mp->m_dev, blkno + 1, &bp)) != 0)		return err;	memcpy(iobuf + BSIZE, bp->b_data, BSIZE);	brelse(bp);	return 0;}/* * Lookup vnode for the specified file/directory. * The vnode is filled properly. */static int arfs_lookup(vnode_t dvp, char *name, vnode_t vp){	struct ar_hdr *hdr;	int blkno, err;	off_t offset;	size_t size;	mount_t mp;	char *p;	dprintf("lookup: name=%s\n", name);	if (*name == '\0')		return ENOENT;	mutex_lock(&arfs_lock);		err = ENOENT;	mp = vp->v_mount;	blkno = 0;	offset = SARMAG;	/* offset in archive image */	for (;;) {		/* Read two blocks for archive header */		if ((err = arfs_readblk(mp, blkno)) != 0)			goto out;		/* Check file header */		hdr = (struct ar_hdr *)(iobuf + (offset % BSIZE));		if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1))			goto out;		/* Get file size */		size = (size_t)atol((char *)&hdr->ar_size);		if (size == 0)			goto out;		/* Convert archive name */		if ((p = memchr(&hdr->ar_name, '/', 16)) != NULL)			*p = '\0';		if (strncmp(name, (char *)&hdr->ar_name, 16) == 0)			break;		/* Proceed to next archive header */		offset += (sizeof(struct ar_hdr) + size);		offset += (offset % 2); /* Pad to even boundary */		blkno = (int)(offset / BSIZE);	}	vp->v_type = VREG;	vp->v_mode = (mode_t)(S_IRWXU | S_IRWXG | S_IRWXO | S_IFREG);	vp->v_size = size;	vp->v_blkno = blkno;	vp->v_data = (void *)(offset + sizeof(struct ar_hdr));	err = 0; out:	mutex_unlock(&arfs_lock);	dprintf("lookup: err=%d\n\n", err);	return err;}static int arfs_read(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result){	off_t offset, file_pos, buf_pos;	int blkno, err;	size_t nr_read, nr_copy;	mount_t mp;	struct buf *bp;	dprintf("****read: start size=%d\n", size);	mutex_lock(&arfs_lock);	*result = 0;	mp = vp->v_mount;	/* Check if current file position is already end of file. */	file_pos = fp->f_offset;	if (file_pos >= vp->v_size) {		err = 0;		goto out;	}	/* Get the actual read size. */	if (vp->v_size - file_pos < size)		size = vp->v_size - file_pos;	/* Read and copy data */	offset = (off_t)vp->v_data;	nr_read = 0;	for (;;) {		dprintf("file_pos=%d buf=%x size=%d\n", file_pos, buf, size);		blkno = (offset + file_pos) / BSIZE;		buf_pos = (offset + file_pos) % BSIZE;		if ((err = bread(mp->m_dev, blkno, &bp)) != 0)			goto out;		nr_copy = BSIZE;		if (buf_pos > 0)			nr_copy -= buf_pos;		if (buf_pos + size < BSIZE)			nr_copy = size;		ASSERT(nr_copy > 0);		memcpy(buf, bp->b_data + buf_pos, nr_copy);		brelse(bp);		file_pos += nr_copy;		dprintf("file_pos=%d nr_copy=%d\n", file_pos, nr_copy);		nr_read += nr_copy;		size -= nr_copy;		if (size <= 0)			break;		buf += nr_copy;		buf_pos = 0;	}	fp->f_offset = file_pos;	*result = nr_read;	err = 0; out:	mutex_unlock(&arfs_lock);	dprintf("read: err=%d\n\n", err);	return err;}/* * Check if the seek offset is valid. */static int arfs_seek(vnode_t vp, file_t fp, off_t oldoff, off_t newoff){	if (newoff > vp->v_size)		return -1;	return 0;}static int arfs_readdir(vnode_t vp, file_t fp, struct dirent *dir){	struct ar_hdr *hdr;	int blkno, i, err;	off_t offset;	size_t size;	mount_t mp;	char *p;	dprintf("readdir: start\n");	mutex_lock(&arfs_lock);		i = 0;	mp = vp->v_mount;	blkno = 0;	offset = SARMAG;	/* offset in archive image */	for (;;) {		/* Read two blocks for archive header */		if ((err = arfs_readblk(mp, blkno)) != 0)			goto out;		hdr = (struct ar_hdr *)(iobuf + (offset % BSIZE));		/* Get file size */		size = (size_t)atol((char *)&hdr->ar_size);		if (size == 0) {			err = ENOENT;			goto out;		}		if (i == fp->f_offset)			break;		/* Proceed to next archive header */		offset += (sizeof(struct ar_hdr) + size);		offset += (offset % 2); /* Pad to even boundary */		blkno = offset / BSIZE;		i++;	}	/* Convert archive name */	if ((p = memchr(&hdr->ar_name, '/', 16)) != NULL)		*p = '\0';	strcpy((char *)&dir->d_name, (char *)&hdr->ar_name);	dir->d_namlen = strlen(dir->d_name);	dir->d_fileno = fp->f_offset;	dir->d_type = DT_REG;	fp->f_offset++;	err = 0; out:	mutex_unlock(&arfs_lock);	return err;}const struct vnops arfs_vnops = {	.open     = VOP_NULL,	.close    = VOP_NULL,	.read     = arfs_read,	.write    = VOP_NULL,	.seek     = arfs_seek,	.ioctl    = VOP_EINVAL,	.fsync    = VOP_NULL,	.readdir  = arfs_readdir,	.lookup   = arfs_lookup,	.create   = VOP_EINVAL,	.remove   = VOP_EINVAL,	.rename   = VOP_EINVAL,	.mkdir    = VOP_EINVAL,	.rmdir    = VOP_EINVAL,	.getattr  = VOP_NULL,	.setattr  = VOP_NULL,	.inactive = VOP_NULL,};int arfs_init(void){	return 0;}

⌨️ 快捷键说明

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