Changeset 0f57d0e in mainline for uspace/srv/fs/fat/fat_fat.c


Ignore:
Timestamp:
2008-10-26T14:10:53Z (16 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b1178d0
Parents:
033ef7d3
Message:

Move functionality related to manipulatings file allocation tables to fat_fat.c.

File:
1 edited

Legend:

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

    r033ef7d3 r0f57d0e  
    3636 */
    3737
     38#include "fat_fat.h"
     39#include "fat_dentry.h"
     40#include "fat.h"
     41#include "../../vfs/vfs.h"
     42#include <libfs.h>
     43#include <errno.h>
     44#include <byteorder.h>
     45#include <align.h>
     46#include <assert.h>
     47
     48block_t *
     49_fat_block_get(dev_handle_t dev_handle, fat_cluster_t firstc, off_t offset)
     50{
     51        block_t *bb;
     52        block_t *b;
     53        unsigned bps;
     54        unsigned spc;
     55        unsigned rscnt;         /* block address of the first FAT */
     56        unsigned fatcnt;
     57        unsigned rde;
     58        unsigned rds;           /* root directory size */
     59        unsigned sf;
     60        unsigned ssa;           /* size of the system area */
     61        unsigned clusters;
     62        fat_cluster_t clst = firstc;
     63        unsigned i;
     64
     65        bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
     66        bps = uint16_t_le2host(FAT_BS(bb)->bps);
     67        spc = FAT_BS(bb)->spc;
     68        rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt);
     69        fatcnt = FAT_BS(bb)->fatcnt;
     70        rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max);
     71        sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat);
     72        block_put(bb);
     73
     74        rds = (sizeof(fat_dentry_t) * rde) / bps;
     75        rds += ((sizeof(fat_dentry_t) * rde) % bps != 0);
     76        ssa = rscnt + fatcnt * sf + rds;
     77
     78        if (firstc == FAT_CLST_ROOT) {
     79                /* root directory special case */
     80                assert(offset < rds);
     81                b = block_get(dev_handle, rscnt + fatcnt * sf + offset, bps);
     82                return b;
     83        }
     84
     85        clusters = offset / spc;
     86        for (i = 0; i < clusters; i++) {
     87                unsigned fsec;  /* sector offset relative to FAT1 */
     88                unsigned fidx;  /* FAT1 entry index */
     89
     90                assert(clst >= FAT_CLST_FIRST && clst < FAT_CLST_BAD);
     91                fsec = (clst * sizeof(fat_cluster_t)) / bps;
     92                fidx = clst % (bps / sizeof(fat_cluster_t));
     93                /* read FAT1 */
     94                b = block_get(dev_handle, rscnt + fsec, bps);
     95                clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
     96                assert(clst != FAT_CLST_BAD);
     97                assert(clst < FAT_CLST_LAST1);
     98                block_put(b);
     99        }
     100
     101        b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * spc +
     102            offset % spc, bps);
     103
     104        return b;
     105}
     106
     107/** Return number of blocks allocated to a file.
     108 *
     109 * @param dev_handle    Device handle of the device with the file.
     110 * @param firstc        First cluster of the file.
     111 *
     112 * @return              Number of blocks allocated to the file.
     113 */
     114uint16_t
     115_fat_blcks_get(dev_handle_t dev_handle, fat_cluster_t firstc)
     116{
     117        block_t *bb;
     118        block_t *b;
     119        unsigned bps;
     120        unsigned spc;
     121        unsigned rscnt;         /* block address of the first FAT */
     122        unsigned clusters = 0;
     123        fat_cluster_t clst = firstc;
     124
     125        bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
     126        bps = uint16_t_le2host(FAT_BS(bb)->bps);
     127        spc = FAT_BS(bb)->spc;
     128        rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt);
     129        block_put(bb);
     130
     131        if (firstc == FAT_CLST_RES0) {
     132                /* No space allocated to the file. */
     133                return 0;
     134        }
     135
     136        while (clst < FAT_CLST_LAST1) {
     137                unsigned fsec;  /* sector offset relative to FAT1 */
     138                unsigned fidx;  /* FAT1 entry index */
     139
     140                assert(clst >= FAT_CLST_FIRST);
     141                fsec = (clst * sizeof(fat_cluster_t)) / bps;
     142                fidx = clst % (bps / sizeof(fat_cluster_t));
     143                /* read FAT1 */
     144                b = block_get(dev_handle, rscnt + fsec, bps);
     145                clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
     146                assert(clst != FAT_CLST_BAD);
     147                block_put(b);
     148                clusters++;
     149        }
     150
     151        return clusters * spc;
     152}
     153
     154uint16_t fat_bps_get(dev_handle_t dev_handle)
     155{
     156        block_t *bb;
     157        uint16_t bps;
     158       
     159        bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
     160        assert(bb != NULL);
     161        bps = uint16_t_le2host(FAT_BS(bb)->bps);
     162        block_put(bb);
     163
     164        return bps;
     165}
     166
     167/** Fill the gap between EOF and a new file position.
     168 *
     169 * @param nodep         FAT node with the gap.
     170 * @param mcl           First cluster in an independent cluster chain that will
     171 *                      be later appended to the end of the node's own cluster
     172 *                      chain. If pos is still in the last allocated cluster,
     173 *                      this argument is ignored.
     174 * @param pos           Position in the last node block.
     175 */
     176void fat_fill_gap(fat_node_t *nodep, fat_cluster_t mcl, off_t pos)
     177{
     178        uint16_t bps;
     179        unsigned spc;
     180        block_t *bb, *b;
     181        off_t o, boundary;
     182
     183        bb = block_get(nodep->idx->dev_handle, BS_BLOCK, BS_SIZE);
     184        bps = uint16_t_le2host(FAT_BS(bb)->bps);
     185        spc = FAT_BS(bb)->spc;
     186        block_put(bb);
     187       
     188        boundary = ROUND_UP(nodep->size, bps * spc);
     189
     190        /* zero out already allocated space */
     191        for (o = nodep->size - 1; o < pos && o < boundary;
     192            o = ALIGN_DOWN(o + bps, bps)) {
     193                b = fat_block_get(nodep, o / bps);
     194                memset(b->data + o % bps, 0, bps - o % bps);
     195                b->dirty = true;                /* need to sync node */
     196                block_put(b);
     197        }
     198       
     199        if (o >= pos)
     200                return;
     201       
     202        /* zero out the initial part of the new cluster chain */
     203        for (o = boundary; o < pos; o += bps) {
     204                b = _fat_block_get(nodep->idx->dev_handle, mcl,
     205                    (o - boundary) / bps);
     206                memset(b->data, 0, min(bps, pos - o));
     207                b->dirty = true;                /* need to sync node */
     208                block_put(b);
     209        }
     210}
     211
     212void
     213fat_mark_cluster(dev_handle_t dev_handle, unsigned fatno, fat_cluster_t clst,
     214    fat_cluster_t value)
     215{
     216        /* TODO */
     217}
     218
     219void
     220fat_alloc_shadow_clusters(dev_handle_t dev_handle, fat_cluster_t *lifo,
     221    unsigned nclsts)
     222{
     223        /* TODO */
     224}
     225
     226int
     227fat_alloc_clusters(dev_handle_t dev_handle, unsigned nclsts, fat_cluster_t *mcl,
     228    fat_cluster_t *lcl)
     229{
     230        uint16_t bps;
     231        uint16_t rscnt;
     232        uint16_t sf;
     233        block_t *bb, *blk;
     234        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
     235        unsigned found = 0;     /* top of the free cluster number stack */
     236        unsigned b, c, cl;
     237
     238        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
     239        if (lifo)
     240                return ENOMEM;
     241       
     242        bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
     243        bps = uint16_t_le2host(FAT_BS(bb)->bps);
     244        rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt);
     245        sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat);
     246        block_put(bb);
     247       
     248        /*
     249         * Search FAT1 for unused clusters.
     250         */
     251        for (b = 0, cl = 0; b < sf; blk++) {
     252                blk = block_get(dev_handle, rscnt + b, bps);
     253                for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) {
     254                        fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
     255                        if (*clst == FAT_CLST_RES0) {
     256                                /*
     257                                 * The cluster is free. Put it into our stack
     258                                 * of found clusters and mark it as non-free.
     259                                 */
     260                                lifo[found] = cl;
     261                                if (found == 0)
     262                                        *clst = FAT_CLST_LAST1;
     263                                else
     264                                        *clst = lifo[found - 1];
     265                                blk->dirty = true;      /* need to sync block */
     266                                if (++found == nclsts) {
     267                                        /* we are almost done */
     268                                        block_put(blk);
     269                                        /* update the shadow copies of FAT */
     270                                        fat_alloc_shadow_clusters(dev_handle,
     271                                            lifo, nclsts);
     272                                        *mcl = lifo[found - 1];
     273                                        *lcl = lifo[0];
     274                                        free(lifo);
     275                                        return EOK;
     276                                }
     277                        }
     278                }
     279                block_put(blk);
     280        }
     281
     282        /*
     283         * We could not find enough clusters. Now we need to free the clusters
     284         * we have allocated so far.
     285         */
     286        while (found--)
     287                fat_mark_cluster(dev_handle, FAT1, lifo[found], FAT_CLST_RES0);
     288       
     289        free(lifo);
     290        return ENOSPC;
     291}
     292
     293void fat_append_clusters(fat_node_t *nodep, fat_cluster_t mcl)
     294{
     295}
    38296
    39297/**
Note: See TracChangeset for help on using the changeset viewer.