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

📄 namei.c

📁 带中文注释的 linux 0.11 源代码0.11,很好的
💻 C
📖 第 1 页 / 共 4 页
字号:
}//// 系统调用函数 - 删除指定名称的目录。// 参数: name - 目录名(路径名)。// 返回:返回0 表示成功,否则返回出错号。intsys_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)    {				/* we may not delete ".", but "../dir" is ok */      iput (inode);		/* 我们不可以删除".",但可以删除"../dir" */      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,否则返回出错号。intsys_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,否则返回出错号。intsys_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 + -