Subversion Repositories HelenOS

Rev

Rev 3513 | Rev 3517 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3513 Rev 3516
Line 44... Line 44...
44
#include <byteorder.h>
44
#include <byteorder.h>
45
#include <align.h>
45
#include <align.h>
46
#include <assert.h>
46
#include <assert.h>
47
 
47
 
48
block_t *
48
block_t *
49
_fat_block_get(dev_handle_t dev_handle, fat_cluster_t firstc, off_t offset)
49
_fat_block_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
-
 
50
    off_t offset)
50
{
51
{
51
    block_t *bb;
-
 
52
    block_t *b;
52
    block_t *b;
53
    unsigned bps;
53
    unsigned bps;
54
    unsigned spc;
54
    unsigned spc;
55
    unsigned rscnt;     /* block address of the first FAT */
55
    unsigned rscnt;     /* block address of the first FAT */
56
    unsigned fatcnt;
56
    unsigned fatcnt;
Line 60... Line 60...
60
    unsigned ssa;       /* size of the system area */
60
    unsigned ssa;       /* size of the system area */
61
    unsigned clusters;
61
    unsigned clusters;
62
    fat_cluster_t clst = firstc;
62
    fat_cluster_t clst = firstc;
63
    unsigned i;
63
    unsigned i;
64
 
64
 
65
    bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
-
 
66
    bps = uint16_t_le2host(FAT_BS(bb)->bps);
65
    bps = uint16_t_le2host(bs->bps);
67
    spc = FAT_BS(bb)->spc;
66
    spc = bs->spc;
68
    rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt);
67
    rscnt = uint16_t_le2host(bs->rscnt);
69
    fatcnt = FAT_BS(bb)->fatcnt;
68
    fatcnt = bs->fatcnt;
70
    rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max);
69
    rde = uint16_t_le2host(bs->root_ent_max);
71
    sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat);
70
    sf = uint16_t_le2host(bs->sec_per_fat);
72
    block_put(bb);
-
 
73
 
71
 
74
    rds = (sizeof(fat_dentry_t) * rde) / bps;
72
    rds = (sizeof(fat_dentry_t) * rde) / bps;
75
    rds += ((sizeof(fat_dentry_t) * rde) % bps != 0);
73
    rds += ((sizeof(fat_dentry_t) * rde) % bps != 0);
76
    ssa = rscnt + fatcnt * sf + rds;
74
    ssa = rscnt + fatcnt * sf + rds;
77
 
75
 
Line 104... Line 102...
104
    return b;
102
    return b;
105
}
103
}
106
 
104
 
107
/** Return number of blocks allocated to a file.
105
/** Return number of blocks allocated to a file.
108
 *
106
 *
-
 
107
 * @param bs        Buffer holding the boot sector for the file.
109
 * @param dev_handle    Device handle of the device with the file.
108
 * @param dev_handle    Device handle of the device with the file.
110
 * @param firstc    First cluster of the file.
109
 * @param firstc    First cluster of the file.
111
 * @param lastc     If non-NULL, output argument holding the
110
 * @param lastc     If non-NULL, output argument holding the
112
 *          last cluster.
111
 *          last cluster.
113
 *
112
 *
114
 * @return      Number of blocks allocated to the file.
113
 * @return      Number of blocks allocated to the file.
115
 */
114
 */
116
uint16_t
115
uint16_t
117
_fat_blcks_get(dev_handle_t dev_handle, fat_cluster_t firstc,
116
_fat_blcks_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
118
    fat_cluster_t *lastc)
117
    fat_cluster_t *lastc)
