Changeset 97bc3ee in mainline for uspace/srv/fs/fat/fat_fat.c


Ignore:
Timestamp:
2011-04-09T19:23:12Z (13 years ago)
Author:
Oleg Romanenko <romanenko.oleg@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d260a95
Parents:
fc35e98
Message:

Full support for FAT12 file system. Correct creating directories and files. Fixing addressing issue.
Type of FAT (12,16,32) is determined only on the basis of the count of clusters(according to Microsoft FAT specification). I.e. FAT
with 4085 clusters or less will be determined as FAT12. FAT16 must contain more than 4085 clusters but less then 65525.

File:
1 edited

Legend:

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

    rfc35e98 r97bc3ee  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    3333/**
     
    5353 * primitive boot sector members.
    5454 */
    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 
    5955#define CLBN2PBN(bs, cl, bn) \
    6056        (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
     
    6460 * during allocation of clusters. The lock does not have to be held durring
    6561 * deallocation of clusters.
    66  */ 
     62 */
    6763static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    6864
     
    7672 * @param numc          If non-NULL, output argument holding the number of
    7773 *                      clusters seen during the walk.
    78  * @param max_clusters  Maximum number of clusters to visit.   
     74 * @param max_clusters  Maximum number of clusters to visit.
    7975 *
    8076 * @return              EOK on success or a negative error code.
    8177 */
    82 int 
     78int
    8379fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,
    8480    fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
     
    105101
    106102                /* read FAT1 */
    107                 /* We should use fat_get_cluster instead */
    108103                rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &clst);
    109104                if (rc != EOK)
     
    145140                return ELIMIT;
    146141
    147         if (nodep->firstc == FAT_CLST_ROOT) 
     142        if (nodep->firstc == FAT_CLST_ROOT)
    148143                goto fall_through;
    149144
     
    172167        if (rc != EOK)
    173168                return rc;
    174        
     169
    175170        /*
    176171         * Update the "current" cluster cache.
     
    192187 * @param clp           If not NULL, address where the cluster containing bn
    193188 *                      will be stored.
    194  *                      stored 
     189 *                      stored
    195190 * @param bn            Block number.
    196191 * @param flags         Flags passed to libblock.
     
    269264                        return rc;
    270265        }
    271        
     266
    272267        if (o >= pos)
    273268                return EOK;
    274        
     269
    275270        /* zero out the initial part of the new cluster chain */
    276271        for (o = boundary; o < pos; o += BPS(bs)) {
     
    302297    fat_cluster_t clst, fat_cluster_t *value)
    303298{
    304         block_t *b;
    305         fat_cluster_t *cp;
    306         aoff64_t fsec;  /* sector offset relative to FAT */
    307         unsigned fidx;  /* entry index */
     299        block_t *b, *b1;
     300        aoff64_t offset;
    308301        int rc;
    309302
    310303        assert(fatno < FATCNT(bs));
    311304
    312 
    313305        if (FATTYPE(bs) == 16)
    314         {
    315             fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
    316             fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
     306            offset = (clst * 2);
     307        else
     308            offset = (clst + clst/2);
     309
     310        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
     311                       offset / BPS(bs), BLOCK_FLAGS_NONE);
     312        if (rc != EOK)
     313                return rc;
     314
     315        /* This cluster access spans a sector boundary. Check only for FAT12 */
     316        if (FATTYPE(bs) == 12 && (offset % BPS(bs)+1 == BPS(bs))) {
     317            /* Is it last sector of FAT? */
     318            if (offset / BPS(bs) < SF(bs)) { /* NO */
     319                /* Reading next sector */
     320                rc = block_get(&b1, devmap_handle, 1+RSCNT(bs)+SF(bs)*fatno +
     321                               offset / BPS(bs), BLOCK_FLAGS_NONE);
     322                if (rc != EOK) {
     323                    block_put(b);
     324                    return rc;
     325                }
     326                /*
     327                 * Combining value with last byte of current sector and
     328                 * first byte of next sector
     329                 */
     330                *value  = *(uint8_t *)(b->data + BPS(bs) - 1);
     331                *value |= *(uint8_t *)(b1->data);
     332
     333                rc = block_put(b1);
     334                if (rc != EOK) {
     335                    block_put(b);
     336                    return rc;
     337                }
     338            }
     339            else {      /* YES */
     340                block_put(b);
     341                return ERANGE;
     342            }
    317343        }
    318344        else
    319         {
    320             fsec = (clst + clst/2) / BPS(bs);
    321             fidx = clst % (2 * BPS(bs) / 3 );
    322         }
    323 
    324         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    325                        fsec, BLOCK_FLAGS_NONE);
    326         if (rc != EOK)
    327                 return rc;
    328 
    329         if (FATTYPE(bs) == 16)
    330             cp = &((fat_cluster_t *)b->data)[fidx];
    331         else
    332             cp = (fat_cluster_t *)(b->data + fidx);
    333 
    334         *value = *cp;
    335 
    336         if (FATTYPE(bs) == 12)
    337         {
     345            *value = *(fat_cluster_t *)(b->data + offset % BPS(bs));
     346
     347        if (FATTYPE(bs) == 12) {
    338348            if (clst & 0x0001)
    339349                *value = (*value) >> 4;
     
    344354        *value = uint16_t_le2host(*value);
    345355        rc = block_put(b);
    346        
     356
    347357        return rc;
    348358}
     
    362372    fat_cluster_t clst, fat_cluster_t value)
    363373{
    364         block_t *b;
    365         fat_cluster_t *cp;
    366         int rc;
    367         aoff64_t fsec;  /* sector offset relative to FAT */
    368         unsigned fidx;  /* entry index */
     374        block_t *b, *b1;
     375        aoff64_t offset;
     376        fat_cluster_t *cp, temp;
     377        int rc;
     378        int spans = 0;
    369379
    370380        assert(fatno < FATCNT(bs));
    371381
    372382        if (FATTYPE(bs) == 16)
    373         {
    374             fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
    375             fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
     383            offset = (clst * sizeof(fat_cluster_t));
     384        else
     385            offset = (clst + clst/2);
     386
     387        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
     388                       offset / BPS(bs), BLOCK_FLAGS_NONE);
     389        if (rc != EOK)
     390                return rc;
     391
     392        /* This cluster access spans a sector boundary. Check only for FAT12 */
     393        if (FATTYPE(bs) == 12 && (offset % BPS(bs)+1 == BPS(bs))) {
     394            /* Is it last sector of FAT? */
     395            if (offset / BPS(bs) < SF(bs)) { /* NO */
     396                /* Reading next sector */
     397                rc = block_get(&b1, devmap_handle, 1+RSCNT(bs)+SF(bs)*fatno +
     398                               offset / BPS(bs), BLOCK_FLAGS_NONE);
     399                if (rc != EOK) {
     400                    block_put(b);
     401                    return rc;
     402                }
     403                /*
     404                 * Combining value with last byte of current sector and
     405                 * first byte of next sector
     406                 */
     407                spans=1;
     408                cp = &temp;
     409                *cp  = *(uint8_t *)(b->data + BPS(bs) - 1);
     410                *cp |= *(uint8_t *)(b1->data);
     411            }
     412            else {      /* YES */
     413                block_put(b);
     414                return ERANGE;
     415            }
    376416        }
    377417        else
    378         {
    379             fsec = (clst + clst/2) / BPS(bs);
    380             fidx = clst % (2 * BPS(bs) / 3 );
    381         }
    382 
    383         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    384                        fsec, BLOCK_FLAGS_NONE);
    385         if (rc != EOK)
    386                 return rc;
    387 
    388         if (FATTYPE(bs) == 12)
    389         {
    390             cp = (fat_cluster_t *)(b->data + fidx);
    391             if (clst & 0x0001)
     418            cp = (fat_cluster_t *)(b->data + offset % BPS(bs));
     419
     420        value = host2uint16_t_le(value);
     421        if (FATTYPE(bs) == 12) {
     422            if (clst & 0x0001) {
     423                *cp &= 0x000f;
     424                *cp |= value << 4;
     425            }
     426            else {
     427                *cp &= 0xf000;
     428                *cp |= value & 0x0fff;
     429            }
     430
     431            if (spans)
    392432            {
    393                 *cp &= 0x000f;
    394                 *cp |= host2uint16_t_le(value) << 4;
    395             }
    396             else
    397             {
    398                 *cp &= 0xf000;
    399                 *cp |= host2uint16_t_le(value) & 0x0fff;
     433                *(uint8_t *)(b->data + BPS(bs) - 1) = cp[0];
     434                *(uint8_t *)(b1->data) = cp[1];
     435
     436                b1->dirty = true;
     437                rc = block_put(b1);
     438                if (rc != EOK) {
     439                    block_put(b);
     440                    return rc;
     441                }
    400442            }
    401443        }
    402444        else
    403         {
    404             cp = &((fat_cluster_t *)b->data)[fidx];
    405             *cp = host2uint16_t_le(value);
    406         }
     445            *cp = value;
    407446
    408447        b->dirty = true;                /* need to sync block */
     
    464503        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    465504        unsigned found = 0;     /* top of the free cluster number stack */
    466         fat_cluster_t clst, max_clst, value;
     505        fat_cluster_t clst, value;
    467506        int rc = EOK;
    468507        uint16_t clst_last1 = FATTYPE(bs) == 16 ? FAT16_CLST_LAST1 :
    469508                                                  FAT12_CLST_LAST1;
    470509
    471 
    472510        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
    473511        if (!lifo)
    474512                return ENOMEM;
    475 
    476513        /*
    477514         * Search FAT1 for unused clusters.
    478515         */
    479 
    480         if (FATTYPE(bs) == 16)
    481             max_clst = SF(bs) * BPS(bs) / sizeof(fat_cluster_t);
    482         else
    483             max_clst = 2 *SF(bs) * BPS(bs) / 3;
    484 
    485516        fibril_mutex_lock(&fat_alloc_lock);
    486         for (clst=0; clst < max_clst && found < nclsts; clst++)
    487         {
     517        for (clst=FAT_CLST_FIRST; clst < CC(bs)+2 && found < nclsts; clst++) {
    488518            rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &value);
    489519            if (rc != EOK)
    490520                break;
    491             /*
    492             * Check if the entire cluster is physically there.
    493             * This check becomes necessary when the file system is
    494             * created with fewer total sectors than how many is
    495             * inferred from the size of the file allocation table
    496             * or when the last cluster ends beyond the end of the
    497             * device.
    498             */
    499             if ((clst >= FAT_CLST_FIRST) &&
    500                 CLBN2PBN(bs, clst, SPC(bs) - 1) >= TS(bs)) {
    501                     rc = EIO;
    502                     break;
    503             }
     521
    504522            if (value == FAT_CLST_RES0) {
    505523                /*
     
    518536        }
    519537
    520         if (rc == EOK && found == nclsts)
    521         {
     538        if (rc == EOK && found == nclsts) {
    522539            rc = fat_alloc_shadow_clusters(bs, devmap_handle, lifo, nclsts);
    523             if (rc == EOK)
    524             {
     540            if (rc == EOK) {
    525541                *mcl = lifo[found - 1];
    526542                *lcl = lifo[0];
     
    532548
    533549        /* If something wrong - free the clusters */
    534         if (found > 0)
    535         {
     550        if (found > 0) {
    536551            while (found--) {
    537552                rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
     
    735750
    736751        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    737             bs->totsec16 != bs->totsec32) 
     752            bs->totsec16 != bs->totsec32)
    738753                return ENOTSUP;
    739754
     
    775790                 * set to one.
    776791                 */
    777                 /* Disabled for testing FAT12
    778                 if ((e0 >> 8) != 0xff || e1 != 0xffff)
     792                if (FATTYPE(bs)!=12 && ((e0 >> 8) != 0xff || e1 != 0xffff))
    779793                        return ENOTSUP;
    780                 */
    781794        }
    782795
     
    786799/**
    787800 * @}
    788  */ 
     801 */
Note: See TracChangeset for help on using the changeset viewer.