xref: /minix/minix/lib/libsffs/lookup.c (revision 0a6a1f1d)
1 /* This file provides path-to-inode lookup functionality.
2  *
3  * The entry points into this file are:
4  *   do_lookup		perform the LOOKUP file system call
5  *
6  * Created:
7  *   April 2009 (D.C. van Moolenbroek)
8  */
9 
10 #include "inc.h"
11 
12 /*===========================================================================*
13  *				go_up					     *
14  *===========================================================================*/
15 static int go_up(
16 	char path[PATH_MAX],    /* path to take the last part from */
17 	struct inode *ino,      /* inode of the current directory */
18 	struct inode **res_ino, /* place to store resulting inode */
19 	struct sffs_attr *attr  /* place to store inode attributes */
20 )
21 {
22 /* Given an inode, progress into the parent directory.
23  */
24   struct inode *parent;
25   int r;
26 
27   pop_path(path);
28 
29   parent = ino->i_parent;
30   assert(parent != NULL);
31 
32   if ((r = verify_path(path, parent, attr, NULL)) != OK)
33 	return r;
34 
35   get_inode(parent);
36 
37   *res_ino = parent;
38 
39   return r;
40 }
41 
42 /*===========================================================================*
43  *				go_down					     *
44  *===========================================================================*/
45 static int go_down(
46 	char path[PATH_MAX],    /* path to add the name to */
47 	struct inode *parent,   /* inode of the current directory */
48 	char *name,             /* name of the directory entry */
49 	struct inode **res_ino, /* place to store resulting inode */
50 	struct sffs_attr *attr  /* place to store inode attributes */
51 )
52 {
53 /* Given a directory inode and a name, progress into a directory entry.
54  */
55   struct inode *ino;
56   int r, stale = 0;
57 
58   if ((r = push_path(path, name)) != OK)
59 	return r;
60 
61   dprintf(("%s: go_down: name '%s', path now '%s'\n", sffs_name, name, path));
62 
63   ino = lookup_dentry(parent, name);
64 
65   dprintf(("%s: lookup_dentry('%s') returned %p\n", sffs_name, name, ino));
66 
67   if (ino != NULL)
68 	r = verify_path(path, ino, attr, &stale);
69   else
70 	r = sffs_table->t_getattr(path, attr);
71 
72   dprintf(("%s: path query returned %d\n", sffs_name, r));
73 
74   if (r != OK) {
75 	if (ino != NULL) {
76 		put_inode(ino);
77 
78 		ino = NULL;
79 	}
80 
81 	if (!stale)
82 		return r;
83   }
84 
85   dprintf(("%s: name '%s'\n", sffs_name, name));
86 
87   if (ino == NULL) {
88 	if ((ino = get_free_inode()) == NULL)
89 		return ENFILE;
90 
91 	dprintf(("%s: inode %p ref %d\n", sffs_name, ino, ino->i_ref));
92 
93 	ino->i_flags = MODE_TO_DIRFLAG(attr->a_mode);
94 
95 	add_dentry(parent, name, ino);
96   }
97 
98   *res_ino = ino;
99   return OK;
100 }
101 
102 /*===========================================================================*
103  *				do_lookup				     *
104  *===========================================================================*/
105 int do_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
106 	int *is_mountpt)
107 {
108 /* Resolve a path string to an inode.
109  */
110   struct inode *dir_ino, *ino = NULL;
111   struct sffs_attr attr;
112   char path[PATH_MAX];
113   int r;
114 
115   dprintf(("%s: lookup: got query for %"PRIu64", '%s'\n",
116 	sffs_name, dir_nr, name));
117 
118   if ((dir_ino = find_inode(dir_nr)) == NULL)
119 	return EINVAL;
120 
121   attr.a_mask = SFFS_ATTR_MODE | SFFS_ATTR_SIZE;
122 
123   if ((r = verify_inode(dir_ino, path, &attr)) != OK)
124 	return r;
125 
126   if (!IS_DIR(dir_ino))
127 	return ENOTDIR;
128 
129   r = OK;
130   if (!strcmp(name, "."))
131 	get_inode(ino = dir_ino);
132   else if (!strcmp(name, ".."))
133 	r = go_up(path, dir_ino, &ino, &attr);
134   else
135 	r = go_down(path, dir_ino, name, &ino, &attr);
136 
137   if (r != OK)
138 	return r;
139 
140   node->fn_ino_nr = INODE_NR(ino);
141   node->fn_mode = get_mode(ino, attr.a_mode);
142   node->fn_size = attr.a_size;
143   node->fn_uid = sffs_params->p_uid;
144   node->fn_gid = sffs_params->p_gid;
145   node->fn_dev = NO_DEV;
146 
147   *is_mountpt = FALSE;
148 
149   return OK;
150 }
151