119
{
118
{
120
    block_t *bb;
-
 
121
    block_t *b;
119
    block_t *b;
122
    unsigned bps;
120
    unsigned bps;
123
    unsigned spc;
121
    unsigned spc;
124
    unsigned rscnt;     /* block address of the first FAT */
122
    unsigned rscnt;     /* block address of the first FAT */
125
    unsigned clusters = 0;
123
    unsigned clusters = 0;
126
    fat_cluster_t clst = firstc;
124
    fat_cluster_t clst = firstc;
127
 
125
 
128
    bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
-
 
129
    bps = uint16_t_le2host(FAT_BS(bb)->bps);
126
    bps = uint16_t_le2host(bs->bps);
130
    spc = FAT_BS(bb)->spc;
127
    spc = bs->spc;
131
    rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt);
128
    rscnt = uint16_t_le2host(bs->rscnt);
132
    block_put(bb);
-
 
133
 
129
 
134
    if (firstc == FAT_CLST_RES0) {
130
    if (firstc == FAT_CLST_RES0) {
135
        /* No space allocated to the file. */
131
        /* No space allocated to the file. */
136
        if (lastc)
132
        if (lastc)
137
            *lastc = firstc;
133
            *lastc = firstc;
Line 158... Line 154...
158
    if (lastc)
154
    if (lastc)
159
        *lastc = clst;
155
        *lastc = clst;
160
    return clusters * spc;
156
    return clusters * spc;
161
}
157
}
162
 
158
 
163
uint16_t fat_bps_get(dev_handle_t dev_handle)
-
 
164
{
-
 
165
    block_t *bb;
-
 
166
    uint16_t bps;
-
 
167
   
-
 
168
    bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
-
 
169
    assert(bb != NULL);
-
 
170
    bps = uint16_t_le2host(FAT_BS(bb)->bps);
-
 
171
    block_put(bb);
-
 
172
 
-
 
173
    return bps;
-
 
174
}
-
 
175
 
-
 
176
/** Fill the gap between EOF and a new file position.
159
/** Fill the gap between EOF and a new file position.
177
 *
160
 *
-
 
161
 * @param bs        Buffer holding the boot sector for nodep.
178
 * @param nodep     FAT node with the gap.
162
 * @param nodep     FAT node with the gap.
179
 * @param mcl       First cluster in an independent cluster chain that will
163
 * @param mcl       First cluster in an independent cluster chain that will
180
 *          be later appended to the end of the node's own cluster
164
 *          be later appended to the end of the node's own cluster
181
 *          chain. If pos is still in the last allocated cluster,
165
 *          chain. If pos is still in the last allocated cluster,
182
 *          this argument is ignored.
166
 *          this argument is ignored.
183
 * @param pos       Position in the last node block.
167
 * @param pos       Position in the last node block.
184
 */
168
 */
185
void fat_fill_gap(fat_node_t *nodep, fat_cluster_t mcl, off_t pos)
169
void fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, off_t pos)
186
{
170
{
187
    uint16_t bps;
171
    uint16_t bps;
188
    unsigned spc;
172
    unsigned spc;
189
    block_t *bb, *b;
173
    block_t *b;
190
    off_t o, boundary;
174
    off_t o, boundary;
191
 
175
 
192
    bb = block_get(nodep->idx->dev_handle, BS_BLOCK, BS_SIZE);
-
 
193
    bps = uint16_t_le2host(FAT_BS(bb)->bps);
176
    bps = uint16_t_le2host(bs->bps);
194
    spc = FAT_BS(bb)->spc;
177
    spc = bs->spc;
195
    block_put(bb);
-
 
196
   
178
   
197
    boundary = ROUND_UP(nodep->size, bps * spc);
179
    boundary = ROUND_UP(nodep->size, bps * spc);
198
 
180
 
199
    /* zero out already allocated space */
181
    /* zero out already allocated space */
200
    for (o = nodep->size - 1; o < pos && o < boundary;
182
    for (o = nodep->size - 1; o < pos && o < boundary;
201
        o = ALIGN_DOWN(o + bps, bps)) {
183
        o = ALIGN_DOWN(o + bps, bps)) {
202
        b = fat_block_get(nodep, o / bps);
184
        b = fat_block_get(bs, nodep, o / bps);
203
        memset(b->data + o % bps, 0, bps - o % bps);
185
        memset(b->data + o % bps, 0, bps - o % bps);
204
        b->dirty = true;        /* need to sync node */
186
        b->dirty = true;        /* need to sync node */
205
        block_put(b);
187
        block_put(b);
206
    }
188
    }
207
   
189
   
208
    if (o >= pos)
190
    if (o >= pos)
209
        return;
191
        return;
210
   
192
   
211
    /* zero out the initial part of the new cluster chain */
193
    /* zero out the initial part of the new cluster chain */
212
    for (o = boundary; o < pos; o += bps) {
194
    for (o = boundary; o < pos; o += bps) {
213
        b = _fat_block_get(nodep->idx->dev_handle, mcl,
195
        b = _fat_block_get(bs, nodep->idx->dev_handle, mcl,
214
            (o - boundary) / bps);
196
            (o - boundary) / bps);
215
        memset(b->data, 0, min(bps, pos - o));
197
        memset(b->data, 0, min(bps, pos - o));
216
        b->dirty = true;        /* need to sync node */
198
        b->dirty = true;        /* need to sync node */
217
        block_put(b);
199
        block_put(b);
218
    }
200
    }
219
}
201
}
220
 
