Changeset 5dfb1948 in mainline


Ignore:
Timestamp:
2011-06-27T16:45:48Z (13 years ago)
Author:
Oleg Romanenko <romanenko.oleg@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
bba3d90
Parents:
7194a60
Message:
  1. Implement fat_directory_write
  2. Add few high-level functions for managing directory:

2.1 Looking for file name: fat_directory_lookup_name
2.2 Looking for short file name entry: fat_directory_is_sfn_exist
2.3 Expand directory by adding cluster: fat_directory_expand
2.4 Write directory entry: fat_directory_write_dentry
2.5 Looking for chain of free entries: fat_directory_lookup_free
2.6 Create short name from long name: fat_directory_create_sfn

Location:
uspace/srv/fs/fat
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/fat/fat_directory.c

    r7194a60 r5dfb1948  
    3737
    3838#include "fat_directory.h"
     39#include "fat_fat.h"
    3940#include <libblock.h>
    4041#include <errno.h>
     
    136137        aoff64_t _pos = di->pos;
    137138        int rc;
     139
    138140        di->pos = pos;
    139141        rc = fat_directory_block_load(di);
     
    175177                                                (di->checksum == FAT_LFN_CHKSUM(d))) {
    176178                                                /* Right order! */
    177                                                 fat_lfn_copy_entry(d, di->wname, &di->lfn_offset);
     179                                                fat_lfn_get_entry(d, di->wname, &di->lfn_offset);
    178180                                        } else {
    179181                                                /* Something wrong with order. Skip this long entries set */
     
    190192                                                                (FAT_LFN_COUNT(d) - 1)) + fat_lfn_size(d);
    191193                                                        di->lfn_offset = di->lfn_size;
    192                                                         fat_lfn_copy_entry(d, di->wname, &di->lfn_offset);
     194                                                        fat_lfn_get_entry(d, di->wname, &di->lfn_offset);
    193195                                                        di->checksum = FAT_LFN_CHKSUM(d);
    194196                                                }
     
    200202                                        (di->checksum == fat_dentry_chksum(d->name))) {
    201203                                        di->wname[di->lfn_size] = '\0';
    202                                         if (utf16_to_str(name, FAT_LFN_NAME_SIZE, di->wname)!=EOK)
     204                                        if (wstr_to_str(name, FAT_LFN_NAME_SIZE, di->wname)!=EOK)
    203205                                                fat_dentry_name_get(d, name);
    204206                                }
     
    254256}
    255257
    256 int fat_directory_write(fat_directory_t *di, char *name, fat_dentry_t *de)
    257 {
    258         /* TODO: create LFN records if necessarry and create SFN record */
     258int fat_directory_write(fat_directory_t *di, const char *name, fat_dentry_t *de)
     259{
     260        int rc;
     261        rc = str_to_wstr(di->wname, FAT_LFN_NAME_SIZE, name);
     262        if (rc != EOK)
     263                return rc;
     264        if (fat_dentry_is_sfn(di->wname)) {
     265                /* NAME could be directly stored in dentry without creating LFN */
     266                fat_dentry_name_set(de, name);
     267
     268                if (fat_directory_is_sfn_exist(di, de))
     269                        return EEXIST;
     270                rc = fat_directory_lookup_free(di, 1);
     271                if (rc != EOK)
     272                        return rc;
     273                rc = fat_directory_write_dentry(di, de);
     274                if (rc != EOK)
     275                        return rc;
     276
     277                return EOK;
     278        }
     279        else
     280        {
     281                /* We should create long entries to store name */
     282                di->lfn_size = wstr_length(di->wname);
     283                di->long_entry_count = di->lfn_size / FAT_LFN_ENTRY_SIZE;
     284                if (di->lfn_size % FAT_LFN_ENTRY_SIZE)
     285                        di->long_entry_count++;
     286                rc = fat_directory_lookup_free(di, di->long_entry_count+1);
     287                if (rc != EOK)
     288                        return rc;
     289                aoff64_t start_pos = di->pos;
     290
     291                /* Write Short entry */
     292                rc = fat_directory_create_sfn(di, de);
     293                if (rc != EOK)
     294                        return rc;
     295                di->checksum = fat_dentry_chksum(de->name);
     296
     297                rc = fat_directory_seek(di, start_pos+di->long_entry_count);
     298                if (rc != EOK)
     299                        return rc;
     300                rc = fat_directory_write_dentry(di, de);
     301                if (rc != EOK)
     302                        return rc;
     303
     304                /* Write Long entry by parts */
     305                di->lfn_offset = 0;
     306                fat_dentry_t *d;
     307                size_t idx = 0;
     308                do {
     309                        rc = fat_directory_prev(di);
     310                        if (rc != EOK)
     311                                return rc;
     312                        rc = fat_directory_get(di, &d);
     313                        if (rc != EOK)
     314                                return rc;
     315                        fat_lfn_set_entry(di->wname, &di->lfn_offset, di->lfn_size+1, d);
     316                        FAT_LFN_CHKSUM(d) = di->checksum;
     317                        FAT_LFN_ORDER(d) = ++idx;
     318                        di->b->dirty = true;
     319                } while (di->lfn_offset < di->lfn_size);
     320                FAT_LFN_ORDER(d) |= FAT_LFN_LAST;
     321
     322                rc = fat_directory_seek(di, start_pos+di->long_entry_count);
     323                if (rc != EOK)
     324                        return rc;
     325                return EOK;
     326        }
     327}
     328
     329int fat_directory_create_sfn(fat_directory_t *di, fat_dentry_t *de)
     330{
     331        char name[FAT_NAME_LEN+1];
     332        char ext[FAT_EXT_LEN+1];
     333        char number[FAT_NAME_LEN+1];
     334        memset(name, FAT_PAD, FAT_NAME_LEN);
     335        memset(ext, FAT_PAD, FAT_EXT_LEN);
     336        memset(number, FAT_PAD, FAT_NAME_LEN);
     337
     338        size_t name_len = wstr_size(di->wname);
     339        wchar_t *pdot = wstr_rchr(di->wname, '.');
     340        ext[FAT_EXT_LEN] = '\0';
     341        if (pdot) {
     342                pdot++;
     343                wstr_to_ascii(ext, pdot, FAT_EXT_LEN, FAT_SFN_CHAR);
     344                name_len = (pdot - di->wname - 1);
     345        }
     346        if (name_len > FAT_NAME_LEN)
     347                name_len = FAT_NAME_LEN;
     348        wstr_to_ascii(name, di->wname, name_len, FAT_SFN_CHAR);
     349
     350        size_t idx;
     351        for (idx=1; idx <= FAT_MAX_SFN; idx++) {
     352                if (size_t_str(idx, 10, number, FAT_NAME_LEN-2)!=EOK)
     353                        return EOVERFLOW;
     354
     355                /* Fill de->name with FAT_PAD */
     356                memset(de->name, FAT_PAD, FAT_NAME_LEN+FAT_EXT_LEN);
     357                /* Copy ext */
     358                memcpy(de->ext, ext, str_size(ext));
     359                /* Copy name */
     360                memcpy(de->name, name, str_size(name));
     361
     362                /* Copy number */
     363                size_t offset;
     364                if (str_size(name)+str_size(number)+1 >FAT_NAME_LEN)
     365                        offset = FAT_NAME_LEN - str_size(number)-1;
     366                else
     367                        offset = str_size(name);
     368                de->name[offset] = '~';
     369                offset++;
     370                memcpy(de->name+offset, number, str_size(number));
     371
     372                if (!fat_directory_is_sfn_exist(di, de))
     373                        return EOK;
     374        }
     375        return ERANGE;
     376}
     377
     378int fat_directory_write_dentry(fat_directory_t *di, fat_dentry_t *de)
     379{
     380        fat_dentry_t *d;
     381        int rc;
     382
     383        rc = fat_directory_get(di, &d);
     384        if (rc!=EOK)
     385                return rc;
     386        memcpy(d, de, sizeof(fat_dentry_t));
     387        di->b->dirty = true;
    259388        return EOK;
    260389}
    261390
    262 
     391int fat_directory_expand(fat_directory_t *di)
     392{
     393        int rc;
     394        fat_cluster_t mcl, lcl;
     395
     396        if (!FAT_IS_FAT32(di->bs) && di->nodep->firstc == FAT_CLST_ROOT) {
     397                /* Can't grow the root directory on FAT12/16. */
     398                return ENOSPC;
     399        }
     400        rc = fat_alloc_clusters(di->bs, di->nodep->idx->devmap_handle, 1, &mcl, &lcl);
     401        if (rc != EOK)
     402                return rc;
     403        rc = fat_zero_cluster(di->bs, di->nodep->idx->devmap_handle, mcl);
     404        if (rc != EOK) {
     405                (void) fat_free_clusters(di->bs, di->nodep->idx->devmap_handle, mcl);
     406                return rc;
     407        }
     408        rc = fat_append_clusters(di->bs, di->nodep, mcl, lcl);
     409        if (rc != EOK) {
     410                (void) fat_free_clusters(di->bs, di->nodep->idx->devmap_handle, mcl);
     411                return rc;
     412        }
     413        di->nodep->size += BPS(di->bs) * SPC(di->bs);
     414        di->nodep->dirty = true;                /* need to sync node */
     415        di->blocks = di->nodep->size / BPS(di->bs);
     416       
     417        return EOK;
     418}
     419
     420int fat_directory_lookup_free(fat_directory_t *di, size_t count)
     421{
     422        fat_dentry_t *d;
     423        size_t found;
     424        aoff64_t pos;
     425       
     426        do {
     427                found = 0;
     428                pos=0;
     429                fat_directory_seek(di, 0);
     430                do {
     431                        if (fat_directory_get(di, &d) == EOK) {
     432                                switch (fat_classify_dentry(d)) {
     433                                case FAT_DENTRY_LAST:
     434                                case FAT_DENTRY_FREE:
     435                                        if (found==0) pos = di->pos;
     436                                        found++;
     437                                        if (found == count) {
     438                                                fat_directory_seek(di, pos);
     439                                                return EOK;
     440                                        }
     441                                        break;
     442                                case FAT_DENTRY_VALID:
     443                                case FAT_DENTRY_LFN:
     444                                case FAT_DENTRY_SKIP:
     445                                default:
     446                                        found = 0;
     447                                        break;
     448                                }
     449                        }
     450                } while (fat_directory_next(di) == EOK);       
     451        } while (fat_directory_expand(di) == EOK);
     452        return ENOSPC;
     453}
     454
     455int fat_directory_lookup_name(fat_directory_t *di, const char *name, fat_dentry_t **de)
     456{
     457        char entry[FAT_LFN_NAME_SIZE];
     458        fat_directory_seek(di, 0);
     459        while (fat_directory_read(di, entry, de) == EOK) {
     460                if (fat_dentry_namecmp(entry, name) == 0) {
     461                        return EOK;
     462                } else {
     463                        if (fat_directory_next(di) != EOK)
     464                                break;
     465                }
     466        }
     467        return ENOENT;
     468}
     469
     470bool fat_directory_is_sfn_exist(fat_directory_t *di, fat_dentry_t *de)
     471{
     472        fat_dentry_t *d;
     473        fat_directory_seek(di, 0);
     474        do {
     475                if (fat_directory_get(di, &d) == EOK) {
     476                        switch (fat_classify_dentry(d)) {
     477                        case FAT_DENTRY_LAST:
     478                                return false;
     479                        case FAT_DENTRY_VALID:
     480                                        if (bcmp(de->name, d->name, FAT_NAME_LEN+FAT_EXT_LEN)==0)
     481                                                return true;
     482                                        break;
     483                        default:
     484                        case FAT_DENTRY_LFN:
     485                        case FAT_DENTRY_SKIP:
     486                        case FAT_DENTRY_FREE:
     487                                break;
     488                        }
     489                }
     490        } while (fat_directory_next(di) == EOK);       
     491        return false;
     492}
    263493
    264494/**
  • uspace/srv/fs/fat/fat_directory.h

    r7194a60 r5dfb1948  
    3838#include "fat_dentry.h"
    3939
     40#define FAT_MAX_SFN 9999
     41
    4042typedef struct {
    4143        /* Directory data */
     
    4850        bool last;
    4951        /* Long entry data */
    50         uint16_t wname[FAT_LFN_MAX_COUNT * FAT_LFN_ENTRY_SIZE];
     52        wchar_t wname[FAT_LFN_NAME_SIZE];
    5153        size_t lfn_offset;
    5254        size_t lfn_size;
     
    6264extern int fat_directory_next(fat_directory_t *);
    6365extern int fat_directory_prev(fat_directory_t *);
    64 extern int fat_directory_seek(fat_directory_t *, aoff64_t pos);
     66extern int fat_directory_seek(fat_directory_t *, aoff64_t);
    6567extern int fat_directory_get(fat_directory_t *, fat_dentry_t **);
    66 extern int fat_directory_dirty(fat_directory_t *);
    6768
    6869extern int fat_directory_read(fat_directory_t *, char *, fat_dentry_t **);
    69 extern int fat_directory_write(fat_directory_t *, char *, fat_dentry_t *);
     70extern int fat_directory_write(fat_directory_t *, const char *, fat_dentry_t *);
    7071extern int fat_directory_erase(fat_directory_t *);
     72extern int fat_directory_lookup_name(fat_directory_t *, const char *, fat_dentry_t **);
     73extern bool fat_directory_is_sfn_exist(fat_directory_t *, fat_dentry_t *);
     74
     75extern int fat_directory_lookup_free(fat_directory_t *di, size_t count);
     76extern int fat_directory_write_dentry(fat_directory_t *di, fat_dentry_t *de);
     77extern int fat_directory_create_sfn(fat_directory_t *di, fat_dentry_t *de);
     78extern int fat_directory_expand(fat_directory_t *di);
    7179
    7280
Note: See TracChangeset for help on using the changeset viewer.