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

📄 namei.c.bak

📁 linux0.11原码
💻 BAK
📖 第 1 页 / 共 3 页
字号:
		iput(inode);		return -ENOSPC;	}
// 令该目录项的i 节点字段等于新i 节点号,置高速缓冲区已修改标志,释放目录和新的i 节点,释放
// 高速缓冲区,最后返回0(成功)。	de->inode = inode->i_num;	bh->b_dirt = 1;	dir->i_nlinks++;	dir->i_dirt = 1;	iput(dir);	iput(inode);	brelse(bh);	return 0;}/* * 用于检查指定的目录是否为空的子程序(用于rmdir 系统调用函数)。 */
//// 检查指定目录是否是空的。
// 参数:inode - 指定目录的i 节点指针。
// 返回:0 - 是空的;1 - 不空。
static int empty_dir(struct m_inode * inode)
{	int nr,block;	int len;	struct buffer_head * bh;	struct dir_entry * de;
// 计算指定目录中现有目录项的个数(应该起码有2 个,即"."和".."两个文件目录项)。	len = inode->i_size / sizeof (struct dir_entry);
// 如果目录项个数少于2 个或者该目录i 节点的第1 个直接块没有指向任何磁盘块号,或者相应磁盘
// 块读不出,则显示警告信息“设备dev 上目录错”,返回0(失败)。	if (len<2 || !inode->i_zone[0] ||	    !(bh=bread(inode->i_dev,inode->i_zone[0]))) {	    	printk("warning - bad directory on dev %04x\n",inode->i_dev);		return 0;	}
// 让de 指向含有读出磁盘块数据的高速缓冲区中第1 项目录项。	de = (struct dir_entry *) bh->b_data;
// 如果第1 个目录项的i 节点号字段值不等于该目录的i 节点号,或者第2 个目录项的i 节点号字段
// 为零,或者两个目录项的名字字段不分别等于"."和"..",则显示出错警告信息“设备dev 上目录错”
// 并返回0。	if (de[0].inode != inode->i_num || !de[1].inode || 	    strcmp(".",de[0].name) || strcmp("..",de[1].name)) {	    	printk("warning - bad directory on dev %04x\n",inode->i_dev);		return 0;	}
// 令nr 等于目录项序号;de 指向第三个目录项。	nr = 2;	de += 2;
// 循环检测该目录中所有的目录项(len-2 个),看有没有目录项的i 节点号字段不为0(被使用)。	while (nr<len) {
// 如果该块磁盘块中的目录项已经检测完,则释放该磁盘块的高速缓冲区,读取下一块含有目录项的
// 磁盘块。若相应块没有使用(或已经不用,如文件已经删除等),则继续读下一块,若读不出,则出
// 错,返回0。否则让de 指向读出块的首个目录项。		if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {			brelse(bh);			block=bmap(inode,nr/DIR_ENTRIES_PER_BLOCK);			if (!block) {				nr += DIR_ENTRIES_PER_BLOCK;				continue;			}			if (!(bh=bread(inode->i_dev,block)))				return 0;			de = (struct dir_entry *) bh->b_data;		}
// 如果该目录项的i 节点号字段不等于0,则表示该目录项目前正被使用,则释放该高速缓冲区,
// 返回0,退出。		if (de->inode) {			brelse(bh);			return 0;		}
// 否则,若还没有查询完该目录中的所有目录项,则继续检测。		de++;		nr++;	}
// 到这里说明该目录中没有找到已用的目录项(当然除了头两个以外),则返回缓冲区,返回1。	brelse(bh);	return 1;}
//// 系统调用函数- 删除指定名称的目录。
// 参数: name - 目录名(路径名)。
// 返回:返回0 表示成功,否则返回出错号。int sys_rmdir(const char * name){	const char * basename;	int namelen;	struct m_inode * dir, * inode;	struct buffer_head * bh;	struct dir_entry * de;
// 如果不是超级用户,则返回访问许可出错码。	if (!suser())		return -EPERM;
// 如果找不到对应路径名目录的i 节点,则返回出错码。	if (!(dir = dir_namei(name,&namelen,&basename)))		return -ENOENT;
// 如果最顶端的文件名长度为0,则说明给出的路径名最后没有指定文件名,释放该目录i 节点,返回
// 出错码,退出。	if (!namelen) {		iput(dir);		return -ENOENT;	}
// 如果在该目录中没有写的权限,则释放该目录的i 节点,返回访问许可出错码,退出。	if (!permission(dir,MAY_WRITE)) {		iput(dir);		return -EPERM;	}
// 如果对应路径名上最后的文件名的目录项不存在,则释放包含该目录项的高速缓冲区,释放目录
// 的i 节点,返回文件已经存在出错码,退出。否则dir 是包含要被删除目录名的目录i 节点,de
// 是要被删除目录的目录项结构。	bh = find_entry(&dir,basename,namelen,&de);	if (!bh) {		iput(dir);		return -ENOENT;	}
// 取该目录项指明的i 节点。若出错则释放目录的i 节点,并释放含有目录项的高速缓冲区,返回
// 出错号。	if (!(inode = iget(dir->i_dev, de->inode))) {		iput(dir);		brelse(bh);		return -EPERM;	}
// 若该目录设置了受限删除标志并且进程的有效用户id 不等于该i 节点的用户id,则表示没有权限删
// 除该目录,于是释放包含要删除目录名的目录i 节点和该要删除目录的i 节点,释放高速缓冲区,
// 返回出错码。	if ((dir->i_mode & S_ISVTX) && current->euid &&	    inode->i_uid != current->euid) {		iput(dir);		iput(inode);		brelse(bh);		return -EPERM;	}
// 如果要被删除的目录项的i 节点的设备号不等于包含该目录项的目录的设备号,或者该被删除目录的
// 引用连接计数大于1(表示有符号连接等),则不能删除该目录,于是释放包含要删除目录名的目录
// i 节点和该要删除目录的i 节点,释放高速缓冲区,返回出错码。	if (inode->i_dev != dir->i_dev || inode->i_count>1) {		iput(dir);		iput(inode);		brelse(bh);		return -EPERM;	}
// 如果要被删除目录的目录项i 节点的节点号等于包含该需删除目录的i 节点号,则表示试图删除"."
// 目录。于是释放包含要删除目录名的目录i 节点和该要删除目录的i 节点,释放高速缓冲区,返回
// 出错码。	if (inode == dir) {	/* 我们不可以删除".",但可以删除"../dir"*/		iput(inode);		iput(dir);		brelse(bh);		return -EPERM;	}
// 若要被删除的目录的i 节点的属性表明这不是一个目录,则释放包含要删除目录名的目录i 节点和
// 该要删除目录的i 节点,释放高速缓冲区,返回出错码。	if (!S_ISDIR(inode->i_mode)) {		iput(inode);		iput(dir);		brelse(bh);		return -ENOTDIR;	}
// 若该需被删除的目录不空,则释放包含要删除目录名的目录i 节点和该要删除目录的i 节点,释放
// 高速缓冲区,返回出错码。	if (!empty_dir(inode)) {		iput(inode);		iput(dir);		brelse(bh);		return -ENOTEMPTY;	}
// 若该需被删除目录的i 节点的连接数不等于2,则显示警告信息。	if (inode->i_nlinks != 2)		printk("empty directory has nlink!=2 (%d)",inode->i_nlinks);
// 置该需被删除目录的目录项的i 节点号字段为0,表示该目录项不再使用,并置含有该目录项的高速
// 缓冲区已修改标志,并释放该缓冲区。	de->inode = 0;	bh->b_dirt = 1;	brelse(bh);
// 置被删除目录的i 节点的连接数为0,并置i 节点已修改标志。	inode->i_nlinks=0;	inode->i_dirt=1;
// 将包含被删除目录名的目录的i 节点引用计数减1,修改其改变时间和修改时间为当前时间,并置
// 该节点已修改标志。	dir->i_nlinks--;	dir->i_ctime = dir->i_mtime = CURRENT_TIME;	dir->i_dirt=1;
// 最后释放包含要删除目录名的目录i 节点和该要删除目录的i 节点,返回0(成功)。	iput(dir);	iput(inode);	return 0;}
//// 系统调用函数- 删除文件名以及可能也删除其相关的文件。
// 从文件系统删除一个名字。如果是一个文件的最后一个连接,并且没有进程正打开该文件,则该文件
// 也将被删除,并释放所占用的设备空间。
// 参数:name - 文件名。
// 返回:成功则返回0,否则返回出错号。int sys_unlink(const char * name){	const char * basename;	int namelen;	struct m_inode * dir, * inode;	struct buffer_head * bh;	struct dir_entry * de;
// 如果找不到对应路径名目录的i 节点,则返回出错码。	if (!(dir = dir_namei(name,&namelen,&basename)))		return -ENOENT;
// 如果最顶端的文件名长度为0,则说明给出的路径名最后没有指定文件名,释放该目录i 节点,返回
// 出错码,退出。	if (!namelen) {		iput(dir);		return -ENOENT;	}
// 如果在该目录中没有写的权限,则释放该目录的i 节点,返回访问许可出错码,退出。	if (!permission(dir,MAY_WRITE)) {		iput(dir);		return -EPERM;	}
// 如果对应路径名上最后的文件名的目录项不存在,则释放包含该目录项的高速缓冲区,释放目录
// 的i 节点,返回文件已经存在出错码,退出。否则dir 是包含要被删除目录名的目录i 节点,de
// 是要被删除目录的目录项结构。	bh = find_entry(&dir,basename,namelen,&de);	if (!bh) {		iput(dir);		return -ENOENT;	}
// 取该目录项指明的i 节点。若出错则释放目录的i 节点,并释放含有目录项的高速缓冲区,返回
// 出错号。	if (!(inode = iget(dir->i_dev, de->inode))) {		iput(dir);		brelse(bh);		return -ENOENT;	}
// 如果该目录设置了受限删除标志并且用户不是超级用户,并且进程的有效用户id 不等于被删除文件
// 名i 节点的用户id,并且进程的有效用户id 也不等于目录i 节点的用户id,则没有权限删除该文件
// 名。则释放该目录i 节点和该文件名目录项的i 节点,释放包含该目录项的缓冲区,返回出错号。	if ((dir->i_mode & S_ISVTX) && !suser() &&	    current->euid != inode->i_uid &&	    current->euid != dir->i_uid) {		iput(dir);		iput(inode);		brelse(bh);		return -EPERM;	}
// 如果该指定文件名是一个目录,则也不能删除,释放该目录i 节点和该文件名目录项的i 节点,
// 释放包含该目录项的缓冲区,返回出错号。	if (S_ISDIR(inode->i_mode)) {		iput(inode);		iput(dir);		brelse(bh);		return -EPERM;	}
// 如果该i 节点的连接数已经为0,则显示警告信息,修正其为1。	if (!inode->i_nlinks) {		printk("Deleting nonexistent file (%04x:%d), %d\n",			inode->i_dev,inode->i_num,inode->i_nlinks);		inode->i_nlinks=1;	}
// 将该文件名的目录项中的i 节点号字段置为0,表示释放该目录项,并设置包含该目录项的缓冲区
// 已修改标志,释放该高速缓冲区。	de->inode = 0;	bh->b_dirt = 1;	brelse(bh);
// 该i 节点的连接数减1,置已修改标志,更新改变时间为当前时间。最后释放该i 节点和目录的i 节
// 点,返回0(成功)。	inode->i_nlinks--;	inode->i_dirt = 1;	inode->i_ctime = CURRENT_TIME;	iput(inode);	iput(dir);	return 0;}
//// 系统调用函数- 为文件建立一个文件名。
// 为一个已经存在的文件创建一个新连接(也称为硬连接- hard link)。
// 参数:oldname - 原路径名;newname - 新的路径名。
// 返回:若成功则返回0,否则返回出错号。int sys_link(const char * oldname, const char * newname){	struct dir_entry * de;	struct m_inode * oldinode, * dir;	struct buffer_head * bh;	const char * basename;	int namelen;
// 取原文件路径名对应的i 节点oldinode。如果为0,则表示出错,返回出错号。	oldinode=namei(oldname);	if (!oldinode)		return -ENOENT;
// 如果原路径名对应的是一个目录名,则释放该i 节点,返回出错号。	if (S_ISDIR(oldinode->i_mode)) {		iput(oldinode);		return -EPERM;	}
// 查找新路径名的最顶层目录的i 节点,并返回最后的文件名及其长度。如果目录的i 节点没有找到,
// 则释放原路径名的i 节点,返回出错号。	dir = dir_namei(newname,&namelen,&basename);	if (!dir) {		iput(oldinode);		return -EACCES;	}
// 如果新路径名中不包括文件名,则释放原路径名i 节点和新路径名目录的i 节点,返回出错号。	if (!namelen) {		iput(oldinode);		iput(dir);		return -EPERM;	}
// 如果新路径名目录的设备号与原路径名的设备号不一样,则也不能建立连接,于是释放新路径名
// 目录的i 节点和原路径名的i 节点,返回出错号。	if (dir->i_dev != oldinode->i_dev) {		iput(dir);		iput(oldinode);		return -EXDEV;	}
// 如果用户没有在新目录中写的权限,则也不能建立连接,于是释放新路径名目录的i 节点
// 和原路径名的i 节点,返回出错号。	if (!permission(dir,MAY_WRITE)) {		iput(dir);		iput(oldinode);		return -EACCES;	}
// 查询该新路径名是否已经存在,如果存在,则也不能建立连接,于是释放包含该已存在目录项的
// 高速缓冲区,释放新路径名目录的i 节点和原路径名的i 节点,返回出错号。	bh = find_entry(&dir,basename,namelen,&de);	if (bh) {		brelse(bh);		iput(dir);		iput(oldinode);		return -EEXIST;	}
// 在新目录中添加一个目录项。若失败则释放该目录的i 节点和原路径名的i 节点,返回出错号。	bh = add_entry(dir,basename,namelen,&de);	if (!bh) {		iput(dir);		iput(oldinode);		return -ENOSPC;	}
// 否则初始设置该目录项的i 节点号等于原路径名的i 节点号,并置包含该新添目录项的高速缓冲区
// 已修改标志,释放该缓冲区,释放目录的i 节点。	de->inode = oldinode->i_num;	bh->b_dirt = 1;	brelse(bh);	iput(dir);
// 将原节点的应用计数加1,修改其改变时间为当前时间,并设置i 节点已修改标志,最后释放原
// 路径名的i 节点,并返回0(成功)。	oldinode->i_nlinks++;	oldinode->i_ctime = CURRENT_TIME;	oldinode->i_dirt = 1;	iput(oldinode);	return 0;}

⌨️ 快捷键说明

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