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

📄 open.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/open.c * *  Copyright (C) 1991, 1992  Linus Torvalds */#include <linux/string.h>#include <linux/mm.h>#include <linux/utime.h>#include <linux/file.h>#include <linux/smp_lock.h>#include <linux/quotaops.h>#include <linux/dnotify.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/tty.h>#include <linux/iobuf.h>#include <asm/uaccess.h>#define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))int vfs_statfs(struct super_block *sb, struct statfs *buf){	int retval = -ENODEV;	if (sb) {		retval = -ENOSYS;		if (sb->s_op && sb->s_op->statfs) {			memset(buf, 0, sizeof(struct statfs));			lock_kernel();			retval = sb->s_op->statfs(sb, buf);			unlock_kernel();		}	}	return retval;}asmlinkage long sys_statfs(const char * path, struct statfs * buf){	struct nameidata nd;	int error;	error = user_path_walk(path, &nd);	if (!error) {		struct statfs tmp;		error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);		if (!error && copy_to_user(buf, &tmp, sizeof(struct statfs)))			error = -EFAULT;		path_release(&nd);	}	return error;}asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf){	struct file * file;	struct statfs tmp;	int error;	error = -EBADF;	file = fget(fd);	if (!file)		goto out;	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);	if (!error && copy_to_user(buf, &tmp, sizeof(struct statfs)))		error = -EFAULT;	fput(file);out:	return error;}int do_truncate(struct dentry *dentry, loff_t length){	struct inode *inode = dentry->d_inode;	int error;	struct iattr newattrs;	/* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */	if (length < 0)		return -EINVAL;	down(&inode->i_sem);	newattrs.ia_size = length;	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;	error = notify_change(dentry, &newattrs);	up(&inode->i_sem);	return error;}static inline long do_sys_truncate(const char * path, loff_t length){	struct nameidata nd;	struct inode * inode;	int error;	error = -EINVAL;	if (length < 0)	/* sorry, but loff_t says... */		goto out;	error = user_path_walk(path, &nd);	if (error)		goto out;	inode = nd.dentry->d_inode;	/* For directories it's -EISDIR, for other non-regulars - -EINVAL */	error = -EISDIR;	if (S_ISDIR(inode->i_mode))		goto dput_and_out;	error = -EINVAL;	if (!S_ISREG(inode->i_mode))		goto dput_and_out;	error = permission(inode,MAY_WRITE);	if (error)		goto dput_and_out;	error = -EROFS;	if (IS_RDONLY(inode))		goto dput_and_out;	error = -EPERM;	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))		goto dput_and_out;	/*	 * Make sure that there are no leases.	 */	error = get_lease(inode, FMODE_WRITE);	if (error)		goto dput_and_out;	error = get_write_access(inode);	if (error)		goto dput_and_out;	error = locks_verify_truncate(inode, NULL, length);	if (!error) {		DQUOT_INIT(inode);		error = do_truncate(nd.dentry, length);	}	put_write_access(inode);dput_and_out:	path_release(&nd);out:	return error;}asmlinkage long sys_truncate(const char * path, unsigned long length){	/* on 32-bit boxen it will cut the range 2^31--2^32-1 off */	return do_sys_truncate(path, (long)length);}static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small){	struct inode * inode;	struct dentry *dentry;	struct file * file;	int error;	error = -EINVAL;	if (length < 0)		goto out;	error = -EBADF;	file = fget(fd);	if (!file)		goto out;	/* explicitly opened as large or we are on 64-bit box */	if (file->f_flags & O_LARGEFILE)		small = 0;	dentry = file->f_dentry;	inode = dentry->d_inode;	error = -EINVAL;	if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))		goto out_putf;	error = -EINVAL;	/* Cannot ftruncate over 2^31 bytes without large file support */	if (small && length > MAX_NON_LFS)		goto out_putf;	error = -EPERM;	if (IS_APPEND(inode))		goto out_putf;	error = locks_verify_truncate(inode, file, length);	if (!error)		error = do_truncate(dentry, length);out_putf:	fput(file);out:	return error;}asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length){	return do_sys_ftruncate(fd, length, 1);}/* LFS versions of truncate are only needed on 32 bit machines */#if BITS_PER_LONG == 32asmlinkage long sys_truncate64(const char * path, loff_t length){	return do_sys_truncate(path, length);}asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length){	return do_sys_ftruncate(fd, length, 0);}#endif#if !(defined(__alpha__) || defined(__ia64__))/* * sys_utime() can be implemented in user-level using sys_utimes(). * Is this for backwards compatibility?  If so, why not move it * into the appropriate arch directory (for those architectures that * need it). *//* If times==NULL, set access and modification to current time, * must be owner or have write permission. * Else, update from *times, must be owner or super user. */asmlinkage long sys_utime(char * filename, struct utimbuf * times){	int error;	struct nameidata nd;	struct inode * inode;	struct iattr newattrs;	error = user_path_walk(filename, &nd);	if (error)		goto out;	inode = nd.dentry->d_inode;	error = -EROFS;	if (IS_RDONLY(inode))		goto dput_and_out;	/* Don't worry, the checks are done in inode_change_ok() */	newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;	if (times) {		error = get_user(newattrs.ia_atime, &times->actime);		if (!error) 			error = get_user(newattrs.ia_mtime, &times->modtime);		if (error)			goto dput_and_out;		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;	} else {		if (current->fsuid != inode->i_uid &&		    (error = permission(inode,MAY_WRITE)) != 0)			goto dput_and_out;	}	error = notify_change(nd.dentry, &newattrs);dput_and_out:	path_release(&nd);out:	return error;}#endif/* If times==NULL, set access and modification to current time, * must be owner or have write permission. * Else, update from *times, must be owner or super user. */asmlinkage long sys_utimes(char * filename, struct timeval * utimes){	int error;	struct nameidata nd;	struct inode * inode;	struct iattr newattrs;	error = user_path_walk(filename, &nd);	if (error)		goto out;	inode = nd.dentry->d_inode;	error = -EROFS;	if (IS_RDONLY(inode))		goto dput_and_out;	/* Don't worry, the checks are done in inode_change_ok() */	newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;	if (utimes) {		struct timeval times[2];		error = -EFAULT;		if (copy_from_user(&times, utimes, sizeof(times)))			goto dput_and_out;		newattrs.ia_atime = times[0].tv_sec;		newattrs.ia_mtime = times[1].tv_sec;		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;	} else {		if ((error = permission(inode,MAY_WRITE)) != 0)			goto dput_and_out;	}	error = notify_change(nd.dentry, &newattrs);dput_and_out:	path_release(&nd);out:	return error;}/* * access() needs to use the real uid/gid, not the effective uid/gid. * We do this by temporarily clearing all FS-related capabilities and * switching the fsuid/fsgid around to the real ones. */asmlinkage long sys_access(const char * filename, int mode){	struct nameidata nd;	int old_fsuid, old_fsgid;	kernel_cap_t old_cap;	int res;	if (mode & ~S_IRWXO)	/* where's F_OK, X_OK, W_OK, R_OK? */		return -EINVAL;	old_fsuid = current->fsuid;	old_fsgid = current->fsgid;	old_cap = current->cap_effective;	current->fsuid = current->uid;	current->fsgid = current->gid;	/* Clear the capabilities if we switch to a non-root user */	if (current->uid)		cap_clear(current->cap_effective);	else		current->cap_effective = current->cap_permitted;	res = user_path_walk(filename, &nd);	if (!res) {		res = permission(nd.dentry->d_inode, mode);		/* SuS v2 requires we report a read only fs too */		if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)		   && !special_file(nd.dentry->d_inode->i_mode))			res = -EROFS;		path_release(&nd);	}	current->fsuid = old_fsuid;	current->fsgid = old_fsgid;	current->cap_effective = old_cap;	return res;}asmlinkage long sys_chdir(const char * filename){	int error;	struct nameidata nd;	char *name;	name = getname(filename);	error = PTR_ERR(name);	if (IS_ERR(name))		goto out;	error = 0;	if (path_init(name,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd))		error = path_walk(name, &nd);	putname(name);	if (error)		goto out;	error = permission(nd.dentry->d_inode,MAY_EXEC);	if (error)		goto dput_and_out;	set_fs_pwd(current->fs, nd.mnt, nd.dentry);dput_and_out:	path_release(&nd);out:	return error;}asmlinkage long sys_fchdir(unsigned int fd){	struct file *file;	struct dentry *dentry;	struct inode *inode;	struct vfsmount *mnt;	int error;	error = -EBADF;	file = fget(fd);	if (!file)		goto out;	dentry = file->f_dentry;	mnt = file->f_vfsmnt;	inode = dentry->d_inode;	error = -ENOTDIR;	if (!S_ISDIR(inode->i_mode))		goto out_putf;	error = permission(inode, MAY_EXEC);	if (!error)		set_fs_pwd(current->fs, mnt, dentry);out_putf:	fput(file);out:	return error;}asmlinkage long sys_chroot(const char * filename){	int error;	struct nameidata nd;	char *name;	name = getname(filename);	error = PTR_ERR(name);	if (IS_ERR(name))		goto out;	path_init(name, LOOKUP_POSITIVE | LOOKUP_FOLLOW |		      LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);	error = path_walk(name, &nd);		putname(name);	if (error)		goto out;	error = permission(nd.dentry->d_inode,MAY_EXEC);	if (error)		goto dput_and_out;	error = -EPERM;	if (!capable(CAP_SYS_CHROOT))		goto dput_and_out;	set_fs_root(current->fs, nd.mnt, nd.dentry);	set_fs_altroot();	error = 0;dput_and_out:

⌨️ 快捷键说明

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