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