Changeset a8e9ab8d in mainline for uspace/srv/vfs/vfs_ops.c


Ignore:
Timestamp:
2008-03-09T17:18:30Z (17 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4072980
Parents:
2664838b
Message:

Support for rename().

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/vfs/vfs_ops.c

    r2664838b ra8e9ab8d  
    3636 */
    3737
     38#include "vfs.h"
    3839#include <ipc/ipc.h>
    3940#include <async.h>
     
    5152#include <assert.h>
    5253#include <atomic.h>
    53 #include "vfs.h"
     54#include <vfs/canonify.h>
    5455
    5556/* Forward declarations of static functions. */
     
    307308                return;
    308309        }
    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 path
    314          * directly into the PLB using some kind of a callback.
    315          */
    316310        char *path = malloc(len + 1);
    317        
    318311        if (!path) {
    319312                ipc_answer_0(callid, ENOMEM);
     
    321314                return;
    322315        }
    323 
    324316        int rc;
    325317        if ((rc = ipc_data_write_finalize(callid, path, len))) {
     
    630622                return;
    631623        }
    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 path
    637          * directly into the PLB using some kind of a callback.
    638          */
    639624        char *path = malloc(len + 1);
    640        
    641625        if (!path) {
    642626                ipc_answer_0(callid, ENOMEM);
     
    644628                return;
    645629        }
    646 
    647630        int rc;
    648631        if ((rc = ipc_data_write_finalize(callid, path, len))) {
     
    673656                return;
    674657        }
    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 path
    680          * directly into the PLB using some kind of a callback.
    681          */
    682658        char *path = malloc(len + 1);
    683        
    684659        if (!path) {
    685660                ipc_answer_0(callid, ENOMEM);
     
    687662                return;
    688663        }
    689 
    690664        int rc;
    691665        if ((rc = ipc_data_write_finalize(callid, path, len))) {
     
    699673        lflag &= L_DIRECTORY;   /* sanitize lflag */
    700674        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);
    702676        free(path);
    703677        if (rc != EOK) {
     
    719693}
    720694
     695void 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
    721856/**
    722857 * @}
Note: See TracChangeset for help on using the changeset viewer.