?? namei.c.bak
字號:
iput(inode); return -ENOSPC; }
// 令該目錄項的i 節(jié)點字段等于新i 節(jié)點號,置高速緩沖區(qū)已修改標志,釋放目錄和新的i 節(jié)點,釋放
// 高速緩沖區(qū),最后返回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 系統(tǒng)調用函數(shù))。 */
//// 檢查指定目錄是否是空的。
// 參數(shù):inode - 指定目錄的i 節(jié)點指針。
// 返回:0 - 是空的;1 - 不空。
static int empty_dir(struct m_inode * inode)
{ int nr,block; int len; struct buffer_head * bh; struct dir_entry * de;
// 計算指定目錄中現(xiàn)有目錄項的個數(shù)(應該起碼有2 個,即"."和".."兩個文件目錄項)。 len = inode->i_size / sizeof (struct dir_entry);
// 如果目錄項個數(shù)少于2 個或者該目錄i 節(jié)點的第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 指向含有讀出磁盤塊數(shù)據(jù)的高速緩沖區(qū)中第1 項目錄項。 de = (struct dir_entry *) bh->b_data;
// 如果第1 個目錄項的i 節(jié)點號字段值不等于該目錄的i 節(jié)點號,或者第2 個目錄項的i 節(jié)點號字段
// 為零,或者兩個目錄項的名字字段不分別等于"."和"..",則顯示出錯警告信息“設備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;
// 循環(huán)檢測該目錄中所有的目錄項(len-2 個),看有沒有目錄項的i 節(jié)點號字段不為0(被使用)。 while (nr<len) {
// 如果該塊磁盤塊中的目錄項已經(jīng)檢測完,則釋放該磁盤塊的高速緩沖區(qū),讀取下一塊含有目錄項的
// 磁盤塊。若相應塊沒有使用(或已經(jīng)不用,如文件已經(jīng)刪除等),則繼續(xù)讀下一塊,若讀不出,則出
// 錯,返回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 節(jié)點號字段不等于0,則表示該目錄項目前正被使用,則釋放該高速緩沖區(qū),
// 返回0,退出。 if (de->inode) { brelse(bh); return 0; }
// 否則,若還沒有查詢完該目錄中的所有目錄項,則繼續(xù)檢測。 de++; nr++; }
// 到這里說明該目錄中沒有找到已用的目錄項(當然除了頭兩個以外),則返回緩沖區(qū),返回1。 brelse(bh); return 1;}
//// 系統(tǒng)調用函數(shù)- 刪除指定名稱的目錄。
// 參數(shù): 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 節(jié)點,則返回出錯碼。 if (!(dir = dir_namei(name,&namelen,&basename))) return -ENOENT;
// 如果最頂端的文件名長度為0,則說明給出的路徑名最后沒有指定文件名,釋放該目錄i 節(jié)點,返回
// 出錯碼,退出。 if (!namelen) { iput(dir); return -ENOENT; }
// 如果在該目錄中沒有寫的權限,則釋放該目錄的i 節(jié)點,返回訪問許可出錯碼,退出。 if (!permission(dir,MAY_WRITE)) { iput(dir); return -EPERM; }
// 如果對應路徑名上最后的文件名的目錄項不存在,則釋放包含該目錄項的高速緩沖區(qū),釋放目錄
// 的i 節(jié)點,返回文件已經(jīng)存在出錯碼,退出。否則dir 是包含要被刪除目錄名的目錄i 節(jié)點,de
// 是要被刪除目錄的目錄項結構。 bh = find_entry(&dir,basename,namelen,&de); if (!bh) { iput(dir); return -ENOENT; }
// 取該目錄項指明的i 節(jié)點。若出錯則釋放目錄的i 節(jié)點,并釋放含有目錄項的高速緩沖區(qū),返回
// 出錯號。 if (!(inode = iget(dir->i_dev, de->inode))) { iput(dir); brelse(bh); return -EPERM; }
// 若該目錄設置了受限刪除標志并且進程的有效用戶id 不等于該i 節(jié)點的用戶id,則表示沒有權限刪
// 除該目錄,于是釋放包含要刪除目錄名的目錄i 節(jié)點和該要刪除目錄的i 節(jié)點,釋放高速緩沖區(qū),
// 返回出錯碼。 if ((dir->i_mode & S_ISVTX) && current->euid && inode->i_uid != current->euid) { iput(dir); iput(inode); brelse(bh); return -EPERM; }
// 如果要被刪除的目錄項的i 節(jié)點的設備號不等于包含該目錄項的目錄的設備號,或者該被刪除目錄的
// 引用連接計數(shù)大于1(表示有符號連接等),則不能刪除該目錄,于是釋放包含要刪除目錄名的目錄
// i 節(jié)點和該要刪除目錄的i 節(jié)點,釋放高速緩沖區(qū),返回出錯碼。 if (inode->i_dev != dir->i_dev || inode->i_count>1) { iput(dir); iput(inode); brelse(bh); return -EPERM; }
// 如果要被刪除目錄的目錄項i 節(jié)點的節(jié)點號等于包含該需刪除目錄的i 節(jié)點號,則表示試圖刪除"."
// 目錄。于是釋放包含要刪除目錄名的目錄i 節(jié)點和該要刪除目錄的i 節(jié)點,釋放高速緩沖區(qū),返回
// 出錯碼。 if (inode == dir) { /* 我們不可以刪除".",但可以刪除"../dir"*/ iput(inode); iput(dir); brelse(bh); return -EPERM; }
// 若要被刪除的目錄的i 節(jié)點的屬性表明這不是一個目錄,則釋放包含要刪除目錄名的目錄i 節(jié)點和
// 該要刪除目錄的i 節(jié)點,釋放高速緩沖區(qū),返回出錯碼。 if (!S_ISDIR(inode->i_mode)) { iput(inode); iput(dir); brelse(bh); return -ENOTDIR; }
// 若該需被刪除的目錄不空,則釋放包含要刪除目錄名的目錄i 節(jié)點和該要刪除目錄的i 節(jié)點,釋放
// 高速緩沖區(qū),返回出錯碼。 if (!empty_dir(inode)) { iput(inode); iput(dir); brelse(bh); return -ENOTEMPTY; }
// 若該需被刪除目錄的i 節(jié)點的連接數(shù)不等于2,則顯示警告信息。 if (inode->i_nlinks != 2) printk("empty directory has nlink!=2 (%d)",inode->i_nlinks);
// 置該需被刪除目錄的目錄項的i 節(jié)點號字段為0,表示該目錄項不再使用,并置含有該目錄項的高速
// 緩沖區(qū)已修改標志,并釋放該緩沖區(qū)。 de->inode = 0; bh->b_dirt = 1; brelse(bh);
// 置被刪除目錄的i 節(jié)點的連接數(shù)為0,并置i 節(jié)點已修改標志。 inode->i_nlinks=0; inode->i_dirt=1;
// 將包含被刪除目錄名的目錄的i 節(jié)點引用計數(shù)減1,修改其改變時間和修改時間為當前時間,并置
// 該節(jié)點已修改標志。 dir->i_nlinks--; dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_dirt=1;
// 最后釋放包含要刪除目錄名的目錄i 節(jié)點和該要刪除目錄的i 節(jié)點,返回0(成功)。 iput(dir); iput(inode); return 0;}
//// 系統(tǒng)調用函數(shù)- 刪除文件名以及可能也刪除其相關的文件。
// 從文件系統(tǒng)刪除一個名字。如果是一個文件的最后一個連接,并且沒有進程正打開該文件,則該文件
// 也將被刪除,并釋放所占用的設備空間。
// 參數(shù):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 節(jié)點,則返回出錯碼。 if (!(dir = dir_namei(name,&namelen,&basename))) return -ENOENT;
// 如果最頂端的文件名長度為0,則說明給出的路徑名最后沒有指定文件名,釋放該目錄i 節(jié)點,返回
// 出錯碼,退出。 if (!namelen) { iput(dir); return -ENOENT; }
// 如果在該目錄中沒有寫的權限,則釋放該目錄的i 節(jié)點,返回訪問許可出錯碼,退出。 if (!permission(dir,MAY_WRITE)) { iput(dir); return -EPERM; }
// 如果對應路徑名上最后的文件名的目錄項不存在,則釋放包含該目錄項的高速緩沖區(qū),釋放目錄
// 的i 節(jié)點,返回文件已經(jīng)存在出錯碼,退出。否則dir 是包含要被刪除目錄名的目錄i 節(jié)點,de
// 是要被刪除目錄的目錄項結構。 bh = find_entry(&dir,basename,namelen,&de); if (!bh) { iput(dir); return -ENOENT; }
// 取該目錄項指明的i 節(jié)點。若出錯則釋放目錄的i 節(jié)點,并釋放含有目錄項的高速緩沖區(qū),返回
// 出錯號。 if (!(inode = iget(dir->i_dev, de->inode))) { iput(dir); brelse(bh); return -ENOENT; }
// 如果該目錄設置了受限刪除標志并且用戶不是超級用戶,并且進程的有效用戶id 不等于被刪除文件
// 名i 節(jié)點的用戶id,并且進程的有效用戶id 也不等于目錄i 節(jié)點的用戶id,則沒有權限刪除該文件
// 名。則釋放該目錄i 節(jié)點和該文件名目錄項的i 節(jié)點,釋放包含該目錄項的緩沖區(qū),返回出錯號。 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 節(jié)點和該文件名目錄項的i 節(jié)點,
// 釋放包含該目錄項的緩沖區(qū),返回出錯號。 if (S_ISDIR(inode->i_mode)) { iput(inode); iput(dir); brelse(bh); return -EPERM; }
// 如果該i 節(jié)點的連接數(shù)已經(jīng)為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 節(jié)點號字段置為0,表示釋放該目錄項,并設置包含該目錄項的緩沖區(qū)
// 已修改標志,釋放該高速緩沖區(qū)。 de->inode = 0; bh->b_dirt = 1; brelse(bh);
// 該i 節(jié)點的連接數(shù)減1,置已修改標志,更新改變時間為當前時間。最后釋放該i 節(jié)點和目錄的i 節(jié)
// 點,返回0(成功)。 inode->i_nlinks--; inode->i_dirt = 1; inode->i_ctime = CURRENT_TIME; iput(inode); iput(dir); return 0;}
//// 系統(tǒng)調用函數(shù)- 為文件建立一個文件名。
// 為一個已經(jīng)存在的文件創(chuàng)建一個新連接(也稱為硬連接- hard link)。
// 參數(shù):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 節(jié)點oldinode。如果為0,則表示出錯,返回出錯號。 oldinode=namei(oldname); if (!oldinode) return -ENOENT;
// 如果原路徑名對應的是一個目錄名,則釋放該i 節(jié)點,返回出錯號。 if (S_ISDIR(oldinode->i_mode)) { iput(oldinode); return -EPERM; }
// 查找新路徑名的最頂層目錄的i 節(jié)點,并返回最后的文件名及其長度。如果目錄的i 節(jié)點沒有找到,
// 則釋放原路徑名的i 節(jié)點,返回出錯號。 dir = dir_namei(newname,&namelen,&basename); if (!dir) { iput(oldinode); return -EACCES; }
// 如果新路徑名中不包括文件名,則釋放原路徑名i 節(jié)點和新路徑名目錄的i 節(jié)點,返回出錯號。 if (!namelen) { iput(oldinode); iput(dir); return -EPERM; }
// 如果新路徑名目錄的設備號與原路徑名的設備號不一樣,則也不能建立連接,于是釋放新路徑名
// 目錄的i 節(jié)點和原路徑名的i 節(jié)點,返回出錯號。 if (dir->i_dev != oldinode->i_dev) { iput(dir); iput(oldinode); return -EXDEV; }
// 如果用戶沒有在新目錄中寫的權限,則也不能建立連接,于是釋放新路徑名目錄的i 節(jié)點
// 和原路徑名的i 節(jié)點,返回出錯號。 if (!permission(dir,MAY_WRITE)) { iput(dir); iput(oldinode); return -EACCES; }
// 查詢該新路徑名是否已經(jīng)存在,如果存在,則也不能建立連接,于是釋放包含該已存在目錄項的
// 高速緩沖區(qū),釋放新路徑名目錄的i 節(jié)點和原路徑名的i 節(jié)點,返回出錯號。 bh = find_entry(&dir,basename,namelen,&de); if (bh) { brelse(bh); iput(dir); iput(oldinode); return -EEXIST; }
// 在新目錄中添加一個目錄項。若失敗則釋放該目錄的i 節(jié)點和原路徑名的i 節(jié)點,返回出錯號。 bh = add_entry(dir,basename,namelen,&de); if (!bh) { iput(dir); iput(oldinode); return -ENOSPC; }
// 否則初始設置該目錄項的i 節(jié)點號等于原路徑名的i 節(jié)點號,并置包含該新添目錄項的高速緩沖區(qū)
// 已修改標志,釋放該緩沖區(qū),釋放目錄的i 節(jié)點。 de->inode = oldinode->i_num; bh->b_dirt = 1; brelse(bh); iput(dir);
// 將原節(jié)點的應用計數(shù)加1,修改其改變時間為當前時間,并設置i 節(jié)點已修改標志,最后釋放原
// 路徑名的i 節(jié)點,并返回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 + -