?? namei.c
字號:
bh->b_dirt = 1; brelse (bh); iput (dir); *res_inode = inode; return 0; }// 若上面在目錄中取文件名對應的目錄項結構操作成功(也即bh 不為NULL),取出該目錄項的i 節點號// 和其所在的設備號,并釋放該高速緩沖區以及目錄的i 節點。 inr = de->inode; dev = dir->i_dev; brelse (bh); iput (dir);// 如果獨占使用標志O_EXCL 置位,則返回文件已存在出錯碼,退出。 if (flag & O_EXCL) return -EEXIST;// 如果取該目錄項對應i 節點的操作失敗,則返回訪問出錯碼,退出。 if (!(inode = iget (dev, inr))) return -EACCES;// 若該i 節點是一個目錄的節點并且訪問模式是只讀或只寫,或者沒有訪問的許可權限,則釋放該i// 節點,返回訪問權限出錯碼,退出。 if ((S_ISDIR (inode->i_mode) && (flag & O_ACCMODE)) || !permission (inode, ACC_MODE (flag))) { iput (inode); return -EPERM; }// 更新該i 節點的訪問時間字段為當前時間。 inode->i_atime = CURRENT_TIME;// 如果設立了截0 標志,則將該i 節點的文件長度截為0。 if (flag & O_TRUNC) truncate (inode);// 最后返回該目錄項i 節點的指針,并返回0(成功)。 *res_inode = inode; return 0;}//// 系統調用函數 - 創建一個特殊文件或普通文件節點(node)。// 創建名稱為filename,由mode 和dev 指定的文件系統節點(普通文件、設備特殊文件或命名管道)。// 參數:filename - 路徑名;mode - 指定使用許可以及所創建節點的類型;dev - 設備號。// 返回:成功則返回0,否則返回出錯碼。intsys_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;// 如果找不到對應路徑名目錄的i 節點,則返回出錯碼。 if (!(dir = dir_namei (filename, &namelen, &basename))) return -ENOENT;// 如果最頂端的文件名長度為0,則說明給出的路徑名最后沒有指定文件名,釋放該目錄i 節點,返回// 出錯碼,退出。 if (!namelen) { iput (dir); return -ENOENT; }// 如果在該目錄中沒有寫的權限,則釋放該目錄的i 節點,返回訪問許可出錯碼,退出。 if (!permission (dir, MAY_WRITE)) { iput (dir); return -EPERM; }// 如果對應路徑名上最后的文件名的目錄項已經存在,則釋放包含該目錄項的高速緩沖區,釋放目錄// 的i 節點,返回文件已經存在出錯碼,退出。 bh = find_entry (&dir, basename, namelen, &de); if (bh) { brelse (bh); iput (dir); return -EEXIST; }// 申請一個新的i 節點,如果不成功,則釋放目錄的i 節點,返回無空間出錯碼,退出。 inode = new_inode (dir->i_dev); if (!inode) { iput (dir); return -ENOSPC; }// 設置該i 節點的屬性模式。如果要創建的是塊設備文件或者是字符設備文件,則令i 節點的直接塊// 指針0 等于設備號。 inode->i_mode = mode; if (S_ISBLK (mode) || S_ISCHR (mode)) inode->i_zone[0] = dev;// 設置該i 節點的修改時間、訪問時間為當前時間。 inode->i_mtime = inode->i_atime = CURRENT_TIME; inode->i_dirt = 1;// 在目錄中新添加一個目錄項,如果失敗(包含該目錄項的高速緩沖區指針為NULL),則釋放目錄的// i 節點;所申請的i 節點引用連接計數復位,并釋放該i 節點。返回出錯碼,退出。 bh = add_entry (dir, basename, namelen, &de); if (!bh) { iput (dir); inode->i_nlinks = 0; iput (inode); return -ENOSPC; }// 令該目錄項的i 節點字段等于新i 節點號,置高速緩沖區已修改標志,釋放目錄和新的i 節點,釋放// 高速緩沖區,最后返回0(成功)。 de->inode = inode->i_num; bh->b_dirt = 1; iput (dir); iput (inode); brelse (bh); return 0;}//// 系統調用函數 - 創建目錄。// 參數:pathname - 路徑名;mode - 目錄使用的權限屬性。// 返回:成功則返回0,否則返回出錯碼。intsys_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;// 如果找不到對應路徑名目錄的i 節點,則返回出錯碼。 if (!(dir = dir_namei (pathname, &namelen, &basename))) return -ENOENT;// 如果最頂端的文件名長度為0,則說明給出的路徑名最后沒有指定文件名,釋放該目錄i 節點,返回// 出錯碼,退出。 if (!namelen) { iput (dir); return -ENOENT; }// 如果在該目錄中沒有寫的權限,則釋放該目錄的i 節點,返回訪問許可出錯碼,退出。 if (!permission (dir, MAY_WRITE)) { iput (dir); return -EPERM; }// 如果對應路徑名上最后的文件名的目錄項已經存在,則釋放包含該目錄項的高速緩沖區,釋放目錄// 的i 節點,返回文件已經存在出錯碼,退出。 bh = find_entry (&dir, basename, namelen, &de); if (bh) { brelse (bh); iput (dir); return -EEXIST; }// 申請一個新的i 節點,如果不成功,則釋放目錄的i 節點,返回無空間出錯碼,退出。 inode = new_inode (dir->i_dev); if (!inode) { iput (dir); return -ENOSPC; }// 置該新i 節點對應的文件長度為32(一個目錄項的大小),置節點已修改標志,以及節點的修改時間// 和訪問時間。 inode->i_size = 32; inode->i_dirt = 1; inode->i_mtime = inode->i_atime = CURRENT_TIME;// 為該i 節點申請一磁盤塊,并令節點第一個直接塊指針等于該塊號。如果申請失敗,則釋放對應目錄// 的i 節點;復位新申請的i 節點連接計數;釋放該新的i 節點,返回沒有空間出錯碼,退出。 if (!(inode->i_zone[0] = new_block (inode->i_dev))) { iput (dir); inode->i_nlinks--; iput (inode); return -ENOSPC; }// 置該新的i 節點已修改標志。 inode->i_dirt = 1;// 讀新申請的磁盤塊。若出錯,則釋放對應目錄的i 節點;釋放申請的磁盤塊;復位新申請的i 節點// 連接計數;釋放該新的i 節點,返回沒有空間出錯碼,退出。 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 指向目錄項數據塊,置該目錄項的i 節點號字段等于新申請的i 節點號,名字字段等于"."。 de = (struct dir_entry *) dir_block->b_data; de->inode = inode->i_num; strcpy (de->name, ".");// 然后de 指向下一個目錄項結構,該結構用于存放上級目錄的節點號和名字".."。 de++; de->inode = dir->i_num; strcpy (de->name, ".."); inode->i_nlinks = 2;// 然后設置該高速緩沖區已修改標志,并釋放該緩沖區。 dir_block->b_dirt = 1; brelse (dir_block);// 初始化設置新i 節點的模式字段,并置該i 節點已修改標志。 inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask); inode->i_dirt = 1;// 在目錄中新添加一個目錄項,如果失敗(包含該目錄項的高速緩沖區指針為NULL),則釋放目錄的// i 節點;所申請的i 節點引用連接計數復位,并釋放該i 節點。返回出錯碼,退出。 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; }// 令該目錄項的i 節點字段等于新i 節點號,置高速緩沖區已修改標志,釋放目錄和新的i 節點,釋放// 高速緩沖區,最后返回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;}/** routine to check that the specified directory is empty (for rmdir)*//** 用于檢查指定的目錄是否為空的子程序(用于rmdir 系統調用函數)。*///// 檢查指定目錄是否是空的。// 參數:inode - 指定目錄的i 節點指針。// 返回:0 - 是空的;1 - 不空。static intempty_dir (struct m_inode *inode){ int nr, block; int len; struct buffer_head *bh; struct dir_entry *de;// 計算指定目錄中現有目錄項的個數(應該起碼有2 個,即"."和".."兩個文件目錄項)。 len = inode->i_size / sizeof (struct dir_entry);// 如果目錄項個數少于2 個或者該目錄i 節點的第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 指向含有讀出磁盤塊數據的高速緩沖區中第1 項目錄項。 de = (struct dir_entry *) bh->b_data;// 如果第1 個目錄項的i 節點號字段值不等于該目錄的i 節點號,或者第2 個目錄項的i 節點號字段// 為零,或者兩個目錄項的名字字段不分別等于"."和"..",則顯示出錯警告信息“設備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;// 循環檢測該目錄中所有的目錄項(len-2 個),看有沒有目錄項的i 節點號字段不為0(被使用)。 while (nr < len) {// 如果該塊磁盤塊中的目錄項已經檢測完,則釋放該磁盤塊的高速緩沖區,讀取下一塊含有目錄項的// 磁盤塊。若相應塊沒有使用(或已經不用,如文件已經刪除等),則繼續讀下一塊,若讀不出,則出// 錯,返回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 節點號字段不等于0,則表示該目錄項目前正被使用,則釋放該高速緩沖區,// 返回0,退出。 if (de->inode) { brelse (bh); return 0; }// 否則,若還沒有查詢完該目錄中的所有目錄項,則繼續檢測。 de++; nr++; }// 到這里說明該目錄中沒有找到已用的目錄項(當然除了頭兩個以外),則返回緩沖區,返回1。 brelse (bh); return 1;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -