~helenos-nicf/helenos/nicf

« back to all changes in this revision

Viewing changes to uspace/srv/fs/fat/fat_fat.c

  • Committer: Radim Vansa
  • Date: 2011-09-20 21:55:59 UTC
  • mfrom: (697.1.517 HelenOS.mainline)
  • Revision ID: radim.vansa@matfyz.cz-20110920215559-7fjpai6wt5ieurcq
Merge with mainline

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Copyright (c) 2008 Jakub Jermar
 
3
 * Copyright (c) 2011 Oleg Romanenko
3
4
 * All rights reserved.
4
5
 *
5
6
 * Redistribution and use in source and binary forms, with or without
28
29
 
29
30
/** @addtogroup fs
30
31
 * @{
31
 
 */ 
 
32
 */
32
33
 
33
34
/**
34
35
 * @file        fat_fat.c
49
50
#include <malloc.h>
50
51
#include <mem.h>
51
52
 
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)))
 
53
#define IS_ODD(number)  (number & 0x1)
62
54
 
63
55
/**
64
56
 * The fat_alloc_lock mutex protects all copies of the File Allocation Table
65
57
 * during allocation of clusters. The lock does not have to be held durring
66
58
 * deallocation of clusters.
67
 
 */  
 
59
 */
68
60
static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
69
61
 
70
62
/** Walk the cluster chain.
71
63
 *
72
64
 * @param bs            Buffer holding the boot sector for the file.
73
 
 * @param devmap_handle Device handle of the device with the file.
 
65
 * @param service_id    Service ID of the device with the file.
74
66
 * @param firstc        First cluster to start the walk with.
75
67
 * @param lastc         If non-NULL, output argument hodling the last cluster
76
68
 *                      number visited.
77
69
 * @param numc          If non-NULL, output argument holding the number of
78
70
 *                      clusters seen during the walk.
79
 
 * @param max_clusters  Maximum number of clusters to visit.    
 
71
 * @param max_clusters  Maximum number of clusters to visit.
80
72
 *
81
73
 * @return              EOK on success or a negative error code.
82
74
 */
83
 
int 
84
 
fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,
85
 
    fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
 
75
int
 
76
fat_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)
86
78
{
87
 
        block_t *b;
88
 
        uint16_t clusters = 0;
89
 
        fat_cluster_t clst = firstc;
 
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);
90
82
        int rc;
91
83
 
92
84
        if (firstc == FAT_CLST_RES0) {
98
90
                return EOK;
99
91
        }
100
92
 
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
 
 
 
93
        while (clst < clst_last1 && clusters < max_clusters) {
105
94
                assert(clst >= FAT_CLST_FIRST);
106
95
                if (lastc)
107
96
                        *lastc = clst;  /* remember the last cluster number */
108
 
                fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
109
 
                fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
 
97
 
110
98
                /* read FAT1 */
111
 
                rc = block_get(&b, devmap_handle, 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;
 
99
                rc = fat_get_cluster(bs, service_id, FAT1, clst, &clst);
 
100
                if (rc != EOK)
 
101
                        return rc;
 
102
 
 
103
                assert(clst != clst_bad);
120
104
                clusters++;
121
105
        }
122
106
 
123
 
        if (lastc && clst < FAT_CLST_LAST1)
 
107
        if (lastc && clst < clst_last1)
124
108
                *lastc = clst;
125
109
        if (numc)
126
110
                *numc = clusters;
150
134
        if (!nodep->size)
151
135
                return ELIMIT;
152
136
 
153
 
        if (nodep->firstc == FAT_CLST_ROOT) 
 
137
        if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)
154
138
                goto fall_through;
155
139
 
156
140
        if (((((nodep->size - 1) / BPS(bs)) / SPC(bs)) == bn / SPC(bs)) &&
159
143
                 * This is a request to read a block within the last cluster
160
144
                 * when fortunately we have the last cluster number cached.
161
145
                 */
162
 
                return block_get(block, nodep->idx->devmap_handle,
 
146
                return block_get(block, nodep->idx->service_id,
163
147
                    CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags);
164
148
        }
165
149
 
173
157
        }
