xref: /minix/minix/fs/isofs/path.c (revision 83133719)
1 #include "inc.h"
2 
3 static int search_dir(
4 	struct inode *ldir_ptr,		/* dir record parent */
5 	char string[NAME_MAX],			/* component to search for */
6 	ino_t *numb				/* pointer to new dir record */
7 ) {
8 	/* The search_dir function performs the operation of searching for the
9 	 * component ``string" in ldir_ptr. It returns the response and the
10 	 * number of the inode in numb.
11 	 */
12 	struct inode *dir_tmp;
13 	size_t pos = 0;
14 	int r;
15 
16 	/*
17 	 * This function search a particular element (in string) in a inode and
18 	 * return its number.
19 	 */
20 
21 	if ((ldir_ptr->i_stat.st_mode & S_IFMT) != S_IFDIR)
22 		return ENOTDIR;
23 
24 	if (strcmp(string, ".") == 0) {
25 		*numb = ldir_ptr->i_stat.st_ino;
26 		return OK;
27 	}
28 
29 	/*
30 	 * Parent directories need special attention to make sure directory
31 	 * inodes stay consistent.
32 	*/
33 	if (strcmp(string, "..") == 0) {
34 		if (ldir_ptr->i_stat.st_ino ==
35 		    v_pri.inode_root->i_stat.st_ino) {
36 			*numb = v_pri.inode_root->i_stat.st_ino;
37 			return OK;
38 		}
39 		else {
40 			dir_tmp = alloc_inode();
41 			r = read_inode(dir_tmp, ldir_ptr->extent, pos, &pos);
42 			if ((r != OK) || (pos >= ldir_ptr->i_stat.st_size)) {
43 				put_inode(dir_tmp);
44 				return ENOENT;
45 			}
46 			/* Temporary fix for extent spilling */
47 			put_inode(dir_tmp);
48 			dir_tmp = alloc_inode();
49 			/* End of fix */
50 			r = read_inode(dir_tmp, ldir_ptr->extent, pos, &pos);
51 			if ((r != OK) || (pos >= ldir_ptr->i_stat.st_size)) {
52 				put_inode(dir_tmp);
53 				return ENOENT;
54 			}
55 			*numb = dir_tmp->i_stat.st_ino;
56 			put_inode(dir_tmp);
57 			return OK;
58 		}
59 	}
60 
61 	/* Read the dir's content */
62 	while (TRUE) {
63 		dir_tmp = alloc_inode();
64 		r = read_inode(dir_tmp, ldir_ptr->extent, pos, &pos);
65 		if ((r != OK) || (pos >= ldir_ptr->i_stat.st_size)) {
66 			put_inode(dir_tmp);
67 			return ENOENT;
68 		}
69 
70 		if ((strcmp(dir_tmp->i_name, string) == 0) ||
71 		    (strcmp(dir_tmp->i_name, "..") &&
72 		    strcmp(string, "..") == 0)) {
73 			if (dir_tmp->i_stat.st_ino ==
74 			    v_pri.inode_root->i_stat.st_ino) {
75 				*numb = v_pri.inode_root->i_stat.st_ino;
76 				put_inode(dir_tmp);
77 				return OK;
78 			}
79 
80 			*numb = dir_tmp->i_stat.st_ino;
81 			put_inode(dir_tmp);
82 			return OK;
83 		}
84 
85 		put_inode(dir_tmp);
86 	}
87 }
88 
89 int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
90 	int *is_mountpt)
91 {
92 	/* Given a directory and a component of a path, look up the component
93 	 * in the directory, find the inode, open it, and return its details.
94 	 */
95 	struct inode *dirp, *rip;
96 	ino_t ino_nr;
97 	int r;
98 
99 	/* Find the starting inode. */
100 	if ((dirp = find_inode(dir_nr)) == NULL)
101 		return EINVAL;
102 
103 	/* Look up the directory entry. */
104 	if ((r = search_dir(dirp, name, &ino_nr)) != OK)
105 		return r;
106 
107 	/* The component has been found in the directory.  Get the inode. */
108 	if ((rip = get_inode(ino_nr)) == NULL)
109 		return EIO;	/* FIXME: this could have multiple causes */
110 
111 	/* Return its details to the caller. */
112 	node->fn_ino_nr	= rip->i_stat.st_ino;
113 	node->fn_mode	= rip->i_stat.st_mode;
114 	node->fn_size	= rip->i_stat.st_size;
115 	node->fn_uid	= rip->i_stat.st_uid;
116 	node->fn_gid	= rip->i_stat.st_gid;
117 	node->fn_dev	= rip->i_stat.st_rdev;
118 
119 	*is_mountpt = rip->i_mountpoint;
120 
121 	return OK;
122 }
123