Ignore:
File:
1 edited

Legend:

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

    rd70d80ed r5f116e7  
    4646#include <align.h>
    4747#include <assert.h>
    48 #include <fibril_synch.h>
     48#include <fibril_sync.h>
    4949#include <mem.h>
    50 
    51 /*
    52  * Convenience macros for computing some frequently used values from the
    53  * primitive boot sector members.
    54  */
    55 #define RDS(bs)         ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
    56                         (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
    57 #define SSA(bs)         (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
    58 
    59 #define CLBN2PBN(bs, cl, bn) \
    60         (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
    6150
    6251/**
     
    7059 *
    7160 * @param bs            Buffer holding the boot sector for the file.
    72  * @param devmap_handle Device handle of the device with the file.
     61 * @param dev_handle    Device handle of the device with the file.
    7362 * @param firstc        First cluster to start the walk with.
    74  * @param lastc         If non-NULL, output argument hodling the last cluster
    75  *                      number visited.
    76  * @param numc          If non-NULL, output argument holding the number of
    77  *                      clusters seen during the walk.
     63 * @param lastc         If non-NULL, output argument hodling the last cluster number visited.
    7864 * @param max_clusters  Maximum number of clusters to visit.   
    7965 *
    80  * @return              EOK on success or a negative error code.
    81  */
    82 int
    83 fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,
    84     fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
    85 {
    86         block_t *b;
     66 * @return              Number of clusters seen during the walk.
     67 */
     68uint16_t
     69fat_cluster_walk(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
     70    fat_cluster_t *lastc, uint16_t max_clusters)
     71{
     72        block_t *b;
     73        unsigned bps;
     74        unsigned rscnt;         /* block address of the first FAT */
    8775        uint16_t clusters = 0;
    8876        fat_cluster_t clst = firstc;
    89         int rc;
     77
     78        bps = uint16_t_le2host(bs->bps);
     79        rscnt = uint16_t_le2host(bs->rscnt);
    9080
    9181        if (firstc == FAT_CLST_RES0) {
     
    9383                if (lastc)
    9484                        *lastc = firstc;
    95                 if (numc)
    96                         *numc = 0;
    97                 return EOK;
     85                return 0;
    9886        }
    9987
    10088        while (clst < FAT_CLST_LAST1 && clusters < max_clusters) {
    101                 aoff64_t fsec;  /* sector offset relative to FAT1 */
     89                bn_t fsec;      /* sector offset relative to FAT1 */
    10290                unsigned fidx;  /* FAT1 entry index */
    10391
     
    10593                if (lastc)
    10694                        *lastc = clst;  /* remember the last cluster number */
    107                 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
    108                 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
     95                fsec = (clst * sizeof(fat_cluster_t)) / bps;
     96                fidx = clst % (bps / sizeof(fat_cluster_t));
    10997                /* read FAT1 */
    110                 rc = block_get(&b, devmap_handle, RSCNT(bs) + fsec,
    111                     BLOCK_FLAGS_NONE);
    112                 if (rc != EOK)
    113                         return rc;
     98                b = block_get(dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE);
    11499                clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
    115100                assert(clst != FAT_CLST_BAD);
    116                 rc = block_put(b);
    117                 if (rc != EOK)
    118                         return rc;
     101                block_put(b);
    119102                clusters++;
    120103        }
     
    122105        if (lastc && clst < FAT_CLST_LAST1)
    123106                *lastc = clst;
    124         if (numc)
    125                 *numc = clusters;
    126 
    127         return EOK;
     107
     108        return clusters;
    128109}
    129110
    130111/** Read block from file located on a FAT file system.
    131112 *
    132  * @param block         Pointer to a block pointer for storing result.
    133113 * @param bs            Buffer holding the boot sector of the file system.
    134  * @param nodep         FAT node.
     114 * @param dev_handle    Device handle of the file system.
     115 * @param firstc        First cluster used by the file. Can be zero if the file
     116 *                      is empty.
    135117 * @param bn            Block number.
    136118 * @param flags         Flags passed to libblock.
    137119 *
    138  * @return              EOK on success or a negative error code.
    139  */
    140 int
    141 fat_block_get(block_t **block, struct fat_bs *bs, fat_node_t *nodep,
    142     aoff64_t bn, int flags)
    143 {
    144         fat_cluster_t firstc = nodep->firstc;
    145         fat_cluster_t currc;
    146         aoff64_t relbn = bn;
    147         int rc;
    148 
    149         if (!nodep->size)
    150                 return ELIMIT;
    151 
    152         if (nodep->firstc == FAT_CLST_ROOT)
    153                 goto fall_through;
    154 
    155         if (((((nodep->size - 1) / BPS(bs)) / SPC(bs)) == bn / SPC(bs)) &&
    156             nodep->lastc_cached_valid) {
    157                 /*
    158                  * This is a request to read a block within the last cluster
    159                  * when fortunately we have the last cluster number cached.
    160                  */
    161                 return block_get(block, nodep->idx->devmap_handle,
    162                     CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags);
    163         }
    164 
    165         if (nodep->currc_cached_valid && bn >= nodep->currc_cached_bn) {
    166                 /*
    167                  * We can start with the cluster cached by the previous call to
    168                  * fat_block_get().
    169                  */
    170                 firstc = nodep->currc_cached_value;
    171                 relbn -= (nodep->currc_cached_bn / SPC(bs)) * SPC(bs);
    172         }
    173 
    174 fall_through:
    175         rc = _fat_block_get(block, bs, nodep->idx->devmap_handle, firstc,
    176             &currc, relbn, flags);
    177         if (rc != EOK)
    178                 return rc;
    179        
    180         /*
    181          * Update the "current" cluster cache.
    182          */
    183         nodep->currc_cached_valid = true;
    184         nodep->currc_cached_bn = bn;
    185         nodep->currc_cached_value = currc;
    186 
    187         return rc;
    188 }
    189 
    190 /** Read block from file located on a FAT file system.
    191  *
    192  * @param block         Pointer to a block pointer for storing result.
    193  * @param bs            Buffer holding the boot sector of the file system.
    194  * @param devmap_handle Device handle of the file system.
    195  * @param fcl           First cluster used by the file. Can be zero if the file
    196  *                      is empty.
    197  * @param clp           If not NULL, address where the cluster containing bn
    198  *                      will be stored.
    199  *                      stored
    200  * @param bn            Block number.
    201  * @param flags         Flags passed to libblock.
    202  *
    203  * @return              EOK on success or a negative error code.
    204  */
    205 int
    206 _fat_block_get(block_t **block, fat_bs_t *bs, devmap_handle_t devmap_handle,
    207     fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
    208 {
    209         uint16_t clusters;
    210         unsigned max_clusters;
    211         fat_cluster_t c;
    212         int rc;
    213 
    214         /*
    215          * This function can only operate on non-zero length files.
    216          */
    217         if (fcl == FAT_CLST_RES0)
    218                 return ELIMIT;
    219 
    220         if (fcl == FAT_CLST_ROOT) {
     120 * @return              Block structure holding the requested block.
     121 */
     122block_t *
     123_fat_block_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
     124    bn_t bn, int flags)
     125{
     126        block_t *b;
     127        unsigned bps;
     128        unsigned rscnt;         /* block address of the first FAT */
     129        unsigned rde;
     130        unsigned rds;           /* root directory size */
     131        unsigned sf;
     132        unsigned ssa;           /* size of the system area */
     133        unsigned clusters, max_clusters;
     134        fat_cluster_t lastc;
     135
     136        bps = uint16_t_le2host(bs->bps);
     137        rscnt = uint16_t_le2host(bs->rscnt);
     138        rde = uint16_t_le2host(bs->root_ent_max);
     139        sf = uint16_t_le2host(bs->sec_per_fat);
     140
     141        rds = (sizeof(fat_dentry_t) * rde) / bps;
     142        rds += ((sizeof(fat_dentry_t) * rde) % bps != 0);
     143        ssa = rscnt + bs->fatcnt * sf + rds;
     144
     145        if (firstc == FAT_CLST_ROOT) {
    221146                /* root directory special case */
    222                 assert(bn < RDS(bs));
    223                 rc = block_get(block, devmap_handle,
    224                     RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags);
    225                 return rc;
    226         }
    227 
    228         max_clusters = bn / SPC(bs);
    229         rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters);
    230         if (rc != EOK)
    231                 return rc;
     147                assert(bn < rds);
     148                b = block_get(dev_handle, rscnt + bs->fatcnt * sf + bn, flags);
     149                return b;
     150        }
     151
     152        max_clusters = bn / bs->spc;
     153        clusters = fat_cluster_walk(bs, dev_handle, firstc, &lastc,
     154            max_clusters);
    232155        assert(clusters == max_clusters);
    233156
    234         rc = block_get(block, devmap_handle, CLBN2PBN(bs, c, bn), flags);
    235 
    236         if (clp)
    237                 *clp = c;
    238 
    239         return rc;
     157        b = block_get(dev_handle, ssa + (lastc - FAT_CLST_FIRST) * bs->spc +
     158            bn % bs->spc, flags);
     159
     160        return b;
    240161}
    241162
     
    249170 *                      this argument is ignored.
    250171 * @param pos           Position in the last node block.
    251  *
    252  * @return              EOK on success or a negative error code.
    253  */
    254 int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
    255 {
    256         block_t *b;
    257         aoff64_t o, boundary;
    258         int rc;
    259 
    260         boundary = ROUND_UP(nodep->size, BPS(bs) * SPC(bs));
     172 */
     173void fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, off_t pos)
     174{
     175        uint16_t bps;
     176        unsigned spc;
     177        block_t *b;
     178        off_t o, boundary;
     179
     180        bps = uint16_t_le2host(bs->bps);
     181        spc = bs->spc;
     182       
     183        boundary = ROUND_UP(nodep->size, bps * spc);
    261184
    262185        /* zero out already allocated space */
    263186        for (o = nodep->size; o < pos && o < boundary;
    264             o = ALIGN_DOWN(o + BPS(bs), BPS(bs))) {
    265                 int flags = (o % BPS(bs) == 0) ?
     187            o = ALIGN_DOWN(o + bps, bps)) {
     188                int flags = (o % bps == 0) ?
    266189                    BLOCK_FLAGS_NOREAD : BLOCK_FLAGS_NONE;
    267                 rc = fat_block_get(&b, bs, nodep, o / BPS(bs), flags);
    268                 if (rc != EOK)
    269                         return rc;
    270                 memset(b->data + o % BPS(bs), 0, BPS(bs) - o % BPS(bs));
     190                b = fat_block_get(bs, nodep, o / bps, flags);
     191                memset(b->data + o % bps, 0, bps - o % bps);
    271192                b->dirty = true;                /* need to sync node */
    272                 rc = block_put(b);
    273                 if (rc != EOK)
    274                         return rc;
     193                block_put(b);
    275194        }
    276195       
    277196        if (o >= pos)
    278                 return EOK;
     197                return;
    279198       
    280199        /* zero out the initial part of the new cluster chain */
    281         for (o = boundary; o < pos; o += BPS(bs)) {
    282                 rc = _fat_block_get(&b, bs, nodep->idx->devmap_handle, mcl,
    283                     NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD);
    284                 if (rc != EOK)
    285                         return rc;
    286                 memset(b->data, 0, min(BPS(bs), pos - o));
     200        for (o = boundary; o < pos; o += bps) {
     201                b = _fat_block_get(bs, nodep->idx->dev_handle, mcl,
     202                    (o - boundary) / bps, BLOCK_FLAGS_NOREAD);
     203                memset(b->data, 0, min(bps, pos - o));
    287204                b->dirty = true;                /* need to sync node */
    288                 rc = block_put(b);
    289                 if (rc != EOK)
    290                         return rc;
    291         }
    292 
    293         return EOK;
     205                block_put(b);
     206        }
    294207}
    295208
     
    297210 *
    298211 * @param bs            Buffer holding the boot sector for the file system.
    299  * @param devmap_handle Device handle for the file system.
     212 * @param dev_handle    Device handle for the file system.
    300213 * @param clst          Cluster which to get.
    301  * @param value         Output argument holding the value of the cluster.
    302  *
    303  * @return              EOK or a negative error code.
    304  */
    305 int
    306 fat_get_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
    307     fat_cluster_t clst, fat_cluster_t *value)
    308 {
    309         block_t *b;
    310         fat_cluster_t *cp;
    311         int rc;
    312 
    313         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    314             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    315         if (rc != EOK)
    316                 return rc;
    317         cp = (fat_cluster_t *)b->data +
    318             clst % (BPS(bs) / sizeof(fat_cluster_t));
    319         *value = uint16_t_le2host(*cp);
    320         rc = block_put(b);
    321        
    322         return rc;
     214 *
     215 * @return              Value found in the cluster.
     216 */
     217fat_cluster_t
     218fat_get_cluster(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t clst)
     219{
     220        block_t *b;
     221        uint16_t bps;
     222        uint16_t rscnt;
     223        fat_cluster_t *cp, value;
     224
     225        bps = uint16_t_le2host(bs->bps);
     226        rscnt = uint16_t_le2host(bs->rscnt);
     227
     228        b = block_get(dev_handle, rscnt + (clst * sizeof(fat_cluster_t)) / bps,
     229            BLOCK_FLAGS_NONE);
     230        cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t));
     231        value = uint16_t_le2host(*cp);
     232        block_put(b);
     233       
     234        return value;
    323235}
    324236
     
    326238 *
    327239 * @param bs            Buffer holding the boot sector for the file system.
    328  * @param devmap_handle Device handle for the file system.
     240 * @param dev_handle    Device handle for the file system.
    329241 * @param fatno         Number of the FAT instance where to make the change.
    330242 * @param clst          Cluster which is to be set.
    331243 * @param value         Value to set the cluster with.
    332  *
    333  * @return              EOK on success or a negative error code.
    334  */
    335 int
    336 fat_set_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
     244 */
     245void
     246fat_set_cluster(fat_bs_t *bs, dev_handle_t dev_handle, unsigned fatno,
    337247    fat_cluster_t clst, fat_cluster_t value)
    338248{
    339249        block_t *b;
     250        uint16_t bps;
     251        uint16_t rscnt;
     252        uint16_t sf;
    340253        fat_cluster_t *cp;
    341         int rc;
    342 
    343         assert(fatno < FATCNT(bs));
    344         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    345             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    346         if (rc != EOK)
    347                 return rc;
    348         cp = (fat_cluster_t *)b->data +
    349             clst % (BPS(bs) / sizeof(fat_cluster_t));
     254
     255        bps = uint16_t_le2host(bs->bps);
     256        rscnt = uint16_t_le2host(bs->rscnt);
     257        sf = uint16_t_le2host(bs->sec_per_fat);
     258
     259        assert(fatno < bs->fatcnt);
     260        b = block_get(dev_handle, rscnt + sf * fatno +
     261            (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE);
     262        cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t));
    350263        *cp = host2uint16_t_le(value);
    351264        b->dirty = true;                /* need to sync block */
    352         rc = block_put(b);
    353         return rc;
     265        block_put(b);
    354266}
    355267
     
    357269 *
    358270 * @param bs            Buffer holding the boot sector of the file system.
    359  * @param devmap_handle Device handle of the file system.
     271 * @param dev_handle    Device handle of the file system.
    360272 * @param lifo          Chain of allocated clusters.
    361273 * @param nclsts        Number of clusters in the lifo chain.
    362  *
    363  * @return              EOK on success or a negative error code.
    364  */
    365 int fat_alloc_shadow_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle,
     274 */
     275void fat_alloc_shadow_clusters(fat_bs_t *bs, dev_handle_t dev_handle,
    366276    fat_cluster_t *lifo, unsigned nclsts)
    367277{
    368278        uint8_t fatno;
    369279        unsigned c;
    370         int rc;
    371280
    372281        for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
    373282                for (c = 0; c < nclsts; c++) {
    374                         rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],
     283                        fat_set_cluster(bs, dev_handle, fatno, lifo[c],
    375284                            c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
    376                         if (rc != EOK)
    377                                 return rc;
    378285                }
    379286        }
    380 
    381         return EOK;
    382287}
    383288
     
    390295 *
    391296 * @param bs            Buffer holding the boot sector of the file system.
    392  * @param devmap_handle Device handle of the file system.
     297 * @param dev_handle    Device handle of the file system.
    393298 * @param nclsts        Number of clusters to allocate.
    394299 * @param mcl           Output parameter where the first cluster in the chain
     
    400305 */
    401306int
    402 fat_alloc_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned nclsts,
     307fat_alloc_clusters(fat_bs_t *bs, dev_handle_t dev_handle, unsigned nclsts,
    403308    fat_cluster_t *mcl, fat_cluster_t *lcl)
    404309{
     310        uint16_t bps;
     311        uint16_t rscnt;
     312        uint16_t sf;
    405313        block_t *blk;
    406314        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    407315        unsigned found = 0;     /* top of the free cluster number stack */
    408316        unsigned b, c, cl;
    409         int rc;
    410317
    411318        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
    412319        if (!lifo)
    413320                return ENOMEM;
     321       
     322        bps = uint16_t_le2host(bs->bps);
     323        rscnt = uint16_t_le2host(bs->rscnt);
     324        sf = uint16_t_le2host(bs->sec_per_fat);
    414325       
    415326        /*
     
    417328         */
    418329        fibril_mutex_lock(&fat_alloc_lock);
    419         for (b = 0, cl = 0; b < SF(bs); b++) {
    420                 rc = block_get(&blk, devmap_handle, RSCNT(bs) + b,
    421                     BLOCK_FLAGS_NONE);
    422                 if (rc != EOK)
    423                         goto error;
    424                 for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) {
    425                         /*
    426                          * Check if the entire cluster is physically there.
    427                          * This check becomes necessary when the file system is
    428                          * created with fewer total sectors than how many is
    429                          * inferred from the size of the file allocation table
    430                          * or when the last cluster ends beyond the end of the
    431                          * device.
    432                          */
    433                         if ((cl >= FAT_CLST_FIRST) &&
    434                             CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) {
    435                                 rc = block_put(blk);
    436                                 if (rc != EOK)
    437                                         goto error;
    438                                 goto out;
    439                         }
    440 
     330        for (b = 0, cl = 0; b < sf; b++) {
     331                blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NONE);
     332                for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) {
    441333                        fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
    442334                        if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
     
    452344                                if (++found == nclsts) {
    453345                                        /* we are almost done */
    454                                         rc = block_put(blk);
    455                                         if (rc != EOK)
    456                                                 goto error;
     346                                        block_put(blk);
    457347                                        /* update the shadow copies of FAT */
    458                                         rc = fat_alloc_shadow_clusters(bs,
    459                                             devmap_handle, lifo, nclsts);
    460                                         if (rc != EOK)
    461                                                 goto error;
     348                                        fat_alloc_shadow_clusters(bs,
     349                                            dev_handle, lifo, nclsts);
    462350                                        *mcl = lifo[found - 1];
    463351                                        *lcl = lifo[0];
     
    468356                        }
    469357                }
    470                 rc = block_put(blk);
    471                 if (rc != EOK) {
    472 error:
    473                         fibril_mutex_unlock(&fat_alloc_lock);
    474                         free(lifo);
    475                         return rc;
    476                 }
    477         }
    478 out:
     358                block_put(blk);
     359        }
    479360        fibril_mutex_unlock(&fat_alloc_lock);
    480361
     
    484365         */
    485366        while (found--) {
    486                 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
     367                fat_set_cluster(bs, dev_handle, FAT1, lifo[found],
    487368                    FAT_CLST_RES0);
    488                 if (rc != EOK) {
    489                         free(lifo);
    490                         return rc;
    491                 }
    492369        }
    493370       
     
    499376 *
    500377 * @param bs            Buffer hodling the boot sector of the file system.
    501  * @param devmap_handle Device handle of the file system.
     378 * @param dev_handle    Device handle of the file system.
    502379 * @param firstc        First cluster in the chain which is to be freed.
    503  *
    504  * @return              EOK on success or a negative return code.
    505  */
    506 int
    507 fat_free_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc)
     380 */
     381void
     382fat_free_clusters(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc)
    508383{
    509384        unsigned fatno;
    510385        fat_cluster_t nextc;
    511         int rc;
    512386
    513387        /* Mark all clusters in the chain as free in all copies of FAT. */
    514388        while (firstc < FAT_CLST_LAST1) {
    515389                assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
    516                 rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc);
    517                 if (rc != EOK)
    518                         return rc;
    519                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    520                         rc = fat_set_cluster(bs, devmap_handle, fatno, firstc,
     390                nextc = fat_get_cluster(bs, dev_handle, firstc);
     391                for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
     392                        fat_set_cluster(bs, dev_handle, fatno, firstc,
    521393                            FAT_CLST_RES0);
    522                         if (rc != EOK)
    523                                 return rc;
    524                 }
    525 
    526394                firstc = nextc;
    527395        }
    528 
    529         return EOK;
    530396}
    531397
     
    535401 * @param nodep         Node representing the file.
    536402 * @param mcl           First cluster of the cluster chain to append.
    537  * @param lcl           Last cluster of the cluster chain to append.
    538  *
    539  * @return              EOK on success or a negative error code.
    540  */
    541 int
    542 fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
    543     fat_cluster_t lcl)
    544 {
    545         devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
    546         fat_cluster_t lastc;
     403 */
     404void fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl)
     405{
     406        dev_handle_t dev_handle = nodep->idx->dev_handle;
     407        fat_cluster_t lcl;
    547408        uint8_t fatno;
    548         int rc;
    549 
    550         if (nodep->firstc == FAT_CLST_RES0) {
     409
     410        if (fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl,
     411            (uint16_t) -1) == 0) {
    551412                /* No clusters allocated to the node yet. */
    552413                nodep->firstc = mcl;
    553                 nodep->dirty = true;    /* need to sync node */
    554         } else {
    555                 if (nodep->lastc_cached_valid) {
    556                         lastc = nodep->lastc_cached_value;
    557                         nodep->lastc_cached_valid = false;
    558                 } else {
    559                         rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,
    560                             &lastc, NULL, (uint16_t) -1);
    561                         if (rc != EOK)
    562                                 return rc;
    563                 }
    564 
    565                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    566                         rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno,
    567                             lastc, mcl);
    568                         if (rc != EOK)
    569                                 return rc;
    570                 }
    571         }
    572 
    573         nodep->lastc_cached_valid = true;
    574         nodep->lastc_cached_value = lcl;
    575 
    576         return EOK;
     414                nodep->dirty = true;            /* need to sync node */
     415                return;
     416        }
     417
     418        for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
     419                fat_set_cluster(bs, nodep->idx->dev_handle, fatno, lcl, mcl);
    577420}
    578421
     
    581424 * @param bs            Buffer holding the boot sector of the file system.
    582425 * @param nodep         FAT node where the chopping will take place.
    583  * @param lcl           Last cluster which will remain in the node. If this
     426 * @param lastc         Last cluster which will remain in the node. If this
    584427 *                      argument is FAT_CLST_RES0, then all clusters will
    585428 *                      be chopped off.
    586  *
    587  * @return              EOK on success or a negative return code.
    588  */
    589 int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl)
    590 {
    591         int rc;
    592         devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
    593 
    594         /*
    595          * Invalidate cached cluster numbers.
    596          */
    597         nodep->lastc_cached_valid = false;
    598         if (nodep->currc_cached_value != lcl)
    599                 nodep->currc_cached_valid = false;
    600 
    601         if (lcl == FAT_CLST_RES0) {
     429 */
     430void fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lastc)
     431{
     432        dev_handle_t dev_handle = nodep->idx->dev_handle;
     433        if (lastc == FAT_CLST_RES0) {
    602434                /* The node will have zero size and no clusters allocated. */
    603                 rc = fat_free_clusters(bs, devmap_handle, nodep->firstc);
    604                 if (rc != EOK)
    605                         return rc;
     435                fat_free_clusters(bs, dev_handle, nodep->firstc);
    606436                nodep->firstc = FAT_CLST_RES0;
    607437                nodep->dirty = true;            /* need to sync node */
     
    610440                unsigned fatno;
    611441
    612                 rc = fat_get_cluster(bs, devmap_handle, FAT1, lcl, &nextc);
    613                 if (rc != EOK)
    614                         return rc;
     442                nextc = fat_get_cluster(bs, dev_handle, lastc);
    615443
    616444                /* Terminate the cluster chain in all copies of FAT. */
    617                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    618                         rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,
    619                             FAT_CLST_LAST1);
    620                         if (rc != EOK)
    621                                 return rc;
    622                 }
     445                for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
     446                        fat_set_cluster(bs, dev_handle, fatno, lastc, FAT_CLST_LAST1);
    623447
    624448                /* Free all following clusters. */
    625                 rc = fat_free_clusters(bs, devmap_handle, nextc);
    626                 if (rc != EOK)
    627                         return rc;
    628         }
    629 
    630         /*
    631          * Update and re-enable the last cluster cache.
    632          */
    633         nodep->lastc_cached_valid = true;
    634         nodep->lastc_cached_value = lcl;
    635 
    636         return EOK;
    637 }
    638 
    639 int
    640 fat_zero_cluster(struct fat_bs *bs, devmap_handle_t devmap_handle, fat_cluster_t c)
     449                fat_free_clusters(bs, dev_handle, nextc);
     450        }
     451}
     452
     453void
     454fat_zero_cluster(struct fat_bs *bs, dev_handle_t dev_handle, fat_cluster_t c)
    641455{
    642456        int i;
    643457        block_t *b;
    644         int rc;
    645 
    646         for (i = 0; i < SPC(bs); i++) {
    647                 rc = _fat_block_get(&b, bs, devmap_handle, c, NULL, i,
    648                     BLOCK_FLAGS_NOREAD);
    649                 if (rc != EOK)
    650                         return rc;
    651                 memset(b->data, 0, BPS(bs));
     458        unsigned bps;
     459
     460        bps = uint16_t_le2host(bs->bps);
     461       
     462        for (i = 0; i < bs->spc; i++) {
     463                b = _fat_block_get(bs, dev_handle, c, i, BLOCK_FLAGS_NOREAD);
     464                memset(b->data, 0, bps);
    652465                b->dirty = true;
    653                 rc = block_put(b);
    654                 if (rc != EOK)
    655                         return rc;
    656         }
    657 
    658         return EOK;
    659 }
    660 
    661 /** Perform basic sanity checks on the file system.
    662  *
    663  * Verify if values of boot sector fields are sane. Also verify media
    664  * descriptor. This is used to rule out cases when a device obviously
    665  * does not contain a fat file system.
    666  */
    667 int fat_sanity_check(fat_bs_t *bs, devmap_handle_t devmap_handle)
    668 {
    669         fat_cluster_t e0, e1;
    670         unsigned fat_no;
    671         int rc;
    672 
    673         /* Check number of FATs. */
    674         if (bs->fatcnt == 0)
    675                 return ENOTSUP;
    676 
    677         /* Check total number of sectors. */
    678 
    679         if (bs->totsec16 == 0 && bs->totsec32 == 0)
    680                 return ENOTSUP;
    681 
    682         if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    683             bs->totsec16 != bs->totsec32)
    684                 return ENOTSUP;
    685 
    686         /* Check media descriptor. Must be between 0xf0 and 0xff. */
    687         if ((bs->mdesc & 0xf0) != 0xf0)
    688                 return ENOTSUP;
    689 
    690         /* Check number of sectors per FAT. */
    691         if (bs->sec_per_fat == 0)
    692                 return ENOTSUP;
    693 
    694         /*
    695          * Check that the root directory entries take up whole blocks.
    696          * This check is rather strict, but it allows us to treat the root
    697          * directory and non-root directories uniformly in some places.
    698          * It can be removed provided that functions such as fat_read() are
    699          * sanitized to support file systems with this property.
    700          */
    701         if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) %
    702             uint16_t_le2host(bs->bps) != 0)
    703                 return ENOTSUP;
    704 
    705         /* Check signature of each FAT. */
    706 
    707         for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
    708                 rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0);
    709                 if (rc != EOK)
    710                         return EIO;
    711 
    712                 rc = fat_get_cluster(bs, devmap_handle, fat_no, 1, &e1);
    713                 if (rc != EOK)
    714                         return EIO;
    715 
    716                 /* Check that first byte of FAT contains the media descriptor. */
    717                 if ((e0 & 0xff) != bs->mdesc)
    718                         return ENOTSUP;
    719 
    720                 /*
    721                  * Check that remaining bits of the first two entries are
    722                  * set to one.
    723                  */
    724                 if ((e0 >> 8) != 0xff || e1 != 0xffff)
    725                         return ENOTSUP;
    726         }
    727 
    728         return EOK;
     466                block_put(b);
     467        }
    729468}
    730469
Note: See TracChangeset for help on using the changeset viewer.