174
158
 
175
159
fall_through:
176
 
        rc = _fat_block_get(block, bs, nodep->idx->devmap_handle, firstc,
 
160
        rc = _fat_block_get(block, bs, nodep->idx->service_id, firstc,
177
161
            &currc, relbn, flags);
178
162
        if (rc != EOK)
179
163
                return rc;
180
 
        
 
164
 
181
165
        /*
182
166
         * Update the "current" cluster cache.
183
167
         */
192
176
 *
193
177
 * @param block         Pointer to a block pointer for storing result.
194
178
 * @param bs            Buffer holding the boot sector of the file system.
195
 
 * @param devmap_handle Device handle of the file system.
 
179
 * @param service_id    Service ID handle of the file system.
196
180
 * @param fcl           First cluster used by the file. Can be zero if the file
197
181
 *                      is empty.
198
182
 * @param clp           If not NULL, address where the cluster containing bn
199
183
 *                      will be stored.
200
 
 *                      stored 
 
184
 *                      stored
201
185
 * @param bn            Block number.
202
186
 * @param flags         Flags passed to libblock.
203
187
 *
204
188
 * @return              EOK on success or a negative error code.
205
189
 */
206
190
int
207
 
_fat_block_get(block_t **block, fat_bs_t *bs, devmap_handle_t devmap_handle,
 
191
_fat_block_get(block_t **block, fat_bs_t *bs, service_id_t service_id,
208
192
    fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
209
193
{
210
 
        uint16_t clusters;
211
 
        unsigned max_clusters;
 
194
        uint32_t clusters;
 
195
        uint32_t max_clusters;
212
196
        fat_cluster_t c;
213
197
        int rc;
214
198
 
218
202
        if (fcl == FAT_CLST_RES0)
219
203
                return ELIMIT;
220
204
 
221
 
        if (fcl == FAT_CLST_ROOT) {
 
205
        if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) {
222
206
                /* root directory special case */
223
207
                assert(bn < RDS(bs));
224
 
                rc = block_get(block, devmap_handle,
 
208
                rc = block_get(block, service_id,
225
209
                    RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags);
226
210
                return rc;
227
211
        }
228
212
 
229
213
        max_clusters = bn / SPC(bs);
230
 
        rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters);
 
214
        rc = fat_cluster_walk(bs, service_id, fcl, &c, &clusters, max_clusters);
231
215
        if (rc != EOK)
232
216
                return rc;
233
217
        assert(clusters == max_clusters);
234
218
 
235
 
        rc = block_get(block, devmap_handle, CLBN2PBN(bs, c, bn), flags);
 
219
        rc = block_get(block, service_id, CLBN2PBN(bs, c, bn), flags);
236
220
 
237
221
        if (clp)
238
222
                *clp = c;
252
236
 *
253
237
 * @return              EOK on success or a negative error code.
254
238
 */
255
 
int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
 
239
int
 
240
fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
256
241
{
257
242
        block_t *b;
258
243
        aoff64_t o, boundary;
274
259
                if (rc != EOK)
275
260
                        return rc;
276
261
        }
277
 
        
 
262
 
278
263
        if (o >= pos)
279
264
                return EOK;
280
 
        
 
265
 
281
266
        /* zero out the initial part of the new cluster chain */
282
267
        for (o = boundary; o < pos; o += BPS(bs)) {
283
 
                rc = _fat_block_get(&b, bs, nodep->idx->devmap_handle, mcl,
 
268
                rc = _fat_block_get(&b, bs, nodep->idx->service_id, mcl,
284
269
                    NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD);
285
270
                if (rc != EOK)
286
271
                        return rc;
297
282
/** Get cluster from the first FAT.
298
283
 *
299
284
 * @param bs            Buffer holding the boot sector for the file system.
300
 
 * @param devmap_handle Device handle for the file system.
301
 
 * @param clst          Cluster which to get.
302
 
 * @param value         Output argument holding the value of the cluster.
303
 
 *
304
 
 * @return              EOK or a negative error code.
305
 
 */
306
 
int
307
 
fat_get_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
308
 
    fat_cluster_t clst, fat_cluster_t *value)
309
 
{
310
 
        block_t *b;
311
 
        fat_cluster_t *cp;
312
 
        int rc;
313
 
 
314
 
        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
315
 
            (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
316
 
        if (rc != EOK)
317
 
                return rc;
318
 
        cp = (fat_cluster_t *)b->data +
319
 
            clst % (BPS(bs) / sizeof(fat_cluster_t));
320
 
        *value = uint16_t_le2host(*cp);
321
 
        rc = block_put(b);
322
 
        
323
 
        return rc;
324
 
}
325
 
 
326
 
/** Set cluster in one instance of FAT.
327
 
 *
328
 
 * @param bs            Buffer holding the boot sector for the file system.
329
 
 * @param devmap_handle Device handle for the file system.
330
 
 * @param fatno         Number of the FAT instance where to make the change.
331
 
 * @param clst          Cluster which is to be set.
332
 
 * @param value         Value to set the cluster with.
333
 
 *
334
 
 * @return              EOK on success or a negative error code.
335
 
 */
336
 
int
337
 
fat_set_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
338
 
    fat_cluster_t clst, fat_cluster_t value)
339
 
{
340
 
        block_t *b;
341
 
        fat_cluster_t *cp;
342
 
        int rc;
343
 
 
344
 
        assert(fatno < FATCNT(bs));
345
 
        rc = block_get(&b, devmap_handle, 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);
 
285
 * @param service_id    Service ID for the file system.
 
286
 * @param clst          Cluster which to get.
 
287
 * @param value         Output argument holding the value of the cluster.
 
288
 *
 
289
 * @return              EOK or a negative error code.
 
290
 */
 
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
 */
 
425
int
 
426
fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
 
427
    fat_cluster_t clst, fat_cluster_t *value)
 
428
{
 
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
        
 
466
        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
 
467
            offset / BPS(bs), BLOCK_FLAGS_NONE);
 
468
        if (rc != EOK)
 
469
                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 */
 
526
        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
 
 
598
        return rc;
 
599
}
 
600
 
 
601
/** Set cluster in one instance of FAT.
 
602
 *
 
603
 * @param bs            Buffer holding the boot sector for the file system.
 
604
 * @param service_id    Device service ID for the file system.
 
605
 * @param fatno         Number of the FAT instance where to make the change.
 
606
 * @param clst          Cluster which is to be set.
 
607
 * @param value         Value to set the cluster with.
 
608
 *
 
609
 * @return              EOK on success or a negative error code.
 
610
 */
 
611
int
 
612
fat_set_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
 
613
    fat_cluster_t clst, fat_cluster_t value)
 
614
{
 
615
        int rc;
 
616
 
 
617
        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
 
354
626
        return rc;
355
627
}
356
628
 
357
629
/** Replay the allocatoin of clusters in all shadow instances of FAT.
358
630
 *
359
631
 * @param bs            Buffer holding the boot sector of the file system.
360
 
 * @param devmap_handle Device handle of the file system.
 
632
 * @param service_id    Service ID of the file system.
361
633
 * @param lifo          Chain of allocated clusters.
362
634
 * @param nclsts        Number of clusters in the lifo chain.
363
635
 *
364
636
 * @return              EOK on success or a negative error code.
365
637
 */
366
 
int fat_alloc_shadow_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle,
 
638
int fat_alloc_shadow_clusters(fat_bs_t *bs, service_id_t service_id,
367
639
    fat_cluster_t *lifo, unsigned nclsts)
368
640
{
369
641
        uint8_t fatno;
370
642
        unsigned c;
 
643
        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
371
644
        int rc;
372
645
 
373
 
        for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
 
646
        for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) {
374
647
                for (c = 0; c < nclsts; c++) {
375
 
                        rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],
376
 
                            c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
 
648
                        rc = fat_set_cluster(bs, service_id, fatno, lifo[c],
 
649
                            c == 0 ? clst_last1 : lifo[c - 1]);
377
650
                        if (rc != EOK)
378
651
                                return rc;
379
652
                }
390
663
 * file yet).
391
664
 *
392
665
 * @param bs            Buffer holding the boot sector of the file system.
393
 
 * @param devmap_handle Device handle of the file system.
 
666
 * @param service_id    Device service ID of the file system.
394
667
 * @param nclsts        Number of clusters to allocate.
395
668
 * @param mcl           Output parameter where the first cluster in the chain
396
669
 *                      will be returned.
400
673
 * @return              EOK on success, a negative error code otherwise.
401
674
 */
402
675
int
403
 
fat_alloc_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned nclsts,
 
676
fat_alloc_clusters(fat_bs_t *bs, service_id_t service_id, unsigned nclsts,
404
677
    fat_cluster_t *mcl, fat_cluster_t *lcl)
405
678
{
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;
 
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;
411
683
 
412
684
        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
413
685
        if (!lifo)
417
689
         * Search FAT1 for unused clusters.
418
690
         */
419
691
        fibril_mutex_lock(&fat_alloc_lock);
420
 
        for (b = 0, cl = 0; b < SF(bs); b++) {
421
 
                rc = block_get(&blk, devmap_handle, RSCNT(bs) + b,
422
 
                    BLOCK_FLAGS_NONE);
 
692
        for (clst = FAT_CLST_FIRST; clst < CC(bs) + 2 && found < nclsts;
 
693
            clst++) {
 
694
                rc = fat_get_cluster(bs, service_id, FAT1, clst, &value);
423
695
                if (rc != EOK)
424
 
                        goto error;
425
 
                for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) {
 
696
                        break;
 
697
 
 
698
                if (value == FAT_CLST_RES0) {
426
699
                        /*
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.
 
700
                         * The cluster is free. Put it into our stack
 
701
                         * of found clusters and mark it as non-free.
433
702
                         */
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
 
                        }
 
703
                        lifo[found] = clst;
 
704
                        rc = fat_set_cluster(bs, service_id, FAT1, clst,
 
705
                            (found == 0) ?  clst_last1 : lifo[found - 1]);
 
706
                        if (rc != EOK)
 
707
                                break;
441
708
 
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
 
                                            devmap_handle, 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
 
                        }
 
709
                        found++;
470
710
                }
471
 
                rc = block_put(blk);
472
 
                if (rc != EOK) {
473
 
error:
 
711
        }
 
712
 
 
713
        if (rc == EOK && found == nclsts) {
 
714
                rc = fat_alloc_shadow_clusters(bs, service_id, lifo, nclsts);
 
715
                if (rc == EOK) {
 
716
                        *mcl = lifo[found - 1];
 
717
                        *lcl = lifo[0];
 
718
                        free(lifo);
474
719
                        fibril_mutex_unlock(&fat_alloc_lock);
475
 
                        free(lifo);
476
 
                        return rc;
 
720
                        return EOK;
477
721
                }
478
722
        }
479
 
out:
480
 
        fibril_mutex_unlock(&fat_alloc_lock);
481
723
 
482
 
        /*
483
 
         * We could not find enough clusters. Now we need to free the clusters
484
 
         * we have allocated so far.
485
 
         */
 
724
        /* If something wrong - free the clusters */
486
725
        while (found--) {
487
 
                rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
 
726
                (void) fat_set_cluster(bs, service_id, FAT1, lifo[found],
488
727
                    FAT_CLST_RES0);
489
 
                if (rc != EOK) {
490
 
                        free(lifo);
491
 
                        return rc;
492
 
                }
493
728
        }
494
 
        
 
729
 
495
730
        free(lifo);
 
731
        fibril_mutex_unlock(&fat_alloc_lock);
 
732
 
496
733
        return ENOSPC;
497
734
}
498
735
 
499
736
/** Free clusters forming a cluster chain in all copies of FAT.
500
737
 *
501
738
 * @param bs            Buffer hodling the boot sector of the file system.
502
 
 * @param devmap_handle Device handle of the file system.
 
739
 * @param service_id    Device service ID of the file system.
503
740
 * @param firstc        First cluster in the chain which is to be freed.
504
741
 *
505
742
 * @return              EOK on success or a negative return code.
506
743
 */
507
744
int
508
 
fat_free_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc)
 
745
fat_free_clusters(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc)
509
746
{
510
747
        unsigned fatno;
511
 
        fat_cluster_t nextc;
 
748
        fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs);
512
749
        int rc;
513
750
 
514
751
        /* Mark all clusters in the chain as free in all copies of FAT. */
515
 
        while (firstc < FAT_CLST_LAST1) {
516
 
                assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
517
 
                rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc);
 
752
        while (firstc < FAT_CLST_LAST1(bs)) {
 
753
                assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);
 
754
 
 
755
                rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc);
