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

📄 syscalls.c

📁 微内核软实时操作系统
💻 C
字号:
/* * Copyright (c) 2005-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. *//* * syscalls.c - Virtual File System System Call */#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/list.h>#include <sys/buf.h>#include <limits.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include "vfs.h"int sys_open(char *path, int flags, mode_t mode, file_t *file){	vnode_t vp, dvp;	file_t fp;	char *filename;	int err;	dprintf("sys_open: path=%s flags=%x mode=%x\n", path, flags, mode);	if (flags & O_CREAT) {		err = namei(path, &vp);		if (err == ENOENT) {			/* Create new file. */			if ((err = lookup(path, &dvp, &filename)) != 0)				return err;			if (dvp->v_mount->m_flags & MNT_RDONLY) {				vput(dvp);				return EROFS;			}			mode &= ~S_IFMT;			mode |= S_IFREG;			err = VOP_CREATE(dvp, filename, mode);			vput(dvp);			if (err)				return err;			if ((err = namei(path, &vp)) != 0)				return err;			flags &= ~O_TRUNC;		} else if (err) {			return err;		} else {			/* File already exits */			if (flags & O_EXCL) {				vput(vp);				return EEXIST;			}			flags &= ~O_CREAT;		}	} else {		/* Open */		if ((err = namei(path, &vp)) != 0)			return err;	}	if ((flags & O_CREAT) == 0) {		if ((flags & O_ACCMODE) != O_RDONLY || flags & O_TRUNC) {			if (vp->v_mount->m_flags & MNT_RDONLY) {				vput(vp);				return EROFS;			}			if (vp->v_type == VDIR) {				/* Openning directory with writable. */				vput(vp);				return EISDIR;			}		}	}	/* Setup file structure */	if (!(fp = malloc(sizeof(struct file)))) {		vput(vp);		return ENOMEM;	}	/* Request to file system */	if ((err = VOP_OPEN(vp, mode)) != 0) {		free(fp);		vput(vp);		return err;	}	memset(fp, 0, sizeof(struct file));	fp->f_vnode = vp;	fp->f_flags = flags;	fp->f_offset = 0;	fp->f_count = 1;	*file = fp;	vn_unlock(vp);	return 0;}int sys_close(file_t fp){	vnode_t vp;	int err;	dprintf("sys_close: fp=%x\n", (u_int)fp);	vp = fp->f_vnode;	if (--fp->f_count > 0) {		vrele(vp);		return 0;	}	vn_lock(vp);	if ((err = VOP_CLOSE(vp, fp)) != 0) {		vn_unlock(vp);		return err;	}	vput(vp);	free(fp);	return 0;}int sys_read(file_t fp, void *buf, size_t size, size_t *count){	vnode_t vp;	int err;	dprintf("sys_read: fp=%x buf=%x size=%d\n", (u_int)fp, (u_int)buf, size);	if ((fp->f_flags & O_ACCMODE) == O_WRONLY)		return EPERM;	if (size == 0) {		*count = 0;		return 0;	}	vp = fp->f_vnode;	vn_lock(vp);	err = VOP_READ(vp, fp, buf, size, count);	vn_unlock(vp);	return err;}int sys_write(file_t fp, void *buf, size_t size, size_t *count){	vnode_t vp;	int err;	dprintf("sys_write: fp=%x buf=%x size=%d\n", (u_int)fp, (u_int)buf, size);	if (size == 0) {		*count = 0;		return 0;	}	vp = fp->f_vnode;	vn_lock(vp);	err = VOP_WRITE(vp, fp, buf, size, count);	vn_unlock(vp);	return err;}int sys_lseek(file_t fp, off_t off, int type, off_t *origin){	vnode_t vp;	dprintf("sys_seek: fp=%x off=%d type=%d\n", (u_int)fp, (u_int)off, type);	vp = fp->f_vnode;	vn_lock(vp);	switch (type) {	case SEEK_SET:		if (off < 0)			off = 0;		if (off > vp->v_size)			off = vp->v_size;		break;	case SEEK_CUR:		if (fp->f_offset + off > vp->v_size)			off = vp->v_size;		else if (fp->f_offset + off < 0)			off = 0;		else			off = fp->f_offset + off;		break;	case SEEK_END:		if (off > 0)			off = vp->v_size;		else if (vp->v_size + off < 0)			off = 0;		else			off = vp->v_size + off;		break;	default:		vn_unlock(vp);		return EINVAL;	}	/* Request to check the file offset */	if (VOP_SEEK(vp, fp, fp->f_offset, off) != 0) {		vn_unlock(vp);		return EINVAL;	}	*origin = off;	fp->f_offset = off;	vn_unlock(vp);	return 0;}int sys_ioctl(file_t fp, u_int cmd, u_long arg){	vnode_t vp;	int err;	dprintf("sys_ioctl: fp=%x cmd=%d arg=%d\n", fp, cmd, arg);	vp = fp->f_vnode;	vn_lock(vp);	err = VOP_IOCTL(vp, fp, cmd, arg);	vn_unlock(vp);	return err;}int sys_fsync(file_t fp){	vnode_t vp;	int err;	dprintf("sys_fsync: fp=%x\n", fp);	if ((fp->f_flags & O_ACCMODE) == O_RDONLY)		return EBADF;	vp = fp->f_vnode;	vn_lock(vp);	err = VOP_FSYNC(vp, fp);	vn_unlock(vp);	return err;       }int sys_fstat(file_t fp, struct stat *st){	vnode_t vp;	dprintf("sys_fstat: fp=%x\n", fp);	memset(st, 0, sizeof(struct stat));	vp = fp->f_vnode;	vn_lock(vp);	st->st_ino = (ino_t)&vp;	st->st_size = vp->v_size;	st->st_mode = vp->v_mode;	vn_unlock(vp);	return 0;}/* * Return 0 if directory is empty */static int check_dir_empty(char *path){	int err;	file_t fp;	struct dirent dir;	if ((err = sys_opendir(path, &fp)) != 0)		return err;	do {		err = sys_readdir(fp, &dir);		if (err)			break;	} while (!strcmp(dir.d_name, ".") || !strcmp(dir.d_name, ".."));	sys_closedir(fp);	if (err == ENOENT)		return 0;	else if (err == 0)		return EEXIST;	return err;}int sys_opendir(char *path, file_t *file){	vnode_t dvp;	file_t fp;	int err;	dprintf("sys_opendir: path=%s\n", path);	if ((err = sys_open(path, O_RDONLY, 0, &fp)) != 0)		return err;	dvp = fp->f_vnode;	vn_lock(dvp);	if (dvp->v_type != VDIR) {		vn_unlock(dvp);		sys_close(fp);		return ENOTDIR;	}	vn_unlock(dvp);	*file = fp;	return 0;}int sys_closedir(file_t fp){	vnode_t dvp;	int err;	dprintf("sys_closedir: fp=%x\n", fp);	dvp = fp->f_vnode;	vn_lock(dvp);	if (dvp->v_type != VDIR) {		vn_unlock(dvp);		return EBADF;	}	vn_unlock(dvp);	err = sys_close(fp);	return err;}int sys_readdir(file_t fp, struct dirent *dir){	vnode_t dvp;	int err;	dprintf("sys_readdir: fp=%x\n", fp);	dvp = fp->f_vnode;	vn_lock(dvp);	if (dvp->v_type != VDIR) {		vn_unlock(dvp);		return ENOTDIR;	}	err = VOP_READDIR(dvp, fp, dir);	vn_unlock(dvp);	return err;}int sys_rewinddir(file_t fp){	vnode_t dvp;	dvp = fp->f_vnode;	vn_lock(dvp);	if (dvp->v_type != VDIR) {		vn_unlock(dvp);		return EINVAL;	}	fp->f_offset = 0;	vn_unlock(dvp);	return 0;}int sys_seekdir(file_t fp, long loc){	vnode_t dvp;	dvp = fp->f_vnode;	vn_lock(dvp);	if (dvp->v_type != VDIR) {		vn_unlock(dvp);		return EINVAL;	}	fp->f_offset = (off_t)loc;	vn_unlock(dvp);	return 0;}int sys_telldir(file_t fp, long *loc){	vnode_t dvp;	dvp = fp->f_vnode;	vn_lock(dvp);	if (dvp->v_type != VDIR) {		vn_unlock(dvp);		return EINVAL;	}	*loc = (long)fp->f_offset;	vn_unlock(dvp);	return 0;}int sys_mkdir(char *path, mode_t mode){	char *name;	vnode_t vp, dvp;	int err;	dprintf("sys_mkdir: path=%s mode=%d\n", path, mode);	if ((err = namei(path, &vp)) == 0) {		/* File already exists */		vput(vp);		return EEXIST;	}	if ((err = lookup(path, &dvp, &name)) != 0) {		/* Directory already exists */		vput(vp);		return err;	}	if (dvp->v_mount->m_flags & MNT_RDONLY) {		err = EROFS;		goto out;	}	mode &= ~S_IFMT;	mode |= S_IFDIR;	err = VOP_MKDIR(dvp, name, mode); out:	vput(dvp);	return err;}int sys_rmdir(char *path){	vnode_t vp, dvp;	int err;	char *name;	dprintf("sys_rmdir: path=%s\n", path);	if ((err = check_dir_empty(path)) != 0)		return err;	if ((err = namei(path, &vp)) != 0)		return err;	if (vp->v_mount->m_flags & MNT_RDONLY) {		err = EROFS;		goto out;	}	if (vp->v_type != VDIR) {		err = ENOTDIR;		goto out;	}	if (vp->v_flags & VROOT || vcount(vp) >= 2) {		err = EBUSY;		goto out;	}	if ((err = lookup(path, &dvp, &name)) != 0)		goto out;	err = VOP_RMDIR(dvp, vp, name);	vn_unlock(vp);	vgone(vp);	vput(dvp);	return err; out:	vput(vp);	return err;}int sys_mknod(char *path, mode_t mode){	char *name;	vnode_t vp, dvp;	int err;	dprintf("sys_mknod: path=%s mode=%d\n", path, mode);	if ((err = namei(path, &vp)) == 0) {		vput(vp);		return EEXIST;	}	if ((err = lookup(path, &dvp, &name)) != 0)		return err;	if (S_ISDIR(mode))		err = VOP_MKDIR(dvp, name, mode);	else		err = VOP_CREATE(dvp, name, mode);	vput(dvp);	return err;}int sys_rename(char *src, char *dest){	vnode_t vp1, vp2 = 0, dvp1, dvp2;	char *sname, *dname;	int err;	size_t len;	char root[] = "/";	dprintf("sys_rename: src=%s dest=%s\n", src, dest);	if ((err = namei(src, &vp1)) != 0)		return err;	if (vp1->v_mount->m_flags & MNT_RDONLY) {		err = EROFS;		goto err1;	}	/* If source and dest are the same, do nothing */	if (!strncmp(src, dest, PATH_MAX))		goto err1;	/* Check if target is directory of source */	len = strlen(dest);	if (!strncmp(src, dest, len)) {		err = EINVAL;		goto err1;	}	/* Is the source busy ? */	if (vcount(vp1) >= 2) {		err = EBUSY;		goto err1;	}	/* Check type of source & target */	err = namei(dest, &vp2);	if (err == 0) {		/* target exists */		if (vp1->v_type == VDIR && vp2->v_type != VDIR) {			err = ENOTDIR;			goto err2;		} else if (vp1->v_type != VDIR && vp2->v_type == VDIR) {			err = EISDIR;			goto err2;		}		if (vp2->v_type == VDIR && check_dir_empty(dest)) {			err = EEXIST;			goto err2;		}		if (vcount(vp2) >= 2) {			err = EBUSY;			goto err2;		}	}	dname = strrchr(dest, '/');	if (dname == NULL) {		err = ENOTDIR;		goto err2;	}	if (dname == dest)		dest = root;	*dname = 0;	dname++;	if ((err = lookup(src, &dvp1, &sname)) != 0)		goto err2;	if ((err = namei(dest, &dvp2)) != 0)		goto err3;	/* The source and dest must be same file system */	if (dvp1->v_mount != dvp2->v_mount) {		err = EXDEV;		goto err4;	}	err = VOP_RENAME(dvp1, vp1, sname, dvp2, vp2, dname); err4:	vput(dvp2); err3:	vput(dvp1); err2:	if (vp2)		vput(vp2); err1:	vput(vp1);	return err;}int sys_unlink(char *path){	char *name;	vnode_t vp, dvp;	int err;	dprintf("sys_unlink: path=%s\n", path);	if ((err = namei(path, &vp)) != 0)		return err;	if (vp->v_mount->m_flags & MNT_RDONLY) {		err = EROFS;		goto out;	}	if (vp->v_type == VDIR) {		err = EPERM;		goto out;	}	if (vp->v_flags & VROOT || vcount(vp) >= 2) {		err = EBUSY;		goto out;	}	if ((err = lookup(path, &dvp, &name)) != 0)		goto out;	err = VOP_REMOVE(dvp, vp, name);	vn_unlock(vp);	vgone(vp);	vput(dvp);	return 0; out:	vput(vp);	return err;}

⌨️ 快捷键说明

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