Changeset a8e9ab8d in mainline for uspace/srv


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().

Location:
uspace/srv
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/tmpfs/tmpfs_ops.c

    r2664838b ra8e9ab8d  
    7171/* Forward declarations of static functions. */
    7272static bool tmpfs_match(void *, void *, const char *);
     73static void *tmpfs_node_get(int, int, unsigned long);
    7374static void *tmpfs_create_node(int);
    7475static bool tmpfs_link_node(void *, void *, const char *);
     
    125126libfs_ops_t tmpfs_libfs_ops = {
    126127        .match = tmpfs_match,
     128        .node_get = tmpfs_node_get,
    127129        .create = tmpfs_create_node,
    128130        .destroy = tmpfs_destroy_node,
     
    259261
    260262        return !strcmp(namep->name, component);
     263}
     264
     265void *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);
    261271}
    262272
  • uspace/srv/vfs/vfs.c

    r2664838b ra8e9ab8d  
    115115                        vfs_unlink(callid, &call);
    116116                        break;
     117                case VFS_RENAME:
     118                        vfs_rename(callid, &call);
     119                        break;
    117120                default:
    118121                        ipc_answer_0(callid, ENOTSUP);
  • uspace/srv/vfs/vfs.h

    r2664838b ra8e9ab8d  
    167167#define L_CREATE        8
    168168/**
    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
    170174 * cannot be passed directly by the client, but will be set by VFS during
    171175 * VFS_UNLINK.
    172176 */
    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     
    174183
    175184typedef struct {
     
    251260extern int fs_name_to_handle(char *, bool);
    252261
    253 extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *, vfs_pair_t *);
     262extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *, vfs_pair_t *,
     263    ...);
    254264
    255265extern bool vfs_nodes_init(void);
     
    280290extern void vfs_mkdir(ipc_callid_t, ipc_call_t *);
    281291extern void vfs_unlink(ipc_callid_t, ipc_call_t *);
     292extern void vfs_rename(ipc_callid_t, ipc_call_t *);
    282293
    283294#endif
  • uspace/srv/vfs/vfs_lookup.c

    r2664838b ra8e9ab8d  
    4141#include <errno.h>
    4242#include <string.h>
     43#include <stdarg.h>
    4344#include <bool.h>
    4445#include <futex.h>
     
    6667 */
    6768int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result,
    68     vfs_pair_t *altroot)
     69    vfs_pair_t *altroot, ...)
    6970{
    7071        vfs_pair_t *root;
     
    8283        if (!path)
    8384                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        }
    8494       
    8595        futex_down(&plb_futex);
     
    150160        ipc_call_t answer;
    151161        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,
    153163            (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);
    155166        vfs_release_phone(phone);
    156167
  • 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.