xref: /minix3/minix/lib/libpuffs/path.c (revision ba736c796854b82e29da17267614db0a449419db)
1*ba736c79SDavid van Moolenbroek /*
2*ba736c79SDavid van Moolenbroek  * This file contains the procedures that look up path names in the directory
3*ba736c79SDavid van Moolenbroek  * system and determine the pnode number that goes with a given path name.
4*ba736c79SDavid van Moolenbroek  *
5*ba736c79SDavid van Moolenbroek  * Created (based on MFS):
6*ba736c79SDavid van Moolenbroek  *   June 2011 (Evgeniy Ivanov)
7*ba736c79SDavid van Moolenbroek  */
8*ba736c79SDavid van Moolenbroek 
9*ba736c79SDavid van Moolenbroek #include "fs.h"
10*ba736c79SDavid van Moolenbroek 
11*ba736c79SDavid van Moolenbroek #include <sys/cdefs.h>
12*ba736c79SDavid van Moolenbroek #include <sys/stat.h>
13*ba736c79SDavid van Moolenbroek #include <sys/types.h>
14*ba736c79SDavid van Moolenbroek 
15*ba736c79SDavid van Moolenbroek /*===========================================================================*
16*ba736c79SDavid van Moolenbroek  *				fs_lookup				     *
17*ba736c79SDavid van Moolenbroek  *===========================================================================*/
fs_lookup(ino_t dir_nr,char * name,struct fsdriver_node * node,int * is_mountpt)18*ba736c79SDavid van Moolenbroek int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
19*ba736c79SDavid van Moolenbroek 	int *is_mountpt)
20*ba736c79SDavid van Moolenbroek {
21*ba736c79SDavid van Moolenbroek   struct puffs_node *pn, *pn_dir;
22*ba736c79SDavid van Moolenbroek 
23*ba736c79SDavid van Moolenbroek   /* Find the pnode of the directory node. */
24*ba736c79SDavid van Moolenbroek   if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL) {
25*ba736c79SDavid van Moolenbroek 	lpuffs_debug("nodewalk failed\n");
26*ba736c79SDavid van Moolenbroek 	return(EINVAL);
27*ba736c79SDavid van Moolenbroek   }
28*ba736c79SDavid van Moolenbroek 
29*ba736c79SDavid van Moolenbroek   if (!S_ISDIR(pn_dir->pn_va.va_mode))
30*ba736c79SDavid van Moolenbroek 	return ENOTDIR;
31*ba736c79SDavid van Moolenbroek 
32*ba736c79SDavid van Moolenbroek   if ((pn = advance(pn_dir, name)) == NULL)
33*ba736c79SDavid van Moolenbroek 	return err_code;
34*ba736c79SDavid van Moolenbroek 
35*ba736c79SDavid van Moolenbroek   pn->pn_count++; /* open pnode */
36*ba736c79SDavid van Moolenbroek 
37*ba736c79SDavid van Moolenbroek   node->fn_ino_nr = pn->pn_va.va_fileid;
38*ba736c79SDavid van Moolenbroek   node->fn_mode = pn->pn_va.va_mode;
39*ba736c79SDavid van Moolenbroek   node->fn_size = pn->pn_va.va_size;
40*ba736c79SDavid van Moolenbroek   node->fn_uid = pn->pn_va.va_uid;
41*ba736c79SDavid van Moolenbroek   node->fn_gid = pn->pn_va.va_gid;
42*ba736c79SDavid van Moolenbroek   node->fn_dev = pn->pn_va.va_rdev;
43*ba736c79SDavid van Moolenbroek 
44*ba736c79SDavid van Moolenbroek   *is_mountpt = pn->pn_mountpoint;
45*ba736c79SDavid van Moolenbroek 
46*ba736c79SDavid van Moolenbroek   return OK;
47*ba736c79SDavid van Moolenbroek }
48*ba736c79SDavid van Moolenbroek 
49*ba736c79SDavid van Moolenbroek 
50*ba736c79SDavid van Moolenbroek /*===========================================================================*
51*ba736c79SDavid van Moolenbroek  *				advance					     *
52*ba736c79SDavid van Moolenbroek  *===========================================================================*/
advance(struct puffs_node * pn_dir,char string[NAME_MAX+1])53*ba736c79SDavid van Moolenbroek struct puffs_node *advance(
54*ba736c79SDavid van Moolenbroek 	struct puffs_node *pn_dir,	/* pnode for directory to be searched */
55*ba736c79SDavid van Moolenbroek 	char string[NAME_MAX + 1]	/* component name to look for */
56*ba736c79SDavid van Moolenbroek )
57*ba736c79SDavid van Moolenbroek {
58*ba736c79SDavid van Moolenbroek /* Given a directory and a component of a path, look up the component in
59*ba736c79SDavid van Moolenbroek  * the directory, find the pnode, open it, and return a pointer to its pnode
60*ba736c79SDavid van Moolenbroek  * slot.
61*ba736c79SDavid van Moolenbroek  * TODO: instead of string, should get pcn.
62*ba736c79SDavid van Moolenbroek  */
63*ba736c79SDavid van Moolenbroek   struct puffs_node *pn;
64*ba736c79SDavid van Moolenbroek 
65*ba736c79SDavid van Moolenbroek   struct puffs_newinfo pni;
66*ba736c79SDavid van Moolenbroek 
67*ba736c79SDavid van Moolenbroek   struct puffs_kcn pkcnp;
68*ba736c79SDavid van Moolenbroek   PUFFS_MAKECRED(pcr, &global_kcred);
69*ba736c79SDavid van Moolenbroek   struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
70*ba736c79SDavid van Moolenbroek 
71*ba736c79SDavid van Moolenbroek   enum vtype node_vtype;
72*ba736c79SDavid van Moolenbroek   voff_t size;
73*ba736c79SDavid van Moolenbroek   dev_t rdev;
74*ba736c79SDavid van Moolenbroek   int error;
75*ba736c79SDavid van Moolenbroek 
76*ba736c79SDavid van Moolenbroek   assert(pn_dir != NULL);
77*ba736c79SDavid van Moolenbroek 
78*ba736c79SDavid van Moolenbroek   err_code = OK;
79*ba736c79SDavid van Moolenbroek 
80*ba736c79SDavid van Moolenbroek   /* If 'string' is empty, return an error. */
81*ba736c79SDavid van Moolenbroek   if (string[0] == '\0') {
82*ba736c79SDavid van Moolenbroek 	err_code = ENOENT;
83*ba736c79SDavid van Moolenbroek 	return(NULL);
84*ba736c79SDavid van Moolenbroek   }
85*ba736c79SDavid van Moolenbroek 
86*ba736c79SDavid van Moolenbroek   /* If dir has been removed return ENOENT. */
87*ba736c79SDavid van Moolenbroek   if (pn_dir->pn_va.va_nlink == NO_LINK) {
88*ba736c79SDavid van Moolenbroek 	err_code = ENOENT;
89*ba736c79SDavid van Moolenbroek 	return(NULL);
90*ba736c79SDavid van Moolenbroek   }
91*ba736c79SDavid van Moolenbroek 
92*ba736c79SDavid van Moolenbroek   if (strcmp(string, ".") == 0) {
93*ba736c79SDavid van Moolenbroek 	/* Otherwise we will fall into trouble: path for pnode to be looked up
94*ba736c79SDavid van Moolenbroek 	 * will be parent path (same pnode as the one to be looked up) +
95*ba736c79SDavid van Moolenbroek 	 * requested path. E.g. after several lookups we might get advance
96*ba736c79SDavid van Moolenbroek 	 * for "." with parent path "/././././././././.".
97*ba736c79SDavid van Moolenbroek 	 * FIXME: how is ".." handled then?
98*ba736c79SDavid van Moolenbroek 	 *
99*ba736c79SDavid van Moolenbroek 	 * Another problem is that after lookup pnode will be added
100*ba736c79SDavid van Moolenbroek 	 * to the pu_pnodelst, which already contains pnode instance for this
101*ba736c79SDavid van Moolenbroek 	 * pnode. It will cause lot of troubles.
102*ba736c79SDavid van Moolenbroek 	 * FIXME: check if this is actually correct, because if it is, we are
103*ba736c79SDavid van Moolenbroek 	 * in lots of trouble; there are many ways to reach already-open pnodes
104*ba736c79SDavid van Moolenbroek 	 */
105*ba736c79SDavid van Moolenbroek 	return pn_dir;
106*ba736c79SDavid van Moolenbroek   }
107*ba736c79SDavid van Moolenbroek 
108*ba736c79SDavid van Moolenbroek   pni.pni_cookie = (void** )&pn;
109*ba736c79SDavid van Moolenbroek   pni.pni_vtype = &node_vtype;
110*ba736c79SDavid van Moolenbroek   pni.pni_size = &size;
111*ba736c79SDavid van Moolenbroek   pni.pni_rdev = &rdev;
112*ba736c79SDavid van Moolenbroek 
113*ba736c79SDavid van Moolenbroek   pcn.pcn_namelen = strlen(string);
114*ba736c79SDavid van Moolenbroek   assert(pcn.pcn_namelen <= MAXPATHLEN);
115*ba736c79SDavid van Moolenbroek   strcpy(pcn.pcn_name, string);
116*ba736c79SDavid van Moolenbroek 
117*ba736c79SDavid van Moolenbroek   if (buildpath) {
118*ba736c79SDavid van Moolenbroek 	if (puffs_path_pcnbuild(global_pu, &pcn, pn_dir) != 0) {
119*ba736c79SDavid van Moolenbroek 		lpuffs_debug("pathbuild error\n");
120*ba736c79SDavid van Moolenbroek 		err_code = ENOENT;
121*ba736c79SDavid van Moolenbroek 		return(NULL);
122*ba736c79SDavid van Moolenbroek 	}
123*ba736c79SDavid van Moolenbroek   }
124*ba736c79SDavid van Moolenbroek 
125*ba736c79SDavid van Moolenbroek   /* lookup *must* be present */
126*ba736c79SDavid van Moolenbroek   error = global_pu->pu_ops.puffs_node_lookup(global_pu, pn_dir, &pni, &pcn);
127*ba736c79SDavid van Moolenbroek 
128*ba736c79SDavid van Moolenbroek   if (buildpath) {
129*ba736c79SDavid van Moolenbroek 	if (error) {
130*ba736c79SDavid van Moolenbroek 		global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
131*ba736c79SDavid van Moolenbroek 		err_code = ENOENT;
132*ba736c79SDavid van Moolenbroek 		return(NULL);
133*ba736c79SDavid van Moolenbroek 	} else {
134*ba736c79SDavid van Moolenbroek 		struct puffs_node *_pn;
135*ba736c79SDavid van Moolenbroek 
136*ba736c79SDavid van Moolenbroek 		/*
137*ba736c79SDavid van Moolenbroek 		 * did we get a new node or a
138*ba736c79SDavid van Moolenbroek 		 * recycled node?
139*ba736c79SDavid van Moolenbroek 		 */
140*ba736c79SDavid van Moolenbroek 		_pn = PU_CMAP(global_pu, pn);
141*ba736c79SDavid van Moolenbroek 		if (_pn->pn_po.po_path == NULL)
142*ba736c79SDavid van Moolenbroek 			_pn->pn_po = pcn.pcn_po_full;
143*ba736c79SDavid van Moolenbroek 		else
144*ba736c79SDavid van Moolenbroek 			global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
145*ba736c79SDavid van Moolenbroek 	}
146*ba736c79SDavid van Moolenbroek   }
147*ba736c79SDavid van Moolenbroek 
148*ba736c79SDavid van Moolenbroek   if (error) {
149*ba736c79SDavid van Moolenbroek 	err_code = error < 0 ? error : -error;
150*ba736c79SDavid van Moolenbroek 	return(NULL);
151*ba736c79SDavid van Moolenbroek   }
152*ba736c79SDavid van Moolenbroek 
153*ba736c79SDavid van Moolenbroek   err_code = OK;
154*ba736c79SDavid van Moolenbroek 
155*ba736c79SDavid van Moolenbroek   assert(pn != NULL);
156*ba736c79SDavid van Moolenbroek 
157*ba736c79SDavid van Moolenbroek   return(pn);
158*ba736c79SDavid van Moolenbroek }
159