forked from Imagelibrary/rtems
2003-03-25 Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
PR 367/filesystem * src/dosfs/Makefile.am, src/dosfs/fat.c, src/dosfs/fat.h, src/dosfs/fat_fat_operations.c, src/dosfs/fat_file.c, src/dosfs/msdos.h, src/dosfs/msdos_dir.c: Some bugs were still present in the DOSFS implementation: - FAT12 did not work properly on Big-Endian machines - Some synchronization and error handling problems were present - Some legal codings for EOC were not recognized
This commit is contained in:
@@ -1,3 +1,15 @@
|
|||||||
|
2003-03-25 Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
|
||||||
|
|
||||||
|
PR 367/filesystem
|
||||||
|
* src/dosfs/Makefile.am, src/dosfs/fat.c, src/dosfs/fat.h,
|
||||||
|
src/dosfs/fat_fat_operations.c, src/dosfs/fat_file.c,
|
||||||
|
src/dosfs/msdos.h, src/dosfs/msdos_dir.c: Some bugs were still
|
||||||
|
present in the DOSFS implementation:
|
||||||
|
- FAT12 did not work properly on Big-Endian machines
|
||||||
|
- Some synchronization and error handling problems were present
|
||||||
|
- Some legal codings for EOC were not recognized
|
||||||
|
|
||||||
|
|
||||||
2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
||||||
|
|
||||||
* configure.ac: Remove AC_CONFIG_AUX_DIR.
|
* configure.ac: Remove AC_CONFIG_AUX_DIR.
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ include_HEADERS = dosfs.h
|
|||||||
H_FILES = $(PROJECT_INCLUDE) \
|
H_FILES = $(PROJECT_INCLUDE) \
|
||||||
$(include_HEADERS:%=$(PROJECT_INCLUDE)/%)
|
$(include_HEADERS:%=$(PROJECT_INCLUDE)/%)
|
||||||
|
|
||||||
|
PREINSTALL_FILES = $(PROJECT_INCLUDE) \
|
||||||
|
$(include_HEADERS:%=$(PROJECT_INCLUDE)/%)
|
||||||
|
|
||||||
|
|
||||||
$(PROJECT_INCLUDE):
|
$(PROJECT_INCLUDE):
|
||||||
@$(mkinstalldirs) $@
|
@$(mkinstalldirs) $@
|
||||||
|
|
||||||
|
|||||||
@@ -260,6 +260,16 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
|
|||||||
i >>= 1, vol->sec_log2++);
|
i >>= 1, vol->sec_log2++);
|
||||||
|
|
||||||
vol->spc = FAT_BR_SECTORS_PER_CLUSTER(boot_rec);
|
vol->spc = FAT_BR_SECTORS_PER_CLUSTER(boot_rec);
|
||||||
|
/*
|
||||||
|
* "sectors per cluster" of zero is invalid
|
||||||
|
* (and would hang the following loop)
|
||||||
|
*/
|
||||||
|
if (vol->spc == 0)
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0;
|
for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0;
|
||||||
i >>= 1, vol->spc_log2++);
|
i >>= 1, vol->spc_log2++);
|
||||||
|
|
||||||
@@ -526,7 +536,7 @@ fat_init_clusters_chain(
|
|||||||
if ( buf == NULL )
|
if ( buf == NULL )
|
||||||
set_errno_and_return_minus_one( EIO );
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
|
||||||
{
|
{
|
||||||
ret = fat_cluster_write(mt_entry, cur_cln, buf);
|
ret = fat_cluster_write(mt_entry, cur_cln, buf);
|
||||||
if ( ret == -1 )
|
if ( ret == -1 )
|
||||||
|
|||||||
@@ -83,9 +83,9 @@ extern "C" {
|
|||||||
|
|
||||||
#define FAT_UNDEFINED_VALUE (unsigned32)0xFFFFFFFF
|
#define FAT_UNDEFINED_VALUE (unsigned32)0xFFFFFFFF
|
||||||
|
|
||||||
#define FAT_FAT12_EOC 0x0FFF
|
#define FAT_FAT12_EOC 0x0FF8
|
||||||
#define FAT_FAT16_EOC 0xFFFF
|
#define FAT_FAT16_EOC 0xFFF8
|
||||||
#define FAT_FAT32_EOC (unsigned32)0x0FFFFFFF
|
#define FAT_FAT32_EOC (unsigned32)0x0FFFFFF8
|
||||||
|
|
||||||
#define FAT_FAT12_FREE 0x0000
|
#define FAT_FAT12_FREE 0x0000
|
||||||
#define FAT_FAT16_FREE 0x0000
|
#define FAT_FAT16_FREE 0x0000
|
||||||
@@ -306,6 +306,7 @@ fat_buf_access(fat_fs_info_t *fs_info, unsigned32 blk, int op_type,
|
|||||||
if (sc != RTEMS_SUCCESSFUL)
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
set_errno_and_return_minus_one(EIO);
|
set_errno_and_return_minus_one(EIO);
|
||||||
fs_info->c.blk_num = blk;
|
fs_info->c.blk_num = blk;
|
||||||
|
fs_info->c.modified = 0;
|
||||||
fs_info->c.state = FAT_CACHE_ACTUAL;
|
fs_info->c.state = FAT_CACHE_ACTUAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,9 +322,10 @@ fat_buf_access(fat_fs_info_t *fs_info, unsigned32 blk, int op_type,
|
|||||||
fs_info->vol.bps);
|
fs_info->vol.bps);
|
||||||
|
|
||||||
sc = rtems_bdbuf_release_modified(fs_info->c.buf);
|
sc = rtems_bdbuf_release_modified(fs_info->c.buf);
|
||||||
|
fs_info->c.state = FAT_CACHE_EMPTY;
|
||||||
|
fs_info->c.modified = 0;
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
set_errno_and_return_minus_one(EIO);
|
set_errno_and_return_minus_one(EIO);
|
||||||
fs_info->c.modified = 0;
|
|
||||||
|
|
||||||
if (sec_of_fat && !fs_info->vol.mirror)
|
if (sec_of_fat && !fs_info->vol.mirror)
|
||||||
{
|
{
|
||||||
@@ -347,6 +349,7 @@ fat_buf_access(fat_fs_info_t *fs_info, unsigned32 blk, int op_type,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
sc = rtems_bdbuf_release(fs_info->c.buf);
|
sc = rtems_bdbuf_release(fs_info->c.buf);
|
||||||
|
fs_info->c.state = FAT_CACHE_EMPTY;
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
set_errno_and_return_minus_one(EIO);
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
@@ -358,6 +361,7 @@ fat_buf_access(fat_fs_info_t *fs_info, unsigned32 blk, int op_type,
|
|||||||
if (sc != RTEMS_SUCCESSFUL)
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
set_errno_and_return_minus_one(EIO);
|
set_errno_and_return_minus_one(EIO);
|
||||||
fs_info->c.blk_num = blk;
|
fs_info->c.blk_num = blk;
|
||||||
|
fs_info->c.state = FAT_CACHE_ACTUAL;
|
||||||
}
|
}
|
||||||
*buf = fs_info->c.buf;
|
*buf = fs_info->c.buf;
|
||||||
return RC_OK;
|
return RC_OK;
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ fat_scan_fat_for_free_clusters(
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((next_cln & fs_info->vol.mask) == FAT_GENFAT_FREE)
|
/*if ((next_cln & fs_info->vol.mask) == FAT_GENFAT_FREE)*/
|
||||||
|
if (next_cln == FAT_GENFAT_FREE)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We are enforced to process allocation of the first free cluster
|
* We are enforced to process allocation of the first free cluster
|
||||||
@@ -177,7 +178,7 @@ fat_free_fat_clusters_chain(
|
|||||||
unsigned32 next_cln = 0;
|
unsigned32 next_cln = 0;
|
||||||
unsigned32 freed_cls_cnt = 0;
|
unsigned32 freed_cls_cnt = 0;
|
||||||
|
|
||||||
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
|
||||||
{
|
{
|
||||||
rc = fat_get_fat_cluster(mt_entry, cur_cln, &next_cln);
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &next_cln);
|
||||||
if ( rc != RC_OK )
|
if ( rc != RC_OK )
|
||||||
@@ -276,7 +277,6 @@ fat_get_fat_cluster(
|
|||||||
*ret_val = (*ret_val) >> FAT12_SHIFT;
|
*ret_val = (*ret_val) >> FAT12_SHIFT;
|
||||||
else
|
else
|
||||||
*ret_val = (*ret_val) & FAT_FAT12_MASK;
|
*ret_val = (*ret_val) & FAT_FAT12_MASK;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FAT_FAT16:
|
case FAT_FAT16:
|
||||||
@@ -342,8 +342,16 @@ fat_set_fat_cluster(
|
|||||||
case FAT_FAT12:
|
case FAT_FAT12:
|
||||||
if ( FAT_CLUSTER_IS_ODD(cln) )
|
if ( FAT_CLUSTER_IS_ODD(cln) )
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* do not perform endian conversion explicitely,
|
||||||
|
* because following code will enforce little
|
||||||
|
* endian format implicitly!
|
||||||
|
*/
|
||||||
fat16_clv = CT_LE_W((((unsigned16)in_val) << FAT_FAT12_SHIFT));
|
fat16_clv = CT_LE_W((((unsigned16)in_val) << FAT_FAT12_SHIFT));
|
||||||
|
#else
|
||||||
|
fat16_clv = ((unsigned16)in_val) << FAT_FAT12_SHIFT;
|
||||||
|
#endif
|
||||||
*((unsigned8 *)(block0->buffer + ofs)) =
|
*((unsigned8 *)(block0->buffer + ofs)) =
|
||||||
(*((unsigned8 *)(block0->buffer + ofs))) & 0x0F;
|
(*((unsigned8 *)(block0->buffer + ofs))) & 0x0F;
|
||||||
|
|
||||||
@@ -379,8 +387,16 @@ fat_set_fat_cluster(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* do not perform endian conversion explicitely,
|
||||||
|
* because following code will enforce little
|
||||||
|
* endian format implicitly!
|
||||||
|
*/
|
||||||
fat16_clv = CT_LE_W((((unsigned16)in_val) & FAT_FAT12_MASK));
|
fat16_clv = CT_LE_W((((unsigned16)in_val) & FAT_FAT12_MASK));
|
||||||
|
#else
|
||||||
|
fat16_clv = ((unsigned16)in_val) & FAT_FAT12_MASK;
|
||||||
|
#endif
|
||||||
*((unsigned8 *)(block0->buffer + ofs)) &= 0x00;
|
*((unsigned8 *)(block0->buffer + ofs)) &= 0x00;
|
||||||
|
|
||||||
*((unsigned8 *)(block0->buffer + ofs)) =
|
*((unsigned8 *)(block0->buffer + ofs)) =
|
||||||
|
|||||||
@@ -770,7 +770,7 @@ fat_file_datasync(
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
/* for each cluster of the file ... */
|
/* for each cluster of the file ... */
|
||||||
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
|
||||||
{
|
{
|
||||||
sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
|
sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
|
||||||
/* for each sector in cluster ... */
|
/* for each sector in cluster ... */
|
||||||
@@ -830,7 +830,7 @@ fat_file_size(
|
|||||||
|
|
||||||
fat_fd->fat_file_size = 0;
|
fat_fd->fat_file_size = 0;
|
||||||
|
|
||||||
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
|
||||||
{
|
{
|
||||||
save_cln = cur_cln;
|
save_cln = cur_cln;
|
||||||
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
|||||||
@@ -138,7 +138,10 @@ typedef rtems_filesystem_node_types_t msdos_node_type_t;
|
|||||||
#define msdos_is_valid_name_char(_ch) (1)
|
#define msdos_is_valid_name_char(_ch) (1)
|
||||||
#define msdos_is_separator(_ch) rtems_filesystem_is_separator(_ch)
|
#define msdos_is_separator(_ch) rtems_filesystem_is_separator(_ch)
|
||||||
|
|
||||||
#define MSDOS_SHORT_NAME_LEN 11 /* 11 characters */
|
#define MSDOS_SHORT_BASE_LEN 8 /* 8 characters */
|
||||||
|
#define MSDOS_SHORT_EXT_LEN 3 /* 3 characters */
|
||||||
|
#define MSDOS_SHORT_NAME_LEN (MSDOS_SHORT_BASE_LEN+\
|
||||||
|
MSDOS_SHORT_EXT_LEN) /* 11 chars */
|
||||||
#define MSDOS_NAME_MAX MSDOS_SHORT_NAME_LEN
|
#define MSDOS_NAME_MAX MSDOS_SHORT_NAME_LEN
|
||||||
#define MSDOS_NAME_MAX_WITH_DOT (MSDOS_NAME_MAX + 1)
|
#define MSDOS_NAME_MAX_WITH_DOT (MSDOS_NAME_MAX + 1)
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,75 @@ msdos_dir_close(rtems_libio_t *iop)
|
|||||||
return RC_OK;
|
return RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* msdos_format_dirent_with_dot --
|
||||||
|
* This routine convert a (short) MSDOS filename as present on disk
|
||||||
|
* (fixed 8+3 characters, filled with blanks, without separator dot)
|
||||||
|
* to a "normal" format, with between 0 and 8 name chars,
|
||||||
|
* a separating dot and up to 3 extension characters
|
||||||
|
* Rules to work:
|
||||||
|
* - copy any (0-8) "name" part characters that are non-blank
|
||||||
|
* - if an extension exists, append a dot
|
||||||
|
* - copy any (0-3) non-blank extension characters
|
||||||
|
* - append a '\0' (dont count it for the rturn code
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* dst: pointer to destination char array (must be big enough)
|
||||||
|
* src: pointer to source characters
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* the number of bytes (without trailing '\0'(written to destination
|
||||||
|
*/
|
||||||
|
static ssize_t
|
||||||
|
msdos_format_dirent_with_dot(char *dst,const char *src)
|
||||||
|
{
|
||||||
|
ssize_t len;
|
||||||
|
int i;
|
||||||
|
const char *src_tmp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find last non-blank character of base name
|
||||||
|
*/
|
||||||
|
for ((i = MSDOS_SHORT_BASE_LEN ,
|
||||||
|
src_tmp = src + MSDOS_SHORT_BASE_LEN-1);
|
||||||
|
((i > 0) &&
|
||||||
|
(*src_tmp == ' '));
|
||||||
|
i--,src_tmp--)
|
||||||
|
{};
|
||||||
|
/*
|
||||||
|
* copy base name to destination
|
||||||
|
*/
|
||||||
|
src_tmp = src;
|
||||||
|
len = i;
|
||||||
|
while (i-- > 0) {
|
||||||
|
*dst++ = *src_tmp++;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* find last non-blank character of extension
|
||||||
|
*/
|
||||||
|
for ((i = MSDOS_SHORT_EXT_LEN ,
|
||||||
|
src_tmp = src + MSDOS_SHORT_BASE_LEN+MSDOS_SHORT_EXT_LEN-1);
|
||||||
|
((i > 0) &&
|
||||||
|
(*src_tmp == ' '));
|
||||||
|
i--,src_tmp--)
|
||||||
|
{};
|
||||||
|
/*
|
||||||
|
* extension is not empty
|
||||||
|
*/
|
||||||
|
if (i > 0) {
|
||||||
|
*dst++ = '.'; /* append dot */
|
||||||
|
len += i + 1; /* extension + dot */
|
||||||
|
src_tmp = src + MSDOS_SHORT_BASE_LEN;
|
||||||
|
while (i-- > 0) {
|
||||||
|
*dst++ = *src_tmp++;
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*dst = '\0'; /* terminate string */
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
/* msdos_dir_read --
|
/* msdos_dir_read --
|
||||||
* This routine will read the next directory entry based on the directory
|
* This routine will read the next directory entry based on the directory
|
||||||
* offset. The offset should be equal to -n- time the size of an
|
* offset. The offset should be equal to -n- time the size of an
|
||||||
@@ -236,12 +305,13 @@ msdos_dir_read(rtems_libio_t *iop, void *buffer, unsigned32 count)
|
|||||||
tmp_dirent.d_off = start + cmpltd;
|
tmp_dirent.d_off = start + cmpltd;
|
||||||
tmp_dirent.d_reclen = sizeof(struct dirent);
|
tmp_dirent.d_reclen = sizeof(struct dirent);
|
||||||
tmp_dirent.d_ino = tmp_fat_fd->ino;
|
tmp_dirent.d_ino = tmp_fat_fd->ino;
|
||||||
tmp_dirent.d_namlen = MSDOS_SHORT_NAME_LEN;
|
/*
|
||||||
memcpy(tmp_dirent.d_name, MSDOS_DIR_NAME((fs_info->cl_buf + i)),
|
* convert dir entry from fixed 8+3 format (without dot)
|
||||||
MSDOS_SHORT_NAME_LEN);
|
* to 0..8 + 1dot + 0..3 format
|
||||||
|
*/
|
||||||
/* d_name is null-terminated */
|
tmp_dirent.d_namlen =
|
||||||
tmp_dirent.d_name[MSDOS_SHORT_NAME_LEN] = 0;
|
msdos_format_dirent_with_dot(tmp_dirent.d_name,
|
||||||
|
fs_info->cl_buf + i); /* src text */
|
||||||
memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
|
memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
|
||||||
|
|
||||||
iop->offset = iop->offset + sizeof(struct dirent);
|
iop->offset = iop->offset + sizeof(struct dirent);
|
||||||
|
|||||||
Reference in New Issue
Block a user