Changeset 1313ee9 in mainline for uspace/lib/libfs/libfs.c
- Timestamp:
- 2009-12-13T15:17:08Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 963dd91
- Parents:
- fc6dd18
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/libfs/libfs.c
rfc6dd18 r1313ee9 1 1 /* 2 * Copyright (c) 2009 Jakub Jermar 2 * Copyright (c) 2009 Jakub Jermar 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 /** @addtogroup libfs 29 /** @addtogroup libfs 30 30 * @{ 31 */ 31 */ 32 32 /** 33 33 * @file 34 * Glue code which is common od to all FS implementations.35 */ 36 37 #include "libfs.h" 34 * Glue code which is common to all FS implementations. 35 */ 36 37 #include "libfs.h" 38 38 #include "../../srv/vfs/vfs.h" 39 39 #include <errno.h> … … 67 67 * code. 68 68 * 69 * @param vfs_phone Open phone for communication with VFS. 70 * @param reg File system registration structure. It will be 71 * initialized by this function. 72 * @param info VFS info structure supplied by the file system 73 * implementation. 74 * @param conn Connection fibril for handling all calls originating in 75 * VFS. 76 * 77 * @return EOK on success or a non-zero error code on errror. 69 * @param vfs_phone Open phone for communication with VFS. 70 * @param reg File system registration structure. It will be 71 * initialized by this function. 72 * @param info VFS info structure supplied by the file system 73 * implementation. 74 * @param conn Connection fibril for handling all calls originating in 75 * VFS. 76 * 77 * @return EOK on success or a non-zero error code on errror. 78 * 78 79 */ 79 80 int fs_register(int vfs_phone, fs_reg_t *reg, vfs_info_t *info, … … 87 88 ipc_call_t answer; 88 89 aid_t req = async_send_0(vfs_phone, VFS_IN_REGISTER, &answer); 89 90 90 91 /* 91 92 * Send our VFS info structure to VFS. … … 96 97 return rc; 97 98 } 98 99 99 100 /* 100 101 * Ask VFS for callback connection. 101 102 */ 102 103 ipc_connect_to_me(vfs_phone, 0, 0, 0, ®->vfs_phonehash); 103 104 104 105 /* 105 106 * Allocate piece of address space for PLB. … … 110 111 return ENOMEM; 111 112 } 112 113 113 114 /* 114 115 * Request sharing the Path Lookup Buffer with VFS. … … 136 137 */ 137 138 async_set_client_connection(conn); 138 139 139 140 return IPC_GET_RETVAL(answer); 140 141 } … … 154 155 int res; 155 156 ipcarg_t rc; 156 157 157 158 ipc_call_t call; 158 159 ipc_callid_t callid; 159 160 /* accept the phone */160 161 /* Accept the phone */ 161 162 callid = async_get_call(&call); 162 163 int mountee_phone = (int)IPC_GET_ARG1(call); 163 164 if ((IPC_GET_METHOD(call) != IPC_M_CONNECTION_CLONE) || 164 mountee_phone < 0) {165 (mountee_phone < 0)) { 165 166 ipc_answer_0(callid, EINVAL); 166 167 ipc_answer_0(rid, EINVAL); 167 168 return; 168 169 } 169 ipc_answer_0(callid, EOK); /* acknowledge the mountee_phone */ 170 171 /* Acknowledge the mountee_phone */ 172 ipc_answer_0(callid, EOK); 170 173 171 174 res = async_data_write_receive(&callid, NULL); … … 176 179 return; 177 180 } 178 181 179 182 fs_node_t *fn; 180 183 res = ops->node_get(&fn, mp_dev_handle, mp_fs_index); 181 if ( res != EOK || !fn) {184 if ((res != EOK) || (!fn)) { 182 185 ipc_hangup(mountee_phone); 183 186 ipc_answer_0(callid, combine_rc(res, ENOENT)); … … 185 188 return; 186 189 } 187 190 188 191 if (fn->mp_data.mp_active) { 189 192 ipc_hangup(mountee_phone); … … 193 196 return; 194 197 } 195 198 196 199 rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME); 197 200 if (rc != EOK) { … … 215 218 fn->mp_data.phone = mountee_phone; 216 219 } 220 217 221 /* 218 222 * Do not release the FS node so that it stays in memory. … … 238 242 ipc_call_t *request) 239 243 { 240 unsigned first = IPC_GET_ARG1(*request);241 unsigned last = IPC_GET_ARG2(*request);242 unsigned next = first;244 unsigned int first = IPC_GET_ARG1(*request); 245 unsigned int last = IPC_GET_ARG2(*request); 246 unsigned int next = first; 243 247 dev_handle_t dev_handle = IPC_GET_ARG3(*request); 244 248 int lflag = IPC_GET_ARG4(*request); 245 fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */249 fs_index_t index = IPC_GET_ARG5(*request); 246 250 char component[NAME_MAX + 1]; 247 251 int len; 248 252 int rc; 249 253 250 254 if (last < next) 251 255 last += PLB_SIZE; 252 256 253 257 fs_node_t *par = NULL; 254 258 fs_node_t *cur = NULL; 255 259 fs_node_t *tmp = NULL; 256 260 257 261 rc = ops->root_get(&cur, dev_handle); 258 262 on_error(rc, goto out_with_answer); 259 263 260 264 if (cur->mp_data.mp_active) { 261 265 ipc_forward_slow(rid, cur->mp_data.phone, VFS_OUT_LOOKUP, … … 265 269 return; 266 270 } 267 271 272 /* Eat slash */ 268 273 if (ops->plb_get_char(next) == '/') 269 next++; /* eat slash */274 next++; 270 275 271 276 while (next <= last) { 272 277 bool has_children; 273 278 274 279 rc = ops->has_children(&has_children, cur); 275 280 on_error(rc, goto out_with_answer); 276 281 if (!has_children) 277 282 break; 278 279 /* collect the component */283 284 /* Collect the component */ 280 285 len = 0; 281 while ((next <= last) && 286 while ((next <= last) && (ops->plb_get_char(next) != '/')) { 282 287 if (len + 1 == NAME_MAX) { 283 /* component length overflow */288 /* Component length overflow */ 284 289 ipc_answer_0(rid, ENAMETOOLONG); 285 290 goto out; 286 291 } 287 292 component[len++] = ops->plb_get_char(next); 288 next++; /* process next character */ 293 /* Process next character */ 294 next++; 289 295 } 290 296 291 297 assert(len); 292 298 component[len] = '\0'; 293 next++; /* eat slash */ 294 295 /* match the component */ 299 /* Eat slash */ 300 next++; 301 302 /* Match the component */ 296 303 rc = ops->match(&tmp, cur, component); 297 304 on_error(rc, goto out_with_answer); 298 299 if ( tmp && tmp->mp_data.mp_active) {305 306 if ((tmp) && (tmp->mp_data.mp_active)) { 300 307 if (next > last) 301 308 next = last = first; 302 309 else 303 310 next--; 304 311 305 312 ipc_forward_slow(rid, tmp->mp_data.phone, 306 313 VFS_OUT_LOOKUP, next, last, tmp->mp_data.dev_handle, … … 312 319 return; 313 320 } 314 315 /* handle miss: match amongst siblings */321 322 /* Handle miss: match amongst siblings */ 316 323 if (!tmp) { 317 324 if (next <= last) { 318 /* there are unprocessed components */325 /* There are unprocessed components */ 319 326 ipc_answer_0(rid, ENOENT); 320 327 goto out; 321 328 } 322 /* miss in the last component */ 323 if (lflag & (L_CREATE | L_LINK)) { 324 /* request to create a new link */ 329 330 /* Miss in the last component */ 331 if (lflag & (L_CREATE | L_LINK)) { 332 /* Request to create a new link */ 325 333 if (!ops->is_directory(cur)) { 326 334 ipc_answer_0(rid, ENOTDIR); 327 335 goto out; 328 336 } 337 329 338 fs_node_t *fn; 330 339 if (lflag & L_CREATE) … … 335 344 index); 336 345 on_error(rc, goto out_with_answer); 346 337 347 if (fn) { 338 348 rc = ops->link(cur, fn, component); … … 349 359 (void) ops->node_put(fn); 350 360 } 351 } else {361 } else 352 362 ipc_answer_0(rid, ENOSPC); 353 }363 354 364 goto out; 355 } 365 } 366 356 367 ipc_answer_0(rid, ENOENT); 357 368 goto out; 358 369 } 359 370 360 371 if (par) { 361 372 rc = ops->node_put(par); 362 373 on_error(rc, goto out_with_answer); 363 374 } 364 365 /* descend one level */375 376 /* Descend one level */ 366 377 par = cur; 367 378 cur = tmp; 368 379 tmp = NULL; 369 380 } 370 371 /* handle miss: excessive components */381 382 /* Handle miss: excessive components */ 372 383 if (next <= last) { 373 384 bool has_children; 374 375 385 rc = ops->has_children(&has_children, cur); 376 386 on_error(rc, goto out_with_answer); 387 377 388 if (has_children) 378 389 goto skip_miss; 379 390 380 391 if (lflag & (L_CREATE | L_LINK)) { 381 392 if (!ops->is_directory(cur)) { … … 383 394 goto out; 384 395 } 385 386 /* collect next component */396 397 /* Collect next component */ 387 398 len = 0; 388 399 while (next <= last) { 389 400 if (ops->plb_get_char(next) == '/') { 390 /* more than one component */401 /* More than one component */ 391 402 ipc_answer_0(rid, ENOENT); 392 403 goto out; 393 404 } 405 394 406 if (len + 1 == NAME_MAX) { 395 /* component length overflow */407 /* Component length overflow */ 396 408 ipc_answer_0(rid, ENAMETOOLONG); 397 409 goto out; 398 410 } 411 399 412 component[len++] = ops->plb_get_char(next); 400 next++; /* process next character */ 413 /* Process next character */ 414 next++; 401 415 } 416 402 417 assert(len); 403 418 component[len] = '\0'; 404 419 405 420 fs_node_t *fn; 406 421 if (lflag & L_CREATE) … … 409 424 rc = ops->node_get(&fn, dev_handle, index); 410 425 on_error(rc, goto out_with_answer); 426 411 427 if (fn) { 412 428 rc = ops->link(cur, fn, component); … … 423 439 (void) ops->node_put(fn); 424 440 } 425 } else {441 } else 426 442 ipc_answer_0(rid, ENOSPC); 427 }443 428 444 goto out; 429 445 } 446 430 447 ipc_answer_0(rid, ENOENT); 431 448 goto out; 432 449 } 450 433 451 skip_miss: 434 435 /* handle hit */452 453 /* Handle hit */ 436 454 if (lflag & L_UNLINK) { 437 unsigned old_lnkcnt = ops->lnkcnt_get(cur);455 unsigned int old_lnkcnt = ops->lnkcnt_get(cur); 438 456 rc = ops->unlink(par, cur, component); 439 ipc_answer_5(rid, (ipcarg_t) rc, fs_handle, dev_handle,457 ipc_answer_5(rid, (ipcarg_t) rc, fs_handle, dev_handle, 440 458 ops->index_get(cur), ops->size_get(cur), old_lnkcnt); 441 459 goto out; 442 460 } 461 443 462 if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) || 444 463 (lflag & L_LINK)) { … … 446 465 goto out; 447 466 } 467 448 468 if ((lflag & L_FILE) && (ops->is_directory(cur))) { 449 469 ipc_answer_0(rid, EISDIR); 450 470 goto out; 451 471 } 472 452 473 if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) { 453 474 ipc_answer_0(rid, ENOTDIR); 454 475 goto out; 455 476 } 456 477 457 478 out_with_answer: 479 458 480 if (rc == EOK) { 459 ipc_answer_5(rid, EOK, fs_handle, dev_handle, 481 if (lflag & L_OPEN) 482 rc = ops->node_open(cur); 483 484 ipc_answer_5(rid, rc, fs_handle, dev_handle, 460 485 ops->index_get(cur), ops->size_get(cur), 461 486 ops->lnkcnt_get(cur)); 462 } else {487 } else 463 488 ipc_answer_0(rid, rc); 464 } 465 489 466 490 out: 491 467 492 if (par) 468 493 (void) ops->node_put(par); 494 469 495 if (cur) 470 496 (void) ops->node_put(cur); 497 471 498 if (tmp) 472 499 (void) ops->node_put(tmp); … … 478 505 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 479 506 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 507 480 508 fs_node_t *fn; 481 int rc; 482 483 rc = ops->node_get(&fn, dev_handle, index); 509 int rc = ops->node_get(&fn, dev_handle, index); 484 510 on_error(rc, answer_and_return(rid, rc)); 485 511 486 512 ipc_callid_t callid; 487 513 size_t size; 488 if (!async_data_read_receive(&callid, &size) || 489 size != sizeof(struct stat)) { 514 if ((!async_data_read_receive(&callid, &size)) || 515 (size != sizeof(struct stat))) { 516 ops->node_put(fn); 490 517 ipc_answer_0(callid, EINVAL); 491 518 ipc_answer_0(rid, EINVAL); 492 519 return; 493 520 } 494 521 495 522 struct stat stat; 496 523 memset(&stat, 0, sizeof(struct stat)); … … 499 526 stat.dev_handle = dev_handle; 500 527 stat.index = index; 501 stat.lnkcnt = ops->lnkcnt_get(fn); 528 stat.lnkcnt = ops->lnkcnt_get(fn); 502 529 stat.is_file = ops->is_file(fn); 530 stat.is_directory = ops->is_directory(fn); 503 531 stat.size = ops->size_get(fn); 504 532 stat.device = ops->device_get(fn); 533 534 ops->node_put(fn); 535 505 536 async_data_read_finalize(callid, &stat, sizeof(struct stat)); 506 537 ipc_answer_0(rid, EOK); … … 509 540 /** Open VFS triplet. 510 541 * 511 * @param ops 512 * 513 * @param rid 514 * @param request 542 * @param ops libfs operations structure with function pointers to 543 * file system implementation 544 * @param rid Request ID of the VFS_OUT_OPEN_NODE request. 545 * @param request VFS_OUT_OPEN_NODE request data itself. 515 546 * 516 547 */ … … 531 562 } 532 563 533 ipc_answer_3(rid, EOK, ops->size_get(fn), ops->lnkcnt_get(fn), 564 rc = ops->node_open(fn); 565 ipc_answer_3(rid, rc, ops->size_get(fn), ops->lnkcnt_get(fn), 534 566 (ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0)); 535 567
Note:
See TracChangeset
for help on using the changeset viewer.