Changeset bf9dc4e2 in mainline for uspace/srv/vfs/vfs_lookup.c


Ignore:
Timestamp:
2013-07-28T19:32:36Z (11 years ago)
Author:
Jiri Zarevucky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
778d26d
Parents:
d60ce4a
Message:

Relativize and simplify lookup().

File:
1 edited

Legend:

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

    rd60ce4a rbf9dc4e2  
    4646#include <adt/list.h>
    4747#include <vfs/canonify.h>
     48#include <dirent.h>
     49#include <assert.h>
     50
     51#define DPRINTF(...)
    4852
    4953#define min(a, b)  ((a) < (b) ? (a) : (b))
     
    5357uint8_t *plb = NULL;
    5458
    55 /** Perform a path lookup.
    56  *
    57  * @param path    Path to be resolved; it must be a NULL-terminated
    58  *                string.
    59  * @param lflag   Flags to be used during lookup.
    60  * @param result  Empty structure where the lookup result will be stored.
    61  *                Can be NULL.
    62  * @param altroot If non-empty, will be used instead of rootfs as the root
    63  *                of the whole VFS tree.
    64  *
    65  * @return EOK on success or an error code from errno.h.
    66  *
    67  */
    68 int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result,
    69     vfs_pair_t *altroot, ...)
    70 {
    71         vfs_pair_t *root;
    72 
    73         if (altroot)
    74                 root = altroot;
    75         else
    76                 root = &rootfs;
    77 
    78         if (!root->fs_handle)
    79                 return ENOENT;
    80        
    81         size_t len;
    82         path = canonify(path, &len);
    83         if (!path)
    84                 return EINVAL;
    85        
    86         fs_index_t index = 0;
    87         if (lflag & L_LINK) {
    88                 va_list ap;
    89 
    90                 va_start(ap, altroot);
    91                 index = va_arg(ap, fs_index_t);
    92                 va_end(ap);
    93         }
    94        
     59static int plb_insert_entry(plb_entry_t *entry, char *path, size_t *start, size_t len)
     60{
    9561        fibril_mutex_lock(&plb_mutex);
    9662
    97         plb_entry_t entry;
    98         link_initialize(&entry.plb_link);
    99         entry.len = len;
     63        link_initialize(&entry->plb_link);
     64        entry->len = len;
    10065
    10166        size_t first;   /* the first free index */
     
    138103         */
    139104
    140         entry.index = first;
    141         entry.len = len;
     105        entry->index = first;
     106        entry->len = len;
    142107
    143108        /*
     
    145110         * buffer.
    146111         */
    147         list_append(&entry.plb_link, &plb_entries);
     112        list_append(&entry->plb_link, &plb_entries);
    148113       
    149114        fibril_mutex_unlock(&plb_mutex);
     
    158123        memcpy(plb, &path[cnt1], cnt2);
    159124
    160         ipc_call_t answer;
    161         async_exch_t *exch = vfs_exchange_grab(root->fs_handle);
    162         aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) first,
    163             (sysarg_t) (first + len - 1) % PLB_SIZE,
    164             (sysarg_t) root->service_id, (sysarg_t) lflag, (sysarg_t) index,
    165             &answer);
    166        
    167         sysarg_t rc;
    168         async_wait_for(req, &rc);
    169         vfs_exchange_release(exch);
    170        
     125        *start = first;
     126        return EOK;
     127}
     128
     129static void plb_clear_entry(plb_entry_t *entry, size_t first, size_t len)
     130{
    171131        fibril_mutex_lock(&plb_mutex);
    172         list_remove(&entry.plb_link);
     132        list_remove(&entry->plb_link);
    173133        /*
    174134         * Erasing the path from PLB will come handy for debugging purposes.
    175135         */
     136        size_t cnt1 = min(len, (PLB_SIZE - first) + 1);
     137        size_t cnt2 = len - cnt1;
    176138        memset(&plb[first], 0, cnt1);
    177139        memset(plb, 0, cnt2);
    178140        fibril_mutex_unlock(&plb_mutex);
    179        
    180         if ((int) rc < EOK)
    181                 return (int) rc;
    182 
    183         if (!result)
    184                 return EOK;
     141}
     142
     143static char *_strrchr(char *path, int c)
     144{
     145        char *res = NULL;
     146        while (*path != 0) {
     147                if (*path == c) {
     148                        res = path;
     149                }
     150                path++;
     151        }
     152        return res;
     153}
     154
     155int vfs_link_internal(vfs_triplet_t *base, char *path, vfs_triplet_t *child)
     156{
     157        assert(base != NULL);
     158        assert(child != NULL);
     159        assert(base->fs_handle);
     160        assert(child->fs_handle);
     161        assert(path != NULL);
     162       
     163        vfs_lookup_res_t res;
     164        char component[NAME_MAX + 1];
     165        int rc;
     166       
     167        size_t len;
     168        char *npath = canonify(path, &len);
     169        if (!npath) {
     170                rc = EINVAL;
     171                goto out;
     172        }
     173        path = npath;
     174       
     175        char *slash = _strrchr(path, '/');
     176        if (slash && slash != path) {
     177                if (slash[1] == 0) {
     178                        rc = EINVAL;
     179                        goto out;
     180                }
     181               
     182                memcpy(component, slash + 1, str_size(slash));
     183                *slash = 0;
     184               
     185                rc = vfs_lookup_internal(base, path, L_DIRECTORY, &res);
     186                if (rc != EOK) {
     187                        goto out;
     188                }
     189                base = &res.triplet;
     190               
     191                *slash = '/';
     192        } else {
     193                memcpy(component, path + 1, str_size(path));
     194        }
     195       
     196        if (base->fs_handle != child->fs_handle || base->service_id != child->service_id) {
     197                rc = EXDEV;
     198                goto out;
     199        }
     200       
     201        async_exch_t *exch = vfs_exchange_grab(base->fs_handle);
     202        aid_t req = async_send_3(exch, VFS_OUT_LINK, base->service_id, base->index, child->index, NULL);
     203       
     204        rc = async_data_write_start(exch, component, str_size(component) + 1);
     205        sysarg_t orig_rc;
     206        async_wait_for(req, &orig_rc);
     207        vfs_exchange_release(exch);
     208        if (orig_rc != EOK) {
     209                rc = orig_rc;
     210        }
     211       
     212out:
     213        DPRINTF("vfs_link_internal() with path '%s' returns %d\n", path, rc);
     214        return rc;
     215}
     216
     217/** Perform a path lookup.
     218 *
     219 * @param base    The file from which to perform the lookup.
     220 * @param path    Path to be resolved; it must be a NULL-terminated
     221 *                string.
     222 * @param lflag   Flags to be used during lookup.
     223 * @param result  Empty structure where the lookup result will be stored.
     224 *                Can be NULL.
     225 *
     226 * @return EOK on success or an error code from errno.h.
     227 *
     228 */
     229int vfs_lookup_internal(vfs_triplet_t *base, char *path, int lflag, vfs_lookup_res_t *result)
     230{
     231        assert(base != NULL);
     232        assert(path != NULL);
     233       
     234        sysarg_t rc;
     235       
     236        if (!base->fs_handle) {
     237                rc = ENOENT;
     238                goto out;
     239        }
     240       
     241        size_t len;
     242        char *npath = canonify(path, &len);
     243        if (!npath) {
     244                rc = EINVAL;
     245                goto out;
     246        }
     247        path = npath;
     248       
     249        assert(path[0] == '/');
     250       
     251        size_t first;
     252       
     253        plb_entry_t entry;
     254        rc = plb_insert_entry(&entry, path, &first, len);
     255        if (rc != EOK) {
     256                goto out;
     257        }
     258       
     259        ipc_call_t answer;
     260        async_exch_t *exch = vfs_exchange_grab(base->fs_handle);
     261        aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) first, (sysarg_t) len,
     262            (sysarg_t) base->service_id, (sysarg_t) base->index, (sysarg_t) lflag, &answer);
     263        async_wait_for(req, &rc);
     264        vfs_exchange_release(exch);
     265       
     266        plb_clear_entry(&entry, first, len);
     267       
     268        if ((int) rc < 0) {
     269                goto out;
     270        }
     271       
     272        if (!result) {
     273                rc = EOK;
     274                goto out;
     275        }
    185276       
    186277        result->triplet.fs_handle = (fs_handle_t) rc;
     
    197288        else
    198289                result->type = VFS_NODE_UNKNOWN;
    199        
    200         return EOK;
     290
     291        rc = EOK;
     292
     293out:
     294        DPRINTF("vfs_lookup_internal() with path '%s' returns %d\n", path, rc);
     295        return rc;
    201296}
    202297
Note: See TracChangeset for help on using the changeset viewer.