Changeset a8e9ab8d in mainline


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
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/tester/vfs/vfs1.c

    r2664838b ra8e9ab8d  
    9696        closedir(dirp);
    9797
    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"))
    99105                return "unlink() failed.\n";
    100106       
    101107        if (!quiet)
    102                 printf("unlinked file /mydir/myfile\n");
     108                printf("unlinked file /mydir/yourfile\n");
    103109
    104110        if (rmdir("/mydir"))
  • uspace/lib/libc/generic/vfs/vfs.c

    r2664838b ra8e9ab8d  
    469469}
    470470
     471int 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
    471538int chdir(const char *path)
    472539{
  • uspace/lib/libc/include/stdio.h

    r2664838b ra8e9ab8d  
    6868#define fprintf(f, fmt, ...) printf(fmt, ##__VA_ARGS__)
    6969
     70extern int rename(const char *, const char *);
     71
    7072#endif
    7173
  • uspace/lib/libfs/libfs.c

    r2664838b ra8e9ab8d  
    142142        int dev_handle = IPC_GET_ARG3(*request);
    143143        int lflag = IPC_GET_ARG4(*request);
     144        int index = IPC_GET_ARG5(*request); /* when L_LINK specified */
    144145
    145146        if (last < next)
     
    181182                /* handle miss: match amongst siblings */
    182183                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 */
    185192                                if (!ops->is_directory(cur)) {
    186193                                        ipc_answer_0(rid, ENOTDIR);
    187194                                        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);
    190202                                if (nodep) {
    191203                                        if (!ops->link(cur, nodep, component)) {
    192                                                 ops->destroy(nodep);
     204                                                if (lflag & L_CREATE)
     205                                                        ops->destroy(nodep);
    193206                                                ipc_answer_0(rid, ENOSPC);
    194207                                        } else {
    195208                                                ipc_answer_5(rid, EOK,
    196209                                                    fs_handle, dev_handle,
    197                                                     ops->index_get(nodep), 0,
     210                                                    ops->index_get(nodep),
     211                                                    ops->size_get(nodep),
    198212                                                    ops->lnkcnt_get(nodep));
    199213                                        }
     
    202216                                }
    203217                                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                        }
    205224                        ipc_answer_0(rid, ENOENT);
    206225                        return;
     
    215234        /* handle miss: excessive components */
    216235        if (!tmp && next <= last) {
    217                 if (lflag & L_CREATE) {
     236                if (lflag & (L_CREATE | L_LINK)) {
    218237                        if (!ops->is_directory(cur)) {
    219238                                ipc_answer_0(rid, ENOTDIR);
     
    240259                        len = 0;
    241260                               
    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);
    243267                        if (nodep) {
    244268                                if (!ops->link(cur, nodep, component)) {
    245                                         ops->destroy(nodep);
     269                                        if (lflag & L_CREATE)
     270                                                ops->destroy(nodep);
    246271                                        ipc_answer_0(rid, ENOSPC);
    247272                                } else {
    248273                                        ipc_answer_5(rid, EOK,
    249274                                            fs_handle, dev_handle,
    250                                             ops->index_get(nodep), 0,
     275                                            ops->index_get(nodep),
     276                                            ops->size_get(nodep),
    251277                                            ops->lnkcnt_get(nodep));
    252278                                }
     
    261287
    262288        /* 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) {
    264297                unsigned old_lnkcnt = ops->lnkcnt_get(cur);
    265298                int res = ops->unlink(par, cur);
     
    268301                return;
    269302        }
    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)) {
    271305                ipc_answer_0(rid, EEXIST);
    272306                return;
  • uspace/lib/libfs/libfs.h

    r2664838b ra8e9ab8d  
    4444typedef struct {
    4545        bool (* match)(void *, void *, const char *);
     46        void * (* node_get)(int, int, unsigned long);
    4647        void * (* create)(int);
    4748        void (* destroy)(void *);
  • 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.