xref: /minix3/minix/lib/libsffs/lookup.c (revision 41a30155b93b5fdc3b6a018df059658fbb97e8b4)
1433d6423SLionel Sambuc /* This file provides path-to-inode lookup functionality.
2433d6423SLionel Sambuc  *
3433d6423SLionel Sambuc  * The entry points into this file are:
4433d6423SLionel Sambuc  *   do_lookup		perform the LOOKUP file system call
5433d6423SLionel Sambuc  *
6433d6423SLionel Sambuc  * Created:
7433d6423SLionel Sambuc  *   April 2009 (D.C. van Moolenbroek)
8433d6423SLionel Sambuc  */
9433d6423SLionel Sambuc 
10433d6423SLionel Sambuc #include "inc.h"
11433d6423SLionel Sambuc 
12433d6423SLionel Sambuc /*===========================================================================*
13433d6423SLionel Sambuc  *				go_up					     *
14433d6423SLionel Sambuc  *===========================================================================*/
go_up(char path[PATH_MAX],struct inode * ino,struct inode ** res_ino,struct sffs_attr * attr)15433d6423SLionel Sambuc static int go_up(
16433d6423SLionel Sambuc 	char path[PATH_MAX],    /* path to take the last part from */
17433d6423SLionel Sambuc 	struct inode *ino,      /* inode of the current directory */
18433d6423SLionel Sambuc 	struct inode **res_ino, /* place to store resulting inode */
19433d6423SLionel Sambuc 	struct sffs_attr *attr  /* place to store inode attributes */
20433d6423SLionel Sambuc )
21433d6423SLionel Sambuc {
22433d6423SLionel Sambuc /* Given an inode, progress into the parent directory.
23433d6423SLionel Sambuc  */
24433d6423SLionel Sambuc   struct inode *parent;
25433d6423SLionel Sambuc   int r;
26433d6423SLionel Sambuc 
27433d6423SLionel Sambuc   pop_path(path);
28433d6423SLionel Sambuc 
29433d6423SLionel Sambuc   parent = ino->i_parent;
30433d6423SLionel Sambuc   assert(parent != NULL);
31433d6423SLionel Sambuc 
32433d6423SLionel Sambuc   if ((r = verify_path(path, parent, attr, NULL)) != OK)
33433d6423SLionel Sambuc 	return r;
34433d6423SLionel Sambuc 
35433d6423SLionel Sambuc   get_inode(parent);
36433d6423SLionel Sambuc 
37433d6423SLionel Sambuc   *res_ino = parent;
38433d6423SLionel Sambuc 
39433d6423SLionel Sambuc   return r;
40433d6423SLionel Sambuc }
41433d6423SLionel Sambuc 
42433d6423SLionel Sambuc /*===========================================================================*
43433d6423SLionel Sambuc  *				go_down					     *
44433d6423SLionel Sambuc  *===========================================================================*/
go_down(char path[PATH_MAX],struct inode * parent,char * name,struct inode ** res_ino,struct sffs_attr * attr)45433d6423SLionel Sambuc static int go_down(
46433d6423SLionel Sambuc 	char path[PATH_MAX],    /* path to add the name to */
47433d6423SLionel Sambuc 	struct inode *parent,   /* inode of the current directory */
48433d6423SLionel Sambuc 	char *name,             /* name of the directory entry */
49433d6423SLionel Sambuc 	struct inode **res_ino, /* place to store resulting inode */
50433d6423SLionel Sambuc 	struct sffs_attr *attr  /* place to store inode attributes */
51433d6423SLionel Sambuc )
52433d6423SLionel Sambuc {
53433d6423SLionel Sambuc /* Given a directory inode and a name, progress into a directory entry.
54433d6423SLionel Sambuc  */
55433d6423SLionel Sambuc   struct inode *ino;
56433d6423SLionel Sambuc   int r, stale = 0;
57433d6423SLionel Sambuc 
58433d6423SLionel Sambuc   if ((r = push_path(path, name)) != OK)
59433d6423SLionel Sambuc 	return r;
60433d6423SLionel Sambuc 
61433d6423SLionel Sambuc   dprintf(("%s: go_down: name '%s', path now '%s'\n", sffs_name, name, path));
62433d6423SLionel Sambuc 
63433d6423SLionel Sambuc   ino = lookup_dentry(parent, name);
64433d6423SLionel Sambuc 
65433d6423SLionel Sambuc   dprintf(("%s: lookup_dentry('%s') returned %p\n", sffs_name, name, ino));
66433d6423SLionel Sambuc 
67433d6423SLionel Sambuc   if (ino != NULL)
68433d6423SLionel Sambuc 	r = verify_path(path, ino, attr, &stale);
69433d6423SLionel Sambuc   else
70433d6423SLionel Sambuc 	r = sffs_table->t_getattr(path, attr);
71433d6423SLionel Sambuc 
72433d6423SLionel Sambuc   dprintf(("%s: path query returned %d\n", sffs_name, r));
73433d6423SLionel Sambuc 
74433d6423SLionel Sambuc   if (r != OK) {
75433d6423SLionel Sambuc 	if (ino != NULL) {
76433d6423SLionel Sambuc 		put_inode(ino);
77433d6423SLionel Sambuc 
78433d6423SLionel Sambuc 		ino = NULL;
79433d6423SLionel Sambuc 	}
80433d6423SLionel Sambuc 
81433d6423SLionel Sambuc 	if (!stale)
82433d6423SLionel Sambuc 		return r;
83433d6423SLionel Sambuc   }
84433d6423SLionel Sambuc 
85433d6423SLionel Sambuc   dprintf(("%s: name '%s'\n", sffs_name, name));
86433d6423SLionel Sambuc 
87433d6423SLionel Sambuc   if (ino == NULL) {
88433d6423SLionel Sambuc 	if ((ino = get_free_inode()) == NULL)
89433d6423SLionel Sambuc 		return ENFILE;
90433d6423SLionel Sambuc 
91433d6423SLionel Sambuc 	dprintf(("%s: inode %p ref %d\n", sffs_name, ino, ino->i_ref));
92433d6423SLionel Sambuc 
93433d6423SLionel Sambuc 	ino->i_flags = MODE_TO_DIRFLAG(attr->a_mode);
94433d6423SLionel Sambuc 
95433d6423SLionel Sambuc 	add_dentry(parent, name, ino);
96433d6423SLionel Sambuc   }
97433d6423SLionel Sambuc 
98433d6423SLionel Sambuc   *res_ino = ino;
99433d6423SLionel Sambuc   return OK;
100433d6423SLionel Sambuc }
101433d6423SLionel Sambuc 
102433d6423SLionel Sambuc /*===========================================================================*
103433d6423SLionel Sambuc  *				do_lookup				     *
104433d6423SLionel Sambuc  *===========================================================================*/
do_lookup(ino_t dir_nr,char * name,struct fsdriver_node * node,int * is_mountpt)105a99c939dSDavid van Moolenbroek int do_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
106a99c939dSDavid van Moolenbroek 	int *is_mountpt)
107433d6423SLionel Sambuc {
108433d6423SLionel Sambuc /* Resolve a path string to an inode.
109433d6423SLionel Sambuc  */
110*41a30155SLionel Sambuc   struct inode *dir_ino, *ino = NULL;
111433d6423SLionel Sambuc   struct sffs_attr attr;
112a99c939dSDavid van Moolenbroek   char path[PATH_MAX];
113433d6423SLionel Sambuc   int r;
114433d6423SLionel Sambuc 
115a99c939dSDavid van Moolenbroek   dprintf(("%s: lookup: got query for %"PRIu64", '%s'\n",
116a99c939dSDavid van Moolenbroek 	sffs_name, dir_nr, name));
117433d6423SLionel Sambuc 
118a99c939dSDavid van Moolenbroek   if ((dir_ino = find_inode(dir_nr)) == NULL)
119433d6423SLionel Sambuc 	return EINVAL;
120433d6423SLionel Sambuc 
121433d6423SLionel Sambuc   attr.a_mask = SFFS_ATTR_MODE | SFFS_ATTR_SIZE;
122433d6423SLionel Sambuc 
123a99c939dSDavid van Moolenbroek   if ((r = verify_inode(dir_ino, path, &attr)) != OK)
124433d6423SLionel Sambuc 	return r;
125433d6423SLionel Sambuc 
126a99c939dSDavid van Moolenbroek   if (!IS_DIR(dir_ino))
127a99c939dSDavid van Moolenbroek 	return ENOTDIR;
128433d6423SLionel Sambuc 
129a99c939dSDavid van Moolenbroek   r = OK;
130a99c939dSDavid van Moolenbroek   if (!strcmp(name, "."))
131a99c939dSDavid van Moolenbroek 	get_inode(ino = dir_ino);
132a99c939dSDavid van Moolenbroek   else if (!strcmp(name, ".."))
133a99c939dSDavid van Moolenbroek 	r = go_up(path, dir_ino, &ino, &attr);
134433d6423SLionel Sambuc   else
135a99c939dSDavid van Moolenbroek 	r = go_down(path, dir_ino, name, &ino, &attr);
136433d6423SLionel Sambuc 
137433d6423SLionel Sambuc   if (r != OK)
138433d6423SLionel Sambuc 	return r;
139433d6423SLionel Sambuc 
140a99c939dSDavid van Moolenbroek   node->fn_ino_nr = INODE_NR(ino);
141a99c939dSDavid van Moolenbroek   node->fn_mode = get_mode(ino, attr.a_mode);
142a99c939dSDavid van Moolenbroek   node->fn_size = attr.a_size;
143a99c939dSDavid van Moolenbroek   node->fn_uid = sffs_params->p_uid;
144a99c939dSDavid van Moolenbroek   node->fn_gid = sffs_params->p_gid;
145a99c939dSDavid van Moolenbroek   node->fn_dev = NO_DEV;
146a99c939dSDavid van Moolenbroek 
147a99c939dSDavid van Moolenbroek   *is_mountpt = FALSE;
148433d6423SLionel Sambuc 
149433d6423SLionel Sambuc   return OK;
150433d6423SLionel Sambuc }
151