Changeset 0fdd6bb in mainline


Ignore:
Timestamp:
2008-11-23T16:22:40Z (15 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a5da446
Parents:
d2093d6
Message:

Add somewhat functional fat_link().

Location:
uspace
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libc/include/errno.h

    rd2093d6 r0fdd6bb  
    4848#define EXDEV           (-264)
    4949#define EIO             (-265)
     50#define EMLINK          (-266)
    5051
    5152#endif
  • uspace/srv/fs/fat/fat.h

    rd2093d6 r0fdd6bb  
    210210extern fat_idx_t *fat_idx_get_by_index(dev_handle_t, fs_index_t);
    211211extern void fat_idx_destroy(fat_idx_t *);
     212extern void fat_idx_hashin(fat_idx_t *);
    212213
    213214extern int fat_idx_init(void);
  • uspace/srv/fs/fat/fat_dentry.c

    rd2093d6 r0fdd6bb  
    3737
    3838#include "fat_dentry.h"
     39#include <ctype.h>
    3940
    4041#define FAT_PAD                 ' '
     
    4546#define FAT_DENTRY_ERASED       0xe5
    4647
    47 void dentry_name_canonify(fat_dentry_t *d, char *buf)
     48static bool is_d_char(const char ch)
     49{
     50        if (isalnum(ch) || ch == '_')
     51                return true;
     52        else
     53                return false;
     54}
     55
     56bool fat_dentry_name_verify(const char *name)
     57{
     58        unsigned i, dot;
     59        bool dot_found = false;
     60       
     61
     62        for (i = 0; name[i]; i++) {
     63                if (name[i] == '.') {
     64                        if (dot_found) {
     65                                return false;
     66                        } else {
     67                                dot_found = true;
     68                                dot = i;
     69                        }
     70                } else {
     71                        if (!is_d_char(name[i]))
     72                                return false;
     73                }
     74        }
     75
     76        if (dot_found) {
     77                if (dot > FAT_NAME_LEN)
     78                        return false;
     79                if (i - dot > FAT_EXT_LEN + 1)
     80                        return false;
     81        } else {
     82                if (i > FAT_NAME_LEN)
     83                        return false;
     84        }
     85
     86        return true;
     87}
     88
     89void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
    4890{
    4991        int i;
     
    72114}
    73115
    74 fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *d)
     116void fat_dentry_name_set(fat_dentry_t *d, const char *name)
     117{
     118        int i;
     119        const char fake_ext[] = "   ";
     120
     121
     122        for (i = 0; i < FAT_NAME_LEN; i++) {
     123                switch ((uint8_t) *name) {
     124                case 0xe5:
     125                        d->name[i] = FAT_DENTRY_E5_ESC;
     126                        name++;
     127                        break;
     128                case '\0':
     129                case '.':
     130                        d->name[i] = FAT_PAD;
     131                        break;
     132                default:
     133                        d->name[i] = toupper(*name++);
     134                        break;
     135                }
     136        }
     137        if (*name++ != '.')
     138                name = fake_ext;
     139        for (i = 0; i < FAT_EXT_LEN; i++) {
     140                switch ((uint8_t) *name) {
     141                case 0xe5:
     142                        d->ext[i] = FAT_DENTRY_E5_ESC;
     143                        name++;
     144                        break;
     145                case '\0':
     146                        d->ext[i] = FAT_PAD;
     147                        break;
     148                default:
     149                        d->ext[i] = toupper(*name++);
     150                        break;
     151                }
     152        }
     153}
     154
     155fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
    75156{
    76157        if (d->attr & FAT_ATTR_VOLLABEL) {
     
    80161        if (d->name[0] == FAT_DENTRY_ERASED) {
    81162                /* not-currently-used entry */
    82                 return FAT_DENTRY_SKIP;
     163                return FAT_DENTRY_FREE;
    83164        }
    84165        if (d->name[0] == FAT_DENTRY_UNUSED) {
  • uspace/srv/fs/fat/fat_dentry.h

    rd2093d6 r0fdd6bb  
    3535
    3636#include <stdint.h>
     37#include <bool.h>
    3738
    3839#define FAT_NAME_LEN            8
     
    4647        FAT_DENTRY_SKIP,
    4748        FAT_DENTRY_LAST,
     49        FAT_DENTRY_FREE,
    4850        FAT_DENTRY_VALID
    4951} fat_dentry_clsf_t;
     
    7173} __attribute__ ((packed)) fat_dentry_t;
    7274
    73 extern void dentry_name_canonify(fat_dentry_t *, char *);
    74 extern fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *);
     75extern bool fat_dentry_name_verify(const char *);
     76extern void fat_dentry_name_get(const fat_dentry_t *, char *);
     77extern void fat_dentry_name_set(fat_dentry_t *, const char *);
     78extern fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *);
    7579
    7680#endif
  • uspace/srv/fs/fat/fat_idx.c

    rd2093d6 r0fdd6bb  
    424424}
    425425
     426void fat_idx_hashin(fat_idx_t *idx)
     427{
     428        unsigned long pkey[] = {
     429                [UPH_DH_KEY] = idx->dev_handle,
     430                [UPH_PFC_KEY] = idx->pfc,
     431                [UPH_PDI_KEY] = idx->pdi,
     432        };
     433
     434        futex_down(&used_futex);
     435        hash_table_insert(&up_hash, pkey, &idx->uph_link);
     436        futex_up(&used_futex);
     437}
     438
    426439fat_idx_t *
    427440fat_idx_get_by_index(dev_handle_t dev_handle, fs_index_t index)
  • uspace/srv/fs/fat/fat_ops.c

    rd2093d6 r0fdd6bb  
    344344int fat_link(void *prnt, void *chld, const char *name)
    345345{
    346         return ENOTSUP; /* not supported at the moment */
     346        fat_node_t *parentp = (fat_node_t *)prnt;
     347        fat_node_t *childp = (fat_node_t *)chld;
     348        fat_dentry_t *d;
     349        fat_bs_t *bs;
     350        block_t *b;
     351        int i, j;
     352        uint16_t bps;
     353        unsigned dps;
     354        unsigned blocks;
     355
     356        futex_down(&childp->lock);
     357        if (childp->lnkcnt == 1) {
     358                /*
     359                 * On FAT, we don't support multiple hard links.
     360                 */
     361                futex_up(&childp->lock);
     362                return EMLINK;
     363        }
     364        assert(childp->lnkcnt == 0);
     365        futex_up(&childp->lock);
     366
     367        if (!fat_dentry_name_verify(name)) {
     368                /*
     369                 * Attempt to create unsupported name.
     370                 */
     371                return ENOTSUP;
     372        }
     373
     374        /*
     375         * Get us an unused parent node's dentry or grow the parent and allocate
     376         * a new one.
     377         */
     378       
     379        futex_down(&parentp->idx->lock);
     380        bs = block_bb_get(parentp->idx->dev_handle);
     381        bps = uint16_t_le2host(bs->bps);
     382        dps = bps / sizeof(fat_dentry_t);
     383
     384        blocks = parentp->size / bps;
     385
     386        for (i = 0; i < blocks; i++) {
     387                b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE);
     388                for (j = 0; j < dps; j++) {
     389                        d = ((fat_dentry_t *)b->data) + j;
     390                        switch (fat_classify_dentry(d)) {
     391                        case FAT_DENTRY_SKIP:
     392                        case FAT_DENTRY_VALID:
     393                                /* skipping used and meta entries */
     394                                continue;
     395                        case FAT_DENTRY_FREE:
     396                        case FAT_DENTRY_LAST:
     397                                /* found an empty slot */
     398                                goto hit;
     399                        }
     400                }
     401                block_put(b);
     402        }
     403       
     404        /*
     405         * We need to grow the parent in order to create a new unused dentry.
     406         */
     407        futex_up(&parentp->idx->lock);
     408        return ENOTSUP; /* XXX */
     409
     410hit:
     411        /*
     412         * At this point we only establish the link between the parent and the
     413         * child.  The dentry, except of the name and the extension, will remain
     414         * uninitialized until the the corresponding node is synced. Thus the
     415         * valid dentry data is kept in the child node structure.
     416         */
     417        memset(d, 0, sizeof(fat_dentry_t));
     418        fat_dentry_name_set(d, name);
     419        b->dirty = true;                /* need to sync block */
     420        block_put(b);
     421        futex_up(&parentp->idx->lock);
     422
     423        futex_down(&childp->idx->lock);
     424        childp->idx->pfc = parentp->firstc;
     425        childp->idx->pdi = i * dps + j;
     426        futex_up(&childp->idx->lock);
     427
     428        futex_down(&childp->lock);
     429        childp->lnkcnt = 1;
     430        childp->dirty = true;           /* need to sync node */
     431        futex_up(&childp->lock);
     432
     433        /*
     434         * Hash in the index structure into the position hash.
     435         */
     436        fat_idx_hashin(childp->idx);
     437
     438        return EOK;
    347439}
    348440
     
    375467                        switch (fat_classify_dentry(d)) {
    376468                        case FAT_DENTRY_SKIP:
     469                        case FAT_DENTRY_FREE:
    377470                                continue;
    378471                        case FAT_DENTRY_LAST:
     
    382475                        default:
    383476                        case FAT_DENTRY_VALID:
    384                                 dentry_name_canonify(d, name);
     477                                fat_dentry_name_get(d, name);
    385478                                break;
    386479                        }
     
    465558                        switch (fat_classify_dentry(d)) {
    466559                        case FAT_DENTRY_SKIP:
     560                        case FAT_DENTRY_FREE:
    467561                                continue;
    468562                        case FAT_DENTRY_LAST:
     
    699793                                switch (fat_classify_dentry(d)) {
    700794                                case FAT_DENTRY_SKIP:
     795                                case FAT_DENTRY_FREE:
    701796                                        continue;
    702797                                case FAT_DENTRY_LAST:
     
    705800                                default:
    706801                                case FAT_DENTRY_VALID:
    707                                         dentry_name_canonify(d, name);
     802                                        fat_dentry_name_get(d, name);
    708803                                        block_put(b);
    709804                                        goto hit;
Note: See TracChangeset for help on using the changeset viewer.