If you want to find a file, you need to find the file’s inode, but there is no file name in the inode. The inode does not care about the contents of a file. If the file is a normal file, it contains the data structure of the file. If the file is a directory, it contains the data structure of the directory entry. The first name in the directory entry is “..” Parent directory. The second “.” indicates the current directory, followed by other file inodes stored in this directory.

dir_namei

For example, pathname = “/a/b/c/ d.xt” is to obtain the directory c inode.

fs/namei.c

static struct m_inode * dir_namei(const char * pathname,int * namelen, const char ** name) { char c; const char * basename; struct m_inode * dir; if (! (dir = get_dir(pathname))) return NULL; basename = pathname; while ((c=get_fs_byte(pathname++))) if (c=='/') basename=pathname; *namelen = pathname-basename-1; *name = basename; return dir; }Copy the code

get_dir

For example, if pathname = “/ a/b/c/d. xt “,get_dir is an absolute or relative path. The path starts with a “/”, so it is an absolute path. Then find the inode named B from the a inode entry, and so on to the C inode.

fs/namei.c

static struct m_inode * get_dir(const char * pathname) { char c; // Const char * thisname; struct m_inode * inode; struct buffer_head * bh; // buffer int namelen,inr,idev; struct dir_entry * de; // Directory entry // Root directory and current directory exist if (! current->root || ! current->root->i_count) panic("No root inode"); if (! current->pwd || ! current->pwd->i_count) panic("No cwd inode"); If ((c=get_fs_byte(pathname))=='/') {inode = current->root; // the current directory is the root pathname++; } else if (c) inode = current-> PWD; Else return NULL; /* empty name is bad */ inode->i_count++; While (1) {thisName = pathname; // If it is not a directory or has no permission to enter a directory, NULL if (! S_ISDIR(inode->i_mode) || ! permission(inode,MAY_EXEC)) { iput(inode); // return inode NULL; } for(namelen=0; (c=get_fs_byte(pathname++))&&(c! = '/'); namelen++) /* nothing */ ; C is null or c is equal to /. If c is null, the search is complete. If c is not null, the search is complete. c) return inode; Thisname is the current directory name, namelen is the current directory name length if (! (bh = find_entry(&inode,thisname,namelen,&de))) { iput(inode); return NULL; } inr = de->inode; Idev = inode->i_dev; idev = inode->i_dev; brelse(bh); iput(inode); if (! (inode = iget(IDEv, INR))) return NULL; (inode = iget(IDEv, inR)) }}Copy the code

find_entry

fs/namei.c

Find_entry Finds the specified inode from the directory entry. The inode does not have the file name attribute.

Struct dir_entry {unsigned short inode; char name[NAME_LEN]; // NAME_LEN=14};Copy the code

Read the directory entry from the directory, find the directory entry matching name, read into the buffer, and return.

static struct buffer_head * find_entry(struct m_inode ** dir, const char * name, int namelen, struct dir_entry ** res_dir) { int entries; int block,i; struct buffer_head * bh; struct dir_entry * de; struct super_block * sb; #ifdef NO_TRUNCATE if (namelen > NAME_LEN) return NULL #else if (namelen > NAME_LEN) namelen = NAME_LEN; #endif // Count the number of directory entries = (*dir)->i_size/(sizeof (struct dir_entry)); *res_dir = NULL; if (! namelen) return NULL; / / check ".." Directory if (namelen = = 2 && get_fs_byte (name) = = '. '&& get_fs_byte (name + 1) = ='. ') {if ((* dir) = = current - > root) namelen = 1; / / the ".." With "." Else if ((*dir)->i_num == ROOT_INO) {ROOT_INO = 1; A superblock sb=get_super((*dir)->i_dev); If (sb->s_imount) {if (sb->s_imount) {iput(*dir); (*dir)=sb->s_imount; (*dir)->i_count++; }}} if (! (block = (*dir)->i_zone[0])) return NULL; if (! (bh = bread((*dir)->i_dev,block)) // At this point we will search for directory entries matching the specified filename in the directory I node data block. Start by having DE point to the data block part of the // buffer block. The search is performed in a loop that does not exceed the number of items in the directory. I is the index number of the directory entry // in the directory. Initialize to 0 at the beginning of the loop. I = 0; de = (struct dir_entry *) bh->b_data; While (I < entries) {if ((char *)de >= BLOCK_SIZE+bh->b_data) {while (I < entries) {if ((char *)de >= BLOCK_SIZE+bh->b_data) { Release the current buffer, // read the next logical block of the directory into buffer brelse(bh); bh = NULL; if (! (block = bmap(*dir,i/DIR_ENTRIES_PER_BLOCK)) || ! (bh = bread((*dir)->i_dev,block))) { i += DIR_ENTRIES_PER_BLOCK; continue; } de = (struct dir_entry *) bh->b_data; If (match(namelen,name,de)) {*res_dir = de; return bh; // find the directory entry, return buffer} de++; i++; } brelse(bh) releases the data block of the specified directory if no corresponding directory is found after all directory items are searched. return NULL; }Copy the code