📄 namei.c
字号:
if (!permission(dir,MAY_WRITE)) { //如果此目录的权限是不可写的,返回
iput(dir);
return -EACCES;
}
inode = new_inode(dir->i_dev); //为在这个目录中不存在的文件建立一个新的inode
if (!inode) {
iput(dir);
return -ENOSPC;
}
inode->i_mode = mode; //设置新的inode的mode
inode->i_dirt = 1;
bh = add_entry(dir,basename,namelen,&de); //在目录文件中写入de->name
if (!bh) {
inode->i_nlinks--;
iput(inode);
iput(dir);
return -ENOSPC;
}
de->inode = inode->i_num; //将de->inode写入实际块号,它将在dir中与de->name对照
bh->b_dirt = 1;
brelse(bh);
iput(dir);
*res_inode = inode;
return 0;
}
inr = de->inode;
dev = dir->i_dev;
brelse(bh);
iput(dir);
if (flag & O_EXCL) //如果flag是检查该文件有没有
return -EEXIST;
if (!(inode=iget(dev,inr))) //取该文件的inode
return -EACCES;
if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
permission(inode,ACC_MODE(flag))!=ACC_MODE(flag)) {
iput(inode);
return -EPERM;
}
inode->i_atime = CURRENT_TIME;
if (flag & O_TRUNC)
truncate(inode);
*res_inode = inode;
return 0;
}
int sys_mkdir(const char * pathname, int mode)
{
const char * basename;
int namelen;
struct m_inode * dir, * inode;
struct buffer_head * bh, *dir_block;
struct dir_entry * de;
if (current->euid && current->uid)
return -EPERM;
if (!(dir = dir_namei(pathname,&namelen,&basename))) //读取待建目录的那个目录
return -ENOENT;
if (!namelen) {
iput(dir);
return -ENOENT;
}
if (!permission(dir,MAY_WRITE)) { //检查此目录的写权限
iput(dir);
return -EPERM;
}
bh = find_entry(dir,basename,namelen,&de); //在这个目录文件中是否有待建目录的名字
if (bh) {
brelse(bh);
iput(dir);
return -EEXIST;
}
inode = new_inode(dir->i_dev); //创建一个新的inode
if (!inode) {
iput(dir);
return -ENOSPC;
}
inode->i_size = 32;
inode->i_dirt = 1;
inode->i_mtime = inode->i_atime = CURRENT_TIME;
if (!(inode->i_zone[0]=new_block(inode->i_dev))) { //为该目录节点创建第一个块
iput(dir);
inode->i_nlinks--;
iput(inode);
return -ENOSPC;
}
inode->i_dirt = 1;
if (!(dir_block=bread(inode->i_dev,inode->i_zone[0]))) { //读该目录块
iput(dir);
free_block(inode->i_dev,inode->i_zone[0]);
inode->i_nlinks--;
iput(inode);
return -ERROR;
}
de = (struct dir_entry *) dir_block->b_data; //de指向该块的数据区
de->inode=inode->i_num; //建立本目录的入口
strcpy(de->name,".");
de++;
de->inode = dir->i_num; //建立父目录的入口
strcpy(de->name,"..");
inode->i_nlinks = 2;
dir_block->b_dirt = 1;
brelse(dir_block);
inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask); //将本节点设为目录文件
inode->i_dirt = 1;
bh = add_entry(dir,basename,namelen,&de); //在父目录中登记本目录文件
if (!bh) {
iput(dir);
free_block(inode->i_dev,inode->i_zone[0]);
inode->i_nlinks=0;
iput(inode);
return -ENOSPC;
}
de->inode = inode->i_num;
bh->b_dirt = 1;
dir->i_nlinks++;
dir->i_dirt = 1;
iput(dir);
iput(inode);
brelse(bh);
return 0;
}
/*
* routine to check that the specified directory is empty (for rmdir)
*/
static int empty_dir(struct m_inode * inode)
{
int nr,block;
int len;
struct buffer_head * bh;
struct dir_entry * de;
len = inode->i_size / sizeof (struct dir_entry); //本目录中有几个项目
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 = (struct dir_entry *) bh->b_data; //de指向目录中的元素
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 = 2;
de += 2;
while (nr<len) {
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; //重新定位指针de
}
if (de->inode) { //如果目录文件中只有本目录和父目录项,那么就是null目录
brelse(bh);
return 0;
}
de++;
nr++;
}
brelse(bh);
return 1;
}
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 (current->euid && current->uid)
return -EPERM;
if (!(dir = dir_namei(name,&namelen,&basename)))
return -ENOENT;
if (!namelen) {
iput(dir);
return -ENOENT;
}
bh = find_entry(dir,basename,namelen,&de); //在目录文件找是否有要删除的那个目录项
if (!bh) {
iput(dir);
return -ENOENT;
}
if (!permission(dir,MAY_WRITE)) { //检查写权限
iput(dir);
brelse(bh);
return -EPERM;
}
if (!(inode = iget(dir->i_dev, de->inode))) { //取要删除的那个文件的inode
iput(dir);
brelse(bh);
return -EPERM;
}
if (inode == dir) { /* we may not delete ".", but "../dir" is ok */ //要删除的目录不能是父目录
iput(inode);
iput(dir);
brelse(bh);
return -EPERM;
}
if (!S_ISDIR(inode->i_mode)) { //此节点必须是目录
iput(inode);
iput(dir);
brelse(bh);
return -ENOTDIR;
}
if (!empty_dir(inode)) { //此节点是否为空
iput(inode);
iput(dir);
brelse(bh);
return -ENOTEMPTY;
}
if (inode->i_nlinks != 2)
printk("empty directory has nlink!=2 (%d)",inode->i_nlinks);
de->inode = 0; //在父目录中清除该目录的节点
bh->b_dirt = 1;
brelse(bh);
inode->i_nlinks=0;
inode->i_dirt=1;
dir->i_nlinks--;
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt=1;
iput(dir);
iput(inode);
return 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;
if (!(dir = dir_namei(name,&namelen,&basename)))
return -ENOENT;
if (!namelen) {
iput(dir);
return -ENOENT;
}
if (!permission(dir,MAY_WRITE)) {
iput(dir);
return -EPERM;
}
bh = find_entry(dir,basename,namelen,&de);
if (!bh) {
iput(dir);
return -ENOENT;
}
inode = iget(dir->i_dev, de->inode);
if (!inode) { //不能联结不存在的文件
printk("iget failed in delete (%04x:%d)",dir->i_dev,de->inode);
iput(dir);
brelse(bh);
return -ENOENT;
}
if (!S_ISREG(inode->i_mode)) { //是否为正常的节点mode
iput(inode);
iput(dir);
brelse(bh);
return -EPERM;
}
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;
}
de->inode = 0;
bh->b_dirt = 1;
brelse(bh);
inode->i_nlinks--;
inode->i_dirt = 1;
inode->i_ctime = CURRENT_TIME;
iput(inode);
iput(dir);
return 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;
oldinode=namei(oldname); //保存老文件名的inode
if (!oldinode)
return -ENOENT;
if (!S_ISREG(oldinode->i_mode)) { //必须是正常文件
iput(oldinode);
return -EPERM;
}
dir = dir_namei(newname,&namelen,&basename); //找出newname的父目录节点
if (!dir) {
iput(oldinode);
return -EACCES;
}
if (!namelen) {
iput(oldinode);
iput(dir);
return -EPERM;
}
if (dir->i_dev != oldinode->i_dev) {
iput(dir);
iput(oldinode);
return -EXDEV;
}
if (!permission(dir,MAY_WRITE)) {
iput(dir);
iput(oldinode);
return -EACCES;
}
bh = find_entry(dir,basename,namelen,&de); //看看父目录中是否有这个名字
if (bh) { //如果有,就不能建立
brelse(bh);
iput(dir);
iput(oldinode);
return -EEXIST;
}
bh = add_entry(dir,basename,namelen,&de); //在父目录中为这个名字建立一个入口点
if (!bh) {
iput(dir);
iput(oldinode);
return -ENOSPC;
}
de->inode = oldinode->i_num; //将此节点指向和oldinode一样的inode
bh->b_dirt = 1;
brelse(bh);
iput(dir);
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 + -