518
756
                if (rc != EOK)
519
757
                        return rc;
520
 
                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
521
 
                        rc = fat_set_cluster(bs, devmap_handle, fatno, firstc,
 
758
 
 
759
                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
 
760
                        rc = fat_set_cluster(bs, service_id, fatno, firstc,
522
761
                            FAT_CLST_RES0);
523
762
                        if (rc != EOK)
524
763
                                return rc;
539
778
 *
540
779
 * @return              EOK on success or a negative error code.
541
780
 */
542
 
int
543
 
fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
 
781
int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
544
782
    fat_cluster_t lcl)
545
783
{
546
 
        devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
 
784
        service_id_t service_id = nodep->idx->service_id;
547
785
        fat_cluster_t lastc;
548
786
        uint8_t fatno;
549
787
        int rc;
557
795
                        lastc = nodep->lastc_cached_value;
558
796
                        nodep->lastc_cached_valid = false;
559
797
                } else {
560
 
                        rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,
561
 
                            &lastc, NULL, (uint16_t) -1);
 
798
                        rc = fat_cluster_walk(bs, service_id, nodep->firstc,
 
799
                            &lastc, NULL, (uint32_t) -1);
562
800
                        if (rc != EOK)
563
801
                                return rc;
564
802
                }
565
803
 
566
 
                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
567
 
                        rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno,
568
 
                            lastc, mcl);
 
804
                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
 
805
                        rc = fat_set_cluster(bs, nodep->idx->service_id,
 
806
                            fatno, lastc, mcl);
569
807
                        if (rc != EOK)
570
808
                                return rc;
571
809
                }
589
827
 */
590
828
int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl)
591
829
{
 
830
        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
592
831
        int rc;
593
 
        devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
 
832
        service_id_t service_id = nodep->idx->service_id;
594
833
 
595
834
        /*
596
835
         * Invalidate cached cluster numbers.
601
840
 
602
841
        if (lcl == FAT_CLST_RES0) {
603
842
                /* The node will have zero size and no clusters allocated. */
604
 
                rc = fat_free_clusters(bs, devmap_handle, nodep->firstc);
 
843
                rc = fat_free_clusters(bs, service_id, nodep->firstc);
605
844
                if (rc != EOK)
606
845
                        return rc;
607
846
                nodep->firstc = FAT_CLST_RES0;
610
849
                fat_cluster_t nextc;
611
850
                unsigned fatno;
612
851
 
613
 
                rc = fat_get_cluster(bs, devmap_handle, FAT1, lcl, &nextc);
 
852
                rc = fat_get_cluster(bs, service_id, FAT1, lcl, &nextc);
614
853
                if (rc != EOK)
615
854
                        return rc;
616
855
 
617
856
                /* Terminate the cluster chain in all copies of FAT. */
618
 
                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
619
 
                        rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,
620
 
                            FAT_CLST_LAST1);
 
