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

4.104.114.84.95
Last change on this file since 4be8e00 was 471feaf, checked in by Joel Sherrill <joel.sherrill@…>, on 10/22/03 at 19:16:44

2003-10-22 Thomas Doerfler <Thomas.Doerfler@…>

PR 515/filesystem

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