Changes in uspace/srv/vfs/vfs_lookup.c [5bcd5b7:3e6a98c5] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_lookup.c
r5bcd5b7 r3e6a98c5 46 46 #include <adt/list.h> 47 47 #include <vfs/canonify.h> 48 #include <dirent.h>49 #include <assert.h>50 51 #define DPRINTF(...)52 48 53 49 #define min(a, b) ((a) < (b) ? (a) : (b)) … … 57 53 uint8_t *plb = NULL; 58 54 59 static int plb_insert_entry(plb_entry_t *entry, char *path, size_t *start, size_t len) 55 /** Perform a path lookup. 56 * 57 * @param path Path to be resolved; it must be a NULL-terminated 58 * string. 59 * @param lflag Flags to be used during lookup. 60 * @param result Empty structure where the lookup result will be stored. 61 * Can be NULL. 62 * @param altroot If non-empty, will be used instead of rootfs as the root 63 * of the whole VFS tree. 64 * 65 * @return EOK on success or an error code from errno.h. 66 * 67 */ 68 int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result, 69 vfs_pair_t *altroot, ...) 60 70 { 71 vfs_pair_t *root; 72 73 if (altroot) 74 root = altroot; 75 else 76 root = &rootfs; 77 78 if (!root->fs_handle) 79 return ENOENT; 80 81 size_t len; 82 path = canonify(path, &len); 83 if (!path) 84 return EINVAL; 85 86 fs_index_t index = 0; 87 if (lflag & L_LINK) { 88 va_list ap; 89 90 va_start(ap, altroot); 91 index = va_arg(ap, fs_index_t); 92 va_end(ap); 93 } 94 61 95 fibril_mutex_lock(&plb_mutex); 62 96 63 link_initialize(&entry->plb_link); 64 entry->len = len; 97 plb_entry_t entry; 98 link_initialize(&entry.plb_link); 99 entry.len = len; 65 100 66 101 size_t first; /* the first free index */ … … 103 138 */ 104 139 105 entry ->index = first;106 entry ->len = len;140 entry.index = first; 141 entry.len = len; 107 142 108 143 /* … … 110 145 * buffer. 111 146 */ 112 list_append(&entry ->plb_link, &plb_entries);147 list_append(&entry.plb_link, &plb_entries); 113 148 114 149 fibril_mutex_unlock(&plb_mutex); … … 123 158 memcpy(plb, &path[cnt1], cnt2); 124 159 125 *start = first; 126 return EOK; 127 } 128 129 static void plb_clear_entry(plb_entry_t *entry, size_t first, size_t len) 130 { 160 ipc_call_t answer; 161 async_exch_t *exch = vfs_exchange_grab(root->fs_handle); 162 aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) first, 163 (sysarg_t) (first + len - 1) % PLB_SIZE, 164 (sysarg_t) root->service_id, (sysarg_t) lflag, (sysarg_t) index, 165 &answer); 166 167 sysarg_t rc; 168 async_wait_for(req, &rc); 169 vfs_exchange_release(exch); 170 131 171 fibril_mutex_lock(&plb_mutex); 132 list_remove(&entry ->plb_link);172 list_remove(&entry.plb_link); 133 173 /* 134 174 * Erasing the path from PLB will come handy for debugging purposes. 135 175 */ 136 size_t cnt1 = min(len, (PLB_SIZE - first) + 1);137 size_t cnt2 = len - cnt1;138 176 memset(&plb[first], 0, cnt1); 139 177 memset(plb, 0, cnt2); 140 178 fibril_mutex_unlock(&plb_mutex); 141 } 142 143 static char *_strrchr(char *path, int c) 144 { 145 char *res = NULL; 146 while (*path != 0) { 147 if (*path == c) { 148 res = path; 149 } 150 path++; 151 } 152 return res; 153 } 154 155 int vfs_link_internal(vfs_node_t *base, char *path, vfs_triplet_t *child) 156 { 157 assert(base != NULL); 158 assert(child != NULL); 159 assert(base->fs_handle); 160 assert(child->fs_handle); 161 assert(path != NULL); 162 163 vfs_lookup_res_t res; 164 char component[NAME_MAX + 1]; 165 int rc; 166 167 size_t len; 168 char *npath = canonify(path, &len); 169 if (!npath) { 170 rc = EINVAL; 171 goto out; 172 } 173 path = npath; 174 175 vfs_triplet_t *triplet; 176 177 char *slash = _strrchr(path, '/'); 178 if (slash && slash != path) { 179 if (slash[1] == 0) { 180 rc = EINVAL; 181 goto out; 182 } 183 184 memcpy(component, slash + 1, str_size(slash)); 185 *slash = 0; 186 187 rc = vfs_lookup_internal(base, path, L_DIRECTORY, &res); 188 if (rc != EOK) { 189 goto out; 190 } 191 triplet = &res.triplet; 192 193 *slash = '/'; 194 } else { 195 if (base->mount != NULL) { 196 rc = EINVAL; 197 goto out; 198 } 199 200 memcpy(component, path + 1, str_size(path)); 201 triplet = (vfs_triplet_t *) base; 202 } 203 204 if (triplet->fs_handle != child->fs_handle || triplet->service_id != child->service_id) { 205 rc = EXDEV; 206 goto out; 207 } 208 209 async_exch_t *exch = vfs_exchange_grab(triplet->fs_handle); 210 aid_t req = async_send_3(exch, VFS_OUT_LINK, triplet->service_id, triplet->index, child->index, NULL); 211 212 rc = async_data_write_start(exch, component, str_size(component) + 1); 213 sysarg_t orig_rc; 214 async_wait_for(req, &orig_rc); 215 vfs_exchange_release(exch); 216 if (orig_rc != EOK) { 217 rc = orig_rc; 218 } 219 220 out: 221 DPRINTF("vfs_link_internal() with path '%s' returns %d\n", path, rc); 222 return rc; 223 } 224 225 static int out_lookup(vfs_triplet_t *base, unsigned *pfirst, unsigned *plen, 226 int lflag, vfs_lookup_res_t *result) 227 { 228 assert(base); 229 assert(result); 230 231 sysarg_t rc; 232 ipc_call_t answer; 233 async_exch_t *exch = vfs_exchange_grab(base->fs_handle); 234 aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) *pfirst, (sysarg_t) *plen, 235 (sysarg_t) base->service_id, (sysarg_t) base->index, (sysarg_t) lflag, &answer); 236 async_wait_for(req, &rc); 237 vfs_exchange_release(exch); 238 239 if ((int) rc < 0) { 179 180 if ((int) rc < EOK) 240 181 return (int) rc; 241 } 242 243 unsigned last = *pfirst + *plen; 244 *pfirst = IPC_GET_ARG3(answer); 245 *plen = last - *pfirst; 182 183 if (!result) 184 return EOK; 246 185 247 186 result->triplet.fs_handle = (fs_handle_t) rc; 248 187 result->triplet.service_id = (service_id_t) IPC_GET_ARG1(answer); 249 188 result->triplet.index = (fs_index_t) IPC_GET_ARG2(answer); 250 result->size = (int64_t)(int32_t) IPC_GET_ARG4(answer); 251 result->type = IPC_GET_ARG5(answer); 189 result->size = 190 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(answer), IPC_GET_ARG4(answer)); 191 result->lnkcnt = (unsigned int) IPC_GET_ARG5(answer); 192 193 if (lflag & L_FILE) 194 result->type = VFS_NODE_FILE; 195 else if (lflag & L_DIRECTORY) 196 result->type = VFS_NODE_DIRECTORY; 197 else 198 result->type = VFS_NODE_UNKNOWN; 199 252 200 return EOK; 253 201 } 254 202 255 /** Perform a path lookup.256 *257 * @param base The file from which to perform the lookup.258 * @param path Path to be resolved; it must be a NULL-terminated259 * string.260 * @param lflag Flags to be used during lookup.261 * @param result Empty structure where the lookup result will be stored.262 * Can be NULL.263 *264 * @return EOK on success or an error code from errno.h.265 *266 */267 int vfs_lookup_internal(vfs_node_t *base, char *path, int lflag, vfs_lookup_res_t *result)268 {269 assert(base != NULL);270 assert(path != NULL);271 272 size_t len;273 int rc;274 char *npath = canonify(path, &len);275 if (!npath) {276 DPRINTF("vfs_lookup_internal() can't canonify path: %s\n", path);277 rc = EINVAL;278 return rc;279 }280 path = npath;281 282 assert(path[0] == '/');283 284 size_t first;285 286 plb_entry_t entry;287 rc = plb_insert_entry(&entry, path, &first, len);288 if (rc != EOK) {289 DPRINTF("vfs_lookup_internal() can't insert entry into PLB: %d\n", rc);290 return rc;291 }292 293 size_t next = first;294 size_t nlen = len;295 296 vfs_lookup_res_t res;297 298 /* Resolve path as long as there are mount points to cross. */299 while (nlen > 0) {300 while (base->mount != NULL) {301 if (lflag & L_DISABLE_MOUNTS) {302 rc = EXDEV;303 goto out;304 }305 306 base = base->mount;307 }308 309 rc = out_lookup((vfs_triplet_t *) base, &next, &nlen, lflag, &res);310 if (rc != EOK) {311 goto out;312 }313 314 if (nlen > 0) {315 base = vfs_node_peek(&res);316 if (base == NULL || base->mount == NULL) {317 rc = ENOENT;318 goto out;319 }320 if (lflag & L_DISABLE_MOUNTS) {321 rc = EXDEV;322 goto out;323 }324 }325 }326 327 assert(nlen == 0);328 rc = EOK;329 330 if (result != NULL) {331 /* The found file may be a mount point. Try to cross it. */332 if (!(lflag & L_MP)) {333 base = vfs_node_peek(&res);334 if (base != NULL && base->mount != NULL) {335 while (base->mount != NULL) {336 base = base->mount;337 }338 339 result->triplet = *(vfs_triplet_t *)base;340 result->type = base->type;341 result->size = base->size;342 goto out;343 }344 }345 346 __builtin_memcpy(result, &res, sizeof(vfs_lookup_res_t));347 }348 349 out:350 plb_clear_entry(&entry, first, len);351 DPRINTF("vfs_lookup_internal() with path '%s' returns %d\n", path, rc);352 return rc;353 }354 355 203 /** 356 204 * @}
Note:
See TracChangeset
for help on using the changeset viewer.