857
                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
 
858
                        rc = fat_set_cluster(bs, service_id, fatno, lcl,
 
859
                            clst_last1);
621
860
                        if (rc != EOK)
622
861
                                return rc;
623
862
                }
624
863
 
625
864
                /* Free all following clusters. */
626
 
                rc = fat_free_clusters(bs, devmap_handle, nextc);
 
865
                rc = fat_free_clusters(bs, service_id, nextc);
627
866
                if (rc != EOK)
628
867
                        return rc;
629
868
        }
638
877
}
639
878
 
640
879
int
641
 
fat_zero_cluster(struct fat_bs *bs, devmap_handle_t devmap_handle, fat_cluster_t c)
 
880
fat_zero_cluster(struct fat_bs *bs, service_id_t service_id, fat_cluster_t c)
642
881
{
643
882
        int i;
644
883
        block_t *b;
645
884
        int rc;
646
885
 
647
886
        for (i = 0; i < SPC(bs); i++) {
648
 
                rc = _fat_block_get(&b, bs, devmap_handle, c, NULL, i,
 
887
                rc = _fat_block_get(&b, bs, service_id, c, NULL, i,
649
888
                    BLOCK_FLAGS_NOREAD);
650
889
                if (rc != EOK)
651
890
                        return rc;
665
904
 * descriptor. This is used to rule out cases when a device obviously
666
905
 * does not contain a fat file system.
667
906
 */
668
 
int fat_sanity_check(fat_bs_t *bs, devmap_handle_t devmap_handle)
 
907
int fat_sanity_check(fat_bs_t *bs, service_id_t service_id)
669
908
{
670
909
        fat_cluster_t e0, e1;
671
910
        unsigned fat_no;
672
911
        int rc;
673
912
 
674
913
        /* Check number of FATs. */
675
 
        if (bs->fatcnt == 0)
 
914
        if (FATCNT(bs) == 0)
676
915
                return ENOTSUP;
677
916
 
678
917
        /* Check total number of sectors. */
679
 
 
680
 
        if (bs->totsec16 == 0 && bs->totsec32 == 0)
 
918
        if (TS(bs) == 0)
681
919
                return ENOTSUP;
682
920
 
683
921
        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
684
 
            bs->totsec16 != bs->totsec32) 
 
922
            bs->totsec16 != bs->totsec32)
685
923
                return ENOTSUP;
686
924
 
687
925
        /* Check media descriptor. Must be between 0xf0 and 0xff. */
689
927
                return ENOTSUP;
690
928
 
691
929
        /* Check number of sectors per FAT. */
692
 
        if (bs->sec_per_fat == 0)
 
930
        if (SF(bs) == 0)
693
931
                return ENOTSUP;
694
932
 
695
933
        /*
699
937
         * It can be removed provided that functions such as fat_read() are
700
938
         * sanitized to support file systems with this property.
701
939
         */
702
 
        if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) %
703
 
            uint16_t_le2host(bs->bps) != 0)
 
