Changeset bf9dc4e2 in mainline for uspace/srv/vfs/vfs_lookup.c
- Timestamp:
- 2013-07-28T19:32:36Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 778d26d
- Parents:
- d60ce4a
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_lookup.c
rd60ce4a rbf9dc4e2 46 46 #include <adt/list.h> 47 47 #include <vfs/canonify.h> 48 #include <dirent.h> 49 #include <assert.h> 50 51 #define DPRINTF(...) 48 52 49 53 #define min(a, b) ((a) < (b) ? (a) : (b)) … … 53 57 uint8_t *plb = NULL; 54 58 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, ...) 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 59 static int plb_insert_entry(plb_entry_t *entry, char *path, size_t *start, size_t len) 60 { 95 61 fibril_mutex_lock(&plb_mutex); 96 62 97 plb_entry_t entry; 98 link_initialize(&entry.plb_link); 99 entry.len = len; 63 link_initialize(&entry->plb_link); 64 entry->len = len; 100 65 101 66 size_t first; /* the first free index */ … … 138 103 */ 139 104 140 entry .index = first;141 entry .len = len;105 entry->index = first; 106 entry->len = len; 142 107 143 108 /* … … 145 110 * buffer. 146 111 */ 147 list_append(&entry .plb_link, &plb_entries);112 list_append(&entry->plb_link, &plb_entries); 148 113 149 114 fibril_mutex_unlock(&plb_mutex); … … 158 123 memcpy(plb, &path[cnt1], cnt2); 159 124 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 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 { 171 131 fibril_mutex_lock(&plb_mutex); 172 list_remove(&entry .plb_link);132 list_remove(&entry->plb_link); 173 133 /* 174 134 * Erasing the path from PLB will come handy for debugging purposes. 175 135 */ 136 size_t cnt1 = min(len, (PLB_SIZE - first) + 1); 137 size_t cnt2 = len - cnt1; 176 138 memset(&plb[first], 0, cnt1); 177 139 memset(plb, 0, cnt2); 178 140 fibril_mutex_unlock(&plb_mutex); 179 180 if ((int) rc < EOK) 181 return (int) rc; 182 183 if (!result) 184 return EOK; 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_triplet_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 char *slash = _strrchr(path, '/'); 176 if (slash && slash != path) { 177 if (slash[1] == 0) { 178 rc = EINVAL; 179 goto out; 180 } 181 182 memcpy(component, slash + 1, str_size(slash)); 183 *slash = 0; 184 185 rc = vfs_lookup_internal(base, path, L_DIRECTORY, &res); 186 if (rc != EOK) { 187 goto out; 188 } 189 base = &res.triplet; 190 191 *slash = '/'; 192 } else { 193 memcpy(component, path + 1, str_size(path)); 194 } 195 196 if (base->fs_handle != child->fs_handle || base->service_id != child->service_id) { 197 rc = EXDEV; 198 goto out; 199 } 200 201 async_exch_t *exch = vfs_exchange_grab(base->fs_handle); 202 aid_t req = async_send_3(exch, VFS_OUT_LINK, base->service_id, base->index, child->index, NULL); 203 204 rc = async_data_write_start(exch, component, str_size(component) + 1); 205 sysarg_t orig_rc; 206 async_wait_for(req, &orig_rc); 207 vfs_exchange_release(exch); 208 if (orig_rc != EOK) { 209 rc = orig_rc; 210 } 211 212 out: 213 DPRINTF("vfs_link_internal() with path '%s' returns %d\n", path, rc); 214 return rc; 215 } 216 217 /** Perform a path lookup. 218 * 219 * @param base The file from which to perform the lookup. 220 * @param path Path to be resolved; it must be a NULL-terminated 221 * string. 222 * @param lflag Flags to be used during lookup. 223 * @param result Empty structure where the lookup result will be stored. 224 * Can be NULL. 225 * 226 * @return EOK on success or an error code from errno.h. 227 * 228 */ 229 int vfs_lookup_internal(vfs_triplet_t *base, char *path, int lflag, vfs_lookup_res_t *result) 230 { 231 assert(base != NULL); 232 assert(path != NULL); 233 234 sysarg_t rc; 235 236 if (!base->fs_handle) { 237 rc = ENOENT; 238 goto out; 239 } 240 241 size_t len; 242 char *npath = canonify(path, &len); 243 if (!npath) { 244 rc = EINVAL; 245 goto out; 246 } 247 path = npath; 248 249 assert(path[0] == '/'); 250 251 size_t first; 252 253 plb_entry_t entry; 254 rc = plb_insert_entry(&entry, path, &first, len); 255 if (rc != EOK) { 256 goto out; 257 } 258 259 ipc_call_t answer; 260 async_exch_t *exch = vfs_exchange_grab(base->fs_handle); 261 aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) first, (sysarg_t) len, 262 (sysarg_t) base->service_id, (sysarg_t) base->index, (sysarg_t) lflag, &answer); 263 async_wait_for(req, &rc); 264 vfs_exchange_release(exch); 265 266 plb_clear_entry(&entry, first, len); 267 268 if ((int) rc < 0) { 269 goto out; 270 } 271 272 if (!result) { 273 rc = EOK; 274 goto out; 275 } 185 276 186 277 result->triplet.fs_handle = (fs_handle_t) rc; … … 197 288 else 198 289 result->type = VFS_NODE_UNKNOWN; 199 200 return EOK; 290 291 rc = EOK; 292 293 out: 294 DPRINTF("vfs_lookup_internal() with path '%s' returns %d\n", path, rc); 295 return rc; 201 296 } 202 297
Note:
See TracChangeset
for help on using the changeset viewer.