📄 namei.c,v
字号:
dev = dir->i_dev; brelse(bh); iput(dir); if (flag & O_EXCL) return -EEXIST; if (!(inode=iget(dev,inr))) return -EACCES; if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) || !permission(inode,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_mknod(const char * filename, int mode, int dev){ const char * basename; int namelen; struct m_inode * dir, * inode; struct buffer_head * bh; struct dir_entry * de; if (!suser()) return -EPERM; if (!(dir = dir_namei(filename,&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); if (!inode) { iput(dir); return -ENOSPC; } inode->i_mode = mode; if (S_ISBLK(mode) || S_ISCHR(mode)) inode->i_zone[0] = dev; inode->i_mtime = inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; bh = add_entry(dir,basename,namelen,&de); if (!bh) { iput(dir); inode->i_nlinks=0; iput(inode); return -ENOSPC; } de->inode = inode->i_num; bh->b_dirt = 1; iput(dir); iput(inode); brelse(bh); 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 (!suser()) 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); 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->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; 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; } if (de->inode) { 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 (!suser()) 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))) { 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_ISDIR(inode->i_mode)) { iput(inode); iput(dir); brelse(bh); return -EPERM; } /* * If the directory has the sticky bit, the user must either * own the file or own the directory or be the superuser to * delete a file in that directory. This is typically used * for /tmp and /usr/tmp. */ if ((dir->i_mode & S_ISVTX) && (current->euid != inode->i_uid) && (current->euid != dir->i_uid) && !suser()) { 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); if (!oldinode) return -ENOENT; if (S_ISDIR(oldinode->i_mode)) { iput(oldinode); return -EPERM; } dir = dir_namei(newname,&namelen,&basename); 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; bh->b_dirt = 1; brelse(bh); iput(dir); oldinode->i_nlinks++; oldinode->i_ctime = CURRENT_TIME; oldinode->i_dirt = 1; iput(oldinode); return 0;}@1.1log@Initial revision@text@d43 1a43 3 if (!(current->uid && current->euid)) mode=0777; else if (current->uid==inode->i_uid || current->euid==inode->i_uid)d45 1a45 1 else if (current->gid==inode->i_gid || current->egid==inode->i_gid)d47 3a49 1 return mode & mask & 0007;d371 1d397 1a397 1 permission(inode,ACC_MODE(flag))!=ACC_MODE(flag)) {d416 1a416 1 if (current->euid && current->uid)d467 1a467 1 if (current->euid && current->uid)d591 1a591 1 if (current->euid && current->uid)d683 13@
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -