source: rtems/cpukit/libfs/src/dosfs/fat.c @ 918a0d8

4.104.115
Last change on this file since 918a0d8 was 918a0d8, checked in by Joel Sherrill <joel.sherrill@…>, on 06/12/09 at 17:38:53

2009-06-12 Joel Sherrill <joel.sherrill@…>

  • libblock/src/flashdisk.c, libblock/src/nvdisk.c, libblock/src/ramdisk.c, libfs/src/dosfs/fat.c, libfs/src/dosfs/msdos_format.c: Eliminate using the GNU/Linux specific error numbers EBADRQC and ENOTBLK. Switch to EINVAL and ENOTTY as appropriate.
  • Property mode set to 100644
File size: 24.3 KB
Line 
1/*
2 * fat.c
3 *
4 * Low-level operations on a volume with FAT filesystem
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
29int
30fat_buf_access(fat_fs_info_t *fs_info, uint32_t   blk, int op_type,
31               rtems_bdbuf_buffer **buf)
32{
33    rtems_status_code sc = RTEMS_SUCCESSFUL;
34    uint8_t           i;
35    bool              sec_of_fat;
36
37
38    if (fs_info->c.state == FAT_CACHE_EMPTY)
39    {
40        if (op_type == FAT_OP_TYPE_READ)
41            sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
42        else
43            sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
44        if (sc != RTEMS_SUCCESSFUL)
45            rtems_set_errno_and_return_minus_one(EIO);
46        fs_info->c.blk_num = blk;
47        fs_info->c.modified = 0;
48        fs_info->c.state = FAT_CACHE_ACTUAL;
49    }
50
51    sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
52                  (fs_info->c.blk_num < fs_info->vol.rdir_loc));
53
54    if (fs_info->c.blk_num != blk)
55    {
56        if (fs_info->c.modified)
57        {
58            if (sec_of_fat && !fs_info->vol.mirror)
59                memcpy(fs_info->sec_buf, fs_info->c.buf->buffer,
60                       fs_info->vol.bps);
61
62            sc = rtems_bdbuf_release_modified(fs_info->c.buf);
63            fs_info->c.state = FAT_CACHE_EMPTY;
64            fs_info->c.modified = 0;
65            if (sc != RTEMS_SUCCESSFUL)
66                rtems_set_errno_and_return_minus_one(EIO);
67
68            if (sec_of_fat && !fs_info->vol.mirror)
69            {
70                rtems_bdbuf_buffer *b;
71
72                for (i = 1; i < fs_info->vol.fats; i++)
73                {
74                    sc = rtems_bdbuf_get(fs_info->vol.dev,
75                                         fs_info->c.blk_num +
76                                         fs_info->vol.fat_length * i,
77                                         &b);
78                    if ( sc != RTEMS_SUCCESSFUL)
79                        rtems_set_errno_and_return_minus_one(ENOMEM);
80                    memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
81                    sc = rtems_bdbuf_release_modified(b);
82                    if ( sc != RTEMS_SUCCESSFUL)
83                        rtems_set_errno_and_return_minus_one(ENOMEM);
84                }
85            }
86        }
87        else
88        {
89            sc = rtems_bdbuf_release(fs_info->c.buf);
90            fs_info->c.state = FAT_CACHE_EMPTY;
91            if (sc != RTEMS_SUCCESSFUL)
92                rtems_set_errno_and_return_minus_one(EIO);
93
94        }
95        if (op_type == FAT_OP_TYPE_READ)
96            sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
97        else
98            sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
99        if (sc != RTEMS_SUCCESSFUL)
100            rtems_set_errno_and_return_minus_one(EIO);
101        fs_info->c.blk_num = blk;
102        fs_info->c.state = FAT_CACHE_ACTUAL;
103    }
104    *buf = fs_info->c.buf;
105    return RC_OK;
106}
107
108int
109fat_buf_release(fat_fs_info_t *fs_info)
110{
111    rtems_status_code sc = RTEMS_SUCCESSFUL;
112    uint8_t           i;
113    bool              sec_of_fat;
114
115    if (fs_info->c.state == FAT_CACHE_EMPTY)
116        return RC_OK;
117
118    sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
119                  (fs_info->c.blk_num < fs_info->vol.rdir_loc));
120
121    if (fs_info->c.modified)
122    {
123        if (sec_of_fat && !fs_info->vol.mirror)
124            memcpy(fs_info->sec_buf, fs_info->c.buf->buffer, fs_info->vol.bps);
125
126        sc = rtems_bdbuf_release_modified(fs_info->c.buf);
127        if (sc != RTEMS_SUCCESSFUL)
128            rtems_set_errno_and_return_minus_one(EIO);
129        fs_info->c.modified = 0;
130
131        if (sec_of_fat && !fs_info->vol.mirror)
132        {
133            rtems_bdbuf_buffer *b;
134
135            for (i = 1; i < fs_info->vol.fats; i++)
136            {
137                sc = rtems_bdbuf_get(fs_info->vol.dev,
138                                     fs_info->c.blk_num +
139                                     fs_info->vol.fat_length * i,
140                                     &b);
141                if ( sc != RTEMS_SUCCESSFUL)
142                    rtems_set_errno_and_return_minus_one(ENOMEM);
143                memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
144                sc = rtems_bdbuf_release_modified(b);
145                if ( sc != RTEMS_SUCCESSFUL)
146                    rtems_set_errno_and_return_minus_one(ENOMEM);
147            }
148        }
149    }
150    else
151    {
152        sc = rtems_bdbuf_release(fs_info->c.buf);
153        if (sc != RTEMS_SUCCESSFUL)
154            rtems_set_errno_and_return_minus_one(EIO);
155    }
156    fs_info->c.state = FAT_CACHE_EMPTY;
157    return RC_OK;
158}
159
160/* _fat_block_read --
161 *     This function reads 'count' bytes from device filesystem is mounted on,
162 *     starts at 'start+offset' position where 'start' computed in sectors
163 *     and 'offset' is offset inside sector (reading may cross sectors
164 *     boundary; in this case assumed we want to read sequential sector(s))
165 *
166 * PARAMETERS:
167 *     mt_entry - mount table entry
168 *     start    - sector num to start read from
169 *     offset   - offset inside sector 'start'
170 *     count    - count of bytes to read
171 *     buff     - buffer provided by user
172 *
173 * RETURNS:
174 *     bytes read on success, or -1 if error occured
175 *     and errno set appropriately
176 */
177ssize_t
178_fat_block_read(
179    rtems_filesystem_mount_table_entry_t *mt_entry,
180    uint32_t                              start,
181    uint32_t                              offset,
182    uint32_t                              count,
183    void                                 *buff
184    )
185{
186    int                     rc = RC_OK;
187    register fat_fs_info_t *fs_info = mt_entry->fs_info;
188    ssize_t                 cmpltd = 0;
189    uint32_t                blk = start;
190    uint32_t                ofs = offset;
191    rtems_bdbuf_buffer     *block = NULL;
192    uint32_t                c = 0;
193
194    while (count > 0)
195    {
196        rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
197        if (rc != RC_OK)
198            return -1;
199
200        c = MIN(count, (fs_info->vol.bps - ofs));
201        memcpy((buff + cmpltd), (block->buffer + ofs), c);
202
203        count -= c;
204        cmpltd += c;
205        blk++;
206        ofs = 0;
207    }
208    return cmpltd;
209}
210
211/* _fat_block_write --
212 *     This function write 'count' bytes to device filesystem is mounted on,
213 *     starts at 'start+offset' position where 'start' computed in sectors
214 *     and 'offset' is offset inside sector (writing may cross sectors
215 *     boundary; in this case assumed we want to write sequential sector(s))
216 *
217 * PARAMETERS:
218 *     mt_entry - mount table entry
219 *     start    - sector num to start read from
220 *     offset   - offset inside sector 'start'
221 *     count    - count of bytes to write
222 *     buff     - buffer provided by user
223 *
224 * RETURNS:
225 *     bytes written on success, or -1 if error occured
226 *     and errno set appropriately
227 */
228ssize_t
229_fat_block_write(
230    rtems_filesystem_mount_table_entry_t *mt_entry,
231    uint32_t                              start,
232    uint32_t                              offset,
233    uint32_t                              count,
234    const void                           *buff)
235{
236    int                 rc = RC_OK;
237    fat_fs_info_t      *fs_info = mt_entry->fs_info;
238    ssize_t             cmpltd = 0;
239    uint32_t            blk  = start;
240    uint32_t            ofs = offset;
241    rtems_bdbuf_buffer *block = NULL;
242    uint32_t            c = 0;
243
244    while(count > 0)
245    {
246        c = MIN(count, (fs_info->vol.bps - ofs));
247
248        if (c == fs_info->vol.bps)
249            rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_GET, &block);
250        else
251            rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
252        if (rc != RC_OK)
253            return -1;
254
255        memcpy((block->buffer + ofs), (buff + cmpltd), c);
256
257        fat_buf_mark_modified(fs_info);
258
259        count -= c;
260        cmpltd +=c;
261        blk++;
262        ofs = 0;
263    }
264    return cmpltd;
265}
266
267/* fat_cluster_read --
268 *     wrapper for reading a whole cluster at once
269 *
270 * PARAMETERS:
271 *     mt_entry - mount table entry
272 *     cln      - number of cluster to read
273 *     buff     - buffer provided by user
274 *
275 * RETURNS:
276 *     bytes read on success, or -1 if error occured
277 *     and errno set appropriately
278 */
279ssize_t
280fat_cluster_read(
281    rtems_filesystem_mount_table_entry_t *mt_entry,
282    uint32_t                              cln,
283    void                                 *buff
284    )
285{
286    fat_fs_info_t *fs_info = mt_entry->fs_info;
287    uint32_t       fsec = 0;
288
289    fsec = fat_cluster_num_to_sector_num(mt_entry, cln);
290
291    return _fat_block_read(mt_entry, fsec, 0,
292                           fs_info->vol.spc << fs_info->vol.sec_log2, buff);
293}
294
295/* fat_cluster_write --
296 *     wrapper for writting a whole cluster at once
297 *
298 * PARAMETERS:
299 *     mt_entry - mount table entry
300 *     cln      - number of cluster to write
301 *     buff     - buffer provided by user
302 *
303 * RETURNS:
304 *     bytes written on success, or -1 if error occured
305 *     and errno set appropriately
306 */
307ssize_t
308fat_cluster_write(
309    rtems_filesystem_mount_table_entry_t *mt_entry,
310    uint32_t                              cln,
311    const void                           *buff
312    )
313{
314    fat_fs_info_t *fs_info = mt_entry->fs_info;
315    uint32_t       fsec = 0;
316
317    fsec = fat_cluster_num_to_sector_num(mt_entry, cln);
318
319    return _fat_block_write(mt_entry, fsec, 0,
320                          fs_info->vol.spc << fs_info->vol.sec_log2, buff);
321}
322
323/* fat_init_volume_info --
324 *     Get inforamtion about volume on which filesystem is mounted on
325 *
326 * PARAMETERS:
327 *     mt_entry - mount table entry
328 *
329 * RETURNS:
330 *     RC_OK on success, or -1 if error occured
331 *     and errno set appropriately
332 */
333int
334fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
335{
336    rtems_status_code   sc = RTEMS_SUCCESSFUL;
337    int                 rc = RC_OK;
338    fat_fs_info_t      *fs_info = mt_entry->fs_info;
339    register fat_vol_t *vol = &fs_info->vol;
340    uint32_t            data_secs = 0;
341    char                boot_rec[FAT_MAX_BPB_SIZE];
342    char                fs_info_sector[FAT_USEFUL_INFO_SIZE];
343    ssize_t             ret = 0;
344    struct stat         stat_buf;
345    int                 i = 0;
346    rtems_bdbuf_buffer *block = NULL;
347
348    rc = stat(mt_entry->dev, &stat_buf);
349    if (rc == -1)
350        return rc;
351
352    /* rtmes feature: no block devices, all are character devices */
353    if (!S_ISCHR(stat_buf.st_mode))
354        rtems_set_errno_and_return_minus_one(ENOTTY);
355
356    /* check that device is registred as block device and lock it */
357    vol->dd = rtems_disk_obtain(stat_buf.st_rdev);
358    if (vol->dd == NULL)
359        rtems_set_errno_and_return_minus_one(ENOTTY);
360
361    vol->dev = stat_buf.st_rdev;
362
363    /* Read boot record */
364    /* FIXME: Asserts FAT_MAX_BPB_SIZE < bdbuf block size */
365    sc = rtems_bdbuf_read( vol->dev, 0, &block);
366    if (sc != RTEMS_SUCCESSFUL)
367    {
368        rtems_disk_release(vol->dd);
369        rtems_set_errno_and_return_minus_one( EIO);
370    }
371
372    memcpy( boot_rec, block->buffer, FAT_MAX_BPB_SIZE);
373
374    sc = rtems_bdbuf_release( block);
375    if (sc != RTEMS_SUCCESSFUL)
376    {
377        rtems_disk_release(vol->dd);
378        rtems_set_errno_and_return_minus_one( EIO );
379    }
380
381    /* Evaluate boot record */
382    vol->bps = FAT_GET_BR_BYTES_PER_SECTOR(boot_rec);
383 
384    if ( (vol->bps != 512)  &&
385         (vol->bps != 1024) &&
386         (vol->bps != 2048) &&
387         (vol->bps != 4096))
388    {
389        rtems_disk_release(vol->dd);
390        rtems_set_errno_and_return_minus_one( EINVAL );
391    }
392
393    for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0;
394         i >>= 1, vol->sec_mul++);
395    for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0;
396         i >>= 1, vol->sec_log2++);
397
398    vol->spc = FAT_GET_BR_SECTORS_PER_CLUSTER(boot_rec);
399    /*
400     * "sectors per cluster" of zero is invalid
401     * (and would hang the following loop)
402     */
403    if (vol->spc == 0)
404    {
405        rtems_disk_release(vol->dd);
406        rtems_set_errno_and_return_minus_one(EINVAL);
407    }
408
409    for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0;
410         i >>= 1, vol->spc_log2++);
411
412    /*
413     * "bytes per cluster" value greater than 32K is invalid
414     */
415    if ((vol->bpc = vol->bps << vol->spc_log2) > MS_BYTES_PER_CLUSTER_LIMIT)
416    {
417        rtems_disk_release(vol->dd);
418        rtems_set_errno_and_return_minus_one(EINVAL);
419    }
420
421    for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0;
422         i >>= 1, vol->bpc_log2++);
423
424    vol->fats = FAT_GET_BR_FAT_NUM(boot_rec);
425    vol->fat_loc = FAT_GET_BR_RESERVED_SECTORS_NUM(boot_rec);
426
427    vol->rdir_entrs = FAT_GET_BR_FILES_PER_ROOT_DIR(boot_rec);
428   
429    /* calculate the count of sectors occupied by the root directory */
430    vol->rdir_secs = ((vol->rdir_entrs * FAT_DIRENTRY_SIZE) + (vol->bps - 1)) /
431                     vol->bps;
432
433    vol->rdir_size = vol->rdir_secs << vol->sec_log2;
434
435    if ( (FAT_GET_BR_SECTORS_PER_FAT(boot_rec)) != 0)
436        vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT(boot_rec);
437    else
438        vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT32(boot_rec);
439 
440    vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length +
441                     vol->rdir_secs;
442
443    /* for  FAT12/16 root dir starts at(sector) */
444    vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length;
445 
446    if ( (FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0)
447        vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec);
448    else
449        vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM32(boot_rec);
450 
451    data_secs = vol->tot_secs - vol->data_fsec;
452
453    vol->data_cls = data_secs / vol->spc;
454
455    /* determine FAT type at least */
456    if ( vol->data_cls < FAT_FAT12_MAX_CLN)
457    {
458        vol->type = FAT_FAT12;
459        vol->mask = FAT_FAT12_MASK;
460        vol->eoc_val = FAT_FAT12_EOC;
461    }
462    else
463    {
464        if ( vol->data_cls < FAT_FAT16_MAX_CLN)
465        {
466            vol->type = FAT_FAT16;
467            vol->mask = FAT_FAT16_MASK;
468            vol->eoc_val = FAT_FAT16_EOC;
469        }
470        else
471        {
472            vol->type = FAT_FAT32;
473            vol->mask = FAT_FAT32_MASK;
474            vol->eoc_val = FAT_FAT32_EOC;
475        }
476    }
477
478    if (vol->type == FAT_FAT32)
479    {
480        vol->rdir_cl = FAT_GET_BR_FAT32_ROOT_CLUSTER(boot_rec);
481     
482        vol->mirror = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR;
483        if (vol->mirror)
484            vol->afat = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM;
485        else
486            vol->afat = 0;
487
488        vol->info_sec = FAT_GET_BR_FAT32_FS_INFO_SECTOR(boot_rec);
489        if( vol->info_sec == 0 )
490        {
491            rtems_disk_release(vol->dd);
492            rtems_set_errno_and_return_minus_one( EINVAL );
493        }
494        else
495        {
496            ret = _fat_block_read(mt_entry, vol->info_sec , 0,
497                                  FAT_FSI_LEADSIG_SIZE, fs_info_sector);
498            if ( ret < 0 )
499            {
500                rtems_disk_release(vol->dd);
501                return -1;
502            }   
503     
504            if (FAT_GET_FSINFO_LEAD_SIGNATURE(fs_info_sector) !=
505                FAT_FSINFO_LEAD_SIGNATURE_VALUE)
506            {
507                rtems_disk_release(vol->dd);
508                rtems_set_errno_and_return_minus_one( EINVAL );
509            }
510            else
511            {
512                ret = _fat_block_read(mt_entry, vol->info_sec , FAT_FSI_INFO,
513                                      FAT_USEFUL_INFO_SIZE, fs_info_sector);
514                if ( ret < 0 )
515                {
516                    rtems_disk_release(vol->dd);
517                    return -1;
518                }   
519                   
520                vol->free_cls = FAT_GET_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector);
521                vol->next_cl = FAT_GET_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector);
522                rc = fat_fat32_update_fsinfo_sector(mt_entry, 0xFFFFFFFF,
523                                                    0xFFFFFFFF);
524                if ( rc != RC_OK )
525                {
526                    rtems_disk_release(vol->dd);
527                    return rc;
528                }
529            }
530        }
531    }
532    else
533    {
534        vol->rdir_cl = 0;
535        vol->mirror = 0;
536        vol->afat = 0;
537        vol->free_cls = 0xFFFFFFFF;
538        vol->next_cl = 0xFFFFFFFF;
539    }
540    vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat;
541
542    /* set up collection of fat-files fd */
543    fs_info->vhash = calloc(FAT_HASH_SIZE, sizeof(rtems_chain_control));
544    if ( fs_info->vhash == NULL )
545    {
546        rtems_disk_release(vol->dd);
547        rtems_set_errno_and_return_minus_one( ENOMEM );
548    }
549
550    for (i = 0; i < FAT_HASH_SIZE; i++)
551        rtems_chain_initialize_empty(fs_info->vhash + i);
552
553    fs_info->rhash = calloc(FAT_HASH_SIZE, sizeof(rtems_chain_control));
554    if ( fs_info->rhash == NULL )
555    {
556        rtems_disk_release(vol->dd);
557        free(fs_info->vhash);
558        rtems_set_errno_and_return_minus_one( ENOMEM );
559    }
560    for (i = 0; i < FAT_HASH_SIZE; i++)
561        rtems_chain_initialize_empty(fs_info->rhash + i);
562
563    fs_info->uino_pool_size = FAT_UINO_POOL_INIT_SIZE;
564    fs_info->uino_base = (vol->tot_secs << vol->sec_mul) << 4;
565    fs_info->index = 0;
566    fs_info->uino = (char *)calloc(fs_info->uino_pool_size, sizeof(char));
567    if ( fs_info->uino == NULL )
568    {
569        rtems_disk_release(vol->dd);
570        free(fs_info->vhash);
571        free(fs_info->rhash);
572        rtems_set_errno_and_return_minus_one( ENOMEM );
573    }
574    fs_info->sec_buf = (uint8_t *)calloc(vol->bps, sizeof(uint8_t));
575    if (fs_info->sec_buf == NULL)
576    {
577        rtems_disk_release(vol->dd);
578        free(fs_info->vhash);
579        free(fs_info->rhash);
580        free(fs_info->uino);
581        rtems_set_errno_and_return_minus_one( ENOMEM );
582    }
583
584    return RC_OK;
585}
586
587/* fat_shutdown_drive --
588 *     Free all allocated resources and synchronize all necessary data
589 *
590 * PARAMETERS:
591 *     mt_entry - mount table entry
592 *
593 * RETURNS:
594 *     RC_OK on success, or -1 if error occured
595 *     and errno set appropriately
596 */
597int
598fat_shutdown_drive(rtems_filesystem_mount_table_entry_t *mt_entry)
599{
600    int            rc = RC_OK;
601    fat_fs_info_t *fs_info = mt_entry->fs_info;
602    int            i = 0;
603
604    if (fs_info->vol.type & FAT_FAT32)
605    {
606        rc = fat_fat32_update_fsinfo_sector(mt_entry, fs_info->vol.free_cls,
607                                            fs_info->vol.next_cl);
608        if ( rc != RC_OK )
609            rc = -1;
610    }
611
612    fat_buf_release(fs_info);
613
614    if (rtems_bdbuf_syncdev(fs_info->vol.dev) != RTEMS_SUCCESSFUL)
615        rc = -1;
616
617    for (i = 0; i < FAT_HASH_SIZE; i++)
618    {
619        rtems_chain_node    *node = NULL;
620        rtems_chain_control *the_chain = fs_info->vhash + i;
621
622        while ( (node = rtems_chain_get(the_chain)) != NULL )
623            free(node);
624    }
625
626    for (i = 0; i < FAT_HASH_SIZE; i++)
627    {
628        rtems_chain_node    *node = NULL;
629        rtems_chain_control *the_chain = fs_info->rhash + i;
630
631        while ( (node = rtems_chain_get(the_chain)) != NULL )
632            free(node);
633    }
634
635    free(fs_info->vhash);
636    free(fs_info->rhash);
637
638    free(fs_info->uino);
639    free(fs_info->sec_buf);
640    rtems_disk_release(fs_info->vol.dd);
641
642    if (rc)
643        errno = EIO;
644    return rc;
645}
646
647/* fat_init_clusters_chain --
648 *     Zeroing contents of all clusters in the chain
649 *
650 * PARAMETERS:
651 *     mt_entry          - mount table entry
652 *     start_cluster_num - num of first cluster in the chain
653 *
654 * RETURNS:
655 *     RC_OK on success, or -1 if error occured
656 *     and errno set appropriately
657 */
658int
659fat_init_clusters_chain(
660    rtems_filesystem_mount_table_entry_t *mt_entry,
661    uint32_t                              start_cln
662    )
663{
664    int                     rc = RC_OK;
665    ssize_t                 ret = 0;
666    register fat_fs_info_t *fs_info = mt_entry->fs_info;
667    uint32_t                cur_cln = start_cln;
668    char                   *buf;
669
670    buf = calloc(fs_info->vol.bpc, sizeof(char));
671    if ( buf == NULL )
672        rtems_set_errno_and_return_minus_one( EIO );
673
674    while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
675    {
676        ret = fat_cluster_write(mt_entry, cur_cln, buf);
677        if ( ret == -1 )
678        {
679            free(buf);
680            return -1;
681        }
682
683        rc  = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
684        if ( rc != RC_OK )
685        {
686            free(buf);
687            return rc;
688        }
689
690    }
691    free(buf);
692    return rc;
693}
694
695#define FAT_UNIQ_INO_BASE 0x0FFFFF00
696
697#define FAT_UNIQ_INO_IS_BUSY(index, arr) \
698  (((arr)[((index)>>3)]>>((index) & (8-1))) & 0x01)
699
700#define FAT_SET_UNIQ_INO_BUSY(index, arr) \
701  ((arr)[((index)>>3)] |= (0x01<<((index) & (8-1))))
702
703#define FAT_SET_UNIQ_INO_FREE(index, arr) \
704  ((arr)[((index)>>3)] &= (~(0x01<<((index) & (8-1)))))
705
706/* fat_get_unique_ino --
707 *     Allocate unique ino from unique ino pool
708 *
709 * PARAMETERS:
710 *     mt_entry - mount table entry
711 *
712 * RETURNS:
713 *     unique inode number on success, or 0 if there is no free unique inode
714 *     number in the pool
715 *
716 * ATTENTION:
717 *     0 means FAILED !!!
718 *
719 */
720uint32_t
721fat_get_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry)
722{
723    register fat_fs_info_t *fs_info = mt_entry->fs_info;
724    uint32_t                j = 0;
725    bool                    resrc_unsuff = false;
726
727    while (!resrc_unsuff)
728    {
729        for (j = 0; j < fs_info->uino_pool_size; j++)
730        {
731            if (!FAT_UNIQ_INO_IS_BUSY(fs_info->index, fs_info->uino))
732            {
733                FAT_SET_UNIQ_INO_BUSY(fs_info->index, fs_info->uino);
734                return (fs_info->uino_base + fs_info->index);
735            }
736            fs_info->index++;
737            if (fs_info->index >= fs_info->uino_pool_size)
738                fs_info->index = 0;
739        }
740
741        if ((fs_info->uino_pool_size << 1) < (0x0FFFFFFF - fs_info->uino_base))
742        {
743            fs_info->uino_pool_size <<= 1;
744            fs_info->uino = realloc(fs_info->uino, fs_info->uino_pool_size);
745            if (fs_info->uino != NULL)
746                fs_info->index = fs_info->uino_pool_size;
747            else
748                resrc_unsuff = true;
749        }
750        else
751            resrc_unsuff = true;
752    }
753    return 0;
754}
755
756/* fat_free_unique_ino --
757 *     Return unique ino to unique ino pool
758 *
759 * PARAMETERS:
760 *     mt_entry - mount table entry
761 *     ino      - inode number to free
762 *
763 * RETURNS:
764 *     None
765 */
766void
767fat_free_unique_ino(
768    rtems_filesystem_mount_table_entry_t *mt_entry,
769    uint32_t                              ino
770    )
771{
772    fat_fs_info_t *fs_info = mt_entry->fs_info;
773
774    FAT_SET_UNIQ_INO_FREE((ino - fs_info->uino_base), fs_info->uino);
775}
776
777/* fat_ino_is_unique --
778 *     Test whether ino is from unique ino pool
779 *
780 * PARAMETERS:
781 *     mt_entry - mount table entry
782 *     ino   - ino to be tested
783 *
784 * RETURNS:
785 *     true if ino is allocated from unique ino pool, false otherwise
786 */
787inline bool
788fat_ino_is_unique(
789    rtems_filesystem_mount_table_entry_t *mt_entry,
790    uint32_t                              ino
791    )
792{
793    fat_fs_info_t *fs_info = mt_entry->fs_info;
794
795    return (ino >= fs_info->uino_base);
796}
797
798/* fat_fat32_update_fsinfo_sector --
799 *     Synchronize fsinfo sector for FAT32 volumes
800 *
801 * PARAMETERS:
802 *     mt_entry   - mount table entry
803 *     free_count - count of free clusters
804 *     next_free  - the next free cluster num
805 *
806 * RETURNS:
807 *     RC_OK on success, or -1 if error occured (errno set appropriately)
808 */
809int
810fat_fat32_update_fsinfo_sector(
811    rtems_filesystem_mount_table_entry_t *mt_entry,
812    uint32_t                              free_count,
813    uint32_t                              next_free
814    )
815{
816    ssize_t                 ret1 = 0, ret2 = 0;
817    register fat_fs_info_t *fs_info = mt_entry->fs_info;
818    uint32_t                le_free_count = 0;
819    uint32_t                le_next_free = 0;
820
821    le_free_count = CT_LE_L(free_count);
822    le_next_free = CT_LE_L(next_free);
823
824    ret1 = _fat_block_write(mt_entry,
825                            fs_info->vol.info_sec,
826                            FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET,
827                            4,
828                            (char *)(&le_free_count));
829
830    ret2 = _fat_block_write(mt_entry,
831                            fs_info->vol.info_sec,
832                            FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET,
833                            4,
834                            (char *)(&le_next_free));
835
836    if ( (ret1 < 0) || (ret2 < 0) )
837        return -1;
838
839    return RC_OK;
840}
Note: See TracBrowser for help on using the repository browser.