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

📄 ramfs_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. */#include <prex/prex.h>#include <sys/stat.h>#include <sys/vnode.h>#include <sys/file.h>#include <sys/mount.h>#include <sys/dirent.h>#include <sys/param.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include "ramfs.h"static mutex_t ramfs_lock = MUTEX_INITIALIZER;struct ramfs_node *ramfs_allocate_node(char *name, int type){	struct ramfs_node *node;	node = malloc(sizeof(struct ramfs_node));	if (node == NULL)		return NULL;	memset(node, 0, sizeof(struct ramfs_node));	node->namelen = strlen(name);	node->name = malloc(node->namelen + 1);	if (node->name == NULL) {		free(node);		return NULL;	}	strcpy(node->name, name);	node->type = type;	return node;}void ramfs_free_node(struct ramfs_node *node){	free(node->name);	free(node);}static struct ramfs_node *ramfs_add_node(struct ramfs_node *dir_node, char *name, int type){	struct ramfs_node *node, *prev;	node = ramfs_allocate_node(name, type);	if (node == NULL)		return NULL;	mutex_lock(&ramfs_lock);	/* Link to the directory list */	if (dir_node->child == NULL) {		dir_node->child = node;	} else {		prev = dir_node->child;		while (prev->next != NULL)			prev = prev->next;		prev->next = node;	}	mutex_unlock(&ramfs_lock);	return node;}static int ramfs_remove_node(struct ramfs_node *dir_node,			     struct ramfs_node *node){	struct ramfs_node *prev;	if (dir_node->child == NULL)		return EBUSY;	mutex_lock(&ramfs_lock);	/* Unlink from the directory list */	if (dir_node->child == node) {		dir_node->child = node->next;	} else {		for (prev = dir_node->child; prev->next != node;		     prev = prev->next) {			if (prev->next == NULL) {				mutex_lock(&ramfs_lock);				return ENOENT;			}		}		prev->next = node->next;	}	ramfs_free_node(node);	mutex_unlock(&ramfs_lock);	return 0;}static int ramfs_rename_node(struct ramfs_node *node, char *name){	size_t len;	char *tmp;	len = strlen(name);	if (len <= node->namelen) {		/* Reuse current name buffer */		strcpy(node->name, name);	} else {		/* Expand name buffer */		tmp = malloc(len + 1);		if (tmp == NULL)			return ENOMEM;		strcpy(tmp, name);		free(node->name);		node->name = tmp;	}	node->namelen = len;	return 0;}static int ramfs_lookup(vnode_t dvp, char *name, vnode_t vp){	struct ramfs_node *node, *dir_node;	size_t len;	if (*name == '\0')		return ENOENT;	mutex_lock(&ramfs_lock);	len = strlen(name);	dir_node = dvp->v_data;	for (node = dir_node->child; node != NULL; node = node->next) {		if (node->namelen == len &&		    memcmp(name, node->name, len) == 0)			break;	}	if (node == NULL) {		mutex_unlock(&ramfs_lock);		return ENOENT;	}	vp->v_data = node;	vp->v_mode = S_IRWXU | S_IRWXG | S_IRWXO;	if (node->type == VDIR)		vp->v_mode |= S_IFDIR;	else		vp->v_mode |= S_IFREG;	vp->v_type = node->type;	vp->v_size = node->size;	mutex_unlock(&ramfs_lock);	return 0;}static int ramfs_mkdir(vnode_t dvp, char *name, mode_t mode){	struct ramfs_node *node;	if (!S_ISDIR(mode))		return EINVAL;	node = ramfs_add_node(dvp->v_data, name, VDIR);	if (node == NULL)		return ENOMEM;	node->size = 0;	return 0;}/* Remove a directory */static int ramfs_rmdir(vnode_t dvp, vnode_t vp, char *name){	return ramfs_remove_node(dvp->v_data, vp->v_data);}/* Remove a file */static int ramfs_remove(vnode_t dvp, vnode_t vp, char *name){	struct ramfs_node *node;	int err;	dprintf("remove %s in %s\n", name, dvp->v_path);	err = ramfs_remove_node(dvp->v_data, vp->v_data);	if (err)		return err;	node = vp->v_data;	if (node->buf != NULL)		vm_free(task_self(), node->buf);	return 0;}/* * Create empty file. */static int ramfs_create(vnode_t dvp, char *name, mode_t mode){	struct ramfs_node *node;	dprintf("create %s in %s\n", name, dvp->v_path);	if (!S_ISREG(mode))		return EINVAL;	node = ramfs_add_node(dvp->v_data, name, VREG);	if (node == NULL)		return ENOMEM;	return 0;}static int ramfs_read(vnode_t vp, file_t fp, void *buf, size_t size,		      size_t *result){	struct ramfs_node *node;	off_t offset;	*result = 0;	if (vp->v_type == VDIR)		return EISDIR;	if (vp->v_type != VREG)		return EINVAL;	offset = fp->f_offset;	if (offset >= vp->v_size)		return 0;	if (vp->v_size - offset < size)		size = vp->v_size - offset;	node = vp->v_data;	memcpy(buf, node->buf + offset, size);	fp->f_offset += size;	*result = size;	return 0;}static int ramfs_write(vnode_t vp, file_t fp, void *buf, size_t size,		       size_t *result){	struct ramfs_node *node;	off_t file_pos, end_pos;	void *new_buf;	size_t new_size;	task_t task;	*result = 0;	if (vp->v_type == VDIR)		return EISDIR;	if (vp->v_type != VREG)		return EINVAL;	node = vp->v_data;	/* Check if the file position exceeds the end of file. */	end_pos = vp->v_size;	file_pos = (fp->f_flags & O_APPEND) ? end_pos : fp->f_offset;	if (file_pos + size > end_pos) {		/* Expand the file size before writing to it */		end_pos = file_pos + size;		if (end_pos > node->bufsize) {			task = task_self();			/*			 * We allocate the data buffer in page boundary.			 * So that we can reduce the memory allocation unless			 * the file size exceeds next page boundary.			 * This will prevent the memory fragmentation by			 * many malloc/free calls.			 */			new_size = round_page(end_pos);			if (vm_allocate(task, &new_buf, new_size, 1))				return EIO;			if (node->size != 0) {				memcpy(new_buf, node->buf, end_pos);				vm_free(task, node->buf);			}			node->buf = new_buf;			node->bufsize = new_size;		}		node->size = end_pos;		vp->v_size = end_pos;	}	memcpy(node->buf + file_pos, buf, size);	fp->f_offset += size;	*result = size;	return 0;}static int ramfs_rename(vnode_t dvp1, vnode_t vp1, char *name1,			vnode_t dvp2, vnode_t vp2, char *name2){	struct ramfs_node *node, *old_node;	int err;	if (vp2) {		/* Remove destination file, first */		err = ramfs_remove_node(dvp2->v_data, vp2->v_data);		if (err)			return err;	}	/* Same directory ? */	if (dvp1 == dvp2) {		/* Change the name of existing file */		err = ramfs_rename_node(vp1->v_data, name2);		if (err)			return err;	} else {		/* Create new file or directory */		old_node = vp1->v_data;		node = ramfs_add_node(dvp2->v_data, name2, VREG);		if (node == NULL)			return ENOMEM;		if (vp1->v_type == VREG) {			/* Copy file data */ 			node->buf = old_node->buf;			node->size = old_node->size;			node->bufsize = old_node->bufsize;		}		/* Remove source file */		ramfs_remove_node(dvp1->v_data, vp1->v_data);	}	return 0;}/* * @vp: vnode of the directory. */static int ramfs_readdir(vnode_t vp, file_t fp, struct dirent *dir){	struct ramfs_node *node, *dir_node;	int i;	mutex_lock(&ramfs_lock);	if (fp->f_offset == 0) {		dir->d_type = DT_DIR;		strcpy((char *)&dir->d_name, ".");	} else if (fp->f_offset == 1) {		dir->d_type = DT_DIR;		strcpy((char *)&dir->d_name, "..");	} else {		dir_node = vp->v_data;		node = dir_node->child;		if (node == NULL)			return ENOENT;				for (i = 0; i != (fp->f_offset - 2); i++) {			node = node->next;			if (node == NULL) {				mutex_unlock(&ramfs_lock);				return ENOENT;			}		}		if (node->type == VDIR)			dir->d_type = DT_DIR;		else 			dir->d_type = DT_REG;		strcpy((char *)&dir->d_name, node->name);	}	dir->d_fileno = fp->f_offset;	dir->d_namlen = strlen(dir->d_name);	fp->f_offset++;	mutex_unlock(&ramfs_lock);	return 0;}struct vnops ramfs_vnops = {	.open     = VOP_NULL,	.close    = VOP_NULL,	.read     = ramfs_read,	.write    = ramfs_write,	.seek     = VOP_NULL,	.ioctl    = VOP_EINVAL,	.fsync    = VOP_NULL,	.readdir  = ramfs_readdir,	.lookup   = ramfs_lookup,	.create   = ramfs_create,	.remove   = ramfs_remove,	.rename   = ramfs_rename,	.mkdir    = ramfs_mkdir,	.rmdir    = ramfs_rmdir,	.getattr  = VOP_NULL,	.setattr  = VOP_NULL,	.inactive = VOP_NULL,};int ramfs_init(void){	return 0;}

⌨️ 快捷键说明

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