Changes in / [375ab5e:7fadb65] in mainline


Ignore:
Files:
23 deleted
14 edited

Legend:

Unmodified
Added
Removed
  • boot/Makefile.common

    r375ab5e r7fadb65  
    102102        $(USPACE_PATH)/srv/fs/tmpfs/tmpfs \
    103103        $(USPACE_PATH)/srv/fs/fat/fat \
    104         $(USPACE_PATH)/srv/fs/exfat/exfat \
    105104        $(USPACE_PATH)/srv/fs/ext2fs/ext2fs \
    106105        $(USPACE_PATH)/srv/taskmon/taskmon \
     
    149148        $(USPACE_PATH)/app/dload/dload \
    150149        $(USPACE_PATH)/app/edit/edit \
    151         $(USPACE_PATH)/app/filecrc/filecrc \
    152         $(USPACE_PATH)/app/filegen/filegen \
    153150        $(USPACE_PATH)/app/ext2info/ext2info \
    154151        $(USPACE_PATH)/app/kill/kill \
  • uspace/Makefile

    r375ab5e r7fadb65  
    3939        app/devctl \
    4040        app/edit \
    41         app/filecrc \
    42         app/filegen \
    4341        app/ext2info \
    4442        app/getterm \
     
    8179        srv/bd/part/guid_part \
    8280        srv/bd/part/mbr_part \
    83         srv/fs/exfat \
    8481        srv/fs/fat \
    8582        srv/fs/tmpfs \
  • uspace/app/mkfat/fat.h

    r375ab5e r7fadb65  
    3838#define BS_BLOCK                0
    3939#define BS_SIZE                 512
     40
    4041#define DIRENT_SIZE             32
    41 
    42 #define FAT12_CLST_MAX    4085
    43 #define FAT16_CLST_MAX    65525
    44 
    45 #define FAT12   12
    46 #define FAT16   16
    47 #define FAT32   32
    48 
    49 #define FAT_SIZE(a) ((a==FAT12)? 1.5 : ( (a==FAT16)? 2 : 4  ) )
    5042
    5143typedef struct fat_bs {
  • uspace/app/mkfat/mkfat.c

    r375ab5e r7fadb65  
    3535 * @brief       Tool for creating new FAT file systems.
    3636 *
    37  * Currently we can create 12/16/32-bit FAT.
     37 * Currently we can only create 16-bit FAT.
    3838 */
    3939
     
    5555#define div_round_up(a, b) (((a) + (b) - 1) / (b))
    5656
    57 /** Default file-system parameters */
     57/** Predefined file-system parameters */
    5858enum {
    59         default_sector_size             = 512,
    60         default_sectors_per_cluster     = 4,
    61         default_fat_count               = 2,
    62         default_reserved_clusters       = 2,
    63         default_media_descriptor        = 0xF8 /**< fixed disk */
     59        sector_size             = 512,
     60        sectors_per_cluster     = 8,
     61        fat_count               = 2,
     62        reserved_clusters       = 2,
     63        media_descriptor        = 0xF8 /**< fixed disk */
    6464};
    6565
    6666/** Configurable file-system parameters */
    6767typedef struct fat_cfg {
    68         int fat_type; /* FAT12 = 12, FAT16 = 16, FAT32 = 32 */
    69         size_t sector_size;
    7068        uint32_t total_sectors;
    7169        uint16_t root_ent_max;
    72         uint32_t addt_res_sectors;
    73         uint8_t sectors_per_cluster;
    74 
     70        uint16_t addt_res_sectors;
     71} fat_cfg_t;
     72
     73/** Derived file-system parameters */
     74typedef struct fat_params {
     75        struct fat_cfg cfg;
    7576        uint16_t reserved_sectors;
    76         uint32_t rootdir_sectors;
     77        uint16_t rootdir_sectors;
    7778        uint32_t fat_sectors;
    78         uint32_t total_clusters;
    79         uint8_t fat_count;
    80 } fat_cfg_t;
     79        uint16_t total_clusters;
     80} fat_params_t;
    8181
    8282static void syntax_print(void);
    8383
    84 static int fat_params_compute(struct fat_cfg *cfg);
    85 static int fat_blocks_write(struct fat_cfg const *cfg, service_id_t service_id);
    86 static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs);
     84static int fat_params_compute(struct fat_cfg const *cfg,
     85    struct fat_params *par);
     86static int fat_blocks_write(struct fat_params const *par,
     87    service_id_t service_id);
     88static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs);
    8789
    8890int main(int argc, char **argv)
    8991{
     92        struct fat_params par;
    9093        struct fat_cfg cfg;
    9194
     
    9396        char *dev_path;
    9497        service_id_t service_id;
     98        size_t block_size;
    9599        char *endptr;
    96100        aoff64_t dev_nblocks;
    97101
    98         cfg.sector_size = default_sector_size;
    99         cfg.sectors_per_cluster = default_sectors_per_cluster;
    100         cfg.fat_count = default_fat_count;
    101102        cfg.total_sectors = 0;
    102103        cfg.addt_res_sectors = 0;
    103104        cfg.root_ent_max = 128;
    104         cfg.fat_type = FAT16;
    105105
    106106        if (argc < 2) {
     
    111111
    112112        --argc; ++argv;
     113
    113114        if (str_cmp(*argv, "--size") == 0) {
    114115                --argc; ++argv;
     
    129130        }
    130131
    131         if (str_cmp(*argv, "--type") == 0) {
    132                 --argc; ++argv;
    133                 if (*argv == NULL) {
    134                         printf(NAME ": Error, argument missing.\n");
    135                         syntax_print();
    136                         return 1;
    137                 }
    138 
    139                 cfg.fat_type = strtol(*argv, &endptr, 10);
    140                 if (*endptr != '\0') {
    141                         printf(NAME ": Error, invalid argument.\n");
    142                         syntax_print();
    143                         return 1;
    144                 }
    145 
    146                 --argc; ++argv;
    147         }
    148 
    149132        if (argc != 1) {
    150133                printf(NAME ": Error, unexpected argument.\n");
     
    154137
    155138        dev_path = *argv;
    156         printf("Device: %s\n", dev_path);
    157139
    158140        rc = loc_service_get_id(dev_path, &service_id, 0);
     
    168150        }
    169151
    170         rc = block_get_bsize(service_id, &cfg.sector_size);
     152        rc = block_get_bsize(service_id, &block_size);
    171153        if (rc != EOK) {
    172154                printf(NAME ": Error determining device block size.\n");
     
    183165        }
    184166
    185         if (cfg.fat_type == FAT12 && cfg.sector_size != 512) {
    186                 printf(NAME ": Error. Device block size is not 512 bytes for FAT12 file system.\n");
     167        if (block_size != 512) {
     168                printf(NAME ": Error. Device block size is not 512 bytes.\n");
    187169                return 2;
    188170        }
     
    193175        }
    194176
    195         printf(NAME ": Creating FAT%d filesystem on device %s.\n", cfg.fat_type, dev_path);
    196 
    197         rc = fat_params_compute(&cfg);
     177        printf(NAME ": Creating FAT filesystem on device %s.\n", dev_path);
     178
     179        rc = fat_params_compute(&cfg, &par);
    198180        if (rc != EOK) {
    199181                printf(NAME ": Invalid file-system parameters.\n");
     
    201183        }
    202184
    203         rc = fat_blocks_write(&cfg, service_id);
     185        rc = fat_blocks_write(&par, service_id);
    204186        if (rc != EOK) {
    205187                printf(NAME ": Error writing device.\n");
     
    215197static void syntax_print(void)
    216198{
    217         printf("syntax: mkfat32 [--size <sectors>] [--type 12|16|32] <device_name>\n");
     199        printf("syntax: mkfat [--size <num_blocks>] <device_name>\n");
    218200}
    219201
     
    223205 * file system params.
    224206 */
    225 static int fat_params_compute(struct fat_cfg *cfg)
     207static int fat_params_compute(struct fat_cfg const *cfg, struct fat_params *par)
    226208{
    227209        uint32_t fat_bytes;
     
    229211
    230212        /*
    231      * Make a conservative guess on the FAT size needed for the file
    232      * system. The optimum could be potentially smaller since we
    233      * do not subtract size of the FAT itself when computing the
    234      * size of the data region.
    235      */
    236 
    237         if (cfg->fat_type == FAT12)
    238                 cfg->sectors_per_cluster = 1;
    239 
    240         cfg->reserved_sectors = 1 + cfg->addt_res_sectors;
    241         if (cfg->fat_type != FAT32) {
    242                 cfg->rootdir_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE,
    243                         cfg->sector_size);
    244         }
    245         else
    246                 cfg->rootdir_sectors = 0;
    247         non_data_sectors_lb = cfg->reserved_sectors + cfg->rootdir_sectors;
    248 
    249         cfg->total_clusters = div_round_up(cfg->total_sectors - non_data_sectors_lb,
    250             cfg->sectors_per_cluster);
    251 
    252         if ((cfg->fat_type == FAT12 && cfg->total_clusters > FAT12_CLST_MAX) ||
    253                 (cfg->fat_type == FAT16 && (cfg->total_clusters <= FAT12_CLST_MAX ||
    254                 cfg->total_clusters > FAT16_CLST_MAX)) ||
    255             (cfg->fat_type == FAT32 && cfg->total_clusters <= FAT16_CLST_MAX))
    256                 return ENOSPC;
    257 
    258         fat_bytes = (cfg->total_clusters + 2) * FAT_SIZE(cfg->fat_type);
    259         cfg->fat_sectors = div_round_up(fat_bytes, cfg->sector_size);
     213         * Make a conservative guess on the FAT size needed for the file
     214         * system. The optimum could be potentially smaller since we
     215         * do not subtract size of the FAT itself when computing the
     216         * size of the data region.
     217         */
     218
     219        par->reserved_sectors = 1 + cfg->addt_res_sectors;
     220        par->rootdir_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE,
     221            sector_size);
     222        non_data_sectors_lb = par->reserved_sectors + par->rootdir_sectors;
     223
     224        par->total_clusters = div_round_up(cfg->total_sectors - non_data_sectors_lb,
     225            sectors_per_cluster);
     226
     227        fat_bytes = (par->total_clusters + 2) * 2;
     228        par->fat_sectors = div_round_up(fat_bytes, sector_size);
     229
     230        par->cfg = *cfg;
    260231
    261232        return EOK;
     
    263234
    264235/** Create file system with the given parameters. */
    265 static int fat_blocks_write(struct fat_cfg const *cfg, service_id_t service_id)
     236static int fat_blocks_write(struct fat_params const *par, service_id_t service_id)
    266237{
    267238        aoff64_t addr;
     
    272243        struct fat_bs bs;
    273244
    274         fat_bootsec_create(cfg, &bs);
     245        fat_bootsec_create(par, &bs);
    275246
    276247        rc = block_write_direct(service_id, BS_BLOCK, 1, &bs);
     
    280251        addr = BS_BLOCK + 1;
    281252
    282         buffer = calloc(cfg->sector_size, 1);
     253        buffer = calloc(sector_size, 1);
    283254        if (buffer == NULL)
    284255                return ENOMEM;
    285         memset(buffer, 0, cfg->sector_size);
    286256
    287257        /* Reserved sectors */
    288         for (i = 0; i < cfg->reserved_sectors - 1; ++i) {
     258        for (i = 0; i < par->reserved_sectors - 1; ++i) {
    289259                rc = block_write_direct(service_id, addr, 1, buffer);
    290260                if (rc != EOK)
     
    295265
    296266        /* File allocation tables */
    297         for (i = 0; i < cfg->fat_count; ++i) {
     267        for (i = 0; i < fat_count; ++i) {
    298268                printf("Writing allocation table %d.\n", i + 1);
    299269
    300                 for (j = 0; j < cfg->fat_sectors; ++j) {
    301                         memset(buffer, 0, cfg->sector_size);
     270                for (j = 0; j < par->fat_sectors; ++j) {
     271                        memset(buffer, 0, sector_size);
    302272                        if (j == 0) {
    303                                 buffer[0] = default_media_descriptor;
     273                                buffer[0] = media_descriptor;
    304274                                buffer[1] = 0xFF;
    305275                                buffer[2] = 0xFF;
    306                                 if (cfg->fat_type == FAT16) {
    307                                         buffer[3] = 0xFF;
    308                                 } else if (cfg->fat_type == FAT32) {
    309                                         buffer[3] = 0x0F;
    310                                         buffer[4] = 0xFF;
    311                                         buffer[5] = 0xFF;
    312                                         buffer[6] = 0xFF;
    313                                         buffer[7] = 0x0F;
    314                                         buffer[8] = 0xF8;
    315                                         buffer[9] = 0xFF;
    316                                         buffer[10] = 0xFF;
    317                                         buffer[11] = 0x0F;
    318                                 }
     276                                buffer[3] = 0xFF;
    319277                        }
    320278
     
    327285        }
    328286
     287        printf("Writing root directory.\n");
     288
     289        memset(buffer, 0, sector_size);
     290
    329291        /* Root directory */
    330         printf("Writing root directory.\n");
    331         memset(buffer, 0, cfg->sector_size);
    332         if (cfg->fat_type != FAT32) {
    333                 size_t idx;
    334                 for (idx = 0; idx < cfg->rootdir_sectors; ++idx) {
    335                         rc = block_write_direct(service_id, addr, 1, buffer);
    336                         if (rc != EOK)
    337                                 return EIO;
    338 
    339                         ++addr;
    340                 }
    341         } else {
    342                 for (i=0; i<cfg->sectors_per_cluster; i++) {
    343                         rc = block_write_direct(service_id, addr, 1, buffer);
    344                         if (rc != EOK)
    345                                 return EIO;
    346 
    347                         ++addr;
    348                 }       
     292        for (i = 0; i < par->rootdir_sectors; ++i) {
     293                rc = block_write_direct(service_id, addr, 1, buffer);
     294                if (rc != EOK)
     295                        return EIO;
     296
     297                ++addr;
    349298        }
    350299
     
    355304
    356305/** Construct boot sector with the given parameters. */
    357 static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs)
     306static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs)
    358307{
    359308        memset(bs, 0, sizeof(*bs));
     
    366315
    367316        /* BIOS Parameter Block */
    368         bs->bps = host2uint16_t_le(cfg->sector_size);
    369         bs->spc = cfg->sectors_per_cluster;
    370         bs->rscnt = host2uint16_t_le(cfg->reserved_sectors);
    371         bs->fatcnt = cfg->fat_count;
    372         bs->root_ent_max = host2uint16_t_le(cfg->root_ent_max);
    373 
    374         if (cfg->total_sectors < 0x10000) {
    375                 bs->totsec16 = host2uint16_t_le(cfg->total_sectors);
    376                 bs->totsec32 = 0;
    377         } else {
    378                 bs->totsec16 = 0;
    379                 bs->totsec32 = host2uint32_t_le(cfg->total_sectors);
    380         }
    381 
    382         bs->mdesc = default_media_descriptor;
     317        bs->bps = host2uint16_t_le(sector_size);
     318        bs->spc = sectors_per_cluster;
     319        bs->rscnt = host2uint16_t_le(par->reserved_sectors);
     320        bs->fatcnt = fat_count;
     321        bs->root_ent_max = host2uint16_t_le(par->cfg.root_ent_max);
     322
     323        if (par->cfg.total_sectors < 0x10000)
     324                bs->totsec16 = host2uint16_t_le(par->cfg.total_sectors);
     325        else
     326                bs->totsec16 = host2uint16_t_le(0);
     327
     328        bs->mdesc = media_descriptor;
     329        bs->sec_per_fat = host2uint16_t_le(par->fat_sectors);
    383330        bs->sec_per_track = host2uint16_t_le(63);
    384         bs->signature = host2uint16_t_be(0x55AA);
    385331        bs->headcnt = host2uint16_t_le(6);
    386332        bs->hidden_sec = host2uint32_t_le(0);
    387333
    388         if (cfg->fat_type == FAT32) {
    389                 bs->sec_per_fat = 0;
    390                 bs->fat32.sectors_per_fat = host2uint32_t_le(cfg->fat_sectors);
    391 
    392                 bs->fat32.pdn = 0x80;
    393                 bs->fat32.ebs = 0x29;
    394                 bs->fat32.id = host2uint32_t_be(0x12345678);
    395                 bs->fat32.root_cluster = 2;
    396 
    397                 memcpy(bs->fat32.label, "HELENOS_NEW", 11);
    398                 memcpy(bs->fat32.type, "FAT32   ", 8);
    399         } else {
    400                 bs->sec_per_fat = host2uint16_t_le(cfg->fat_sectors);
    401                 bs->pdn = 0x80;
    402                 bs->ebs = 0x29;
    403                 bs->id = host2uint32_t_be(0x12345678);
    404 
    405                 memcpy(bs->label, "HELENOS_NEW", 11);
    406                 memcpy(bs->type, "FAT   ", 8);
    407         }
     334        if (par->cfg.total_sectors >= 0x10000)
     335                bs->totsec32 = host2uint32_t_le(par->cfg.total_sectors);
     336        else
     337                bs->totsec32 = host2uint32_t_le(0);
     338
     339        /* Extended BPB */
     340        bs->pdn = 0x80;
     341        bs->ebs = 0x29;
     342        bs->id = host2uint32_t_be(0x12345678);
     343
     344        memcpy(bs->label, "HELENOS_NEW", 11);
     345        memcpy(bs->type, "FAT16   ", 8);
     346        bs->signature = host2uint16_t_be(0x55AA);
    408347}
    409348
  • uspace/lib/c/generic/str.c

    r375ab5e r7fadb65  
    33 * Copyright (c) 2008 Jiri Svoboda
    44 * Copyright (c) 2011 Martin Sucha
    5  * Copyright (c) 2011 Oleg Romanenko
    65 * All rights reserved.
    76 *
     
    368367}
    369368
    370 /** Check whether wide string is plain ASCII.
    371  *
    372  * @return True if wide string is plain ASCII.
    373  *
    374  */
    375 bool wstr_is_ascii(const wchar_t *wstr)
    376 {
    377         while (*wstr && ascii_check(*wstr))
    378                 wstr++;
    379         return *wstr == 0;
    380 }
    381 
    382369/** Check whether character is valid
    383370 *
     
    632619 * @param size  Size of the destination buffer.
    633620 * @param src   Source wide string.
    634  *
    635  * @return EOK, if success, negative otherwise.
    636  */
    637 int wstr_to_str(char *dest, size_t size, const wchar_t *src)
    638 {
    639         int rc;
     621 */
     622void wstr_to_str(char *dest, size_t size, const wchar_t *src)
     623{
    640624        wchar_t ch;
    641625        size_t src_idx;
     
    649633
    650634        while ((ch = src[src_idx++]) != 0) {
    651                 rc = chr_encode(ch, dest, &dest_off, size - 1);
    652                 if (rc != EOK)
     635                if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    653636                        break;
    654637        }
    655638
    656639        dest[dest_off] = '\0';
    657         return rc;
    658 }
    659 
    660 /** Convert UTF16 string to string.
    661  *
    662  * Convert utf16 string @a src to string. The output is written to the buffer
    663  * specified by @a dest and @a size. @a size must be non-zero and the string
    664  * written will always be well-formed. Surrogate pairs also supported.
    665  *
    666  * @param dest  Destination buffer.
    667  * @param size  Size of the destination buffer.
    668  * @param src   Source utf16 string.
    669  *
    670  * @return EOK, if success, negative otherwise.
    671  */
    672 int utf16_to_str(char *dest, size_t size, const uint16_t *src)
    673 {
    674         size_t idx=0, dest_off=0;
    675         wchar_t ch;
    676         int rc = EOK;
    677 
    678         /* There must be space for a null terminator in the buffer. */
    679         assert(size > 0);
    680 
    681         while (src[idx]) {
    682                 if ((src[idx] & 0xfc00) == 0xd800) {
    683                         if (src[idx+1] && (src[idx+1] & 0xfc00) == 0xdc00) {
    684                                 ch = 0x10000;
    685                                 ch += (src[idx] & 0x03FF) << 10;
    686                                 ch += (src[idx+1] & 0x03FF);
    687                                 idx += 2;
    688                         }
    689                         else
    690                                 break;
    691                 } else {
    692                         ch = src[idx];
    693                         idx++;
    694                 }
    695                 rc = chr_encode(ch, dest, &dest_off, size-1);
    696                 if (rc != EOK)
    697                         break;
    698         }
    699         dest[dest_off] = '\0';
    700         return rc;
    701 }
    702 
    703 int str_to_utf16(uint16_t *dest, size_t size, const char *src)
    704 {
    705         int rc=EOK;
    706         size_t offset=0;
    707         size_t idx=0;
    708         wchar_t c;
    709 
    710         assert(size > 0);
    711        
    712         while ((c = str_decode(src, &offset, STR_NO_LIMIT)) != 0) {
    713                 if (c > 0x10000) {
    714                         if (idx+2 >= size-1) {
    715                                 rc=EOVERFLOW;
    716                                 break;
    717                         }
    718                         c = (c - 0x10000);
    719                         dest[idx] = 0xD800 | (c >> 10);
    720                         dest[idx+1] = 0xDC00 | (c & 0x3FF);
    721                         idx++;
    722                 } else {
    723                          dest[idx] = c;
    724                 }
    725 
    726                 idx++;
    727                 if (idx >= size-1) {
    728                         rc=EOVERFLOW;
    729                         break;
    730                 }
    731         }
    732 
    733         dest[idx] = '\0';
    734         return rc;
    735 }
    736 
     640}
    737641
    738642/** Convert wide string to new string.
     
    794698 * @param dlen  Length of destination buffer (number of wchars).
    795699 * @param src   Source string.
    796  *
    797  * @return EOK, if success, negative otherwise.
    798  */
    799 int str_to_wstr(wchar_t *dest, size_t dlen, const char *src)
    800 {
    801         int rc=EOK;
     700 */
     701void str_to_wstr(wchar_t *dest, size_t dlen, const char *src)
     702{
    802703        size_t offset;
    803704        size_t di;
     
    810711
    811712        do {
    812                 if (di >= dlen - 1) {
    813                         rc = EOVERFLOW;
     713                if (di >= dlen - 1)
    814714                        break;
    815                 }
    816715
    817716                c = str_decode(src, &offset, STR_NO_LIMIT);
     
    820719
    821720        dest[dlen - 1] = '\0';
    822         return rc;
    823721}
    824722
     
    885783       
    886784        return (char *) res;
    887 }
    888 
    889 /** Find first occurence of character in wide string.
    890  *
    891  * @param wstr String to search.
    892  * @param ch  Character to look for.
    893  *
    894  * @return Pointer to character in @a wstr or NULL if not found.
    895  */
    896 wchar_t *wstr_chr(const wchar_t *wstr, wchar_t ch)
    897 {
    898         while (*wstr && *wstr != ch)
    899                 wstr++;
    900         if (*wstr)
    901                 return (wchar_t *) wstr;
    902         else
    903                 return NULL;
    904 }
    905 
    906 /** Find last occurence of character in wide string.
    907  *
    908  * @param wstr String to search.
    909  * @param ch  Character to look for.
    910  *
    911  * @return Pointer to character in @a wstr or NULL if not found.
    912  */
    913 wchar_t *wstr_rchr(const wchar_t *wstr, wchar_t ch)
    914 {
    915         const wchar_t *res = NULL;
    916         while (*wstr) {
    917                 if (*wstr == ch)
    918                         res = wstr;
    919                 wstr++;
    920         }
    921         return (wchar_t *) res;
    922785}
    923786
     
    11741037}
    11751038
    1176 void str_reverse(char* begin, char* end)
    1177 {
    1178     char aux;
    1179     while(end>begin)
    1180         aux=*end, *end--=*begin, *begin++=aux;
    1181 }
    1182 
    1183 int size_t_str(size_t value, int base, char* str, size_t size)
    1184 {
    1185     static char num[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    1186     char* wstr=str;
    1187        
    1188         if (size == 0)
    1189                 return EINVAL;
    1190     if (base<2 || base>35) {
    1191         *str='\0';
    1192         return EINVAL;
    1193     }
    1194 
    1195     do {
    1196         *wstr++ = num[value % base];
    1197                 if (--size == 0)
    1198                         return EOVERFLOW;
    1199     } while(value /= base);
    1200     *wstr='\0';
    1201 
    1202     // Reverse string
    1203     str_reverse(str,wstr-1);
    1204         return EOK;
    1205 }
    12061039
    12071040/** Convert initial part of string to unsigned long according to given base.
  • uspace/lib/c/include/str.h

    r375ab5e r7fadb65  
    11/*
    22 * Copyright (c) 2005 Martin Decky
    3  * Copyright (c) 2011 Oleg Romanenko
    43 * All rights reserved.
    54 *
     
    7271extern bool ascii_check(wchar_t ch);
    7372extern bool chr_check(wchar_t ch);
    74 extern bool wstr_is_ascii(const wchar_t *wstr);
    7573
    7674extern int str_cmp(const char *s1, const char *s2);
     
    8179extern void str_append(char *dest, size_t size, const char *src);
    8280
    83 extern int wstr_to_str(char *dest, size_t size, const wchar_t *src);
    8481extern int spascii_to_str(char *dest, size_t size, const uint8_t *src, size_t n);
     82extern void wstr_to_str(char *dest, size_t size, const wchar_t *src);
    8583extern char *wstr_to_astr(const wchar_t *src);
     84extern void str_to_wstr(wchar_t *dest, size_t dlen, const char *src);
    8685extern wchar_t *str_to_awstr(const char *src);
    87 extern int str_to_wstr(wchar_t *dest, size_t dlen, const char *src);
    88 extern int utf16_to_str(char *dest, size_t size, const uint16_t *src);
    89 extern int str_to_utf16(uint16_t *dest, size_t size, const char *src);
    9086
    9187extern char *str_chr(const char *str, wchar_t ch);
    9288extern char *str_rchr(const char *str, wchar_t ch);
    93 extern wchar_t *wstr_chr(const wchar_t *wstr, wchar_t ch);
    94 extern wchar_t *wstr_rchr(const wchar_t *wstr, wchar_t ch);
    9589
    9690extern bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos);
     
    9993extern char *str_dup(const char *);
    10094extern char *str_ndup(const char *, size_t max_size);
    101 
    102 extern void str_reverse(char* begin, char* end);
    103 extern int size_t_str(size_t value, int base, char* str, size_t size);
    10495
    10596extern int str_uint64(const char *, char **, unsigned int, bool, uint64_t *);
  • uspace/srv/fs/fat/Makefile

    r375ab5e r7fadb65  
    3939        fat_idx.c \
    4040        fat_dentry.c \
    41         fat_directory.c \
    4241        fat_fat.c
    4342
  • uspace/srv/fs/fat/fat.c

    r375ab5e r7fadb65  
    22 * Copyright (c) 2006 Martin Decky
    33 * Copyright (c) 2008 Jakub Jermar
    4  * Copyright (c) 2011 Oleg Romanenko
    54 * All rights reserved.
    65 *
  • uspace/srv/fs/fat/fat.h

    r375ab5e r7fadb65  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
    3  * Copyright (c) 2011 Oleg Romanenko
    43 * All rights reserved.
    54 *
     
    5655#define RSCNT(bs)       uint16_t_le2host((bs)->rscnt)
    5756#define FATCNT(bs)      (bs)->fatcnt
    58 #define SF(bs)          (uint16_t_le2host((bs)->sec_per_fat) !=0 ? \
    59     uint16_t_le2host((bs)->sec_per_fat) : \
    60     uint32_t_le2host(bs->fat32.sectors_per_fat))
     57#define SF(bs)          uint16_t_le2host((bs)->sec_per_fat)
    6158#define RDE(bs)         uint16_t_le2host((bs)->root_ent_max)
    6259#define TS(bs)          (uint16_t_le2host((bs)->totsec16) != 0 ? \
  • uspace/srv/fs/fat/fat_dentry.c

    r375ab5e r7fadb65  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
    3  * Copyright (c) 2011 Oleg Romanenko
    43 * All rights reserved.
    54 *
     
    4039#include <ctype.h>
    4140#include <str.h>
    42 #include <errno.h>
    43 #include <byteorder.h>
    44 #include <assert.h>
     41
     42static bool is_d_char(const char ch)
     43{
     44        if (isalnum(ch) || ch == '_')
     45                return true;
     46        else
     47                return false;
     48}
    4549
    4650/** Compare path component with the name read from the dentry.
     
    7680}
    7781
    78 void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
    79 {
    80         unsigned int i;
    81        
    82         for (i = 0; i < FAT_NAME_LEN; i++) {
    83                 if (d->name[i] == FAT_PAD)
    84                         break;
    85                
    86                 if (d->name[i] == FAT_DENTRY_E5_ESC)
    87                         *buf++ = 0xe5;
    88                 else {
    89                         if (d->lcase & FAT_LCASE_LOWER_NAME)
    90                                 *buf++ = tolower(d->name[i]);
    91                         else
    92                                 *buf++ = d->name[i];
    93                 }
    94         }
    95        
    96         if (d->ext[0] != FAT_PAD)
    97                 *buf++ = '.';
    98        
    99         for (i = 0; i < FAT_EXT_LEN; i++) {
    100                 if (d->ext[i] == FAT_PAD) {
    101                         *buf = '\0';
    102                         return;
    103                 }
    104                
    105                 if (d->ext[i] == FAT_DENTRY_E5_ESC)
    106                         *buf++ = 0xe5;
    107                 else {
    108                         if (d->lcase & FAT_LCASE_LOWER_EXT)
    109                                 *buf++ = tolower(d->ext[i]);
    110                         else
    111                                 *buf++ = d->ext[i];
    112                 }
    113         }
    114        
    115         *buf = '\0';
    116 }
    117 
    118 void fat_dentry_name_set(fat_dentry_t *d, const char *name)
    119 {
    120         unsigned int i;
    121         const char fake_ext[] = "   ";
    122         bool lower_name = true;
    123         bool lower_ext = true;
    124        
    125         for (i = 0; i < FAT_NAME_LEN; i++) {
    126                 switch ((uint8_t) *name) {
    127                 case 0xe5:
    128                         d->name[i] = FAT_DENTRY_E5_ESC;
    129                         name++;
    130                         break;
    131                 case '\0':
    132                 case '.':
    133                         d->name[i] = FAT_PAD;
    134                         break;
    135                 default:
    136                         if (isalpha(*name)) {
    137                                 if (!islower(*name))
    138                                         lower_name = false;
    139                         }
    140                        
    141                         d->name[i] = toupper(*name++);
    142                         break;
    143                 }
    144         }
    145        
    146         if (*name++ != '.')
    147                 name = fake_ext;
    148        
    149         for (i = 0; i < FAT_EXT_LEN; i++) {
    150                 switch ((uint8_t) *name) {
    151                 case 0xe5:
    152                         d->ext[i] = FAT_DENTRY_E5_ESC;
    153                         name++;
    154                         break;
    155                 case '\0':
    156                         d->ext[i] = FAT_PAD;
    157                         break;
    158                 default:
    159                         if (isalpha(*name)) {
    160                                 if (!islower(*name))
    161                                         lower_ext = false;
    162                         }
    163                        
    164                         d->ext[i] = toupper(*name++);
    165                         break;
    166                 }
    167         }
    168        
    169         if (lower_name)
    170                 d->lcase |= FAT_LCASE_LOWER_NAME;
    171         else
    172                 d->lcase &= ~FAT_LCASE_LOWER_NAME;
    173        
    174         if (lower_ext)
    175                 d->lcase |= FAT_LCASE_LOWER_EXT;
    176         else
    177                 d->lcase &= ~FAT_LCASE_LOWER_EXT;
    178 }
    179 
    180 fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
    181 {
    182         if (d->attr == FAT_ATTR_LFN) {
    183                 /* long name entry */
    184                 if (FAT_LFN_ORDER(d) & FAT_LFN_ERASED)
    185                         return FAT_DENTRY_FREE;
    186                 else
    187                         return FAT_DENTRY_LFN;
    188         }
    189         if (d->attr & FAT_ATTR_VOLLABEL) {
    190                 /* volume label entry */
    191                 return FAT_DENTRY_SKIP;
    192         }
    193         if (d->name[0] == FAT_DENTRY_ERASED) {
    194                 /* not-currently-used entry */
    195                 return FAT_DENTRY_FREE;
    196         }
    197         if (d->name[0] == FAT_DENTRY_UNUSED) {
    198                 /* never used entry */
    199                 return FAT_DENTRY_LAST;
    200         }
    201         if (d->name[0] == FAT_DENTRY_DOT) {
    202                 /*
    203                  * Most likely '.' or '..'.
    204                  * It cannot occur in a regular file name.
    205                  */
    206                 return FAT_DENTRY_SKIP;
    207         }
    208         return FAT_DENTRY_VALID;
    209 }
    210 
    211 /** Compute checksum of Node name.
    212  *
    213  * Returns an unsigned byte checksum computed on an unsigned byte
    214  * array. The array must be 11 bytes long and is assumed to contain
    215  * a name stored in the format of a MS-DOS directory entry.
    216  *
    217  * @param name          Node name read from the dentry.
    218  *
    219  * @return              An 8-bit unsigned checksum of the name.
    220  */
    221 uint8_t fat_dentry_chksum(uint8_t *name)
    222 {
    223         uint8_t i, sum=0;
    224         for (i=0; i<(FAT_NAME_LEN+FAT_EXT_LEN); i++) {
    225                 sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + name[i];
    226         }
    227         return sum;
    228 }
    229 
    230 /** Get number of bytes in a string with size limit.
    231  *
    232  * @param str  NULL-terminated (or not) string.
    233  * @param size Maximum number of bytes to consider.
    234  *
    235  * @return Number of bytes in string (without 0 and ff).
    236  *
    237  */
    238 size_t fat_lfn_str_nlength(const uint16_t *str, size_t size)
    239 {
    240         size_t offset = 0;
    241 
    242         while (offset < size) {
    243                 if (str[offset] == 0 || str[offset] == FAT_LFN_PAD)
    244                         break;
    245                 offset++;
    246         }
    247         return offset;
    248 }
    249 
    250 /** Get number of bytes in a FAT long entry occuped by characters.
    251  *
    252  * @param d FAT long entry.
    253  *
    254  * @return Number of bytes.
    255  *
    256  */
    257 size_t fat_lfn_size(const fat_dentry_t *d)
    258 {
    259         size_t size = 0;
    260        
    261         size += fat_lfn_str_nlength(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE);
    262         size += fat_lfn_str_nlength(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE);
    263         size += fat_lfn_str_nlength(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE);     
    264        
    265         return size;
    266 }
    267 
    268 size_t fat_lfn_get_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset)
    269 {
    270         int i;
    271         for (i=FAT_LFN_PART3_SIZE-1; i>=0 && *offset>0; i--) {
    272                 if (d->lfn.part3[i] == 0 || d->lfn.part3[i] == FAT_LFN_PAD)
    273                         continue;
    274                 (*offset)--;
    275                 dst[(*offset)] = uint16_t_le2host(d->lfn.part3[i]);
    276         }
    277         for (i=FAT_LFN_PART2_SIZE-1; i>=0 && *offset>0; i--) {
    278                 if (d->lfn.part2[i] == 0 || d->lfn.part2[i] == FAT_LFN_PAD)
    279                         continue;
    280                 (*offset)--;
    281                 dst[(*offset)] = uint16_t_le2host(d->lfn.part2[i]);
    282         }
    283         for (i=FAT_LFN_PART1_SIZE-1; i>=0 && *offset>0; i--) {
    284                 if (d->lfn.part1[i] == 0 || d->lfn.part1[i] == FAT_LFN_PAD)
    285                         continue;
    286                 (*offset)--;
    287                 dst[(*offset)] = uint16_t_le2host(d->lfn.part1[i]);
    288         }
    289         return *offset;
    290 }
    291 
    292 size_t fat_lfn_set_entry(const uint16_t *src, size_t *offset, size_t size, fat_dentry_t *d)
    293 {
    294         size_t idx;
    295         for (idx=0; idx < FAT_LFN_PART1_SIZE; idx++) {
    296                 if (*offset < size) {
    297                         d->lfn.part1[idx] = host2uint16_t_le(src[*offset]);
    298                         (*offset)++;
    299                 }
    300                 else
    301                         d->lfn.part1[idx] = FAT_LFN_PAD;
    302         }
    303         for (idx=0; idx < FAT_LFN_PART2_SIZE; idx++) {
    304                 if (*offset < size) {
    305                         d->lfn.part2[idx] = host2uint16_t_le(src[*offset]);
    306                         (*offset)++;
    307                 }
    308                 else
    309                         d->lfn.part2[idx] = FAT_LFN_PAD;
    310         }
    311         for (idx=0; idx < FAT_LFN_PART3_SIZE; idx++) {
    312                 if (*offset < size) {
    313                         d->lfn.part3[idx] = host2uint16_t_le(src[*offset]);
    314                         (*offset)++;
    315                 }
    316                 else
    317                         d->lfn.part3[idx] = FAT_LFN_PAD;
    318         }
    319 
    320         if (src[*offset] == 0)
    321                 offset++;
    322         FAT_LFN_ATTR(d) = FAT_ATTR_LFN;
    323         d->lfn.type = 0;
    324         d->lfn.firstc_lo = 0;
    325        
    326         return *offset;
    327 }
    328 
    329 void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad)
    330 {
    331         wchar_t ch;
    332         size_t off = 0;
    333         size_t i = 0;
    334        
    335         while (i < count) {
    336                 if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) {
    337                         if (ascii_check(ch) & IS_D_CHAR(ch))
    338                                 *dst = toupper(ch);
    339                         else
    340                                 *dst = pad;
    341                 }
    342                 else
    343                         break;
    344 
    345                 dst++;
    346                 i++;
    347         }
    348         *dst = '\0';
    349 }
    350 
    351 bool fat_valid_name(const char *name)
    352 {
    353         wchar_t ch;
    354         size_t offset=0;
    355         bool result = true;
    356        
    357         while ((ch = str_decode(name, &offset, STR_NO_LIMIT)) != 0) {
    358                 if (wstr_chr(FAT_STOP_CHARS, ch) != NULL) {
    359                         result = false;
    360                         break;
    361                 }
    362         }
    363         return result;
    364 }
    365 
    366 bool fat_valid_short_name(const char *name)
     82bool fat_dentry_name_verify(const char *name)
    36783{
    36884        unsigned int i;
    36985        unsigned int dot = 0;
    37086        bool dot_found = false;
     87       
    37188
    37289        for (i = 0; name[i]; i++) {
     
    37996                        }
    38097                } else {
    381                         if (!IS_D_CHAR(name[i]))
     98                        if (!is_d_char(name[i]))
    38299                                return false;
    383100                }
     
    397114}
    398115
    399 size_t utf16_length(const uint16_t *wstr)
    400 {
    401         size_t len = 0;
    402        
    403         while (*wstr++ != 0)
    404                 len++;
    405        
    406         return len;
     116void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
     117{
     118        unsigned int i;
     119       
     120        for (i = 0; i < FAT_NAME_LEN; i++) {
     121                if (d->name[i] == FAT_PAD)
     122                        break;
     123               
     124                if (d->name[i] == FAT_DENTRY_E5_ESC)
     125                        *buf++ = 0xe5;
     126                else {
     127                        if (d->lcase & FAT_LCASE_LOWER_NAME)
     128                                *buf++ = tolower(d->name[i]);
     129                        else
     130                                *buf++ = d->name[i];
     131                }
     132        }
     133       
     134        if (d->ext[0] != FAT_PAD)
     135                *buf++ = '.';
     136       
     137        for (i = 0; i < FAT_EXT_LEN; i++) {
     138                if (d->ext[i] == FAT_PAD) {
     139                        *buf = '\0';
     140                        return;
     141                }
     142               
     143                if (d->ext[i] == FAT_DENTRY_E5_ESC)
     144                        *buf++ = 0xe5;
     145                else {
     146                        if (d->lcase & FAT_LCASE_LOWER_EXT)
     147                                *buf++ = tolower(d->ext[i]);
     148                        else
     149                                *buf++ = d->ext[i];
     150                }
     151        }
     152       
     153        *buf = '\0';
     154}
     155
     156void fat_dentry_name_set(fat_dentry_t *d, const char *name)
     157{
     158        unsigned int i;
     159        const char fake_ext[] = "   ";
     160        bool lower_name = true;
     161        bool lower_ext = true;
     162       
     163        for (i = 0; i < FAT_NAME_LEN; i++) {
     164                switch ((uint8_t) *name) {
     165                case 0xe5:
     166                        d->name[i] = FAT_DENTRY_E5_ESC;
     167                        name++;
     168                        break;
     169                case '\0':
     170                case '.':
     171                        d->name[i] = FAT_PAD;
     172                        break;
     173                default:
     174                        if (isalpha(*name)) {
     175                                if (!islower(*name))
     176                                        lower_name = false;
     177                        }
     178                       
     179                        d->name[i] = toupper(*name++);
     180                        break;
     181                }
     182        }
     183       
     184        if (*name++ != '.')
     185                name = fake_ext;
     186       
     187        for (i = 0; i < FAT_EXT_LEN; i++) {
     188                switch ((uint8_t) *name) {
     189                case 0xe5:
     190                        d->ext[i] = FAT_DENTRY_E5_ESC;
     191                        name++;
     192                        break;
     193                case '\0':
     194                        d->ext[i] = FAT_PAD;
     195                        break;
     196                default:
     197                        if (isalpha(*name)) {
     198                                if (!islower(*name))
     199                                        lower_ext = false;
     200                        }
     201                       
     202                        d->ext[i] = toupper(*name++);
     203                        break;
     204                }
     205        }
     206       
     207        if (lower_name)
     208                d->lcase |= FAT_LCASE_LOWER_NAME;
     209        else
     210                d->lcase &= ~FAT_LCASE_LOWER_NAME;
     211       
     212        if (lower_ext)
     213                d->lcase |= FAT_LCASE_LOWER_EXT;
     214        else
     215                d->lcase &= ~FAT_LCASE_LOWER_EXT;
     216}
     217
     218fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
     219{
     220        if (d->attr & FAT_ATTR_VOLLABEL) {
     221                /* volume label entry */
     222                return FAT_DENTRY_SKIP;
     223        }
     224        if (d->name[0] == FAT_DENTRY_ERASED) {
     225                /* not-currently-used entry */
     226                return FAT_DENTRY_FREE;
     227        }
     228        if (d->name[0] == FAT_DENTRY_UNUSED) {
     229                /* never used entry */
     230                return FAT_DENTRY_LAST;
     231        }
     232        if (d->name[0] == FAT_DENTRY_DOT) {
     233                /*
     234                 * Most likely '.' or '..'.
     235                 * It cannot occur in a regular file name.
     236                 */
     237                return FAT_DENTRY_SKIP;
     238        }
     239        return FAT_DENTRY_VALID;
    407240}
    408241
  • uspace/srv/fs/fat/fat_dentry.h

    r375ab5e r7fadb65  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
    3  * Copyright (c) 2011 Oleg Romanenko
    43 * All rights reserved.
    54 *
     
    3837#include <bool.h>
    3938
    40 #define IS_D_CHAR(ch) (isalnum(ch) || ch == '_')
    41 #define FAT_STOP_CHARS L"*?/\\\n\t|'"
    42 
    4339#define FAT_NAME_LEN            8
    4440#define FAT_EXT_LEN             3
     
    4844#define FAT_EXT_PAD             "   "
    4945
    50 #define FAT_ATTR_RDONLY   0x01
    51 #define FAT_ATTR_HIDDEN   0x02
    52 #define FAT_ATTR_SYSTEM   0x04
    53 #define FAT_ATTR_VOLLABEL 0x08
    54 #define FAT_ATTR_SUBDIR   0x10
    55 #define FAT_ATTR_ARCHIVE  0x20
    56 #define FAT_ATTR_LFN \
    57     (FAT_ATTR_RDONLY | FAT_ATTR_HIDDEN | FAT_ATTR_SYSTEM | FAT_ATTR_VOLLABEL)
    58    
     46#define FAT_ATTR_RDONLY         (1 << 0)
     47#define FAT_ATTR_VOLLABEL       (1 << 3)
     48#define FAT_ATTR_SUBDIR         (1 << 4)
     49
    5950#define FAT_LCASE_LOWER_NAME    0x08
    6051#define FAT_LCASE_LOWER_EXT     0x10
    6152
    62 #define FAT_PAD                 ' '
    63 #define FAT_LFN_PAD     0xffff
    64 #define FAT_SFN_CHAR '_'
     53#define FAT_PAD                 ' '
    6554
    6655#define FAT_DENTRY_UNUSED       0x00
     
    6857#define FAT_DENTRY_DOT          0x2e
    6958#define FAT_DENTRY_ERASED       0xe5
    70 #define FAT_LFN_LAST            0x40
    71 #define FAT_LFN_ERASED          0x80
    72 
    73 #define FAT_LFN_ORDER(d) (d->lfn.order)
    74 #define FAT_IS_LFN(d) \
    75     ((FAT_LFN_ORDER(d) & FAT_LFN_LAST) == FAT_LFN_LAST)
    76 #define FAT_LFN_COUNT(d) \
    77     (FAT_LFN_ORDER(d) ^ FAT_LFN_LAST)
    78 #define FAT_LFN_PART1(d) (d->lfn.part1)
    79 #define FAT_LFN_PART2(d) (d->lfn.part2)
    80 #define FAT_LFN_PART3(d) (d->lfn.part3)
    81 #define FAT_LFN_ATTR(d) (d->lfn.attr)
    82 #define FAT_LFN_CHKSUM(d) (d->lfn.check_sum)
    83 
    84 #define FAT_LFN_NAME_SIZE   260
    85 #define FAT_LFN_MAX_COUNT   20
    86 #define FAT_LFN_PART1_SIZE  5
    87 #define FAT_LFN_PART2_SIZE  6
    88 #define FAT_LFN_PART3_SIZE  2
    89 #define FAT_LFN_ENTRY_SIZE \
    90     (FAT_LFN_PART1_SIZE + FAT_LFN_PART2_SIZE + FAT_LFN_PART3_SIZE)
    9159
    9260typedef enum {
     
    9462        FAT_DENTRY_LAST,
    9563        FAT_DENTRY_FREE,
    96         FAT_DENTRY_VALID,
    97         FAT_DENTRY_LFN
     64        FAT_DENTRY_VALID
    9865} fat_dentry_clsf_t;
    9966
    10067typedef struct {
     68        uint8_t         name[8];
     69        uint8_t         ext[3];
     70        uint8_t         attr;
     71        uint8_t         lcase;
     72        uint8_t         ctime_fine;
     73        uint16_t        ctime;
     74        uint16_t        cdate;
     75        uint16_t        adate;
    10176        union {
    102                 struct {
    103                         uint8_t         name[8];
    104                         uint8_t         ext[3];
    105                         uint8_t         attr;
    106                         uint8_t         lcase;
    107                         uint8_t         ctime_fine;
    108                         uint16_t        ctime;
    109                         uint16_t        cdate;
    110                         uint16_t        adate;
    111                         union {
    112                                 uint16_t        eaidx;          /* FAT12/FAT16 */
    113                                 uint16_t        firstc_hi;      /* FAT32 */
    114                         } __attribute__ ((packed));
    115                         uint16_t        mtime;
    116                         uint16_t        mdate;
    117                         union {
    118                                 uint16_t        firstc;         /* FAT12/FAT16 */
    119                                 uint16_t        firstc_lo;      /* FAT32 */
    120                         } __attribute__ ((packed));
    121                         uint32_t        size;
    122                 } __attribute__ ((packed));
    123                 struct {
    124                         uint8_t         order;
    125                         uint16_t        part1[FAT_LFN_PART1_SIZE];
    126                         uint8_t         attr;
    127                         uint8_t         type;
    128                         uint8_t         check_sum;
    129                         uint16_t        part2[FAT_LFN_PART2_SIZE];
    130                         uint16_t        firstc_lo; /* MUST be 0 */
    131                         uint16_t        part3[FAT_LFN_PART3_SIZE];
    132                 } __attribute__ ((packed)) lfn;
    133         };
     77                uint16_t        eaidx;          /* FAT12/FAT16 */
     78                uint16_t        firstc_hi;      /* FAT32 */
     79        } __attribute__ ((packed));
     80        uint16_t        mtime;
     81        uint16_t        mdate;
     82        union {
     83                uint16_t        firstc;         /* FAT12/FAT16 */
     84                uint16_t        firstc_lo;      /* FAT32 */
     85        } __attribute__ ((packed));
     86        uint32_t        size;
    13487} __attribute__ ((packed)) fat_dentry_t;
    13588
    136 
    13789extern int fat_dentry_namecmp(char *, const char *);
     90extern bool fat_dentry_name_verify(const char *);
    13891extern void fat_dentry_name_get(const fat_dentry_t *, char *);
    13992extern void fat_dentry_name_set(fat_dentry_t *, const char *);
    14093extern fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *);
    141 extern uint8_t fat_dentry_chksum(uint8_t *);
    142 
    143 extern size_t fat_lfn_str_nlength(const uint16_t *, size_t);
    144 extern size_t fat_lfn_size(const fat_dentry_t *);
    145 extern size_t fat_lfn_get_entry(const fat_dentry_t *, uint16_t *, size_t *);
    146 extern size_t fat_lfn_set_entry(const uint16_t *, size_t *, size_t, fat_dentry_t *);
    147 
    148 extern void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad);
    149 extern size_t utf16_length(const uint16_t *wstr);
    150 
    151 extern bool fat_valid_name(const char *name);
    152 extern bool fat_valid_short_name(const char *name);
    153 
    15494
    15595#endif
  • uspace/srv/fs/fat/fat_fat.c

    r375ab5e r7fadb65  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
    3  * Copyright (c) 2011 Oleg Romanenko
    43 * All rights reserved.
    54 *
     
    3029/** @addtogroup fs
    3130 * @{
    32  */
     31 */ 
    3332
    3433/**
     
    5554 * primitive boot sector members.
    5655 */
     56#define RDS(bs)         ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
     57                        (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
     58#define SSA(bs)         (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
     59
    5760#define CLBN2PBN(bs, cl, bn) \
    5861        (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
    59 
    60 #define IS_ODD(number)  (number & 0x1)
    6162
    6263/**
     
    6465 * during allocation of clusters. The lock does not have to be held durring
    6566 * deallocation of clusters.
    66  */
     67 */ 
    6768static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    6869
     
    7677 * @param numc          If non-NULL, output argument holding the number of
    7778 *                      clusters seen during the walk.
    78  * @param max_clusters  Maximum number of clusters to visit.
     79 * @param max_clusters  Maximum number of clusters to visit.   
    7980 *
    8081 * @return              EOK on success or a negative error code.
    8182 */
    82 int
     83int 
    8384fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc,
    84     fat_cluster_t *lastc, uint32_t *numc, uint32_t max_clusters)
    85 {
    86         uint32_t clusters = 0;
    87         fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs);
    88         fat_cluster_t clst_bad = FAT_CLST_BAD(bs);
     85    fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
     86{
     87        block_t *b;
     88        uint16_t clusters = 0;
     89        fat_cluster_t clst = firstc;
    8990        int rc;
    9091
     
    9899        }
    99100
    100         while (clst < clst_last1 && clusters < max_clusters) {
     101        while (clst < FAT_CLST_LAST1 && clusters < max_clusters) {
     102                aoff64_t fsec;  /* sector offset relative to FAT1 */
     103                unsigned fidx;  /* FAT1 entry index */
     104
    101105                assert(clst >= FAT_CLST_FIRST);
    102106                if (lastc)
    103107                        *lastc = clst;  /* remember the last cluster number */
    104 
     108                fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
     109                fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
    105110                /* read FAT1 */
    106                 rc = fat_get_cluster(bs, service_id, FAT1, clst, &clst);
    107                 if (rc != EOK)
    108                         return rc;
    109 
    110                 assert(clst != clst_bad);
     111                rc = block_get(&b, service_id, RSCNT(bs) + fsec,
     112                    BLOCK_FLAGS_NONE);
     113                if (rc != EOK)
     114                        return rc;
     115                clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
     116                assert(clst != FAT_CLST_BAD);
     117                rc = block_put(b);
     118                if (rc != EOK)
     119                        return rc;
    111120                clusters++;
    112121        }
    113122
    114         if (lastc && clst < clst_last1)
     123        if (lastc && clst < FAT_CLST_LAST1)
    115124                *lastc = clst;
    116125        if (numc)
     
    142151                return ELIMIT;
    143152
    144         if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)
     153        if (nodep->firstc == FAT_CLST_ROOT)
    145154                goto fall_through;
    146155
     
    169178        if (rc != EOK)
    170179                return rc;
    171 
     180       
    172181        /*
    173182         * Update the "current" cluster cache.
     
    189198 * @param clp           If not NULL, address where the cluster containing bn
    190199 *                      will be stored.
    191  *                      stored
     200 *                      stored 
    192201 * @param bn            Block number.
    193202 * @param flags         Flags passed to libblock.
     
    199208    fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
    200209{
    201         uint32_t clusters;
    202         uint32_t max_clusters;
     210        uint16_t clusters;
     211        unsigned max_clusters;
    203212        fat_cluster_t c;
    204213        int rc;
     
    210219                return ELIMIT;
    211220
    212         if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) {
     221        if (fcl == FAT_CLST_ROOT) {
    213222                /* root directory special case */
    214223                assert(bn < RDS(bs));
     
    266275                        return rc;
    267276        }
    268 
     277       
    269278        if (o >= pos)
    270279                return EOK;
    271 
     280       
    272281        /* zero out the initial part of the new cluster chain */
    273282        for (o = boundary; o < pos; o += BPS(bs)) {
     
    286295}
    287296
    288 /** Get cluster from the first FAT. FAT12 version
     297/** Get cluster from the first FAT.
    289298 *
    290299 * @param bs            Buffer holding the boot sector for the file system.
     
    296305 */
    297306int
    298 fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     307fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    299308    fat_cluster_t clst, fat_cluster_t *value)
    300309{
    301         block_t *b, *b1;
    302         uint16_t byte1, byte2;
    303         aoff64_t offset;
    304         int rc;
    305 
    306         offset = (clst + clst/2);
    307         if (offset / BPS(bs) >= SF(bs))
    308                 return ERANGE;
     310        block_t *b;
     311        fat_cluster_t *cp;
     312        int rc;
    309313
    310314        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    311             offset / BPS(bs), BLOCK_FLAGS_NONE);
     315            (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    312316        if (rc != EOK)
    313317                return rc;
    314 
    315         byte1 = ((uint8_t*) b->data)[offset % BPS(bs)];
    316         /* This cluster access spans a sector boundary. Check only for FAT12 */
    317         if ((offset % BPS(bs)) + 1 == BPS(bs)) {
    318                 /* Is it last sector of FAT? */
    319                 if (offset / BPS(bs) < SF(bs)) {
    320                         /* No. Reading next sector */
    321                         rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
    322                                 SF(bs)*fatno + offset / BPS(bs), BLOCK_FLAGS_NONE);
    323                         if (rc != EOK) {
    324                                 block_put(b);
    325                                 return rc;
    326                         }
    327                         /*
    328                         * Combining value with last byte of current sector and
    329                         * first byte of next sector
    330                         */
    331                         byte2 = ((uint8_t*) b1->data)[0];
    332 
    333                         rc = block_put(b1);
    334                         if (rc != EOK) {
    335                                 block_put(b);
    336                                 return rc;
    337                         }
    338                 }
    339                 else {
    340                         /* Yes. It is last sector of FAT */
    341                         block_put(b);
    342                         return ERANGE;
    343                 }
    344         }
    345         else
    346                 byte2 = ((uint8_t*) b->data)[(offset % BPS(bs))+1];
    347 
    348         *value = uint16_t_le2host(byte1 | (byte2 << 8));
    349         if (IS_ODD(clst))
    350                 *value = (*value) >> 4;
    351         else
    352                 *value = (*value) & FAT12_MASK;
     318        cp = (fat_cluster_t *)b->data +
     319            clst % (BPS(bs) / sizeof(fat_cluster_t));
     320        *value = uint16_t_le2host(*cp);
     321        rc = block_put(b);
    353322       
    354         rc = block_put(b);
    355         return rc;
    356 }
    357 
    358 /** Get cluster from the first FAT. FAT16 version
    359  *
    360  * @param bs            Buffer holding the boot sector for the file system.
    361  * @param service_id    Service ID for the file system.
    362  * @param clst          Cluster which to get.
    363  * @param value         Output argument holding the value of the cluster.
    364  *
    365  * @return              EOK or a negative error code.
    366  */
    367 int
    368 fat_get_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    369     fat_cluster_t clst, fat_cluster_t *value)
    370 {
    371         block_t *b;
    372         aoff64_t offset;
    373         int rc;
    374 
    375         offset = (clst * FAT16_CLST_SIZE);
    376 
    377         rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    378             offset / BPS(bs), BLOCK_FLAGS_NONE);
    379         if (rc != EOK)
    380                 return rc;
    381 
    382         *value = uint16_t_le2host(*(uint16_t *)(b->data + offset % BPS(bs)));
    383 
    384         rc = block_put(b);
    385 
    386         return rc;
    387 }
    388 
    389 /** Get cluster from the first FAT. FAT32 version
    390  *
    391  * @param bs            Buffer holding the boot sector for the file system.
    392  * @param service_id    Service ID for the file system.
    393  * @param clst          Cluster which to get.
    394  * @param value         Output argument holding the value of the cluster.
    395  *
    396  * @return              EOK or a negative error code.
    397  */
    398 int
    399 fat_get_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    400     fat_cluster_t clst, fat_cluster_t *value)
    401 {
    402         block_t *b;
    403         aoff64_t offset;
    404         int rc;
    405 
    406         offset = (clst * FAT32_CLST_SIZE);
    407 
    408         rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    409             offset / BPS(bs), BLOCK_FLAGS_NONE);
    410         if (rc != EOK)
    411                 return rc;
    412 
    413         *value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))) & FAT32_MASK;
    414 
    415         rc = block_put(b);
    416 
    417         return rc;
    418 }
    419 
    420 
    421 /** Get cluster from the first FAT.
    422  *
    423  * @param bs            Buffer holding the boot sector for the file system.
    424  * @param service_id    Service ID for the file system.
    425  * @param clst          Cluster which to get.
    426  * @param value         Output argument holding the value of the cluster.
    427  *
    428  * @return              EOK or a negative error code.
    429  */
    430 int
    431 fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    432     fat_cluster_t clst, fat_cluster_t *value)
    433 {
    434         int rc;
    435 
    436         assert(fatno < FATCNT(bs));
    437 
    438         if (FAT_IS_FAT12(bs)) {
    439                 rc = fat_get_cluster_fat12(bs, service_id, fatno, clst, value);
    440         }
    441         else {
    442                 if (FAT_IS_FAT32(bs))
    443                         rc = fat_get_cluster_fat32(bs, service_id, fatno, clst, value);
    444                 else
    445                         rc = fat_get_cluster_fat16(bs, service_id, fatno, clst, value);
    446         }
    447 
    448         return rc;
    449 }
    450 
    451 /** Set cluster in one instance of FAT. FAT12 version.
    452  *
    453  * @param bs            Buffer holding the boot sector for the file system.
    454  * @param service_id    Service ID for the file system.
    455  * @param fatno         Number of the FAT instance where to make the change.
    456  * @param clst          Cluster which is to be set.
    457  * @param value         Value to set the cluster with.
    458  *
    459  * @return              EOK on success or a negative error code.
    460  */
    461 int
    462 fat_set_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    463     fat_cluster_t clst, fat_cluster_t value)
    464 {
    465         block_t *b, *b1=NULL;
    466         aoff64_t offset;
    467         uint16_t byte1, byte2;
    468         int rc;
    469 
    470         offset = (clst + clst/2);
    471         if (offset / BPS(bs) >= SF(bs))
    472                 return ERANGE;
    473        
    474         rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    475             offset / BPS(bs), BLOCK_FLAGS_NONE);
    476         if (rc != EOK)
    477                 return rc;
    478 
    479         byte1 = ((uint8_t*) b->data)[offset % BPS(bs)];
    480         bool border = false;
    481         /* This cluster access spans a sector boundary. Check only for FAT12 */
    482         if ((offset % BPS(bs))+1 == BPS(bs)) {
    483                 /* Is it last sector of FAT? */
    484                 if (offset / BPS(bs) < SF(bs)) {
    485                         /* No. Reading next sector */
    486                         rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
    487                                 SF(bs)*fatno + offset / BPS(bs), BLOCK_FLAGS_NONE);
    488                         if (rc != EOK) {
    489                                 block_put(b);
    490                                 return rc;
    491                         }
    492                         /*
    493                          * Combining value with last byte of current sector and
    494                          * first byte of next sector
    495                          */
    496                         byte2 = ((uint8_t*) b1->data)[0];
    497                         border = true;
    498                 }
    499                 else {
    500                         /* Yes. It is last sector of fat */
    501                         block_put(b);
    502                         return ERANGE;
    503                 }
    504         }
    505         else
    506                 byte2 = ((uint8_t*) b->data)[(offset % BPS(bs))+1];
    507 
    508         if (IS_ODD(clst)) {
    509                 byte1 &= 0x0f;
    510                 byte2 = 0;
    511                 value = (value << 4);
    512         } else {
    513                 byte1 = 0;
    514                 byte2 &= 0xf0;
    515                 value &= FAT12_MASK;
    516         }
    517 
    518         byte1 = byte1 | (value & 0xff);
    519         byte2 = byte2 | (value >> 8);
    520 
    521         ((uint8_t*) b->data)[(offset % BPS(bs))] = byte1;
    522         if (border) {
    523                 ((uint8_t*) b1->data)[0] = byte2;
    524 
    525                 b1->dirty = true;
    526                 rc = block_put(b1);
    527                 if (rc != EOK) {
    528                         block_put(b);
    529                         return rc;
    530                 }
    531         } else
    532                 ((uint8_t*) b->data)[(offset % BPS(bs))+1] = byte2;
    533 
    534         b->dirty = true;        /* need to sync block */
    535         rc = block_put(b);
    536         return rc;
    537 }
    538 
    539 /** Set cluster in one instance of FAT. FAT16 version.
    540  *
    541  * @param bs            Buffer holding the boot sector for the file system.
    542  * @param service_id    Service ID for the file system.
    543  * @param fatno         Number of the FAT instance where to make the change.
    544  * @param clst          Cluster which is to be set.
    545  * @param value         Value to set the cluster with.
    546  *
    547  * @return              EOK on success or a negative error code.
    548  */
    549 int
    550 fat_set_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    551     fat_cluster_t clst, fat_cluster_t value)
    552 {
    553         block_t *b;
    554         aoff64_t offset;
    555         int rc;
    556 
    557         offset = (clst * FAT16_CLST_SIZE);
    558 
    559         rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    560             offset / BPS(bs), BLOCK_FLAGS_NONE);
    561         if (rc != EOK)
    562                 return rc;
    563 
    564         *(uint16_t *)(b->data + offset % BPS(bs)) = host2uint16_t_le(value);
    565 
    566         b->dirty = true;        /* need to sync block */
    567         rc = block_put(b);
    568         return rc;
    569 }
    570 
    571 /** Set cluster in one instance of FAT. FAT32 version.
    572  *
    573  * @param bs            Buffer holding the boot sector for the file system.
    574  * @param service_id    Service ID for the file system.
    575  * @param fatno         Number of the FAT instance where to make the change.
    576  * @param clst          Cluster which is to be set.
    577  * @param value         Value to set the cluster with.
    578  *
    579  * @return              EOK on success or a negative error code.
    580  */
    581 int
    582 fat_set_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    583     fat_cluster_t clst, fat_cluster_t value)
    584 {
    585         block_t *b;
    586         aoff64_t offset;
    587         int rc;
    588         fat_cluster_t temp;
    589 
    590         offset = (clst * FAT32_CLST_SIZE);
    591 
    592         rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    593             offset / BPS(bs), BLOCK_FLAGS_NONE);
    594         if (rc != EOK)
    595                 return rc;
    596 
    597         temp = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs)));
    598         temp &= 0xf0000000;
    599         temp |= (value & FAT32_MASK);
    600         *(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(temp);
    601 
    602         b->dirty = true;        /* need to sync block */
    603         rc = block_put(b);
    604323        return rc;
    605324}
     
    619338    fat_cluster_t clst, fat_cluster_t value)
    620339{
     340        block_t *b;
     341        fat_cluster_t *cp;
    621342        int rc;
    622343
    623344        assert(fatno < FATCNT(bs));
    624 
    625         if (FAT_IS_FAT12(bs))
    626                 rc = fat_set_cluster_fat12(bs, service_id, fatno, clst, value);
    627         else if (FAT_IS_FAT32(bs))
    628                 rc = fat_set_cluster_fat32(bs, service_id, fatno, clst, value);
    629         else
    630                 rc = fat_set_cluster_fat16(bs, service_id, fatno, clst, value);
    631 
     345        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     346            (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
     347        if (rc != EOK)
     348                return rc;
     349        cp = (fat_cluster_t *)b->data +
     350            clst % (BPS(bs) / sizeof(fat_cluster_t));
     351        *cp = host2uint16_t_le(value);
     352        b->dirty = true;                /* need to sync block */
     353        rc = block_put(b);
    632354        return rc;
    633355}
     
    647369        uint8_t fatno;
    648370        unsigned c;
    649         fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    650         int rc;
    651 
    652         for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) {
     371        int rc;
     372
     373        for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
    653374                for (c = 0; c < nclsts; c++) {
    654375                        rc = fat_set_cluster(bs, service_id, fatno, lifo[c],
    655                             c == 0 ? clst_last1 : lifo[c - 1]);
     376                            c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
    656377                        if (rc != EOK)
    657378                                return rc;
     
    683404    fat_cluster_t *mcl, fat_cluster_t *lcl)
    684405{
    685         fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    686         unsigned found = 0;     /* top of the free cluster number stack */
    687         fat_cluster_t clst, value, clst_last1 = FAT_CLST_LAST1(bs);
    688         int rc = EOK;
     406        block_t *blk;
     407        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
     408        unsigned found = 0;     /* top of the free cluster number stack */
     409        unsigned b, c, cl;
     410        int rc;
    689411
    690412        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
    691413        if (!lifo)
    692414                return ENOMEM;
     415       
    693416        /*
    694417         * Search FAT1 for unused clusters.
    695418         */
    696419        fibril_mutex_lock(&fat_alloc_lock);
    697         for (clst=FAT_CLST_FIRST; clst < CC(bs)+2 && found < nclsts; clst++) {
    698                 rc = fat_get_cluster(bs, service_id, FAT1, clst, &value);
    699                 if (rc != EOK)
    700                 break;
    701 
    702                 if (value == FAT_CLST_RES0) {
    703                 /*
    704                  * The cluster is free. Put it into our stack
    705                  * of found clusters and mark it as non-free.
    706                  */
    707                 lifo[found] = clst;
    708                 rc = fat_set_cluster(bs, service_id, FAT1, clst,
    709                     (found == 0) ?  clst_last1 : lifo[found - 1]);
    710                 if (rc != EOK)
    711                         break;
    712 
    713                 found++;
     420        for (b = 0, cl = 0; b < SF(bs); b++) {
     421                rc = block_get(&blk, service_id, RSCNT(bs) + b,
     422                    BLOCK_FLAGS_NONE);
     423                if (rc != EOK)
     424                        goto error;
     425                for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) {
     426                        /*
     427                         * Check if the entire cluster is physically there.
     428                         * This check becomes necessary when the file system is
     429                         * created with fewer total sectors than how many is
     430                         * inferred from the size of the file allocation table
     431                         * or when the last cluster ends beyond the end of the
     432                         * device.
     433                         */
     434                        if ((cl >= FAT_CLST_FIRST) &&
     435                            CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) {
     436                                rc = block_put(blk);
     437                                if (rc != EOK)
     438                                        goto error;
     439                                goto out;
     440                        }
     441
     442                        fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
     443                        if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
     444                                /*
     445                                 * The cluster is free. Put it into our stack
     446                                 * of found clusters and mark it as non-free.
     447                                 */
     448                                lifo[found] = cl;
     449                                *clst = (found == 0) ?
     450                                    host2uint16_t_le(FAT_CLST_LAST1) :
     451                                    host2uint16_t_le(lifo[found - 1]);
     452                                blk->dirty = true;      /* need to sync block */
     453                                if (++found == nclsts) {
     454                                        /* we are almost done */
     455                                        rc = block_put(blk);
     456                                        if (rc != EOK)
     457                                                goto error;
     458                                        /* update the shadow copies of FAT */
     459                                        rc = fat_alloc_shadow_clusters(bs,
     460                                            service_id, lifo, nclsts);
     461                                        if (rc != EOK)
     462                                                goto error;
     463                                        *mcl = lifo[found - 1];
     464                                        *lcl = lifo[0];
     465                                        free(lifo);
     466                                        fibril_mutex_unlock(&fat_alloc_lock);
     467                                        return EOK;
     468                                }
     469                        }
    714470                }
    715         }
    716 
    717         if (rc == EOK && found == nclsts) {
    718                 rc = fat_alloc_shadow_clusters(bs, service_id, lifo, nclsts);
    719                 if (rc == EOK) {
    720                         *mcl = lifo[found - 1];
    721                         *lcl = lifo[0];
     471                rc = block_put(blk);
     472                if (rc != EOK) {
     473error:
     474                        fibril_mutex_unlock(&fat_alloc_lock);
    722475                        free(lifo);
    723                         fibril_mutex_unlock(&fat_alloc_lock);
    724                         return EOK;
     476                        return rc;
    725477                }
    726478        }
    727 
    728         /* If something wrong - free the clusters */
    729         if (found > 0) {
    730                 while (found--) {
     479out:
     480        fibril_mutex_unlock(&fat_alloc_lock);
     481
     482        /*
     483         * We could not find enough clusters. Now we need to free the clusters
     484         * we have allocated so far.
     485         */
     486        while (found--) {
    731487                rc = fat_set_cluster(bs, service_id, FAT1, lifo[found],
    732488                    FAT_CLST_RES0);
     489                if (rc != EOK) {
     490                        free(lifo);
     491                        return rc;
    733492                }
    734493        }
    735 
     494       
    736495        free(lifo);
    737         fibril_mutex_unlock(&fat_alloc_lock);
    738496        return ENOSPC;
    739497}
     
    751509{
    752510        unsigned fatno;
    753         fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs);
     511        fat_cluster_t nextc;
    754512        int rc;
    755513
    756514        /* Mark all clusters in the chain as free in all copies of FAT. */
    757         while (firstc < FAT_CLST_LAST1(bs)) {
    758                 assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);
     515        while (firstc < FAT_CLST_LAST1) {
     516                assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
    759517                rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc);
    760518                if (rc != EOK)
    761519                        return rc;
    762                 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
     520                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    763521                        rc = fat_set_cluster(bs, service_id, fatno, firstc,
    764522                            FAT_CLST_RES0);
     
    806564                }
    807565
    808                 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
    809                         rc = fat_set_cluster(bs, nodep->idx->service_id,
    810                             fatno, lastc, mcl);
     566                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     567                        rc = fat_set_cluster(bs, nodep->idx->service_id, fatno,
     568                            lastc, mcl);
    811569                        if (rc != EOK)
    812570                                return rc;
     
    832590int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl)
    833591{
    834         fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    835592        int rc;
    836593        service_id_t service_id = nodep->idx->service_id;
     
    859616
    860617                /* Terminate the cluster chain in all copies of FAT. */
    861                 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
     618                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    862619                        rc = fat_set_cluster(bs, service_id, fatno, lcl,
    863                             clst_last1);
     620                            FAT_CLST_LAST1);
    864621                        if (rc != EOK)
    865622                                return rc;
     
    916673
    917674        /* Check number of FATs. */
    918         if (FATCNT(bs) == 0)
     675        if (bs->fatcnt == 0)
    919676                return ENOTSUP;
    920677
    921678        /* Check total number of sectors. */
    922         if (TS(bs) == 0)
     679
     680        if (bs->totsec16 == 0 && bs->totsec32 == 0)
    923681                return ENOTSUP;
    924682
    925683        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    926             bs->totsec16 != bs->totsec32)
     684            bs->totsec16 != bs->totsec32) 
    927685                return ENOTSUP;
    928686
     
    932690
    933691        /* Check number of sectors per FAT. */
    934         if (SF(bs) == 0)
     692        if (bs->sec_per_fat == 0)
    935693                return ENOTSUP;
    936694
     
    942700         * sanitized to support file systems with this property.
    943701         */
    944         if (!FAT_IS_FAT32(bs) && (RDE(bs) * sizeof(fat_dentry_t)) % BPS(bs) != 0)
     702        if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) %
     703            uint16_t_le2host(bs->bps) != 0)
    945704                return ENOTSUP;
    946705
    947706        /* Check signature of each FAT. */
    948         for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) {
     707
     708        for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
    949709                rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0);
    950710                if (rc != EOK)
     
    963723                 * set to one.
    964724                 */
    965                 if (!FAT_IS_FAT12(bs) &&
    966                         ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs)))
     725                if ((e0 >> 8) != 0xff || e1 != 0xffff)
    967726                        return ENOTSUP;
    968727        }
     
    973732/**
    974733 * @}
    975  */
     734 */ 
  • uspace/srv/fs/fat/fat_fat.h

    r375ab5e r7fadb65  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
    3  * Copyright (c) 2011 Oleg Romanenko
    43 * All rights reserved.
    54 *
     
    3029/** @addtogroup fs
    3130 * @{
    32  */
     31 */ 
    3332
    3433#ifndef FAT_FAT_FAT_H_
     
    4140#define FAT1            0
    4241
    43 #define FAT_CLST_RES0     0
    44 #define FAT_CLST_RES1     1
    45 #define FAT_CLST_FIRST    2
    46 
    47 #define FAT32_CLST_BAD    0x0ffffff7
    48 #define FAT32_CLST_LAST1  0x0ffffff8
    49 #define FAT32_CLST_LAST8  0x0fffffff
    50 
    51 #define FAT12_MASK        0x0fff
    52 #define FAT16_MASK        0xffff
    53 #define FAT32_MASK        0x0fffffff
    54 
    55 #define FAT12_CLST_MAX    4085
    56 #define FAT16_CLST_MAX    65525
    57 
    58 /* Size in bytes for cluster value of FAT */
    59 #define FAT12_CLST_SIZE   2
    60 #define FAT16_CLST_SIZE   2
    61 #define FAT32_CLST_SIZE   4
     42#define FAT_CLST_RES0   0x0000
     43#define FAT_CLST_RES1   0x0001
     44#define FAT_CLST_FIRST  0x0002
     45#define FAT_CLST_BAD    0xfff7
     46#define FAT_CLST_LAST1  0xfff8
     47#define FAT_CLST_LAST8  0xffff
    6248
    6349/* internally used to mark root directory's parent */
     
    6652#define FAT_CLST_ROOT           FAT_CLST_RES1
    6753
    68 /*
    69  * Convenience macros for computing some frequently used values from the
    70  * primitive boot sector members.
    71  */
    72 #define RDS(bs)   ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
    73                    (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
    74 #define SSA(bs)   (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
    75 #define DS(bs)    (TS(bs) - SSA(bs))
    76 #define CC(bs)    (DS(bs) / SPC(bs))
    77 
    78 #define FAT_IS_FAT12(bs)        (CC(bs) < FAT12_CLST_MAX)
    79 #define FAT_IS_FAT16(bs) \
    80     ((CC(bs) >= FAT12_CLST_MAX) && (CC(bs) < FAT16_CLST_MAX))
    81 #define FAT_IS_FAT32(bs)        (CC(bs) >= FAT16_CLST_MAX)
    82 
    83 #define FAT_CLST_SIZE(bs) \
    84     (FAT_IS_FAT32(bs) ? FAT32_CLST_SIZE : FAT16_CLST_SIZE)
    85 
    86 #define FAT_MASK(bs) \
    87     (FAT_IS_FAT12(bs) ? FAT12_MASK : \
    88     (FAT_IS_FAT32(bs) ? FAT32_MASK : FAT16_MASK))
    89 
    90 #define FAT_CLST_LAST1(bs)      (FAT32_CLST_LAST1 & FAT_MASK((bs)))
    91 #define FAT_CLST_LAST8(bs)      (FAT32_CLST_LAST8 & FAT_MASK((bs)))
    92 #define FAT_CLST_BAD(bs)        (FAT32_CLST_BAD & FAT_MASK((bs)))
    93 
    94 #define FAT_ROOT_CLST(bs) \
    95     (FAT_IS_FAT32(bs) ? uint32_t_le2host(bs->fat32.root_cluster) : \
    96     FAT_CLST_ROOT)
    97 
    9854/* forward declarations */
    9955struct block;
     
    10157struct fat_bs;
    10258
    103 typedef uint32_t fat_cluster_t;
     59typedef uint16_t fat_cluster_t;
    10460
    105 #define fat_clusters_get(numc, bs, sid, fc) \
    106     fat_cluster_walk((bs), (sid), (fc), NULL, (numc), (uint32_t) -1)
     61#define fat_clusters_get(numc, bs, dh, fc) \
     62    fat_cluster_walk((bs), (dh), (fc), NULL, (numc), (uint16_t) -1)
    10763extern int fat_cluster_walk(struct fat_bs *, service_id_t, fat_cluster_t,
    108     fat_cluster_t *, uint32_t *, uint32_t);
     64    fat_cluster_t *, uint16_t *, uint16_t);
    10965
    11066extern int fat_block_get(block_t **, struct fat_bs *, struct fat_node *,
     
    12278extern int fat_alloc_shadow_clusters(struct fat_bs *, service_id_t,
    12379    fat_cluster_t *, unsigned);
    124 extern int fat_get_cluster_fat12(struct fat_bs *, service_id_t, unsigned,
    125     fat_cluster_t, fat_cluster_t *);
    126 extern int fat_get_cluster_fat16(struct fat_bs *, service_id_t, unsigned,
    127     fat_cluster_t, fat_cluster_t *);
    128 extern int fat_get_cluster_fat32(struct fat_bs *, service_id_t, unsigned,
    129     fat_cluster_t, fat_cluster_t *);
    13080extern int fat_get_cluster(struct fat_bs *, service_id_t, unsigned,
    13181    fat_cluster_t, fat_cluster_t *);
    132 extern int fat_set_cluster_fat12(struct fat_bs *, service_id_t, unsigned,
    133     fat_cluster_t, fat_cluster_t);
    134 extern int fat_set_cluster_fat16(struct fat_bs *, service_id_t, unsigned,
    135     fat_cluster_t, fat_cluster_t);
    136 extern int fat_set_cluster_fat32(struct fat_bs *, service_id_t, unsigned,
    137     fat_cluster_t, fat_cluster_t);
    13882extern int fat_set_cluster(struct fat_bs *, service_id_t, unsigned,
    13983    fat_cluster_t, fat_cluster_t);
  • uspace/srv/fs/fat/fat_ops.c

    r375ab5e r7fadb65  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
    3  * Copyright (c) 2011 Oleg Romanenko
    43 * All rights reserved.
    54 *
     
    3029/** @addtogroup fs
    3130 * @{
    32  */
     31 */ 
    3332
    3433/**
     
    4039#include "fat_dentry.h"
    4140#include "fat_fat.h"
    42 #include "fat_directory.h"
    4341#include "../../vfs/vfs.h"
    4442#include <libfs.h>
     
    5856#include <align.h>
    5957#include <malloc.h>
    60 #include <str.h>
    6158
    6259#define FAT_NODE(node)  ((node) ? (fat_node_t *) (node)->data : NULL)
     
    107104        node->dirty = false;
    108105        node->lastc_cached_valid = false;
    109         node->lastc_cached_value = 0;
     106        node->lastc_cached_value = FAT_CLST_LAST1;
    110107        node->currc_cached_valid = false;
    111108        node->currc_cached_bn = 0;
    112         node->currc_cached_value = 0;
     109        node->currc_cached_value = FAT_CLST_LAST1;
    113110}
    114111
     
    119116        fat_dentry_t *d;
    120117        int rc;
    121 
     118       
    122119        assert(node->dirty);
    123120
    124121        bs = block_bb_get(node->idx->service_id);
    125 
     122       
    126123        /* Read the block that contains the dentry of interest. */
    127124        rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc,
     
    139136                d->attr = FAT_ATTR_SUBDIR;
    140137        }
    141 
     138       
    142139        /* TODO: update other fields? (e.g time fields) */
    143 
     140       
    144141        b->dirty = true;                /* need to sync block */
    145142        rc = block_put(b);
     
    258255        fn->data = nodep;
    259256        nodep->bp = fn;
    260 
     257       
    261258        *nodepp = nodep;
    262259        return EOK;
     
    294291         * We must instantiate the node from the file system.
    295292         */
    296 
     293       
    297294        assert(idxp->pfc);
    298295
     
    312309
    313310        d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs));
    314         if (FAT_IS_FAT32(bs)) {
    315                 nodep->firstc = uint16_t_le2host(d->firstc_lo) |
    316                     (uint16_t_le2host(d->firstc_hi) << 16);
    317         }
    318         else
    319                 nodep->firstc = uint16_t_le2host(d->firstc);
    320 
    321311        if (d->attr & FAT_ATTR_SUBDIR) {
    322                 /*
     312                /* 
    323313                 * The only directory which does not have this bit set is the
    324314                 * root directory itself. The root directory node is handled
     
    326316                 */
    327317                nodep->type = FAT_DIRECTORY;
    328 
    329318                /*
    330319                 * Unfortunately, the 'size' field of the FAT dentry is not
     
    332321                 * size of the directory by walking the FAT.
    333322                 */
    334                 uint32_t clusters;
    335                 rc = fat_clusters_get(&clusters, bs, idxp->service_id, nodep->firstc);
     323                uint16_t clusters;
     324                rc = fat_clusters_get(&clusters, bs, idxp->service_id,
     325                    uint16_t_le2host(d->firstc));
    336326                if (rc != EOK) {
    337327                        (void) block_put(b);
     
    344334                nodep->size = uint32_t_le2host(d->size);
    345335        }
    346 
     336        nodep->firstc = uint16_t_le2host(d->firstc);
    347337        nodep->lnkcnt = 1;
    348338        nodep->refcnt = 1;
     
    373363int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    374364{
     365        fat_bs_t *bs;
    375366        fat_node_t *parentp = FAT_NODE(pfn);
    376         char name[FAT_LFN_NAME_SIZE];
     367        char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
     368        unsigned i, j;
     369        unsigned blocks;
    377370        fat_dentry_t *d;
    378371        service_id_t service_id;
     372        block_t *b;
    379373        int rc;
    380374
     
    382376        service_id = parentp->idx->service_id;
    383377        fibril_mutex_unlock(&parentp->idx->lock);
    384        
    385         fat_directory_t di;
    386         rc = fat_directory_open(parentp, &di);
    387         if (rc != EOK)
    388                 return rc;
    389 
    390         while (fat_directory_read(&di, name, &d) == EOK) {
    391                 if (fat_dentry_namecmp(name, component) == 0) {
    392                         /* hit */
    393                         fat_node_t *nodep;
    394                         aoff64_t o = di.pos % (BPS(di.bs) / sizeof(fat_dentry_t));
    395                         fat_idx_t *idx = fat_idx_get_by_pos(service_id,
    396                                 parentp->firstc, di.bnum * DPS(di.bs) + o);
    397                         if (!idx) {
    398                                 /*
    399                                  * Can happen if memory is low or if we
    400                                  * run out of 32-bit indices.
    401                                  */
    402                                 rc = fat_directory_close(&di);
    403                                 return (rc == EOK) ? ENOMEM : rc;
     378
     379        bs = block_bb_get(service_id);
     380        blocks = parentp->size / BPS(bs);
     381        for (i = 0; i < blocks; i++) {
     382                rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
     383                if (rc != EOK)
     384                        return rc;
     385                for (j = 0; j < DPS(bs); j++) {
     386                        d = ((fat_dentry_t *)b->data) + j;
     387                        switch (fat_classify_dentry(d)) {
     388                        case FAT_DENTRY_SKIP:
     389                        case FAT_DENTRY_FREE:
     390                                continue;
     391                        case FAT_DENTRY_LAST:
     392                                /* miss */
     393                                rc = block_put(b);
     394                                *rfn = NULL;
     395                                return rc;
     396                        default:
     397                        case FAT_DENTRY_VALID:
     398                                fat_dentry_name_get(d, name);
     399                                break;
    404400                        }
    405                         rc = fat_node_get_core(&nodep, idx);
    406                         fibril_mutex_unlock(&idx->lock);
    407                         if (rc != EOK) {
    408                                 (void) fat_directory_close(&di);
     401                        if (fat_dentry_namecmp(name, component) == 0) {
     402                                /* hit */
     403                                fat_node_t *nodep;
     404                                fat_idx_t *idx = fat_idx_get_by_pos(service_id,
     405                                    parentp->firstc, i * DPS(bs) + j);
     406                                if (!idx) {
     407                                        /*
     408                                         * Can happen if memory is low or if we
     409                                         * run out of 32-bit indices.
     410                                         */
     411                                        rc = block_put(b);
     412                                        return (rc == EOK) ? ENOMEM : rc;
     413                                }
     414                                rc = fat_node_get_core(&nodep, idx);
     415                                fibril_mutex_unlock(&idx->lock);
     416                                if (rc != EOK) {
     417                                        (void) block_put(b);
     418                                        return rc;
     419                                }
     420                                *rfn = FS_NODE(nodep);
     421                                rc = block_put(b);
     422                                if (rc != EOK)
     423                                        (void) fat_node_put(*rfn);
    409424                                return rc;
    410425                        }
    411                         *rfn = FS_NODE(nodep);
    412                         rc = fat_directory_close(&di);
    413                         if (rc != EOK)
    414                                 (void) fat_node_put(*rfn);
    415                         return rc;
    416                 } else {
    417                         rc = fat_directory_next(&di);
    418                         if (rc != EOK)
    419                                 break;
    420                 }
    421         }
    422         (void) fat_directory_close(&di);
     426                }
     427                rc = block_put(b);
     428                if (rc != EOK)
     429                        return rc;
     430        }
     431
    423432        *rfn = NULL;
    424433        return EOK;
     
    582591        fat_bs_t *bs;
    583592        block_t *b;
    584         fat_directory_t di;
    585         fat_dentry_t de;
     593        unsigned i, j;
     594        unsigned blocks;
     595        fat_cluster_t mcl, lcl;
    586596        int rc;
    587597
     
    597607        fibril_mutex_unlock(&childp->lock);
    598608
    599         if (!fat_valid_name(name))
     609        if (!fat_dentry_name_verify(name)) {
     610                /*
     611                 * Attempt to create unsupported name.
     612                 */
    600613                return ENOTSUP;
    601 
     614        }
     615
     616        /*
     617         * Get us an unused parent node's dentry or grow the parent and allocate
     618         * a new one.
     619         */
     620       
    602621        fibril_mutex_lock(&parentp->idx->lock);
    603622        bs = block_bb_get(parentp->idx->service_id);
    604         rc = fat_directory_open(parentp, &di);
    605         if (rc != EOK)
    606                 return rc;
    607 
     623
     624        blocks = parentp->size / BPS(bs);
     625
     626        for (i = 0; i < blocks; i++) {
     627                rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
     628                if (rc != EOK) {
     629                        fibril_mutex_unlock(&parentp->idx->lock);
     630                        return rc;
     631                }
     632                for (j = 0; j < DPS(bs); j++) {
     633                        d = ((fat_dentry_t *)b->data) + j;
     634                        switch (fat_classify_dentry(d)) {
     635                        case FAT_DENTRY_SKIP:
     636                        case FAT_DENTRY_VALID:
     637                                /* skipping used and meta entries */
     638                                continue;
     639                        case FAT_DENTRY_FREE:
     640                        case FAT_DENTRY_LAST:
     641                                /* found an empty slot */
     642                                goto hit;
     643                        }
     644                }
     645                rc = block_put(b);
     646                if (rc != EOK) {
     647                        fibril_mutex_unlock(&parentp->idx->lock);
     648                        return rc;
     649                }
     650        }
     651        j = 0;
     652       
     653        /*
     654         * We need to grow the parent in order to create a new unused dentry.
     655         */
     656        if (parentp->firstc == FAT_CLST_ROOT) {
     657                /* Can't grow the root directory. */
     658                fibril_mutex_unlock(&parentp->idx->lock);
     659                return ENOSPC;
     660        }
     661        rc = fat_alloc_clusters(bs, parentp->idx->service_id, 1, &mcl, &lcl);
     662        if (rc != EOK) {
     663                fibril_mutex_unlock(&parentp->idx->lock);
     664                return rc;
     665        }
     666        rc = fat_zero_cluster(bs, parentp->idx->service_id, mcl);
     667        if (rc != EOK) {
     668                (void) fat_free_clusters(bs, parentp->idx->service_id, mcl);
     669                fibril_mutex_unlock(&parentp->idx->lock);
     670                return rc;
     671        }
     672        rc = fat_append_clusters(bs, parentp, mcl, lcl);
     673        if (rc != EOK) {
     674                (void) fat_free_clusters(bs, parentp->idx->service_id, mcl);
     675                fibril_mutex_unlock(&parentp->idx->lock);
     676                return rc;
     677        }
     678        parentp->size += BPS(bs) * SPC(bs);
     679        parentp->dirty = true;          /* need to sync node */
     680        rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
     681        if (rc != EOK) {
     682                fibril_mutex_unlock(&parentp->idx->lock);
     683                return rc;
     684        }
     685        d = (fat_dentry_t *)b->data;
     686
     687hit:
    608688        /*
    609689         * At this point we only establish the link between the parent and the
     
    612692         * dentry data is kept in the child node structure.
    613693         */
    614         memset(&de, 0, sizeof(fat_dentry_t));
    615 
    616         rc = fat_directory_write(&di, name, &de);
    617         if (rc!=EOK)
    618                 return rc;
    619         rc = fat_directory_close(&di);
    620         if (rc!=EOK)
    621                 return rc;
    622 
     694        memset(d, 0, sizeof(fat_dentry_t));
     695        fat_dentry_name_set(d, name);
     696        b->dirty = true;                /* need to sync block */
     697        rc = block_put(b);
    623698        fibril_mutex_unlock(&parentp->idx->lock);
    624         if (rc != EOK)
     699        if (rc != EOK) 
    625700                return rc;
    626701
    627702        fibril_mutex_lock(&childp->idx->lock);
    628 
     703       
    629704        if (childp->type == FAT_DIRECTORY) {
    630705                /*
     
    645720                d = (fat_dentry_t *) b->data;
    646721                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    647                     (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) {
     722                    (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {
    648723                        memset(d, 0, sizeof(fat_dentry_t));
    649724                        memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN);
     
    655730                d++;
    656731                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    657                     (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) {
     732                    (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {
    658733                        memset(d, 0, sizeof(fat_dentry_t));
    659734                        memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN);
    660735                        memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN);
    661736                        d->attr = FAT_ATTR_SUBDIR;
    662                         d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ?
    663                             host2uint16_t_le(FAT_CLST_ROOTPAR) :
     737                        d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
     738                            host2uint16_t_le(FAT_CLST_RES0) :
    664739                            host2uint16_t_le(parentp->firstc);
    665740                        /* TODO: initialize also the date/time members. */
     
    675750
    676751        childp->idx->pfc = parentp->firstc;
    677         childp->idx->pdi = di.pos;      /* di.pos holds absolute position of SFN entry */
     752        childp->idx->pdi = i * DPS(bs) + j;
    678753        fibril_mutex_unlock(&childp->idx->lock);
    679754
     
    695770        fat_node_t *parentp = FAT_NODE(pfn);
    696771        fat_node_t *childp = FAT_NODE(cfn);
     772        fat_bs_t *bs;
     773        fat_dentry_t *d;
     774        block_t *b;
    697775        bool has_children;
    698776        int rc;
     
    700778        if (!parentp)
    701779                return EBUSY;
    702 
     780       
    703781        rc = fat_has_children(&has_children, cfn);
    704782        if (rc != EOK)
     
    711789        assert(childp->lnkcnt == 1);
    712790        fibril_mutex_lock(&childp->idx->lock);
    713        
    714         fat_directory_t di;
    715         rc = fat_directory_open(parentp,&di);
    716         if (rc != EOK)
     791        bs = block_bb_get(childp->idx->service_id);
     792
     793        rc = _fat_block_get(&b, bs, childp->idx->service_id, childp->idx->pfc,
     794            NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
     795            BLOCK_FLAGS_NONE);
     796        if (rc != EOK)
    717797                goto error;
    718         rc = fat_directory_seek(&di, childp->idx->pdi);
    719         if (rc != EOK)
    720                 goto error;
    721         rc = fat_directory_erase(&di);
    722         if (rc != EOK)
    723                 goto error;
    724         rc = fat_directory_close(&di);
     798        d = (fat_dentry_t *)b->data +
     799            (childp->idx->pdi % (BPS(bs) / sizeof(fat_dentry_t)));
     800        /* mark the dentry as not-currently-used */
     801        d->name[0] = FAT_DENTRY_ERASED;
     802        b->dirty = true;                /* need to sync block */
     803        rc = block_put(b);
    725804        if (rc != EOK)
    726805                goto error;
     
    741820
    742821error:
    743         (void) fat_directory_close(&di);
     822        fibril_mutex_unlock(&parentp->idx->lock);
     823        fibril_mutex_unlock(&childp->lock);
    744824        fibril_mutex_unlock(&childp->idx->lock);
    745         fibril_mutex_unlock(&childp->lock);
    746         fibril_mutex_unlock(&parentp->lock);
    747825        return rc;
    748826}
     
    761839                return EOK;
    762840        }
    763 
     841       
    764842        fibril_mutex_lock(&nodep->idx->lock);
    765843        bs = block_bb_get(nodep->idx->service_id);
     
    769847        for (i = 0; i < blocks; i++) {
    770848                fat_dentry_t *d;
    771 
     849       
    772850                rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE);
    773851                if (rc != EOK) {
     
    797875                if (rc != EOK) {
    798876                        fibril_mutex_unlock(&nodep->idx->lock);
    799                         return rc;
     877                        return rc;     
    800878                }
    801879        }
     
    868946        fat_bs_t *bs;
    869947        int rc;
    870 
     948       
    871949        /* Check for option enabling write through. */
    872950        if (str_cmp(opts, "wtcache") == 0)
     
    9251003                return ENOMEM;
    9261004        }
    927 
    9281005        fs_node_initialize(rfn);
    9291006        fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
     
    9501027
    9511028        rootp->type = FAT_DIRECTORY;
    952         rootp->firstc = FAT_ROOT_CLST(bs);
     1029        rootp->firstc = FAT_CLST_ROOT;
    9531030        rootp->refcnt = 1;
    9541031        rootp->lnkcnt = 0;      /* FS root is not linked */
    955 
    956         if (FAT_IS_FAT32(bs)) {
    957                 uint32_t clusters;
    958                 rc = fat_clusters_get(&clusters, bs, service_id, rootp->firstc);
    959                 if (rc != EOK) {
    960                         free(rfn);
    961                         free(rootp);
    962                         (void) block_cache_fini(service_id);
    963                         block_fini(service_id);
    964                         fat_idx_fini_by_service_id(service_id);
    965                         return ENOTSUP;
    966                 }
    967                 rootp->size = BPS(bs) * SPC(bs) * clusters;
    968         } else
    969                 rootp->size = RDE(bs) * sizeof(fat_dentry_t);
    970 
     1032        rootp->size = RDE(bs) * sizeof(fat_dentry_t);
    9711033        rootp->idx = ridxp;
    9721034        ridxp->nodep = rootp;
    9731035        rootp->bp = rfn;
    9741036        rfn->data = rootp;
    975 
     1037       
    9761038        fibril_mutex_unlock(&ridxp->lock);
    9771039
     
    10021064                return EBUSY;
    10031065        }
    1004 
     1066       
    10051067        /*
    10061068         * Put the root node and force it to the FAT free node list.
     
    10791141                }
    10801142        } else {
     1143                unsigned bnum;
    10811144                aoff64_t spos = pos;
    1082                 char name[FAT_LFN_NAME_SIZE];
     1145                char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
    10831146                fat_dentry_t *d;
    10841147
     
    10871150                assert(BPS(bs) % sizeof(fat_dentry_t) == 0);
    10881151
    1089                 fat_directory_t di;
    1090                 rc = fat_directory_open(nodep, &di);
    1091                 if (rc != EOK) goto err;
    1092                 rc = fat_directory_seek(&di, pos);
    1093                 if (rc != EOK) {
    1094                         (void) fat_directory_close(&di);
    1095                         goto err;
    1096                 }
    1097 
    1098                 rc = fat_directory_read(&di, name, &d);
    1099                 if (rc == EOK) goto hit;
    1100                 if (rc == ENOENT) goto miss;
    1101 
    1102 err:
    1103                 (void) fat_node_put(fn);
    1104                 async_answer_0(callid, rc);
    1105                 return rc;
    1106 
     1152                /*
     1153                 * Our strategy for readdir() is to use the position pointer as
     1154                 * an index into the array of all dentries. On entry, it points
     1155                 * to the first unread dentry. If we skip any dentries, we bump
     1156                 * the position pointer accordingly.
     1157                 */
     1158                bnum = (pos * sizeof(fat_dentry_t)) / BPS(bs);
     1159                while (bnum < nodep->size / BPS(bs)) {
     1160                        aoff64_t o;
     1161
     1162                        rc = fat_block_get(&b, bs, nodep, bnum,
     1163                            BLOCK_FLAGS_NONE);
     1164                        if (rc != EOK)
     1165                                goto err;
     1166                        for (o = pos % (BPS(bs) / sizeof(fat_dentry_t));
     1167                            o < BPS(bs) / sizeof(fat_dentry_t);
     1168                            o++, pos++) {
     1169                                d = ((fat_dentry_t *)b->data) + o;
     1170                                switch (fat_classify_dentry(d)) {
     1171                                case FAT_DENTRY_SKIP:
     1172                                case FAT_DENTRY_FREE:
     1173                                        continue;
     1174                                case FAT_DENTRY_LAST:
     1175                                        rc = block_put(b);
     1176                                        if (rc != EOK)
     1177                                                goto err;
     1178                                        goto miss;
     1179                                default:
     1180                                case FAT_DENTRY_VALID:
     1181                                        fat_dentry_name_get(d, name);
     1182                                        rc = block_put(b);
     1183                                        if (rc != EOK)
     1184                                                goto err;
     1185                                        goto hit;
     1186                                }
     1187                        }
     1188                        rc = block_put(b);
     1189                        if (rc != EOK)
     1190                                goto err;
     1191                        bnum++;
     1192                }
    11071193miss:
    1108                 rc = fat_directory_close(&di);
    1109                 if (rc!=EOK)
    1110                         goto err;
    11111194                rc = fat_node_put(fn);
    11121195                async_answer_0(callid, rc != EOK ? rc : ENOENT);
     
    11141197                return rc != EOK ? rc : ENOENT;
    11151198
     1199err:
     1200                (void) fat_node_put(fn);
     1201                async_answer_0(callid, rc);
     1202                return rc;
     1203
    11161204hit:
    1117                 pos = di.pos;
    1118                 rc = fat_directory_close(&di);
    1119                 if (rc!=EOK)
    1120                         goto err;
    11211205                (void) async_data_read_finalize(callid, name, str_size(name) + 1);
    1122                 bytes = (pos - spos)+1;
     1206                bytes = (pos - spos) + 1;
    11231207        }
    11241208
     
    11471231                return ENOENT;
    11481232        nodep = FAT_NODE(fn);
    1149 
     1233       
    11501234        ipc_callid_t callid;
    11511235        size_t len;
     
    11631247         * but this one greatly simplifies fat_write(). Note that we can afford
    11641248         * to do this because the client must be ready to handle the return
    1165          * value signalizing a smaller number of bytes written.
    1166          */
     1249         * value signalizing a smaller number of bytes written. 
     1250         */ 
    11671251        bytes = min(len, BPS(bs) - pos % BPS(bs));
    11681252        if (bytes == BPS(bs))
    11691253                flags |= BLOCK_FLAGS_NOREAD;
    1170 
     1254       
    11711255        boundary = ROUND_UP(nodep->size, BPC(bs));
    11721256        if (pos < boundary) {
     
    12111295                 */
    12121296                unsigned nclsts;
    1213                 fat_cluster_t mcl, lcl;
    1214 
     1297                fat_cluster_t mcl, lcl; 
     1298 
    12151299                nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs);
    12161300                /* create an independent chain of nclsts clusters in all FATs */
     
    12961380                nodep->size = size;
    12971381                nodep->dirty = true;            /* need to sync node */
    1298                 rc = EOK;
     1382                rc = EOK;       
    12991383        } else {
    13001384                /*
     
    13171401                nodep->size = size;
    13181402                nodep->dirty = true;            /* need to sync node */
    1319                 rc = EOK;
     1403                rc = EOK;       
    13201404        }
    13211405out:
     
    13601444        if (!fn)
    13611445                return ENOENT;
    1362 
     1446       
    13631447        fat_node_t *nodep = FAT_NODE(fn);
    1364 
     1448       
    13651449        nodep->dirty = true;
    13661450        rc = fat_node_sync(nodep);
    1367 
     1451       
    13681452        fat_node_put(fn);
    13691453        return rc;
Note: See TracChangeset for help on using the changeset viewer.