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