Changes in / [4cf5ed46:7fadb65] in mainline


Ignore:
Files:
15 deleted
15 edited

Legend:

Unmodified
Added
Removed
  • boot/Makefile.common

    r4cf5ed46 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 \
  • uspace/Makefile

    r4cf5ed46 r7fadb65  
    7979        srv/bd/part/guid_part \
    8080        srv/bd/part/mbr_part \
    81         srv/fs/exfat \
    8281        srv/fs/fat \
    8382        srv/fs/tmpfs \
  • uspace/app/mkfat/fat.h

    r4cf5ed46 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

    r4cf5ed46 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");
     
    180162                printf(NAME ": Block device has %" PRIuOFF64 " blocks.\n",
    181163                    dev_nblocks);
    182                 if (!cfg.total_sectors || dev_nblocks < cfg.total_sectors)
    183                         cfg.total_sectors = dev_nblocks;
     164                cfg.total_sectors = dev_nblocks;
     165        }
     166
     167        if (block_size != 512) {
     168                printf(NAME ": Error. Device block size is not 512 bytes.\n");
     169                return 2;
    184170        }
    185171
     
    189175        }
    190176
    191         if (cfg.fat_type != FAT12 && cfg.fat_type != FAT16 && cfg.fat_type != FAT32) {
    192                 printf(NAME ": Error. Unknown FAT type.\n");
    193                 return 2;
    194         }
    195 
    196         printf(NAME ": Creating FAT%d filesystem on device %s.\n", cfg.fat_type, dev_path);
    197 
    198         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);
    199180        if (rc != EOK) {
    200181                printf(NAME ": Invalid file-system parameters.\n");
     
    202183        }
    203184
    204         rc = fat_blocks_write(&cfg, service_id);
     185        rc = fat_blocks_write(&par, service_id);
    205186        if (rc != EOK) {
    206187                printf(NAME ": Error writing device.\n");
     
    216197static void syntax_print(void)
    217198{
    218         printf("syntax: mkfat [--size <sectors>] [--type 12|16|32] <device_name>\n");
     199        printf("syntax: mkfat [--size <num_blocks>] <device_name>\n");
    219200}
    220201
     
    224205 * file system params.
    225206 */
    226 static int fat_params_compute(struct fat_cfg *cfg)
     207static int fat_params_compute(struct fat_cfg const *cfg, struct fat_params *par)
    227208{
    228209        uint32_t fat_bytes;
     
    230211
    231212        /*
    232          * Make a conservative guess on the FAT size needed for the file
    233          * system. The optimum could be potentially smaller since we
    234          * do not subtract size of the FAT itself when computing the
    235          * size of the data region.
    236          */
    237 
    238         cfg->reserved_sectors = 1 + cfg->addt_res_sectors;
    239         if (cfg->fat_type != FAT32) {
    240                 cfg->rootdir_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE,
    241                         cfg->sector_size);
    242         } else
    243                 cfg->rootdir_sectors = 0;
    244         non_data_sectors_lb = cfg->reserved_sectors + cfg->rootdir_sectors;
    245 
    246         cfg->total_clusters = div_round_up(cfg->total_sectors - non_data_sectors_lb,
    247             cfg->sectors_per_cluster);
    248 
    249         if ((cfg->fat_type == FAT12 && cfg->total_clusters > FAT12_CLST_MAX) ||
    250             (cfg->fat_type == FAT16 && (cfg->total_clusters <= FAT12_CLST_MAX ||
    251             cfg->total_clusters > FAT16_CLST_MAX)) ||
    252             (cfg->fat_type == FAT32 && cfg->total_clusters <= FAT16_CLST_MAX))
    253                 return ENOSPC;
    254 
    255         fat_bytes = (cfg->total_clusters + 2) * FAT_SIZE(cfg->fat_type);
    256         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;
    257231
    258232        return EOK;
     
    260234
    261235/** Create file system with the given parameters. */
    262 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)
    263237{
    264238        aoff64_t addr;
     
    269243        struct fat_bs bs;
    270244
    271         fat_bootsec_create(cfg, &bs);
     245        fat_bootsec_create(par, &bs);
    272246
    273247        rc = block_write_direct(service_id, BS_BLOCK, 1, &bs);
     
    277251        addr = BS_BLOCK + 1;
    278252
    279         buffer = calloc(cfg->sector_size, 1);
     253        buffer = calloc(sector_size, 1);
    280254        if (buffer == NULL)
    281255                return ENOMEM;
    282         memset(buffer, 0, cfg->sector_size);
    283256
    284257        /* Reserved sectors */
    285         for (i = 0; i < cfg->reserved_sectors - 1; ++i) {
     258        for (i = 0; i < par->reserved_sectors - 1; ++i) {
    286259                rc = block_write_direct(service_id, addr, 1, buffer);
    287260                if (rc != EOK)
     
    292265
    293266        /* File allocation tables */
    294         for (i = 0; i < cfg->fat_count; ++i) {
     267        for (i = 0; i < fat_count; ++i) {
    295268                printf("Writing allocation table %d.\n", i + 1);
    296269
    297                 for (j = 0; j < cfg->fat_sectors; ++j) {
    298                         memset(buffer, 0, cfg->sector_size);
     270                for (j = 0; j < par->fat_sectors; ++j) {
     271                        memset(buffer, 0, sector_size);
    299272                        if (j == 0) {
    300                                 buffer[0] = default_media_descriptor;
     273                                buffer[0] = media_descriptor;
    301274                                buffer[1] = 0xFF;
    302275                                buffer[2] = 0xFF;
    303                                 if (cfg->fat_type == FAT16) {
    304                                         buffer[3] = 0xFF;
    305                                 } else if (cfg->fat_type == FAT32) {
    306                                         buffer[3] = 0x0F;
    307                                         buffer[4] = 0xFF;
    308                                         buffer[5] = 0xFF;
    309                                         buffer[6] = 0xFF;
    310                                         buffer[7] = 0x0F;
    311                                         buffer[8] = 0xF8;
    312                                         buffer[9] = 0xFF;
    313                                         buffer[10] = 0xFF;
    314                                         buffer[11] = 0x0F;
    315                                 }
     276                                buffer[3] = 0xFF;
    316277                        }
    317278
     
    324285        }
    325286
     287        printf("Writing root directory.\n");
     288
     289        memset(buffer, 0, sector_size);
     290
    326291        /* Root directory */
    327         printf("Writing root directory.\n");
    328         memset(buffer, 0, cfg->sector_size);
    329         if (cfg->fat_type != FAT32) {
    330                 size_t idx;
    331                 for (idx = 0; idx < cfg->rootdir_sectors; ++idx) {
    332                         rc = block_write_direct(service_id, addr, 1, buffer);
    333                         if (rc != EOK)
    334                                 return EIO;
    335 
    336                         ++addr;
    337                 }
    338         } else {
    339                 for (i = 0; i < cfg->sectors_per_cluster; i++) {
    340                         rc = block_write_direct(service_id, addr, 1, buffer);
    341                         if (rc != EOK)
    342                                 return EIO;
    343 
    344                         ++addr;
    345                 }       
     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;
    346298        }
    347299
     
    352304
    353305/** Construct boot sector with the given parameters. */
    354 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)
    355307{
    356308        memset(bs, 0, sizeof(*bs));
     
    363315
    364316        /* BIOS Parameter Block */
    365         bs->bps = host2uint16_t_le(cfg->sector_size);
    366         bs->spc = cfg->sectors_per_cluster;
    367         bs->rscnt = host2uint16_t_le(cfg->reserved_sectors);
    368         bs->fatcnt = cfg->fat_count;
    369         bs->root_ent_max = host2uint16_t_le(cfg->root_ent_max);
    370 
    371         if (cfg->total_sectors < 0x10000) {
    372                 bs->totsec16 = host2uint16_t_le(cfg->total_sectors);
    373                 bs->totsec32 = 0;
    374         } else {
    375                 bs->totsec16 = 0;
    376                 bs->totsec32 = host2uint32_t_le(cfg->total_sectors);
    377         }
    378 
    379         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);
    380330        bs->sec_per_track = host2uint16_t_le(63);
    381         bs->signature = host2uint16_t_be(0x55AA);
    382331        bs->headcnt = host2uint16_t_le(6);
    383332        bs->hidden_sec = host2uint32_t_le(0);
    384333
    385         if (cfg->fat_type == FAT32) {
    386                 bs->sec_per_fat = 0;
    387                 bs->fat32.sectors_per_fat = host2uint32_t_le(cfg->fat_sectors);
    388 
    389                 bs->fat32.pdn = 0x80;
    390                 bs->fat32.ebs = 0x29;
    391                 bs->fat32.id = host2uint32_t_be(0x12345678);
    392                 bs->fat32.root_cluster = 2;
    393 
    394                 memcpy(bs->fat32.label, "HELENOS_NEW", 11);
    395                 memcpy(bs->fat32.type, "FAT32   ", 8);
    396         } else {
    397                 bs->sec_per_fat = host2uint16_t_le(cfg->fat_sectors);
    398                 bs->pdn = 0x80;
    399                 bs->ebs = 0x29;
    400                 bs->id = host2uint32_t_be(0x12345678);
    401 
    402                 memcpy(bs->label, "HELENOS_NEW", 11);
    403                 memcpy(bs->type, "FAT   ", 8);
    404         }
     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);
    405347}
    406348
  • uspace/lib/c/generic/str.c

    r4cf5ed46 r7fadb65  
    33 * Copyright (c) 2008 Jiri Svoboda
    44 * Copyright (c) 2011 Martin Sucha
    5  * Copyright (c) 2011 Oleg Romanenko
    65 * All rights reserved.
    76 *
     
    641640}
    642641
    643 /** Convert UTF16 string to string.
    644  *
    645  * Convert utf16 string @a src to string. The output is written to the buffer
    646  * specified by @a dest and @a size. @a size must be non-zero and the string
    647  * written will always be well-formed. Surrogate pairs also supported.
    648  *
    649  * @param dest  Destination buffer.
    650  * @param size  Size of the destination buffer.
    651  * @param src   Source utf16 string.
    652  *
    653  * @return EOK, if success, negative otherwise.
    654  */
    655 int utf16_to_str(char *dest, size_t size, const uint16_t *src)
    656 {
    657         size_t idx = 0, dest_off = 0;
    658         wchar_t ch;
    659         int rc = EOK;
    660 
    661         /* There must be space for a null terminator in the buffer. */
    662         assert(size > 0);
    663 
    664         while (src[idx]) {
    665                 if ((src[idx] & 0xfc00) == 0xd800) {
    666                         if (src[idx + 1] && (src[idx + 1] & 0xfc00) == 0xdc00) {
    667                                 ch = 0x10000;
    668                                 ch += (src[idx] & 0x03FF) << 10;
    669                                 ch += (src[idx + 1] & 0x03FF);
    670                                 idx += 2;
    671                         }
    672                         else
    673                                 break;
    674                 } else {
    675                         ch = src[idx];
    676                         idx++;
    677                 }
    678                 rc = chr_encode(ch, dest, &dest_off, size - 1);
    679                 if (rc != EOK)
    680                         break;
    681         }
    682         dest[dest_off] = '\0';
    683         return rc;
    684 }
    685 
    686 int str_to_utf16(uint16_t *dest, size_t size, const char *src)
    687 {
    688         int rc = EOK;
    689         size_t offset = 0;
    690         size_t idx = 0;
    691         wchar_t c;
    692 
    693         assert(size > 0);
    694        
    695         while ((c = str_decode(src, &offset, STR_NO_LIMIT)) != 0) {
    696                 if (c > 0x10000) {
    697                         if (idx + 2 >= size - 1) {
    698                                 rc = EOVERFLOW;
    699                                 break;
    700                         }
    701                         c = (c - 0x10000);
    702                         dest[idx] = 0xD800 | (c >> 10);
    703                         dest[idx + 1] = 0xDC00 | (c & 0x3FF);
    704                         idx++;
    705                 } else {
    706                          dest[idx] = c;
    707                 }
    708 
    709                 idx++;
    710                 if (idx >= size - 1) {
    711                         rc = EOVERFLOW;
    712                         break;
    713                 }
    714         }
    715 
    716         dest[idx] = '\0';
    717         return rc;
    718 }
    719 
    720 
    721642/** Convert wide string to new string.
    722643 *
     
    11151036        return dest;
    11161037}
     1038
    11171039
    11181040/** Convert initial part of string to unsigned long according to given base.
  • uspace/lib/c/include/str.h

    r4cf5ed46 r7fadb65  
    11/*
    22 * Copyright (c) 2005 Martin Decky
    3  * Copyright (c) 2011 Oleg Romanenko
    43 * All rights reserved.
    54 *
     
    8584extern 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 utf16_to_str(char *dest, size_t size, const uint16_t *src);
    88 extern int str_to_utf16(uint16_t *dest, size_t size, const char *src);
    8986
    9087extern char *str_chr(const char *str, wchar_t ch);
  • uspace/srv/fs/fat/Makefile

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

    r4cf5ed46 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

    r4cf5ed46 r7fadb65  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
    3  * Copyright (c) 2011 Oleg Romanenko
    43 * All rights reserved.
    54 *
     
    4746#endif
    4847
    49 #define min(a, b)       ((a) < (b) ? (a) : (b))
     48#define min(a, b)               ((a) < (b) ? (a) : (b))
    5049
    5150/*
     
    5655#define RSCNT(bs)       uint16_t_le2host((bs)->rscnt)
    5756#define FATCNT(bs)      (bs)->fatcnt
    58 
    59 #define SF(bs)          (uint16_t_le2host((bs)->sec_per_fat) ? \
    60     uint16_t_le2host((bs)->sec_per_fat) : \
    61     uint32_t_le2host(bs->fat32.sectors_per_fat))
    62 
     57#define SF(bs)          uint16_t_le2host((bs)->sec_per_fat)
    6358#define RDE(bs)         uint16_t_le2host((bs)->root_ent_max)
    64 
    65 #define TS(bs)          (uint16_t_le2host((bs)->totsec16) ? \
    66     uint16_t_le2host((bs)->totsec16) : \
    67     uint32_t_le2host(bs->totsec32))
    68 
    69 #define BS_BLOCK        0
    70 #define BS_SIZE         512
     59#define TS(bs)          (uint16_t_le2host((bs)->totsec16) != 0 ? \
     60                        uint16_t_le2host((bs)->totsec16) : \
     61                        uint32_t_le2host(bs->totsec32))
     62
     63#define BS_BLOCK                0
     64#define BS_SIZE                 512
    7165
    7266typedef struct fat_bs {
  • uspace/srv/fs/fat/fat_dentry.c

    r4cf5ed46 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 
    225         for (i = 0; i < (FAT_NAME_LEN + FAT_EXT_LEN); i++)
    226                 sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + name[i];
    227 
    228         return sum;
    229 }
    230 
    231 /** Get number of bytes in a string with size limit.
    232  *
    233  * @param str  NULL-terminated (or not) string.
    234  * @param size Maximum number of bytes to consider.
    235  *
    236  * @return Number of bytes in string (without 0 and ff).
    237  *
    238  */
    239 size_t fat_lfn_str_nlength(const uint16_t *str, size_t size)
    240 {
    241         size_t offset = 0;
    242 
    243         while (offset < size) {
    244                 if (str[offset] == 0 || str[offset] == FAT_LFN_PAD)
    245                         break;
    246                 offset++;
    247         }
    248         return offset;
    249 }
    250 
    251 /** Get number of bytes in a FAT long entry occuped by characters.
    252  *
    253  * @param d FAT long entry.
    254  *
    255  * @return Number of bytes.
    256  *
    257  */
    258 size_t fat_lfn_size(const fat_dentry_t *d)
    259 {
    260         size_t size = 0;
    261        
    262         size += fat_lfn_str_nlength(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE);
    263         size += fat_lfn_str_nlength(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE);
    264         size += fat_lfn_str_nlength(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE);     
    265        
    266         return size;
    267 }
    268 
    269 size_t fat_lfn_get_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset)
    270 {
    271         int i;
    272         for (i = FAT_LFN_PART3_SIZE - 1; i >= 0 && *offset > 0; i--) {
    273                 if (d->lfn.part3[i] == 0 || d->lfn.part3[i] == FAT_LFN_PAD)
    274                         continue;
    275                 (*offset)--;
    276                 dst[(*offset)] = uint16_t_le2host(d->lfn.part3[i]);
    277         }
    278         for (i = FAT_LFN_PART2_SIZE - 1; i >= 0 && *offset > 0; i--) {
    279                 if (d->lfn.part2[i] == 0 || d->lfn.part2[i] == FAT_LFN_PAD)
    280                         continue;
    281                 (*offset)--;
    282                 dst[(*offset)] = uint16_t_le2host(d->lfn.part2[i]);
    283         }
    284         for (i = FAT_LFN_PART1_SIZE - 1; i >= 0 && *offset > 0; i--) {
    285                 if (d->lfn.part1[i] == 0 || d->lfn.part1[i] == FAT_LFN_PAD)
    286                         continue;
    287                 (*offset)--;
    288                 dst[(*offset)] = uint16_t_le2host(d->lfn.part1[i]);
    289         }
    290         return *offset;
    291 }
    292 
    293 size_t fat_lfn_set_entry(const uint16_t *src, size_t *offset, size_t size,
    294     fat_dentry_t *d)
    295 {
    296         size_t idx;
    297         for (idx = 0; idx < FAT_LFN_PART1_SIZE; idx++) {
    298                 if (*offset < size) {
    299                         d->lfn.part1[idx] = host2uint16_t_le(src[*offset]);
    300                         (*offset)++;
    301                 } else
    302                         d->lfn.part1[idx] = FAT_LFN_PAD;
    303         }
    304         for (idx = 0; idx < FAT_LFN_PART2_SIZE; idx++) {
    305                 if (*offset < size) {
    306                         d->lfn.part2[idx] = host2uint16_t_le(src[*offset]);
    307                         (*offset)++;
    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                 } else
    316                         d->lfn.part3[idx] = FAT_LFN_PAD;
    317         }
    318 
    319         if (src[*offset] == 0)
    320                 offset++;
    321         FAT_LFN_ATTR(d) = FAT_ATTR_LFN;
    322         d->lfn.type = 0;
    323         d->lfn.firstc_lo = 0;
    324        
    325         return *offset;
    326 }
    327 
    328 void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad)
    329 {
    330         wchar_t ch;
    331         size_t off = 0;
    332         size_t i = 0;
    333        
    334         while (i < count) {
    335                 if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) {
    336                         if (ascii_check(ch) & IS_D_CHAR(ch))
    337                                 *dst = toupper(ch);
    338                         else
    339                                 *dst = pad;
    340                 } else
    341                         break;
    342 
    343                 dst++;
    344                 i++;
    345         }
    346         *dst = '\0';
    347 }
    348 
    349 bool fat_valid_name(const char *name)
    350 {
    351         wchar_t ch;
    352         size_t offset=0;
    353         bool result = true;
    354        
    355         while ((ch = str_decode(name, &offset, STR_NO_LIMIT)) != 0) {
    356                 if (str_chr(FAT_STOP_CHARS, ch) != NULL) {
    357                         result = false;
    358                         break;
    359                 }
    360         }
    361         return result;
    362 }
    363 
    364 bool fat_valid_short_name(const char *name)
     82bool fat_dentry_name_verify(const char *name)
    36583{
    36684        unsigned int i;
    36785        unsigned int dot = 0;
    36886        bool dot_found = false;
     87       
    36988
    37089        for (i = 0; name[i]; i++) {
     
    37796                        }
    37897                } else {
    379                         if (!IS_D_CHAR(name[i]))
     98                        if (!is_d_char(name[i]))
    38099                                return false;
    381100                }
     
    395114}
    396115
    397 size_t utf16_length(const uint16_t *wstr)
    398 {
    399         size_t len = 0;
    400        
    401         while (*wstr++ != 0)
    402                 len++;
    403        
    404         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;
    405240}
    406241
  • uspace/srv/fs/fat/fat_dentry.h

    r4cf5ed46 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 "*?/\\\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
    100 typedef union {
    101         struct {
    102                 uint8_t         name[8];
    103                 uint8_t         ext[3];
    104                 uint8_t         attr;
    105                 uint8_t         lcase;
    106                 uint8_t         ctime_fine;
    107                 uint16_t        ctime;
    108                 uint16_t        cdate;
    109                 uint16_t        adate;
    110                 union {
    111                         uint16_t        eaidx;          /* FAT12/FAT16 */
    112                         uint16_t        firstc_hi;      /* FAT32 */
    113                 } __attribute__ ((packed));
    114                 uint16_t        mtime;
    115                 uint16_t        mdate;
    116                 union {
    117                         uint16_t        firstc;         /* FAT12/FAT16 */
    118                         uint16_t        firstc_lo;      /* FAT32 */
    119                 } __attribute__ ((packed));
    120                 uint32_t        size;
     67typedef 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;
     76        union {
     77                uint16_t        eaidx;          /* FAT12/FAT16 */
     78                uint16_t        firstc_hi;      /* FAT32 */
    12179        } __attribute__ ((packed));
    122         struct {
    123                 uint8_t         order;
    124                 uint16_t        part1[FAT_LFN_PART1_SIZE];
    125                 uint8_t         attr;
    126                 uint8_t         type;
    127                 uint8_t         check_sum;
    128                 uint16_t        part2[FAT_LFN_PART2_SIZE];
    129                 uint16_t        firstc_lo; /* MUST be 0 */
    130                 uint16_t        part3[FAT_LFN_PART3_SIZE];
    131         } __attribute__ ((packed)) lfn;
     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;
    13287} __attribute__ ((packed)) fat_dentry_t;
    13388
    134 
    13589extern int fat_dentry_namecmp(char *, const char *);
     90extern bool fat_dentry_name_verify(const char *);
    13691extern void fat_dentry_name_get(const fat_dentry_t *, char *);
    13792extern void fat_dentry_name_set(fat_dentry_t *, const char *);
    13893extern fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *);
    139 extern uint8_t fat_dentry_chksum(uint8_t *);
    140 
    141 extern size_t fat_lfn_str_nlength(const uint16_t *, size_t);
    142 extern size_t fat_lfn_size(const fat_dentry_t *);
    143 extern size_t fat_lfn_get_entry(const fat_dentry_t *, uint16_t *, size_t *);
    144 extern size_t fat_lfn_set_entry(const uint16_t *, size_t *, size_t,
    145     fat_dentry_t *);
    146 
    147 extern void str_to_ascii(char *, const char *, size_t, uint8_t);
    148 extern size_t utf16_length(const uint16_t *);
    149 
    150 extern bool fat_valid_name(const char *);
    151 extern bool fat_valid_short_name(const char *);
    15294
    15395#endif
  • uspace/srv/fs/fat/fat_fat.c

    r4cf5ed46 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/**
     
    5150#include <mem.h>
    5251
    53 #define IS_ODD(number)  (number & 0x1)
     52/*
     53 * Convenience macros for computing some frequently used values from the
     54 * primitive boot sector members.
     55 */
     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
     60#define CLBN2PBN(bs, cl, bn) \
     61        (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
    5462
    5563/**
     
    5765 * during allocation of clusters. The lock does not have to be held durring
    5866 * deallocation of clusters.
    59  */
     67 */ 
    6068static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    6169
     
    6977 * @param numc          If non-NULL, output argument holding the number of
    7078 *                      clusters seen during the walk.
    71  * @param max_clusters  Maximum number of clusters to visit.
     79 * @param max_clusters  Maximum number of clusters to visit.   
    7280 *
    7381 * @return              EOK on success or a negative error code.
    7482 */
    75 int
     83int 
    7684fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc,
    77     fat_cluster_t *lastc, uint32_t *numc, uint32_t max_clusters)
    78 {
    79         uint32_t clusters = 0;
    80         fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs);
    81         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;
    8290        int rc;
    8391
     
    9199        }
    92100
    93         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
    94105                assert(clst >= FAT_CLST_FIRST);
    95106                if (lastc)
    96107                        *lastc = clst;  /* remember the last cluster number */
    97 
     108                fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
     109                fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
    98110                /* read FAT1 */
    99                 rc = fat_get_cluster(bs, service_id, FAT1, clst, &clst);
    100                 if (rc != EOK)
    101                         return rc;
    102 
    103                 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;
    104120                clusters++;
    105121        }
    106122
    107         if (lastc && clst < clst_last1)
     123        if (lastc && clst < FAT_CLST_LAST1)
    108124                *lastc = clst;
    109125        if (numc)
     
    135151                return ELIMIT;
    136152
    137         if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)
     153        if (nodep->firstc == FAT_CLST_ROOT)
    138154                goto fall_through;
    139155
     
    162178        if (rc != EOK)
    163179                return rc;
    164 
     180       
    165181        /*
    166182         * Update the "current" cluster cache.
     
    182198 * @param clp           If not NULL, address where the cluster containing bn
    183199 *                      will be stored.
    184  *                      stored
     200 *                      stored 
    185201 * @param bn            Block number.
    186202 * @param flags         Flags passed to libblock.
     
    192208    fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
    193209{
    194         uint32_t clusters;
    195         uint32_t max_clusters;
     210        uint16_t clusters;
     211        unsigned max_clusters;
    196212        fat_cluster_t c;
    197213        int rc;
     
    203219                return ELIMIT;
    204220
    205         if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) {
     221        if (fcl == FAT_CLST_ROOT) {
    206222                /* root directory special case */
    207223                assert(bn < RDS(bs));
     
    237253 * @return              EOK on success or a negative error code.
    238254 */
    239 int
    240 fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
     255int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
    241256{
    242257        block_t *b;
     
    260275                        return rc;
    261276        }
    262 
     277       
    263278        if (o >= pos)
    264279                return EOK;
    265 
     280       
    266281        /* zero out the initial part of the new cluster chain */
    267282        for (o = boundary; o < pos; o += BPS(bs)) {
     
    289304 * @return              EOK or a negative error code.
    290305 */
    291 static int
    292 fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    293     fat_cluster_t clst, fat_cluster_t *value)
    294 {
    295         block_t *b, *b1;
    296         uint16_t byte1, byte2;
    297         aoff64_t offset;
    298         int rc;
    299 
    300         offset = (clst + clst / 2);
    301         if (offset / BPS(bs) >= SF(bs))
    302                 return ERANGE;
    303 
    304         rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    305             offset / BPS(bs), BLOCK_FLAGS_NONE);
    306         if (rc != EOK)
    307                 return rc;
    308 
    309         byte1 = ((uint8_t *) b->data)[offset % BPS(bs)];
    310         /* This cluster access spans a sector boundary. Check only for FAT12 */
    311         if ((offset % BPS(bs)) + 1 == BPS(bs)) {
    312                 /* Is this the last sector of FAT? */
    313                 if (offset / BPS(bs) < SF(bs)) {
    314                         /* No, read the next sector */
    315                         rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
    316                             SF(bs) * fatno + offset / BPS(bs),
    317                             BLOCK_FLAGS_NONE);
    318                         if (rc != EOK) {
    319                                 block_put(b);
    320                                 return rc;
    321                         }
    322                         /*
    323                         * Combining value with last byte of current sector and
    324                         * first byte of next sector
    325                         */
    326                         byte2 = ((uint8_t*) b1->data)[0];
    327 
    328                         rc = block_put(b1);
    329                         if (rc != EOK) {
    330                                 block_put(b);
    331                                 return rc;
    332                         }
    333                 } else {
    334                         /* Yes. This is the last sector of FAT */
    335                         block_put(b);
    336                         return ERANGE;
    337                 }
    338         } else
    339                 byte2 = ((uint8_t *) b->data)[(offset % BPS(bs)) + 1];
    340 
    341         *value = uint16_t_le2host(byte1 | (byte2 << 8));
    342         if (IS_ODD(clst))
    343                 *value = (*value) >> 4;
    344         else
    345                 *value = (*value) & FAT12_MASK;
    346        
    347         rc = block_put(b);
    348 
    349         return rc;
    350 }
    351 
    352 /** Get cluster from the first FAT.
    353  *
    354  * @param bs            Buffer holding the boot sector for the file system.
    355  * @param service_id    Service ID for the file system.
    356  * @param clst          Cluster which to get.
    357  * @param value         Output argument holding the value of the cluster.
    358  *
    359  * @return              EOK or a negative error code.
    360  */
    361 static int
    362 fat_get_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    363     fat_cluster_t clst, fat_cluster_t *value)
    364 {
    365         block_t *b;
    366         aoff64_t offset;
    367         int rc;
    368 
    369         offset = (clst * FAT16_CLST_SIZE);
    370 
    371         rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    372             offset / BPS(bs), BLOCK_FLAGS_NONE);
    373         if (rc != EOK)
    374                 return rc;
    375 
    376         *value = uint16_t_le2host(*(uint16_t *)(b->data + offset % BPS(bs)));
    377 
    378         rc = block_put(b);
    379 
    380         return rc;
    381 }
    382 
    383 /** Get cluster from the first FAT.
    384  *
    385  * @param bs            Buffer holding the boot sector for the file system.
    386  * @param service_id    Service ID for the file system.
    387  * @param clst          Cluster which to get.
    388  * @param value         Output argument holding the value of the cluster.
    389  *
    390  * @return              EOK or a negative error code.
    391  */
    392 static int
    393 fat_get_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    394     fat_cluster_t clst, fat_cluster_t *value)
    395 {
    396         block_t *b;
    397         aoff64_t offset;
    398         int rc;
    399 
    400         offset = (clst * FAT32_CLST_SIZE);
    401 
    402         rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    403             offset / BPS(bs), BLOCK_FLAGS_NONE);
    404         if (rc != EOK)
    405                 return rc;
    406 
    407         *value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))) &
    408             FAT32_MASK;
    409 
    410         rc = block_put(b);
    411 
    412         return rc;
    413 }
    414 
    415 
    416 /** Get cluster from the first FAT.
    417  *
    418  * @param bs            Buffer holding the boot sector for the file system.
    419  * @param service_id    Service ID for the file system.
    420  * @param clst          Cluster which to get.
    421  * @param value         Output argument holding the value of the cluster.
    422  *
    423  * @return              EOK or a negative error code.
    424  */
    425306int
    426307fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    427308    fat_cluster_t clst, fat_cluster_t *value)
    428309{
    429         int rc;
    430 
    431         assert(fatno < FATCNT(bs));
    432 
    433         if (FAT_IS_FAT12(bs))
    434                 rc = fat_get_cluster_fat12(bs, service_id, fatno, clst, value);
    435         else if (FAT_IS_FAT16(bs))
    436                 rc = fat_get_cluster_fat16(bs, service_id, fatno, clst, value);
    437         else
    438                 rc = fat_get_cluster_fat32(bs, service_id, fatno, clst, value);
    439 
    440         return rc;
    441 }
    442 
    443 /** Set cluster in one instance of FAT.
    444  *
    445  * @param bs            Buffer holding the boot sector for the file system.
    446  * @param service_id    Service ID for the file system.
    447  * @param fatno         Number of the FAT instance where to make the change.
    448  * @param clst          Cluster which is to be set.
    449  * @param value         Value to set the cluster with.
    450  *
    451  * @return              EOK on success or a negative error code.
    452  */
    453 static int
    454 fat_set_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    455     fat_cluster_t clst, fat_cluster_t value)
    456 {
    457         block_t *b, *b1 = NULL;
    458         aoff64_t offset;
    459         uint16_t byte1, byte2;
    460         int rc;
    461 
    462         offset = (clst + clst / 2);
    463         if (offset / BPS(bs) >= SF(bs))
    464                 return ERANGE;
    465        
     310        block_t *b;
     311        fat_cluster_t *cp;
     312        int rc;
     313
    466314        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    467             offset / BPS(bs), BLOCK_FLAGS_NONE);
     315            (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    468316        if (rc != EOK)
    469317                return rc;
    470 
    471         byte1 = ((uint8_t*) b->data)[offset % BPS(bs)];
    472         bool border = false;
    473         /* This cluster access spans a sector boundary. */
    474         if ((offset % BPS(bs)) + 1 == BPS(bs)) {
    475                 /* Is it the last sector of FAT? */
    476                 if (offset / BPS(bs) < SF(bs)) {
    477                         /* No, read the next sector */
    478                         rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
    479                             SF(bs) * fatno + offset / BPS(bs),
    480                             BLOCK_FLAGS_NONE);
    481                         if (rc != EOK) {
    482                                 block_put(b);
    483                                 return rc;
    484                         }
    485                         /*
    486                          * Combining value with last byte of current sector and
    487                          * first byte of next sector
    488                          */
    489                         byte2 = ((uint8_t *) b1->data)[0];
    490                         border = true;
    491                 } else {
    492                         /* Yes. This is the last sector of FAT */
    493                         block_put(b);
    494                         return ERANGE;
    495                 }
    496         } else
    497                 byte2 = ((uint8_t*) b->data)[(offset % BPS(bs)) + 1];
    498 
    499         if (IS_ODD(clst)) {
    500                 byte1 &= 0x0f;
    501                 byte2 = 0;
    502                 value = (value << 4);
    503         } else {
    504                 byte1 = 0;
    505                 byte2 &= 0xf0;
    506                 value &= FAT12_MASK;
    507         }
    508 
    509         byte1 = byte1 | (value & 0xff);
    510         byte2 = byte2 | (value >> 8);
    511 
    512         ((uint8_t *) b->data)[(offset % BPS(bs))] = byte1;
    513         if (border) {
    514                 ((uint8_t *) b1->data)[0] = byte2;
    515 
    516                 b1->dirty = true;
    517                 rc = block_put(b1);
    518                 if (rc != EOK) {
    519                         block_put(b);
    520                         return rc;
    521                 }
    522         } else
    523                 ((uint8_t *) b->data)[(offset % BPS(bs)) + 1] = byte2;
    524 
    525         b->dirty = true;        /* need to sync block */
     318        cp = (fat_cluster_t *)b->data +
     319            clst % (BPS(bs) / sizeof(fat_cluster_t));
     320        *value = uint16_t_le2host(*cp);
    526321        rc = block_put(b);
    527 
    528         return rc;
    529 }
    530 
    531 /** Set cluster in one instance of FAT.
    532  *
    533  * @param bs            Buffer holding the boot sector for the file system.
    534  * @param service_id    Service ID for the file system.
    535  * @param fatno         Number of the FAT instance where to make the change.
    536  * @param clst          Cluster which is to be set.
    537  * @param value         Value to set the cluster with.
    538  *
    539  * @return              EOK on success or a negative error code.
    540  */
    541 static int
    542 fat_set_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    543     fat_cluster_t clst, fat_cluster_t value)
    544 {
    545         block_t *b;
    546         aoff64_t offset;
    547         int rc;
    548 
    549         offset = (clst * FAT16_CLST_SIZE);
    550 
    551         rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    552             offset / BPS(bs), BLOCK_FLAGS_NONE);
    553         if (rc != EOK)
    554                 return rc;
    555 
    556         *(uint16_t *)(b->data + offset % BPS(bs)) = host2uint16_t_le(value);
    557 
    558         b->dirty = true;        /* need to sync block */
    559         rc = block_put(b);
    560 
    561         return rc;
    562 }
    563 
    564 /** Set cluster in one instance of FAT.
    565  *
    566  * @param bs            Buffer holding the boot sector for the file system.
    567  * @param service_id    Service ID for the file system.
    568  * @param fatno         Number of the FAT instance where to make the change.
    569  * @param clst          Cluster which is to be set.
    570  * @param value         Value to set the cluster with.
    571  *
    572  * @return              EOK on success or a negative error code.
    573  */
    574 static int
    575 fat_set_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    576     fat_cluster_t clst, fat_cluster_t value)
    577 {
    578         block_t *b;
    579         aoff64_t offset;
    580         int rc;
    581         fat_cluster_t temp;
    582 
    583         offset = (clst * FAT32_CLST_SIZE);
    584 
    585         rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    586             offset / BPS(bs), BLOCK_FLAGS_NONE);
    587         if (rc != EOK)
    588                 return rc;
    589 
    590         temp = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs)));
    591         temp &= 0xf0000000;
    592         temp |= (value & FAT32_MASK);
    593         *(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(temp);
    594 
    595         b->dirty = true;        /* need to sync block */
    596         rc = block_put(b);
    597 
     322       
    598323        return rc;
    599324}
     
    613338    fat_cluster_t clst, fat_cluster_t value)
    614339{
     340        block_t *b;
     341        fat_cluster_t *cp;
    615342        int rc;
    616343
    617344        assert(fatno < FATCNT(bs));
    618 
    619         if (FAT_IS_FAT12(bs))
    620                 rc = fat_set_cluster_fat12(bs, service_id, fatno, clst, value);
    621         else if (FAT_IS_FAT16(bs))
    622                 rc = fat_set_cluster_fat16(bs, service_id, fatno, clst, value);
    623         else
    624                 rc = fat_set_cluster_fat32(bs, service_id, fatno, clst, value);
    625 
     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);
    626354        return rc;
    627355}
     
    641369        uint8_t fatno;
    642370        unsigned c;
    643         fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    644         int rc;
    645 
    646         for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) {
     371        int rc;
     372
     373        for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
    647374                for (c = 0; c < nclsts; c++) {
    648375                        rc = fat_set_cluster(bs, service_id, fatno, lifo[c],
    649                             c == 0 ? clst_last1 : lifo[c - 1]);
     376                            c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
    650377                        if (rc != EOK)
    651378                                return rc;
     
    677404    fat_cluster_t *mcl, fat_cluster_t *lcl)
    678405{
    679         fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    680         unsigned found = 0;     /* top of the free cluster number stack */
    681         fat_cluster_t clst, value, clst_last1 = FAT_CLST_LAST1(bs);
    682         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;
    683411
    684412        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
    685413        if (!lifo)
    686414                return ENOMEM;
     415       
    687416        /*
    688417         * Search FAT1 for unused clusters.
    689418         */
    690419        fibril_mutex_lock(&fat_alloc_lock);
    691         for (clst = FAT_CLST_FIRST; clst < CC(bs) + 2 && found < nclsts;
    692             clst++) {
    693                 rc = fat_get_cluster(bs, service_id, FAT1, clst, &value);
    694                 if (rc != EOK)
    695                         break;
    696 
    697                 if (value == FAT_CLST_RES0) {
     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++) {
    698426                        /*
    699                          * The cluster is free. Put it into our stack
    700                          * of found clusters and mark it as non-free.
     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.
    701433                         */
    702                         lifo[found] = clst;
    703                         rc = fat_set_cluster(bs, service_id, FAT1, clst,
    704                             (found == 0) ?  clst_last1 : lifo[found - 1]);
    705                         if (rc != EOK)
    706                                 break;
    707 
    708                         found++;
     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                        }
    709470                }
    710         }
    711 
    712         if (rc == EOK && found == nclsts) {
    713                 rc = fat_alloc_shadow_clusters(bs, service_id, lifo, nclsts);
    714                 if (rc == EOK) {
    715                         *mcl = lifo[found - 1];
    716                         *lcl = lifo[0];
     471                rc = block_put(blk);
     472                if (rc != EOK) {
     473error:
     474                        fibril_mutex_unlock(&fat_alloc_lock);
    717475                        free(lifo);
    718                         fibril_mutex_unlock(&fat_alloc_lock);
    719                         return EOK;
     476                        return rc;
    720477                }
    721478        }
    722 
    723         /* If something wrong - free the clusters */
     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         */
    724486        while (found--) {
    725                 (void) fat_set_cluster(bs, service_id, FAT1, lifo[found],
     487                rc = fat_set_cluster(bs, service_id, FAT1, lifo[found],
    726488                    FAT_CLST_RES0);
    727         }
    728 
     489                if (rc != EOK) {
     490                        free(lifo);
     491                        return rc;
     492                }
     493        }
     494       
    729495        free(lifo);
    730         fibril_mutex_unlock(&fat_alloc_lock);
    731 
    732496        return ENOSPC;
    733497}
     
    745509{
    746510        unsigned fatno;
    747         fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs);
     511        fat_cluster_t nextc;
    748512        int rc;
    749513
    750514        /* Mark all clusters in the chain as free in all copies of FAT. */
    751         while (firstc < FAT_CLST_LAST1(bs)) {
    752                 assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);
    753 
     515        while (firstc < FAT_CLST_LAST1) {
     516                assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
    754517                rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc);
    755518                if (rc != EOK)
    756519                        return rc;
    757 
    758                 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
     520                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    759521                        rc = fat_set_cluster(bs, service_id, fatno, firstc,
    760522                            FAT_CLST_RES0);
     
    762524                                return rc;
    763525                }
     526
    764527                firstc = nextc;
    765528        }
     
    777540 * @return              EOK on success or a negative error code.
    778541 */
    779 int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
     542int
     543fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
    780544    fat_cluster_t lcl)
    781545{
     
    795559                } else {
    796560                        rc = fat_cluster_walk(bs, service_id, nodep->firstc,
    797                             &lastc, NULL, (uint32_t) -1);
     561                            &lastc, NULL, (uint16_t) -1);
    798562                        if (rc != EOK)
    799563                                return rc;
    800564                }
    801565
    802                 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
    803                         rc = fat_set_cluster(bs, nodep->idx->service_id,
    804                             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);
    805569                        if (rc != EOK)
    806570                                return rc;
     
    826590int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl)
    827591{
    828         fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    829592        int rc;
    830593        service_id_t service_id = nodep->idx->service_id;
     
    853616
    854617                /* Terminate the cluster chain in all copies of FAT. */
    855                 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
     618                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    856619                        rc = fat_set_cluster(bs, service_id, fatno, lcl,
    857                             clst_last1);
     620                            FAT_CLST_LAST1);
    858621                        if (rc != EOK)
    859622                                return rc;
     
    910673
    911674        /* Check number of FATs. */
    912         if (FATCNT(bs) == 0)
     675        if (bs->fatcnt == 0)
    913676                return ENOTSUP;
    914677
    915678        /* Check total number of sectors. */
    916         if (TS(bs) == 0)
     679
     680        if (bs->totsec16 == 0 && bs->totsec32 == 0)
    917681                return ENOTSUP;
    918682
    919683        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    920             bs->totsec16 != bs->totsec32)
     684            bs->totsec16 != bs->totsec32) 
    921685                return ENOTSUP;
    922686
     
    926690
    927691        /* Check number of sectors per FAT. */
    928         if (SF(bs) == 0)
     692        if (bs->sec_per_fat == 0)
    929693                return ENOTSUP;
    930694
     
    936700         * sanitized to support file systems with this property.
    937701         */
    938         if (!FAT_IS_FAT32(bs) &&
    939             (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)
    940704                return ENOTSUP;
    941705
    942706        /* Check signature of each FAT. */
    943         for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) {
     707
     708        for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
    944709                rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0);
    945710                if (rc != EOK)
     
    950715                        return EIO;
    951716
    952                 /*
    953                  * Check that first byte of FAT contains the media descriptor.
    954                  */
     717                /* Check that first byte of FAT contains the media descriptor. */
    955718                if ((e0 & 0xff) != bs->mdesc)
    956719                        return ENOTSUP;
     
    960723                 * set to one.
    961724                 */
    962                 if (!FAT_IS_FAT12(bs) &&
    963                     ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs)))
     725                if ((e0 >> 8) != 0xff || e1 != 0xffff)
    964726                        return ENOTSUP;
    965727        }
     
    970732/**
    971733 * @}
    972  */
     734 */ 
  • uspace/srv/fs/fat/fat_fat.h

    r4cf5ed46 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 CLBN2PBN(bs, cl, bn) \
    79         (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
    80 
    81 #define FAT_IS_FAT12(bs)        (CC(bs) < FAT12_CLST_MAX)
    82 #define FAT_IS_FAT16(bs) \
    83     ((CC(bs) >= FAT12_CLST_MAX) && (CC(bs) < FAT16_CLST_MAX))
    84 #define FAT_IS_FAT32(bs)        (CC(bs) >= FAT16_CLST_MAX)
    85 
    86 #define FAT_CLST_SIZE(bs) \
    87     (FAT_IS_FAT32(bs) ? FAT32_CLST_SIZE : FAT16_CLST_SIZE)
    88 
    89 #define FAT_MASK(bs) \
    90     (FAT_IS_FAT12(bs) ? FAT12_MASK : \
    91     (FAT_IS_FAT32(bs) ? FAT32_MASK : FAT16_MASK))
    92 
    93 #define FAT_CLST_LAST1(bs)      (FAT32_CLST_LAST1 & FAT_MASK((bs)))
    94 #define FAT_CLST_LAST8(bs)      (FAT32_CLST_LAST8 & FAT_MASK((bs)))
    95 #define FAT_CLST_BAD(bs)        (FAT32_CLST_BAD & FAT_MASK((bs)))
    96 
    97 #define FAT_ROOT_CLST(bs) \
    98     (FAT_IS_FAT32(bs) ? uint32_t_le2host(bs->fat32.root_cluster) : \
    99     FAT_CLST_ROOT)
    100 
    10154/* forward declarations */
    10255struct block;
     
    10457struct fat_bs;
    10558
    106 typedef uint32_t fat_cluster_t;
     59typedef uint16_t fat_cluster_t;
    10760
    108 #define fat_clusters_get(numc, bs, sid, fc) \
    109     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)
    11063extern int fat_cluster_walk(struct fat_bs *, service_id_t, fat_cluster_t,
    111     fat_cluster_t *, uint32_t *, uint32_t);
     64    fat_cluster_t *, uint16_t *, uint16_t);
    11265
    11366extern int fat_block_get(block_t **, struct fat_bs *, struct fat_node *,
  • uspace/srv/fs/fat/fat_idx.c

    r4cf5ed46 r7fadb65  
    116116#define UPH_BUCKETS     (1 << UPH_BUCKETS_LOG)
    117117
    118 #define UPH_SID_KEY     0
     118#define UPH_DH_KEY      0
    119119#define UPH_PFC_KEY     1
    120120#define UPH_PDI_KEY     2
     
    122122static hash_index_t pos_hash(unsigned long key[])
    123123{
    124         service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
     124        service_id_t service_id = (service_id_t)key[UPH_DH_KEY];
    125125        fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY];
    126126        unsigned pdi = (unsigned)key[UPH_PDI_KEY];
     
    150150static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item)
    151151{
    152         service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
     152        service_id_t service_id = (service_id_t)key[UPH_DH_KEY];
    153153        fat_cluster_t pfc;
    154154        unsigned pdi;
     
    190190#define UIH_BUCKETS     (1 << UIH_BUCKETS_LOG)
    191191
    192 #define UIH_SID_KEY     0
     192#define UIH_DH_KEY      0
    193193#define UIH_INDEX_KEY   1
    194194
    195195static hash_index_t idx_hash(unsigned long key[])
    196196{
    197         service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
     197        service_id_t service_id = (service_id_t)key[UIH_DH_KEY];
    198198        fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY];
    199199
     
    209209static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item)
    210210{
    211         service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
     211        service_id_t service_id = (service_id_t)key[UIH_DH_KEY];
    212212        fs_index_t index;
    213213        fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link);
     
    402402               
    403403        unsigned long ikey[] = {
    404                 [UIH_SID_KEY] = service_id,
     404                [UIH_DH_KEY] = service_id,
    405405                [UIH_INDEX_KEY] = fidx->index,
    406406        };
     
    420420        link_t *l;
    421421        unsigned long pkey[] = {
    422                 [UPH_SID_KEY] = service_id,
     422                [UPH_DH_KEY] = service_id,
    423423                [UPH_PFC_KEY] = pfc,
    424424                [UPH_PDI_KEY] = pdi,
     
    439439               
    440440                unsigned long ikey[] = {
    441                         [UIH_SID_KEY] = service_id,
     441                        [UIH_DH_KEY] = service_id,
    442442                        [UIH_INDEX_KEY] = fidx->index,
    443443                };
     
    458458{
    459459        unsigned long pkey[] = {
    460                 [UPH_SID_KEY] = idx->service_id,
     460                [UPH_DH_KEY] = idx->service_id,
    461461                [UPH_PFC_KEY] = idx->pfc,
    462462                [UPH_PDI_KEY] = idx->pdi,
     
    471471{
    472472        unsigned long pkey[] = {
    473                 [UPH_SID_KEY] = idx->service_id,
     473                [UPH_DH_KEY] = idx->service_id,
    474474                [UPH_PFC_KEY] = idx->pfc,
    475475                [UPH_PDI_KEY] = idx->pdi,
     
    487487        link_t *l;
    488488        unsigned long ikey[] = {
    489                 [UIH_SID_KEY] = service_id,
     489                [UIH_DH_KEY] = service_id,
    490490                [UIH_INDEX_KEY] = index,
    491491        };
     
    509509{
    510510        unsigned long ikey[] = {
    511                 [UIH_SID_KEY] = idx->service_id,
     511                [UIH_DH_KEY] = idx->service_id,
    512512                [UIH_INDEX_KEY] = idx->index,
    513513        };
     
    571571{
    572572        unsigned long ikey[] = {
    573                 [UIH_SID_KEY] = service_id
     573                [UIH_DH_KEY] = service_id
    574574        };
    575575        unsigned long pkey[] = {
    576                 [UPH_SID_KEY] = service_id
     576                [UPH_DH_KEY] = service_id
    577577        };
    578578
  • uspace/srv/fs/fat/fat_ops.c

    r4cf5ed46 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         } else
    318                 nodep->firstc = uint16_t_le2host(d->firstc);
    319 
    320311        if (d->attr & FAT_ATTR_SUBDIR) {
    321                 /*
     312                /* 
    322313                 * The only directory which does not have this bit set is the
    323314                 * root directory itself. The root directory node is handled
     
    325316                 */
    326317                nodep->type = FAT_DIRECTORY;
    327 
    328318                /*
    329319                 * Unfortunately, the 'size' field of the FAT dentry is not
     
    331321                 * size of the directory by walking the FAT.
    332322                 */
    333                 uint32_t clusters;
     323                uint16_t clusters;
    334324                rc = fat_clusters_get(&clusters, bs, idxp->service_id,
    335                     nodep->firstc);
     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 %
    395                             (BPS(di.bs) / sizeof(fat_dentry_t));
    396                         fat_idx_t *idx = fat_idx_get_by_pos(service_id,
    397                             parentp->firstc, di.bnum * DPS(di.bs) + o);
    398                         if (!idx) {
    399                                 /*
    400                                  * Can happen if memory is low or if we
    401                                  * run out of 32-bit indices.
    402                                  */
    403                                 rc = fat_directory_close(&di);
    404                                 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;
    405400                        }
    406                         rc = fat_node_get_core(&nodep, idx);
    407                         fibril_mutex_unlock(&idx->lock);
    408                         if (rc != EOK) {
    409                                 (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);
    410424                                return rc;
    411425                        }
    412                         *rfn = FS_NODE(nodep);
    413                         rc = fat_directory_close(&di);
    414                         if (rc != EOK)
    415                                 (void) fat_node_put(*rfn);
    416                         return rc;
    417                 } else {
    418                         rc = fat_directory_next(&di);
    419                         if (rc != EOK)
    420                                 break;
    421                 }
    422         }
    423         (void) fat_directory_close(&di);
     426                }
     427                rc = block_put(b);
     428                if (rc != EOK)
     429                        return rc;
     430        }
     431
    424432        *rfn = NULL;
    425433        return EOK;
     
    583591        fat_bs_t *bs;
    584592        block_t *b;
    585         fat_directory_t di;
    586         fat_dentry_t de;
     593        unsigned i, j;
     594        unsigned blocks;
     595        fat_cluster_t mcl, lcl;
    587596        int rc;
    588597
     
    598607        fibril_mutex_unlock(&childp->lock);
    599608
    600         if (!fat_valid_name(name))
     609        if (!fat_dentry_name_verify(name)) {
     610                /*
     611                 * Attempt to create unsupported name.
     612                 */
    601613                return ENOTSUP;
    602 
     614        }
     615
     616        /*
     617         * Get us an unused parent node's dentry or grow the parent and allocate
     618         * a new one.
     619         */
     620       
    603621        fibril_mutex_lock(&parentp->idx->lock);
    604622        bs = block_bb_get(parentp->idx->service_id);
    605         rc = fat_directory_open(parentp, &di);
     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);
    606662        if (rc != EOK) {
    607663                fibril_mutex_unlock(&parentp->idx->lock);
    608664                return rc;
    609665        }
    610 
     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:
    611688        /*
    612689         * At this point we only establish the link between the parent and the
     
    615692         * dentry data is kept in the child node structure.
    616693         */
    617         memset(&de, 0, sizeof(fat_dentry_t));
    618 
    619         rc = fat_directory_write(&di, name, &de);
    620         if (rc != EOK) {
    621                 (void) fat_directory_close(&di);
    622                 fibril_mutex_unlock(&parentp->idx->lock);
    623                 return rc;
    624         }
    625         rc = fat_directory_close(&di);
    626         if (rc != EOK) {
    627                 fibril_mutex_unlock(&parentp->idx->lock);
    628                 return rc;
    629         }
    630 
     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);
    631698        fibril_mutex_unlock(&parentp->idx->lock);
     699        if (rc != EOK)
     700                return rc;
    632701
    633702        fibril_mutex_lock(&childp->idx->lock);
    634 
     703       
    635704        if (childp->type == FAT_DIRECTORY) {
    636705                /*
     
    651720                d = (fat_dentry_t *) b->data;
    652721                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    653                     (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) {
     722                    (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {
    654723                        memset(d, 0, sizeof(fat_dentry_t));
    655724                        memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN);
     
    661730                d++;
    662731                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    663                     (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) {
     732                    (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {
    664733                        memset(d, 0, sizeof(fat_dentry_t));
    665734                        memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN);
    666735                        memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN);
    667736                        d->attr = FAT_ATTR_SUBDIR;
    668                         d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ?
    669                             host2uint16_t_le(FAT_CLST_ROOTPAR) :
     737                        d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
     738                            host2uint16_t_le(FAT_CLST_RES0) :
    670739                            host2uint16_t_le(parentp->firstc);
    671740                        /* TODO: initialize also the date/time members. */
     
    681750
    682751        childp->idx->pfc = parentp->firstc;
    683         childp->idx->pdi = di.pos;      /* di.pos holds absolute position of SFN entry */
     752        childp->idx->pdi = i * DPS(bs) + j;
    684753        fibril_mutex_unlock(&childp->idx->lock);
    685754
     
    701770        fat_node_t *parentp = FAT_NODE(pfn);
    702771        fat_node_t *childp = FAT_NODE(cfn);
     772        fat_bs_t *bs;
     773        fat_dentry_t *d;
     774        block_t *b;
    703775        bool has_children;
    704776        int rc;
     
    706778        if (!parentp)
    707779                return EBUSY;
    708 
     780       
    709781        rc = fat_has_children(&has_children, cfn);
    710782        if (rc != EOK)
     
    717789        assert(childp->lnkcnt == 1);
    718790        fibril_mutex_lock(&childp->idx->lock);
    719        
    720         fat_directory_t di;
    721         rc = fat_directory_open(parentp, &di);
    722         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)
    723797                goto error;
    724         rc = fat_directory_seek(&di, childp->idx->pdi);
    725         if (rc != EOK)
    726                 goto error;
    727         rc = fat_directory_erase(&di);
    728         if (rc != EOK)
    729                 goto error;
    730         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);
    731804        if (rc != EOK)
    732805                goto error;
     
    747820
    748821error:
    749         (void) fat_directory_close(&di);
     822        fibril_mutex_unlock(&parentp->idx->lock);
     823        fibril_mutex_unlock(&childp->lock);
    750824        fibril_mutex_unlock(&childp->idx->lock);
    751         fibril_mutex_unlock(&childp->lock);
    752         fibril_mutex_unlock(&parentp->lock);
    753825        return rc;
    754826}
     
    767839                return EOK;
    768840        }
    769 
     841       
    770842        fibril_mutex_lock(&nodep->idx->lock);
    771843        bs = block_bb_get(nodep->idx->service_id);
     
    775847        for (i = 0; i < blocks; i++) {
    776848                fat_dentry_t *d;
    777 
     849       
    778850                rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE);
    779851                if (rc != EOK) {
     
    803875                if (rc != EOK) {
    804876                        fibril_mutex_unlock(&nodep->idx->lock);
    805                         return rc;
     877                        return rc;     
    806878                }
    807879        }
     
    874946        fat_bs_t *bs;
    875947        int rc;
    876 
     948       
    877949        /* Check for option enabling write through. */
    878950        if (str_cmp(opts, "wtcache") == 0)
     
    9311003                return ENOMEM;
    9321004        }
    933 
    9341005        fs_node_initialize(rfn);
    9351006        fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
     
    9561027
    9571028        rootp->type = FAT_DIRECTORY;
    958         rootp->firstc = FAT_ROOT_CLST(bs);
     1029        rootp->firstc = FAT_CLST_ROOT;
    9591030        rootp->refcnt = 1;
    9601031        rootp->lnkcnt = 0;      /* FS root is not linked */
    961 
    962         if (FAT_IS_FAT32(bs)) {
    963                 uint32_t clusters;
    964                 rc = fat_clusters_get(&clusters, bs, service_id, rootp->firstc);
    965                 if (rc != EOK) {
    966                         free(rfn);
    967                         free(rootp);
    968                         (void) block_cache_fini(service_id);
    969                         block_fini(service_id);
    970                         fat_idx_fini_by_service_id(service_id);
    971                         return ENOTSUP;
    972                 }
    973                 rootp->size = BPS(bs) * SPC(bs) * clusters;
    974         } else
    975                 rootp->size = RDE(bs) * sizeof(fat_dentry_t);
    976 
     1032        rootp->size = RDE(bs) * sizeof(fat_dentry_t);
    9771033        rootp->idx = ridxp;
    9781034        ridxp->nodep = rootp;
    9791035        rootp->bp = rfn;
    9801036        rfn->data = rootp;
    981 
     1037       
    9821038        fibril_mutex_unlock(&ridxp->lock);
    9831039
     
    10081064                return EBUSY;
    10091065        }
    1010 
     1066       
    10111067        /*
    10121068         * Put the root node and force it to the FAT free node list.
     
    10851141                }
    10861142        } else {
     1143                unsigned bnum;
    10871144                aoff64_t spos = pos;
    1088                 char name[FAT_LFN_NAME_SIZE];
     1145                char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
    10891146                fat_dentry_t *d;
    10901147
     
    10931150                assert(BPS(bs) % sizeof(fat_dentry_t) == 0);
    10941151
    1095                 fat_directory_t di;
    1096                 rc = fat_directory_open(nodep, &di);
    1097                 if (rc != EOK)
    1098                         goto err;
    1099                 rc = fat_directory_seek(&di, pos);
    1100                 if (rc != EOK) {
    1101                         (void) fat_directory_close(&di);
    1102                         goto err;
    1103                 }
    1104 
    1105                 rc = fat_directory_read(&di, name, &d);
    1106                 if (rc == EOK)
    1107                         goto hit;
    1108                 if (rc == ENOENT)
    1109                         goto miss;
    1110 
    1111 err:
    1112                 (void) fat_node_put(fn);
    1113                 async_answer_0(callid, rc);
    1114                 return rc;
    1115 
     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                }
    11161193miss:
    1117                 rc = fat_directory_close(&di);
    1118                 if (rc != EOK)
    1119                         goto err;
    11201194                rc = fat_node_put(fn);
    11211195                async_answer_0(callid, rc != EOK ? rc : ENOENT);
     
    11231197                return rc != EOK ? rc : ENOENT;
    11241198
     1199err:
     1200                (void) fat_node_put(fn);
     1201                async_answer_0(callid, rc);
     1202                return rc;
     1203
    11251204hit:
    1126                 pos = di.pos;
    1127                 rc = fat_directory_close(&di);
    1128                 if (rc != EOK)
    1129                         goto err;
    1130                 (void) async_data_read_finalize(callid, name,
    1131                     str_size(name) + 1);
     1205                (void) async_data_read_finalize(callid, name, str_size(name) + 1);
    11321206                bytes = (pos - spos) + 1;
    11331207        }
     
    11571231                return ENOENT;
    11581232        nodep = FAT_NODE(fn);
    1159 
     1233       
    11601234        ipc_callid_t callid;
    11611235        size_t len;
     
    11731247         * but this one greatly simplifies fat_write(). Note that we can afford
    11741248         * to do this because the client must be ready to handle the return
    1175          * value signalizing a smaller number of bytes written.
    1176          */
     1249         * value signalizing a smaller number of bytes written. 
     1250         */ 
    11771251        bytes = min(len, BPS(bs) - pos % BPS(bs));
    11781252        if (bytes == BPS(bs))
    11791253                flags |= BLOCK_FLAGS_NOREAD;
    1180 
     1254       
    11811255        boundary = ROUND_UP(nodep->size, BPC(bs));
    11821256        if (pos < boundary) {
     
    12211295                 */
    12221296                unsigned nclsts;
    1223                 fat_cluster_t mcl, lcl;
    1224 
     1297                fat_cluster_t mcl, lcl; 
     1298 
    12251299                nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs);
    12261300                /* create an independent chain of nclsts clusters in all FATs */
     
    13061380                nodep->size = size;
    13071381                nodep->dirty = true;            /* need to sync node */
    1308                 rc = EOK;
     1382                rc = EOK;       
    13091383        } else {
    13101384                /*
     
    13271401                nodep->size = size;
    13281402                nodep->dirty = true;            /* need to sync node */
    1329                 rc = EOK;
     1403                rc = EOK;       
    13301404        }
    13311405out:
     
    13701444        if (!fn)
    13711445                return ENOENT;
    1372 
     1446       
    13731447        fat_node_t *nodep = FAT_NODE(fn);
    1374 
     1448       
    13751449        nodep->dirty = true;
    13761450        rc = fat_node_sync(nodep);
    1377 
     1451       
    13781452        fat_node_put(fn);
    13791453        return rc;
Note: See TracChangeset for help on using the changeset viewer.