940
        if (!FAT_IS_FAT32(bs) &&
 
941
            (RDE(bs) * sizeof(fat_dentry_t)) % BPS(bs) != 0)
704
942
                return ENOTSUP;
705
943
 
706
944
        /* Check signature of each FAT. */
707
 
 
708
 
        for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
709
 
                rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0);
710
 
                if (rc != EOK)
711
 
                        return EIO;
712
 
 
713
 
                rc = fat_get_cluster(bs, devmap_handle, fat_no, 1, &e1);
714
 
                if (rc != EOK)
715
 
                        return EIO;
716
 
 
717
 
                /* Check that first byte of FAT contains the media descriptor. */
 
945
        for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) {
 
946
                rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0);
 
947
                if (rc != EOK)
 
948
                        return EIO;
 
949
 
 
950
                rc = fat_get_cluster(bs, service_id, fat_no, 1, &e1);
 
951
                if (rc != EOK)
 
952
                        return EIO;
 
953
 
 
954
                /*
 
955
                 * Check that first byte of FAT contains the media descriptor.
 
956
                 */
718
957
                if ((e0 & 0xff) != bs->mdesc)
719
958
                        return ENOTSUP;
720
959
 
722
961
                 * Check that remaining bits of the first two entries are
723
962
                 * set to one.
724
963
                 */
725
 
                if ((e0 >> 8) != 0xff || e1 != 0xffff)
 
964
                if (!FAT_IS_FAT12(bs) && 
 
965
                    ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs)))
726
966
                        return ENOTSUP;
727
967
        }
728
968
 
731
971
 
732
972
/**
733
973
 * @}
734
 
 */ 
 
974
 */