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:
Joel Sherrill
2003-03-25 17:01:45 +00:00
parent ec6422eb96
commit c151cfc347
8 changed files with 138 additions and 19 deletions

View File

@@ -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>
* configure.ac: Remove AC_CONFIG_AUX_DIR.

View File

@@ -27,6 +27,10 @@ include_HEADERS = dosfs.h
H_FILES = $(PROJECT_INCLUDE) \
$(include_HEADERS:%=$(PROJECT_INCLUDE)/%)
PREINSTALL_FILES = $(PROJECT_INCLUDE) \
$(include_HEADERS:%=$(PROJECT_INCLUDE)/%)
$(PROJECT_INCLUDE):
@$(mkinstalldirs) $@

View File

@@ -260,6 +260,16 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
i >>= 1, vol->sec_log2++);
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;
i >>= 1, vol->spc_log2++);
@@ -526,7 +536,7 @@ fat_init_clusters_chain(
if ( buf == NULL )
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);
if ( ret == -1 )

View File

@@ -83,9 +83,9 @@ extern "C" {
#define FAT_UNDEFINED_VALUE (unsigned32)0xFFFFFFFF
#define FAT_FAT12_EOC 0x0FFF
#define FAT_FAT16_EOC 0xFFFF
#define FAT_FAT32_EOC (unsigned32)0x0FFFFFFF
#define FAT_FAT12_EOC 0x0FF8
#define FAT_FAT16_EOC 0xFFF8
#define FAT_FAT32_EOC (unsigned32)0x0FFFFFF8
#define FAT_FAT12_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)
set_errno_and_return_minus_one(EIO);
fs_info->c.blk_num = blk;
fs_info->c.modified = 0;
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);
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)
set_errno_and_return_minus_one(EIO);
fs_info->c.modified = 0;
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
{
sc = rtems_bdbuf_release(fs_info->c.buf);
fs_info->c.state = FAT_CACHE_EMPTY;
if (sc != RTEMS_SUCCESSFUL)
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)
set_errno_and_return_minus_one(EIO);
fs_info->c.blk_num = blk;
fs_info->c.state = FAT_CACHE_ACTUAL;
}
*buf = fs_info->c.buf;
return RC_OK;

View File

@@ -78,7 +78,8 @@ fat_scan_fat_for_free_clusters(
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
@@ -177,7 +178,7 @@ fat_free_fat_clusters_chain(
unsigned32 next_cln = 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);
if ( rc != RC_OK )
@@ -276,7 +277,6 @@ fat_get_fat_cluster(
*ret_val = (*ret_val) >> FAT12_SHIFT;
else
*ret_val = (*ret_val) & FAT_FAT12_MASK;
break;
case FAT_FAT16:
@@ -342,8 +342,16 @@ fat_set_fat_cluster(
case FAT_FAT12:
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));
#else
fat16_clv = ((unsigned16)in_val) << FAT_FAT12_SHIFT;
#endif
*((unsigned8 *)(block0->buffer + ofs)) =
(*((unsigned8 *)(block0->buffer + ofs))) & 0x0F;
@@ -379,8 +387,16 @@ fat_set_fat_cluster(
}
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));
#else
fat16_clv = ((unsigned16)in_val) & FAT_FAT12_MASK;
#endif
*((unsigned8 *)(block0->buffer + ofs)) &= 0x00;
*((unsigned8 *)(block0->buffer + ofs)) =

View File

@@ -770,7 +770,7 @@ fat_file_datasync(
return rc;
/* 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);
/* for each sector in cluster ... */
@@ -830,7 +830,7 @@ fat_file_size(
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;
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);

View File

@@ -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_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_WITH_DOT (MSDOS_NAME_MAX + 1)

View File

@@ -104,6 +104,75 @@ msdos_dir_close(rtems_libio_t *iop)
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 --
* 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
@@ -236,12 +305,13 @@ msdos_dir_read(rtems_libio_t *iop, void *buffer, unsigned32 count)
tmp_dirent.d_off = start + cmpltd;
tmp_dirent.d_reclen = sizeof(struct dirent);
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)),
MSDOS_SHORT_NAME_LEN);
/* d_name is null-terminated */
tmp_dirent.d_name[MSDOS_SHORT_NAME_LEN] = 0;
/*
* convert dir entry from fixed 8+3 format (without dot)
* to 0..8 + 1dot + 0..3 format
*/
tmp_dirent.d_namlen =
msdos_format_dirent_with_dot(tmp_dirent.d_name,
fs_info->cl_buf + i); /* src text */
memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
iop->offset = iop->offset + sizeof(struct dirent);