?? namei.c
字號:
}//// 系統調用函數 - 刪除指定名稱的目錄。// 參數: 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 + -