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. 4 * 5 * Created (based on MFS): 6 * June 2011 (Evgeniy Ivanov) 7 */ 8 9 #include "fs.h" 10 11 #include <sys/cdefs.h> 12 #include <sys/stat.h> 13 #include <sys/types.h> 14 15 /*===========================================================================* 16 * fs_lookup * 17 *===========================================================================*/ 18 int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node, 19 int *is_mountpt) 20 { 21 struct puffs_node *pn, *pn_dir; 22 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); 27 } 28 29 if (!S_ISDIR(pn_dir->pn_va.va_mode)) 30 return ENOTDIR; 31 32 if ((pn = advance(pn_dir, name)) == NULL) 33 return err_code; 34 35 pn->pn_count++; /* open pnode */ 36 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; 43 44 *is_mountpt = pn->pn_mountpoint; 45 46 return OK; 47 } 48 49 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 */ 56 ) 57 { 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. 62 */ 63 struct puffs_node *pn; 64 65 struct puffs_newinfo pni; 66 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}}; 70 71 enum vtype node_vtype; 72 voff_t size; 73 dev_t rdev; 74 int error; 75 76 assert(pn_dir != NULL); 77 78 err_code = OK; 79 80 /* If 'string' is empty, return an error. */ 81 if (string[0] == '\0') { 82 err_code = ENOENT; 83 return(NULL); 84 } 85 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); 90 } 91 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? 98 * 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 104 */ 105 return pn_dir; 106 } 107 108 pni.pni_cookie = (void** )&pn; 109 pni.pni_vtype = &node_vtype; 110 pni.pni_size = &size; 111 pni.pni_rdev = &rdev; 112 113 pcn.pcn_namelen = strlen(string); 114 assert(pcn.pcn_namelen <= MAXPATHLEN); 115 strcpy(pcn.pcn_name, string); 116 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); 122 } 123 } 124 125 /* lookup *must* be present */ 126 error = global_pu->pu_ops.puffs_node_lookup(global_pu, pn_dir, &pni, &pcn); 127 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; 135 136 /* 137 * did we get a new node or a 138 * recycled node? 139 */ 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); 145 } 146 } 147 148 if (error) { 149 err_code = error < 0 ? error : -error; 150 return(NULL); 151 } 152 153 err_code = OK; 154 155 assert(pn != NULL); 156 157 return(pn); 158 } 159