202
 
221
void
203
void
222
fat_mark_cluster(dev_handle_t dev_handle, unsigned fatno, fat_cluster_t clst,
204
fat_mark_cluster(fat_bs_t *bs, dev_handle_t dev_handle, unsigned fatno,
223
    fat_cluster_t value)
205
    fat_cluster_t clst, fat_cluster_t value)
224
{
206
{
225
    block_t *bb, *blk;
207
    block_t *b;
226
    uint16_t bps;
208
    uint16_t bps;
227
    uint16_t rscnt;
209
    uint16_t rscnt;
228
    uint16_t sf;
210
    uint16_t sf;
229
    uint8_t fatcnt;
-
 
230
    fat_cluster_t *cp;
211
    fat_cluster_t *cp;
231
 
212
 
232
    bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
-
 
233
    bps = uint16_t_le2host(FAT_BS(bb)->bps);
213
    bps = uint16_t_le2host(bs->bps);
234
    rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt);
214
    rscnt = uint16_t_le2host(bs->rscnt);
235
    sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat);
215
    sf = uint16_t_le2host(bs->sec_per_fat);
236
    fatcnt = FAT_BS(bb)->fatcnt;
-
 
237
    block_put(bb);
-
 
238
 
216
 
239
    assert(fatno < fatcnt);
217
    assert(fatno < bs->fatcnt);
240
    blk = block_get(dev_handle, rscnt + sf * fatno +
218
    b = block_get(dev_handle, rscnt + sf * fatno +
241
        (clst * sizeof(fat_cluster_t)) / bps, bps);
219
        (clst * sizeof(fat_cluster_t)) / bps, bps);
242
    cp = (fat_cluster_t *)blk->data + clst % (bps / sizeof(fat_cluster_t));
220
    cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t));
243
    *cp = host2uint16_t_le(value);
221
    *cp = host2uint16_t_le(value);
244
    blk->dirty = true;      /* need to sync block */
222
    b->dirty = true;        /* need to sync block */
245
    block_put(blk);
223
    block_put(b);
246
}
224
}
247
 
225
 
248
void fat_alloc_shadow_clusters(dev_handle_t dev_handle, fat_cluster_t *lifo,
226
void fat_alloc_shadow_clusters(fat_bs_t *bs, dev_handle_t dev_handle,
249
    unsigned nclsts)
227
    fat_cluster_t *lifo, unsigned nclsts)
