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>
|
||||
|
||||
* configure.ac: Remove AC_CONFIG_AUX_DIR.
|
||||
|
||||
@@ -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) $@
|
||||
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)) =
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user