source: rtems/cpukit/libfs/src/dosfs/fat_fat_operations.c @ fac44e12

4.115
Last change on this file since fac44e12 was 9b4422a2, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 15:09:24

Remove All CVS Id Strings Possible Using a Script

Script does what is expected and tries to do it as
smartly as possible.

+ remove occurrences of two blank comment lines

next to each other after Id string line removed.

+ remove entire comment blocks which only exited to

contain CVS Ids

+ If the processing left a blank line at the top of

a file, it was removed.

  • Property mode set to 100644
File size: 13.4 KB
Line 
1/*
2 *  fat_fat_operations.c
3 *
4 *  General operations on File Allocation Table
5 *
6 *  Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
7 *  Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
8 */
9
10#if HAVE_CONFIG_H
11#include "config.h"
12#endif
13
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <fcntl.h>
17#include <unistd.h>
18#include <errno.h>
19#include <stdlib.h>
20
21#include <rtems/libio_.h>
22
23#include "fat.h"
24#include "fat_fat_operations.h"
25
26/* fat_scan_fat_for_free_clusters --
27 *     Allocate chain of free clusters from Files Allocation Table
28 *
29 * PARAMETERS:
30 *     mt_entry - mount table entry
31 *     chain    - the number of the first allocated cluster (first cluster
32 *                in  the chain)
33 *     count    - count of clusters to allocate (chain length)
34 *
35 * RETURNS:
36 *     RC_OK on success, or error code if error occured (errno set
37 *     appropriately)
38 *
39 *
40 */
41int
42fat_scan_fat_for_free_clusters(
43    rtems_filesystem_mount_table_entry_t *mt_entry,
44    uint32_t                             *chain,
45    uint32_t                              count,
46    uint32_t                             *cls_added,
47    uint32_t                             *last_cl,
48    bool                                  zero_fill
49    )
50{
51    int            rc = RC_OK;
52    fat_fs_info_t *fs_info = mt_entry->fs_info;
53    uint32_t       cl4find = 2;
54    uint32_t       next_cln = 0;
55    uint32_t       save_cln = 0;
56    uint32_t       data_cls_val = fs_info->vol.data_cls + 2;
57    uint32_t       i = 2;
58
59    *cls_added = 0;
60
61    if (count == 0)
62        return rc;
63
64    if (fs_info->vol.next_cl != FAT_UNDEFINED_VALUE)
65        cl4find = fs_info->vol.next_cl;
66
67    /*
68     * fs_info->vol.data_cls is exactly the count of data clusters
69     * starting at cluster 2, so the maximum valid cluster number is
70     * (fs_info->vol.data_cls + 1)
71     */
72    while (i < data_cls_val)
73    {
74        rc = fat_get_fat_cluster(mt_entry, cl4find, &next_cln);
75        if ( rc != RC_OK )
76        {
77            if (*cls_added != 0)
78                fat_free_fat_clusters_chain(mt_entry, (*chain));
79            return rc;
80        }
81
82        if (next_cln == FAT_GENFAT_FREE)
83        {
84            /*
85             * We are enforced to process allocation of the first free cluster
86             * by separate 'if' statement because otherwise undo function
87             * wouldn't work properly
88             */
89            if (*cls_added == 0)
90            {
91                *chain = cl4find;
92                rc = fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_EOC);
93                if ( rc != RC_OK )
94                {
95                    /*
96                     * this is the first cluster we tried to allocate so no
97                     * cleanup activity needed
98                     */
99                     return rc;
100                }
101            }
102            else
103            {
104                /* set EOC value to new allocated cluster */
105                rc = fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_EOC);
106                if ( rc != RC_OK )
107                {
108                    /* cleanup activity */
109                    fat_free_fat_clusters_chain(mt_entry, (*chain));
110                    return rc;
111                }
112
113                rc = fat_set_fat_cluster(mt_entry, save_cln, cl4find);
114                if ( rc != RC_OK )
115                    goto cleanup;
116            }
117
118            if (zero_fill) {
119                uint32_t sec = fat_cluster_num_to_sector_num(mt_entry,
120                                                             cl4find);
121
122                rc = _fat_block_zero(mt_entry, sec, 0, fs_info->vol.bpc);
123                if ( rc != RC_OK )
124                    goto cleanup;
125            }
126
127            save_cln = cl4find;
128            (*cls_added)++;
129
130            /* have we satisfied request ? */
131            if (*cls_added == count)
132            {
133                    fs_info->vol.next_cl = save_cln;
134                    if (fs_info->vol.free_cls != 0xFFFFFFFF)
135                        fs_info->vol.free_cls -= (*cls_added);
136                *last_cl = save_cln;
137                fat_buf_release(fs_info);
138                return rc;
139            }
140        }
141        i++;
142        cl4find++;
143        if (cl4find >= data_cls_val)
144            cl4find = 2;
145    }
146
147        fs_info->vol.next_cl = save_cln;
148        if (fs_info->vol.free_cls != 0xFFFFFFFF)
149            fs_info->vol.free_cls -= (*cls_added);
150
151    *last_cl = save_cln;
152    fat_buf_release(fs_info);
153    return RC_OK;
154
155cleanup:
156
157    /* cleanup activity */
158    fat_free_fat_clusters_chain(mt_entry, (*chain));
159    /* trying to save last allocated cluster for future use */
160    fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_FREE);
161    fat_buf_release(fs_info);
162    return rc;
163}
164
165/* fat_free_fat_clusters_chain --
166 *     Free chain of clusters in Files Allocation Table.
167 *
168 * PARAMETERS:
169 *     mt_entry - mount table entry
170 *     chain    - number of the first cluster in  the chain
171 *
172 * RETURNS:
173 *     RC_OK on success, or -1 if error occured (errno set appropriately)
174 */
175int
176fat_free_fat_clusters_chain(
177    rtems_filesystem_mount_table_entry_t *mt_entry,
178    uint32_t                              chain
179    )
180{
181    int            rc = RC_OK, rc1 = RC_OK;
182    fat_fs_info_t *fs_info = mt_entry->fs_info;
183    uint32_t       cur_cln = chain;
184    uint32_t       next_cln = 0;
185    uint32_t       freed_cls_cnt = 0;
186
187    while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
188    {
189        rc = fat_get_fat_cluster(mt_entry, cur_cln, &next_cln);
190        if ( rc != RC_OK )
191        {
192              if(fs_info->vol.free_cls != FAT_UNDEFINED_VALUE)
193                fs_info->vol.free_cls += freed_cls_cnt;
194
195            fat_buf_release(fs_info);
196            return rc;
197        }
198
199        rc = fat_set_fat_cluster(mt_entry, cur_cln, FAT_GENFAT_FREE);
200        if ( rc != RC_OK )
201            rc1 = rc;
202
203        freed_cls_cnt++;
204        cur_cln = next_cln;
205    }
206
207        fs_info->vol.next_cl = chain;
208        if (fs_info->vol.free_cls != FAT_UNDEFINED_VALUE)
209            fs_info->vol.free_cls += freed_cls_cnt;
210
211    fat_buf_release(fs_info);
212    if (rc1 != RC_OK)
213        return rc1;
214
215    return RC_OK;
216}
217
218/* fat_get_fat_cluster --
219 *     Fetches the contents of the cluster (link to next cluster in the chain)
220 *     from Files Allocation Table.
221 *
222 * PARAMETERS:
223 *     mt_entry - mount table entry
224 *     cln      - number of cluster to fetch the contents from
225 *     ret_val  - contents of the cluster 'cln' (link to next cluster in
226 *                the chain)
227 *
228 * RETURNS:
229 *     RC_OK on success, or -1 if error occured
230 *     and errno set appropriately
231 */
232int
233fat_get_fat_cluster(
234    rtems_filesystem_mount_table_entry_t *mt_entry,
235    uint32_t                              cln,
236    uint32_t                             *ret_val
237    )
238{
239    int                     rc = RC_OK;
240    register fat_fs_info_t *fs_info = mt_entry->fs_info;
241    rtems_bdbuf_buffer     *block0 = NULL;
242    uint32_t                sec = 0;
243    uint32_t                ofs = 0;
244
245    /* sanity check */
246    if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
247        rtems_set_errno_and_return_minus_one(EIO);
248
249    sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
250          fs_info->vol.afat_loc;
251    ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
252
253    rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
254    if (rc != RC_OK)
255        return rc;
256
257    switch ( fs_info->vol.type )
258    {
259        case FAT_FAT12:
260            /*
261             * we are enforced in complex computations for FAT12 to escape CPU
262             * align problems for some architectures
263             */
264            *ret_val = (*((uint8_t   *)(block0->buffer + ofs)));
265            if ( ofs == (fs_info->vol.bps - 1) )
266            {
267                rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
268                                    &block0);
269                if (rc != RC_OK)
270                    return rc;
271
272                *ret_val |= (*((uint8_t   *)(block0->buffer)))<<8;
273            }
274            else
275            {
276                *ret_val |= (*((uint8_t   *)(block0->buffer + ofs + 1)))<<8;
277            }
278
279            if ( FAT_CLUSTER_IS_ODD(cln) )
280                *ret_val = (*ret_val) >> FAT12_SHIFT;
281            else
282                *ret_val = (*ret_val) & FAT_FAT12_MASK;
283            break;
284
285        case FAT_FAT16:
286            *ret_val = *((uint16_t   *)(block0->buffer + ofs));
287            *ret_val = CF_LE_W(*ret_val);
288            break;
289
290        case FAT_FAT32:
291            *ret_val = *((uint32_t   *)(block0->buffer + ofs));
292            *ret_val = CF_LE_L(*ret_val);
293            break;
294
295        default:
296            rtems_set_errno_and_return_minus_one(EIO);
297            break;
298    }
299
300    return RC_OK;
301}
302
303/* fat_set_fat_cluster --
304 *     Set the contents of the cluster (link to next cluster in the chain)
305 *     from Files Allocation Table.
306 *
307 * PARAMETERS:
308 *     mt_entry - mount table entry
309 *     cln      - number of cluster to set contents to
310 *     in_val   - value to set
311 *
312 * RETURNS:
313 *     RC_OK on success, or -1 if error occured
314 *     and errno set appropriately
315 */
316int
317fat_set_fat_cluster(
318    rtems_filesystem_mount_table_entry_t *mt_entry,
319    uint32_t                              cln,
320    uint32_t                              in_val
321    )
322{
323    int                 rc = RC_OK;
324    fat_fs_info_t      *fs_info = mt_entry->fs_info;
325    uint32_t            sec = 0;
326    uint32_t            ofs = 0;
327    uint16_t            fat16_clv = 0;
328    uint32_t            fat32_clv = 0;
329    rtems_bdbuf_buffer *block0 = NULL;
330
331    /* sanity check */
332    if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
333        rtems_set_errno_and_return_minus_one(EIO);
334
335    sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
336          fs_info->vol.afat_loc;
337    ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
338
339    rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
340    if (rc != RC_OK)
341        return rc;
342
343    switch ( fs_info->vol.type )
344    {
345        case FAT_FAT12:
346            if ( FAT_CLUSTER_IS_ODD(cln) )
347            {
348                fat16_clv = ((uint16_t  )in_val) << FAT_FAT12_SHIFT;
349                *((uint8_t   *)(block0->buffer + ofs)) =
350                        (*((uint8_t   *)(block0->buffer + ofs))) & 0x0F;
351
352                *((uint8_t   *)(block0->buffer + ofs)) =
353                        (*((uint8_t   *)(block0->buffer + ofs))) |
354                        (uint8_t  )(fat16_clv & 0x00FF);
355
356                fat_buf_mark_modified(fs_info);
357
358                if ( ofs == (fs_info->vol.bps - 1) )
359                {
360                    rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
361                                        &block0);
362                    if (rc != RC_OK)
363                        return rc;
364
365                     *((uint8_t   *)(block0->buffer)) &= 0x00;
366
367                     *((uint8_t   *)(block0->buffer)) =
368                            (*((uint8_t   *)(block0->buffer))) |
369                            (uint8_t  )((fat16_clv & 0xFF00)>>8);
370
371                     fat_buf_mark_modified(fs_info);
372                }
373                else
374                {
375                    *((uint8_t   *)(block0->buffer + ofs + 1)) &= 0x00;
376
377                    *((uint8_t   *)(block0->buffer + ofs + 1)) =
378                            (*((uint8_t   *)(block0->buffer + ofs + 1))) |
379                            (uint8_t  )((fat16_clv & 0xFF00)>>8);
380                }
381            }
382            else
383            {
384                fat16_clv = ((uint16_t  )in_val) & FAT_FAT12_MASK;
385                *((uint8_t   *)(block0->buffer + ofs)) &= 0x00;
386
387                *((uint8_t   *)(block0->buffer + ofs)) =
388                        (*((uint8_t   *)(block0->buffer + ofs))) |
389                        (uint8_t  )(fat16_clv & 0x00FF);
390
391                fat_buf_mark_modified(fs_info);
392
393                if ( ofs == (fs_info->vol.bps - 1) )
394                {
395                    rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
396                                        &block0);
397                    if (rc != RC_OK)
398                        return rc;
399
400                    *((uint8_t   *)(block0->buffer)) =
401                            (*((uint8_t   *)(block0->buffer))) & 0xF0;
402
403                    *((uint8_t   *)(block0->buffer)) =
404                            (*((uint8_t   *)(block0->buffer))) |
405                            (uint8_t  )((fat16_clv & 0xFF00)>>8);
406
407                    fat_buf_mark_modified(fs_info);
408                }
409                else
410                {
411                    *((uint8_t   *)(block0->buffer + ofs + 1)) =
412                      (*((uint8_t   *)(block0->buffer + ofs + 1))) & 0xF0;
413
414                    *((uint8_t   *)(block0->buffer + ofs+1)) =
415                           (*((uint8_t   *)(block0->buffer + ofs+1))) |
416                           (uint8_t  )((fat16_clv & 0xFF00)>>8);
417                }
418            }
419            break;
420
421        case FAT_FAT16:
422            *((uint16_t   *)(block0->buffer + ofs)) =
423                    (uint16_t  )(CT_LE_W(in_val));
424            fat_buf_mark_modified(fs_info);
425            break;
426
427        case FAT_FAT32:
428            fat32_clv = CT_LE_L((in_val & FAT_FAT32_MASK));
429
430            *((uint32_t   *)(block0->buffer + ofs)) =
431            (*((uint32_t   *)(block0->buffer + ofs))) & (CT_LE_L(0xF0000000));
432
433            *((uint32_t   *)(block0->buffer + ofs)) =
434                   fat32_clv | (*((uint32_t   *)(block0->buffer + ofs)));
435
436            fat_buf_mark_modified(fs_info);
437            break;
438
439        default:
440            rtems_set_errno_and_return_minus_one(EIO);
441            break;
442
443    }
444
445    return RC_OK;
446}
Note: See TracBrowser for help on using the repository browser.