250
{
228
{
251
    uint8_t fatcnt;
-
 
252
    uint8_t fatno;
229
    uint8_t fatno;
253
    unsigned c;
230
    unsigned c;
254
    block_t *bb;
-
 
255
 
231
 
256
    bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
-
 
257
    fatcnt = FAT_BS(bb)->fatcnt;
-
 
258
    block_put(bb);
-
 
259
   
-
 
260
    for (fatno = FAT1 + 1; fatno < fatcnt; fatno++) {
232
    for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
261
        for (c = 0; c < nclsts; c++) {
233
        for (c = 0; c < nclsts; c++) {
262
            fat_mark_cluster(dev_handle, fatno, lifo[c],
234
            fat_mark_cluster(bs, dev_handle, fatno, lifo[c],
263
                c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
235
                c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
264
        }
236
        }
265
    }
237
    }
266
}
238
}
267
 
239
 
268
int
240
int
269
fat_alloc_clusters(dev_handle_t dev_handle, unsigned nclsts, fat_cluster_t *mcl,
241
fat_alloc_clusters(fat_bs_t *bs, dev_handle_t dev_handle, unsigned nclsts,
270
    fat_cluster_t *lcl)
242
    fat_cluster_t *mcl, fat_cluster_t *lcl)
271
{
243
{
272
    uint16_t bps;
244
    uint16_t bps;
273
    uint16_t rscnt;
245
    uint16_t rscnt;
274
    uint16_t sf;
246
    uint16_t sf;
275
    block_t *bb, *blk;
247
    block_t *blk;
276
    fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
248
    fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
277
    unsigned found = 0; /* top of the free cluster number stack */
249
    unsigned found = 0; /* top of the free cluster number stack */
278
    unsigned b, c, cl;
250
    unsigned b, c, cl;
279
 
251
 
280
    lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
252
    lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
281
    if (lifo)
253
    if (lifo)
282
        return ENOMEM;
254
        return ENOMEM;
283
   
255
   
284
    bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
-
 
285
    bps = uint16_t_le2host(FAT_BS(bb)->bps);
256
    bps = uint16_t_le2host(bs->bps);
286
    rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt);
257
    rscnt = uint16_t_le2host(bs->rscnt);
287
    sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat);
258
    sf = uint16_t_le2host(bs->sec_per_fat);
288
    block_put(bb);
-
 
289
   
259
   
290
    /*
260
    /*
291
     * Search FAT1 for unused clusters.
261
     * Search FAT1 for unused clusters.
292
     */
262
     */
293
    for (b = 0, cl = 0; b < sf; blk++) {
263
    for (b = 0, cl = 0; b < sf; blk++) {
Line 306... Line 276...
306
                blk->dirty = true;  /* need to sync block */
276
                blk->dirty = true;  /* need to sync block */
307
                if (++found == nclsts) {
277
                if (++found == nclsts) {
308
                    /* we are almost done */
278
                    /* we are almost done */
309
                    block_put(blk);
279
                    block_put(blk);
310
                    /* update the shadow copies of FAT */
280
                    /* update the shadow copies of FAT */
311
                    fat_alloc_shadow_clusters(dev_handle,
281
                    fat_alloc_shadow_clusters(bs,
312
                        lifo, nclsts);
282
                        dev_handle, lifo, nclsts);
313
                    *mcl = lifo[found - 1];
283
                    *mcl = lifo[found - 1];
314
                    *lcl = lifo[0];
284
                    *lcl = lifo[0];
315
                    free(lifo);
285
                    free(lifo);
316
                    return EOK;
286
                    return EOK;
317
                }
287
                }
Line 322... Line 292...
322
 
292
 
323
    /*
293
    /*
324
     * We could not find enough clusters. Now we need to free the clusters
294
     * We could not find enough clusters. Now we need to free the clusters
325
     * we have allocated so far.
295
     * we have allocated so far.
326
     */
296
     */
327
    while (found--)
297
    while (found--) {
328
        fat_mark_cluster(dev_handle, FAT1, lifo[found], FAT_CLST_RES0);
298
        fat_mark_cluster(bs, dev_handle, FAT1, lifo[found],
-
 
299
            FAT_CLST_RES0);
-
 
300
    }
329
   
301
   
330
    free(lifo);
302
    free(lifo);
331
    return ENOSPC;
303
    return ENOSPC;
332
}
304
}
333
 
305
 
334
void fat_append_clusters(fat_node_t *nodep, fat_cluster_t mcl)
306
void fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl)
335
{
307
{
336
    block_t *bb;
308
    dev_handle_t dev_handle = nodep->idx->dev_handle;
337
    fat_cluster_t lcl;
309
    fat_cluster_t lcl;
338
    uint8_t fatcnt, fatno;
310
    uint8_t fatno;
339
 
311
 
340
    if (_fat_blcks_get(nodep->idx->dev_handle, nodep->firstc, &lcl) == 0) {
312
    if (_fat_blcks_get(bs, dev_handle, nodep->firstc, &lcl) == 0) {
341
        nodep->firstc = host2uint16_t_le(mcl);
313
        nodep->firstc = host2uint16_t_le(mcl);
342
        nodep->dirty = true;        /* need to sync node */
314
        nodep->dirty = true;        /* need to sync node */
343
        return;
315
        return;
344
    }
316
    }
345
 
317
 
346
    bb = block_get(nodep->idx->dev_handle, BS_BLOCK, BS_SIZE);
-
 
347
    fatcnt = FAT_BS(bb)->fatcnt;
-
 
348
    block_put(bb);
-
 
349
 
-
 
350
    for (fatno = FAT1; fatno < fatcnt; fatno++)
318
    for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
351
        fat_mark_cluster(nodep->idx->dev_handle, fatno, lcl, mcl);
319
        fat_mark_cluster(bs, nodep->idx->dev_handle, fatno, lcl, mcl);
352
}
320
}
353
 
321
 
354
/**
322
/**
355
 * @}
323
 * @}
356
 */
324
 */