summaryrefslogtreecommitdiffstats
path: root/cpukit/libfs/src
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2003-03-25 17:01:45 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2003-03-25 17:01:45 +0000
commitc151cfc347d29c7934db74aa4c7aeceaab0de83f (patch)
treee0d9e3ed17c529fe9aff0bf4463ced288fbb54ab /cpukit/libfs/src
parent2003-03-25 Till Straumann <strauman@slac.stanford.edu> (diff)
downloadrtems-c151cfc347d29c7934db74aa4c7aeceaab0de83f.tar.bz2
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
Diffstat (limited to 'cpukit/libfs/src')
-rw-r--r--cpukit/libfs/src/dosfs/Makefile.am4
-rw-r--r--cpukit/libfs/src/dosfs/fat.c12
-rw-r--r--cpukit/libfs/src/dosfs/fat.h12
-rw-r--r--cpukit/libfs/src/dosfs/fat_fat_operations.c26
-rw-r--r--cpukit/libfs/src/dosfs/fat_file.c4
-rw-r--r--cpukit/libfs/src/dosfs/msdos.h5
-rw-r--r--cpukit/libfs/src/dosfs/msdos_dir.c82
7 files changed, 126 insertions, 19 deletions
diff --git a/cpukit/libfs/src/dosfs/Makefile.am b/cpukit/libfs/src/dosfs/Makefile.am
index 95bee65c42..4ba0b6d6b0 100644
--- a/cpukit/libfs/src/dosfs/Makefile.am
+++ b/cpukit/libfs/src/dosfs/Makefile.am
@@ -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) $@
diff --git a/cpukit/libfs/src/dosfs/fat.c b/cpukit/libfs/src/dosfs/fat.c
index 1b37a22ff5..3c9b10d9f5 100644
--- a/cpukit/libfs/src/dosfs/fat.c
+++ b/cpukit/libfs/src/dosfs/fat.c
@@ -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 )
diff --git a/cpukit/libfs/src/dosfs/fat.h b/cpukit/libfs/src/dosfs/fat.h
index ef7fa7b8d4..b8361d55cf 100644
--- a/cpukit/libfs/src/dosfs/fat.h
+++ b/cpukit/libfs/src/dosfs/fat.h
@@ -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;
diff --git a/cpukit/libfs/src/dosfs/fat_fat_operations.c b/cpukit/libfs/src/dosfs/fat_fat_operations.c
index 49b2ab70d3..df79729f7c 100644
--- a/cpukit/libfs/src/dosfs/fat_fat_operations.c
+++ b/cpukit/libfs/src/dosfs/fat_fat_operations.c
@@ -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)) =
diff --git a/cpukit/libfs/src/dosfs/fat_file.c b/cpukit/libfs/src/dosfs/fat_file.c
index 8046f47720..0d5dcc87ba 100644
--- a/cpukit/libfs/src/dosfs/fat_file.c
+++ b/cpukit/libfs/src/dosfs/fat_file.c
@@ -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);
diff --git a/cpukit/libfs/src/dosfs/msdos.h b/cpukit/libfs/src/dosfs/msdos.h
index 4262d515ef..5a14168012 100644
--- a/cpukit/libfs/src/dosfs/msdos.h
+++ b/cpukit/libfs/src/dosfs/msdos.h
@@ -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)
diff --git a/cpukit/libfs/src/dosfs/msdos_dir.c b/cpukit/libfs/src/dosfs/msdos_dir.c
index 93449cd2fb..5584ec36af 100644
--- a/cpukit/libfs/src/dosfs/msdos_dir.c
+++ b/cpukit/libfs/src/dosfs/msdos_dir.c
@@ -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);