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