Changeset a8e9ab8d in mainline
- Timestamp:
- 2008-03-09T17:18:30Z (17 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4072980
- Parents:
- 2664838b
- Location:
- uspace
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/tester/vfs/vfs1.c
r2664838b ra8e9ab8d 96 96 closedir(dirp); 97 97 98 if (unlink("/mydir/myfile")) 98 if (rename("/mydir/myfile", "/mydir/yourfile")) 99 return "rename() failed.\n"; 100 101 if (!quiet) 102 printf("renamed /mydir/myfile to /mydir/yourfile\n"); 103 104 if (unlink("/mydir/yourfile")) 99 105 return "unlink() failed.\n"; 100 106 101 107 if (!quiet) 102 printf("unlinked file /mydir/ myfile\n");108 printf("unlinked file /mydir/yourfile\n"); 103 109 104 110 if (rmdir("/mydir")) -
uspace/lib/libc/generic/vfs/vfs.c
r2664838b ra8e9ab8d 469 469 } 470 470 471 int rename(const char *old, const char *new) 472 { 473 int res; 474 ipcarg_t rc; 475 aid_t req; 476 477 char *olda = absolutize(old); 478 if (!olda) 479 return ENOMEM; 480 size_t oldc_len; 481 char *oldc = canonify(olda, &oldc_len); 482 if (!oldc) { 483 free(olda); 484 return EINVAL; 485 } 486 char *newa = absolutize(new); 487 if (!newa) { 488 free(olda); 489 return ENOMEM; 490 } 491 size_t newc_len; 492 char *newc = canonify(newa, &newc_len); 493 if (!newc) { 494 free(olda); 495 free(newa); 496 return EINVAL; 497 } 498 499 futex_down(&vfs_phone_futex); 500 async_serialize_start(); 501 if (vfs_phone < 0) { 502 res = vfs_connect(); 503 if (res < 0) { 504 async_serialize_end(); 505 futex_up(&vfs_phone_futex); 506 free(olda); 507 free(newa); 508 return res; 509 } 510 } 511 req = async_send_0(vfs_phone, VFS_RENAME, NULL); 512 rc = ipc_data_write_start(vfs_phone, oldc, oldc_len); 513 if (rc != EOK) { 514 async_wait_for(req, NULL); 515 async_serialize_end(); 516 futex_up(&vfs_phone_futex); 517 free(olda); 518 free(newa); 519 return (int) rc; 520 } 521 rc = ipc_data_write_start(vfs_phone, newc, newc_len); 522 if (rc != EOK) { 523 async_wait_for(req, NULL); 524 async_serialize_end(); 525 futex_up(&vfs_phone_futex); 526 free(olda); 527 free(newa); 528 return (int) rc; 529 } 530 async_wait_for(req, &rc); 531 async_serialize_end(); 532 futex_up(&vfs_phone_futex); 533 free(olda); 534 free(newa); 535 return rc; 536 } 537 471 538 int chdir(const char *path) 472 539 { -
uspace/lib/libc/include/stdio.h
r2664838b ra8e9ab8d 68 68 #define fprintf(f, fmt, ...) printf(fmt, ##__VA_ARGS__) 69 69 70 extern int rename(const char *, const char *); 71 70 72 #endif 71 73 -
uspace/lib/libfs/libfs.c
r2664838b ra8e9ab8d 142 142 int dev_handle = IPC_GET_ARG3(*request); 143 143 int lflag = IPC_GET_ARG4(*request); 144 int index = IPC_GET_ARG5(*request); /* when L_LINK specified */ 144 145 145 146 if (last < next) … … 181 182 /* handle miss: match amongst siblings */ 182 183 if (!tmp) { 183 if ((next > last) && (lflag & L_CREATE)) { 184 /* no components left and L_CREATE specified */ 184 if (next <= last) { 185 /* there are unprocessed components */ 186 ipc_answer_0(rid, ENOENT); 187 return; 188 } 189 /* miss in the last component */ 190 if (lflag & (L_CREATE | L_LINK)) { 191 /* request to create a new link */ 185 192 if (!ops->is_directory(cur)) { 186 193 ipc_answer_0(rid, ENOTDIR); 187 194 return; 188 } 189 void *nodep = ops->create(lflag); 195 } 196 void *nodep; 197 if (lflag & L_CREATE) 198 nodep = ops->create(lflag); 199 else 200 nodep = ops->node_get(fs_handle, 201 dev_handle, index); 190 202 if (nodep) { 191 203 if (!ops->link(cur, nodep, component)) { 192 ops->destroy(nodep); 204 if (lflag & L_CREATE) 205 ops->destroy(nodep); 193 206 ipc_answer_0(rid, ENOSPC); 194 207 } else { 195 208 ipc_answer_5(rid, EOK, 196 209 fs_handle, dev_handle, 197 ops->index_get(nodep), 0, 210 ops->index_get(nodep), 211 ops->size_get(nodep), 198 212 ops->lnkcnt_get(nodep)); 199 213 } … … 202 216 } 203 217 return; 204 } 218 } else if (lflag & L_PARENT) { 219 /* return parent */ 220 ipc_answer_5(rid, EOK, fs_handle, dev_handle, 221 ops->index_get(cur), ops->size_get(cur), 222 ops->lnkcnt_get(cur)); 223 } 205 224 ipc_answer_0(rid, ENOENT); 206 225 return; … … 215 234 /* handle miss: excessive components */ 216 235 if (!tmp && next <= last) { 217 if (lflag & L_CREATE) {236 if (lflag & (L_CREATE | L_LINK)) { 218 237 if (!ops->is_directory(cur)) { 219 238 ipc_answer_0(rid, ENOTDIR); … … 240 259 len = 0; 241 260 242 void *nodep = ops->create(lflag); 261 void *nodep; 262 if (lflag & L_CREATE) 263 nodep = ops->create(lflag); 264 else 265 nodep = ops->node_get(fs_handle, dev_handle, 266 index); 243 267 if (nodep) { 244 268 if (!ops->link(cur, nodep, component)) { 245 ops->destroy(nodep); 269 if (lflag & L_CREATE) 270 ops->destroy(nodep); 246 271 ipc_answer_0(rid, ENOSPC); 247 272 } else { 248 273 ipc_answer_5(rid, EOK, 249 274 fs_handle, dev_handle, 250 ops->index_get(nodep), 0, 275 ops->index_get(nodep), 276 ops->size_get(nodep), 251 277 ops->lnkcnt_get(nodep)); 252 278 } … … 261 287 262 288 /* handle hit */ 263 if (lflag & L_DESTROY) { 289 if (lflag & L_PARENT) { 290 cur = par; 291 if (!cur) { 292 ipc_answer_0(rid, ENOENT); 293 return; 294 } 295 } 296 if (lflag & L_UNLINK) { 264 297 unsigned old_lnkcnt = ops->lnkcnt_get(cur); 265 298 int res = ops->unlink(par, cur); … … 268 301 return; 269 302 } 270 if ((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) { 303 if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) || 304 (lflag & L_LINK)) { 271 305 ipc_answer_0(rid, EEXIST); 272 306 return; -
uspace/lib/libfs/libfs.h
r2664838b ra8e9ab8d 44 44 typedef struct { 45 45 bool (* match)(void *, void *, const char *); 46 void * (* node_get)(int, int, unsigned long); 46 47 void * (* create)(int); 47 48 void (* destroy)(void *); -
uspace/srv/fs/tmpfs/tmpfs_ops.c
r2664838b ra8e9ab8d 71 71 /* Forward declarations of static functions. */ 72 72 static bool tmpfs_match(void *, void *, const char *); 73 static void *tmpfs_node_get(int, int, unsigned long); 73 74 static void *tmpfs_create_node(int); 74 75 static bool tmpfs_link_node(void *, void *, const char *); … … 125 126 libfs_ops_t tmpfs_libfs_ops = { 126 127 .match = tmpfs_match, 128 .node_get = tmpfs_node_get, 127 129 .create = tmpfs_create_node, 128 130 .destroy = tmpfs_destroy_node, … … 259 261 260 262 return !strcmp(namep->name, component); 263 } 264 265 void *tmpfs_node_get(int fs_handle, int dev_handle, unsigned long index) 266 { 267 link_t *lnk = hash_table_find(&dentries, &index); 268 if (!lnk) 269 return NULL; 270 return hash_table_get_instance(lnk, tmpfs_dentry_t, dh_link); 261 271 } 262 272 -
uspace/srv/vfs/vfs.c
r2664838b ra8e9ab8d 115 115 vfs_unlink(callid, &call); 116 116 break; 117 case VFS_RENAME: 118 vfs_rename(callid, &call); 119 break; 117 120 default: 118 121 ipc_answer_0(callid, ENOTSUP); -
uspace/srv/vfs/vfs.h
r2664838b ra8e9ab8d 167 167 #define L_CREATE 8 168 168 /** 169 * L_DESTROY is used to remove leaves from the file system namespace. This flag 169 * L_LINK is used for linking to an already existing nodes. 170 */ 171 #define L_LINK 16 172 /** 173 * L_UNLINK is used to remove leaves from the file system namespace. This flag 170 174 * cannot be passed directly by the client, but will be set by VFS during 171 175 * VFS_UNLINK. 172 176 */ 173 #define L_DESTROY 16 177 #define L_UNLINK 32 178 /** 179 * L_PARENT performs a lookup but returns the triplet of the parent node. 180 * This flag may not be combined with any other lookup flag. 181 */ 182 #define L_PARENT 64 174 183 175 184 typedef struct { … … 251 260 extern int fs_name_to_handle(char *, bool); 252 261 253 extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *, vfs_pair_t *); 262 extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *, vfs_pair_t *, 263 ...); 254 264 255 265 extern bool vfs_nodes_init(void); … … 280 290 extern void vfs_mkdir(ipc_callid_t, ipc_call_t *); 281 291 extern void vfs_unlink(ipc_callid_t, ipc_call_t *); 292 extern void vfs_rename(ipc_callid_t, ipc_call_t *); 282 293 283 294 #endif -
uspace/srv/vfs/vfs_lookup.c
r2664838b ra8e9ab8d 41 41 #include <errno.h> 42 42 #include <string.h> 43 #include <stdarg.h> 43 44 #include <bool.h> 44 45 #include <futex.h> … … 66 67 */ 67 68 int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result, 68 vfs_pair_t *altroot )69 vfs_pair_t *altroot, ...) 69 70 { 70 71 vfs_pair_t *root; … … 82 83 if (!path) 83 84 return EINVAL; 85 86 unsigned long index = 0; 87 if (lflag & L_LINK) { 88 va_list ap; 89 90 va_start(ap, altroot); 91 index = va_arg(ap, unsigned long); 92 va_end(ap); 93 } 84 94 85 95 futex_down(&plb_futex); … … 150 160 ipc_call_t answer; 151 161 int phone = vfs_grab_phone(root->fs_handle); 152 aid_t req = async_send_ 4(phone, VFS_LOOKUP, (ipcarg_t) first,162 aid_t req = async_send_5(phone, VFS_LOOKUP, (ipcarg_t) first, 153 163 (ipcarg_t) (first + len - 1) % PLB_SIZE, 154 (ipcarg_t) root->dev_handle, (ipcarg_t) lflag, &answer); 164 (ipcarg_t) root->dev_handle, (ipcarg_t) lflag, (ipcarg_t) index, 165 &answer); 155 166 vfs_release_phone(phone); 156 167 -
uspace/srv/vfs/vfs_ops.c
r2664838b ra8e9ab8d 36 36 */ 37 37 38 #include "vfs.h" 38 39 #include <ipc/ipc.h> 39 40 #include <async.h> … … 51 52 #include <assert.h> 52 53 #include <atomic.h> 53 #include "vfs.h"54 #include <vfs/canonify.h> 54 55 55 56 /* Forward declarations of static functions. */ … … 307 308 return; 308 309 } 309 310 /*311 * Now we are on the verge of accepting the path.312 *313 * There is one optimization we could do in the future: copy the path314 * directly into the PLB using some kind of a callback.315 */316 310 char *path = malloc(len + 1); 317 318 311 if (!path) { 319 312 ipc_answer_0(callid, ENOMEM); … … 321 314 return; 322 315 } 323 324 316 int rc; 325 317 if ((rc = ipc_data_write_finalize(callid, path, len))) { … … 630 622 return; 631 623 } 632 633 /*634 * Now we are on the verge of accepting the path.635 *636 * There is one optimization we could do in the future: copy the path637 * directly into the PLB using some kind of a callback.638 */639 624 char *path = malloc(len + 1); 640 641 625 if (!path) { 642 626 ipc_answer_0(callid, ENOMEM); … … 644 628 return; 645 629 } 646 647 630 int rc; 648 631 if ((rc = ipc_data_write_finalize(callid, path, len))) { … … 673 656 return; 674 657 } 675 676 /*677 * Now we are on the verge of accepting the path.678 *679 * There is one optimization we could do in the future: copy the path680 * directly into the PLB using some kind of a callback.681 */682 658 char *path = malloc(len + 1); 683 684 659 if (!path) { 685 660 ipc_answer_0(callid, ENOMEM); … … 687 662 return; 688 663 } 689 690 664 int rc; 691 665 if ((rc = ipc_data_write_finalize(callid, path, len))) { … … 699 673 lflag &= L_DIRECTORY; /* sanitize lflag */ 700 674 vfs_lookup_res_t lr; 701 rc = vfs_lookup_internal(path, lflag | L_ DESTROY, &lr, NULL);675 rc = vfs_lookup_internal(path, lflag | L_UNLINK, &lr, NULL); 702 676 free(path); 703 677 if (rc != EOK) { … … 719 693 } 720 694 695 void vfs_rename(ipc_callid_t rid, ipc_call_t *request) 696 { 697 size_t len; 698 ipc_callid_t callid; 699 int rc; 700 701 /* Retrieve the old path. */ 702 if (!ipc_data_write_receive(&callid, &len)) { 703 ipc_answer_0(callid, EINVAL); 704 ipc_answer_0(rid, EINVAL); 705 return; 706 } 707 char *old = malloc(len + 1); 708 if (!old) { 709 ipc_answer_0(callid, ENOMEM); 710 ipc_answer_0(rid, ENOMEM); 711 return; 712 } 713 if ((rc = ipc_data_write_finalize(callid, old, len))) { 714 ipc_answer_0(rid, rc); 715 free(old); 716 return; 717 } 718 old[len] = '\0'; 719 720 /* Retrieve the new path. */ 721 if (!ipc_data_write_receive(&callid, &len)) { 722 ipc_answer_0(callid, EINVAL); 723 ipc_answer_0(rid, EINVAL); 724 free(old); 725 return; 726 } 727 char *new = malloc(len + 1); 728 if (!new) { 729 ipc_answer_0(callid, ENOMEM); 730 ipc_answer_0(rid, ENOMEM); 731 free(old); 732 return; 733 } 734 if ((rc = ipc_data_write_finalize(callid, new, len))) { 735 ipc_answer_0(rid, rc); 736 free(old); 737 free(new); 738 return; 739 } 740 new[len] = '\0'; 741 742 char *oldc = canonify(old, &len); 743 char *newc = canonify(new, NULL); 744 if (!oldc || !newc) { 745 ipc_answer_0(rid, EINVAL); 746 free(old); 747 free(new); 748 return; 749 } 750 if (!strncmp(newc, oldc, len)) { 751 /* oldc is a prefix of newc */ 752 ipc_answer_0(rid, EINVAL); 753 free(old); 754 free(new); 755 return; 756 } 757 758 vfs_lookup_res_t old_lr; 759 vfs_lookup_res_t new_lr; 760 vfs_lookup_res_t new_par_lr; 761 rwlock_write_lock(&namespace_rwlock); 762 /* Lookup the node belonging to the old file name. */ 763 rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL); 764 if (rc != EOK) { 765 rwlock_write_unlock(&namespace_rwlock); 766 ipc_answer_0(rid, rc); 767 free(old); 768 free(new); 769 return; 770 } 771 vfs_node_t *old_node = vfs_node_get(&old_lr); 772 if (!old_node) { 773 rwlock_write_unlock(&namespace_rwlock); 774 ipc_answer_0(rid, ENOMEM); 775 free(old); 776 free(new); 777 return; 778 } 779 /* Lookup parent of the new file name. */ 780 rc = vfs_lookup_internal(newc, L_PARENT, &new_par_lr, NULL); 781 if (rc != EOK) { 782 rwlock_write_unlock(&namespace_rwlock); 783 ipc_answer_0(rid, rc); 784 free(old); 785 free(new); 786 return; 787 } 788 /* Check whether linking to the same file system instance. */ 789 if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) || 790 (old_node->dev_handle != new_par_lr.triplet.dev_handle)) { 791 rwlock_write_unlock(&namespace_rwlock); 792 ipc_answer_0(rid, EXDEV); /* different file systems */ 793 free(old); 794 free(new); 795 return; 796 } 797 /* Destroy the old link for the new name. */ 798 vfs_node_t *new_node = NULL; 799 rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL); 800 switch (rc) { 801 case ENOENT: 802 /* simply not in our way */ 803 break; 804 case EOK: 805 new_node = vfs_node_get(&new_lr); 806 if (!new_node) { 807 rwlock_write_unlock(&namespace_rwlock); 808 ipc_answer_0(rid, ENOMEM); 809 free(old); 810 free(new); 811 return; 812 } 813 new_node->lnkcnt--; 814 break; 815 default: 816 rwlock_write_unlock(&namespace_rwlock); 817 ipc_answer_0(rid, ENOTEMPTY); 818 free(old); 819 free(new); 820 return; 821 } 822 /* Create the new link for the new name. */ 823 rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index); 824 if (rc != EOK) { 825 rwlock_write_unlock(&namespace_rwlock); 826 if (new_node) 827 vfs_node_put(new_node); 828 ipc_answer_0(rid, rc); 829 free(old); 830 free(new); 831 return; 832 } 833 old_node->lnkcnt++; 834 /* Destroy the link for the old name. */ 835 rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL); 836 if (rc != EOK) { 837 rwlock_write_unlock(&namespace_rwlock); 838 vfs_node_put(old_node); 839 if (new_node) 840 vfs_node_put(new_node); 841 ipc_answer_0(rid, rc); 842 free(old); 843 free(new); 844 return; 845 } 846 old_node->lnkcnt--; 847 rwlock_write_unlock(&namespace_rwlock); 848 vfs_node_put(old_node); 849 if (new_node) 850 vfs_node_put(new_node); 851 free(old); 852 free(new); 853 ipc_answer_0(rid, EOK); 854 } 855 721 856 /** 722 857 * @}
Note:
See TracChangeset
for help on using the changeset viewer.