summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2009-04-29 08:31:27 +0000
committerChris Johns <chrisj@rtems.org>2009-04-29 08:31:27 +0000
commit07d6fd513f1c4d3c6905c880948671de1181fac2 (patch)
tree4dabf3fdd0b056bba7b0e9beb40f01277e5c2776 /cpukit
parent2009-04-28 Chris Johns <chrisj@rtems.org> (diff)
downloadrtems-07d6fd513f1c4d3c6905c880948671de1181fac2.tar.bz2
2009-04-29 Chris Johns <chrisj@rtems.org>
* libcsupport/include/rtems/libio.h: Add rtems_off64_t for internal use. Update the internal off_t to the 64bit offset. * libnetworking/lib/ftpfs.c, libnetworking/lib/tftpDriver.c, libfs/src/nfsclient/src/nfs.c, libfs/src/imfs/imfs_fifo.c, libfs/src/imfs/memfile.c, libfs/src/imfs/imfs_directory.c, libfs/src/imfs/imfs.h, libfs/src/imfs/deviceio.c: Change off_t to rtems_off64_t. * libmisc/shell/main_msdosfmt.c: Add an info level so the format code can tell the user what is happening. Add more options to control the format configuration. * libfs/src/dosfs/msdos_format.c: Add a print function to display the format progress and print statements. Select a better default cluster size depending on the size of the disk. This lowers the size of the FAT on large disks. Read and maintain the MRB partition information. * libfs/src/dosfs/dosfs.h, libfs/src/dosfs/fat.h, libfs/src/dosfs/fat_file.c, libfs/src/dosfs/fat_file.h, libfs/src/dosfs/msdos.h, libfs/src/dosfs/msdos_conv.c, libfs/src/dosfs/msdos_create.c, libfs/src/dosfs/msdos_file.c, libfs/src/dosfs/msdos_handlers_dir.c, libfs/src/dosfs/msdos_handlers_file.c, libfs/src/dosfs/msdos_init.c, libfs/src/dosfs/msdos_initsupp.c, libfs/src/dosfs/msdos_misc.c, libfs/src/dosfs/msdos_mknod.c: Add long file name support. Change off_t to rtems_off64_t.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/libcsupport/include/rtems/libio.h25
-rw-r--r--cpukit/libfs/src/dosfs/dosfs.h6
-rw-r--r--cpukit/libfs/src/dosfs/fat.h39
-rw-r--r--cpukit/libfs/src/dosfs/fat_file.c46
-rw-r--r--cpukit/libfs/src/dosfs/fat_file.h57
-rw-r--r--cpukit/libfs/src/dosfs/msdos.h102
-rw-r--r--cpukit/libfs/src/dosfs/msdos_conv.c54
-rw-r--r--cpukit/libfs/src/dosfs/msdos_create.c135
-rw-r--r--cpukit/libfs/src/dosfs/msdos_dir.c282
-rw-r--r--cpukit/libfs/src/dosfs/msdos_eval.c32
-rw-r--r--cpukit/libfs/src/dosfs/msdos_file.c28
-rw-r--r--cpukit/libfs/src/dosfs/msdos_format.c216
-rw-r--r--cpukit/libfs/src/dosfs/msdos_handlers_dir.c2
-rw-r--r--cpukit/libfs/src/dosfs/msdos_handlers_file.c2
-rw-r--r--cpukit/libfs/src/dosfs/msdos_init.c3
-rw-r--r--cpukit/libfs/src/dosfs/msdos_initsupp.c7
-rw-r--r--cpukit/libfs/src/dosfs/msdos_misc.c1171
-rw-r--r--cpukit/libfs/src/dosfs/msdos_mknod.c13
-rw-r--r--cpukit/libfs/src/imfs/deviceio.c10
-rw-r--r--cpukit/libfs/src/imfs/imfs.h28
-rw-r--r--cpukit/libfs/src/imfs/imfs_directory.c4
-rw-r--r--cpukit/libfs/src/imfs/imfs_fifo.c6
-rw-r--r--cpukit/libfs/src/imfs/memfile.c6
-rw-r--r--cpukit/libfs/src/nfsclient/src/nfs.c50
-rw-r--r--cpukit/libmisc/shell/main_msdosfmt.c31
-rw-r--r--cpukit/libnetworking/lib/ftpfs.c2
-rw-r--r--cpukit/libnetworking/lib/tftpDriver.c2
27 files changed, 1761 insertions, 598 deletions
diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h
index 83872b760a..5f840647db 100644
--- a/cpukit/libcsupport/include/rtems/libio.h
+++ b/cpukit/libcsupport/include/rtems/libio.h
@@ -40,6 +40,11 @@ extern "C" {
#endif
/*
+ * A 64bit file offset for internal use by RTEMS. Based on the newlib type.
+ */
+typedef _off64_t rtems_off64_t;
+
+/*
* Valid RTEMS file types.
*/
@@ -83,9 +88,9 @@ typedef int (*rtems_filesystem_ioctl_t)(
void *buffer
);
-typedef off_t (*rtems_filesystem_lseek_t)(
+typedef rtems_off64_t (*rtems_filesystem_lseek_t)(
rtems_libio_t *iop,
- off_t length,
+ rtems_off64_t length,
int whence
);
@@ -101,7 +106,7 @@ typedef int (*rtems_filesystem_fchmod_t)(
typedef int (*rtems_filesystem_ftruncate_t)(
rtems_libio_t *iop,
- off_t length
+ rtems_off64_t length
);
typedef int (*rtems_filesystem_fpathconf_t)(
@@ -347,8 +352,8 @@ typedef enum
struct rtems_libio_tt {
rtems_driver_name_t *driver;
- off_t size; /* size of file */
- off_t offset; /* current offset into file */
+ rtems_off64_t size; /* size of file */
+ rtems_off64_t offset; /* current offset into file */
uint32_t flags;
rtems_filesystem_location_info_t pathinfo;
rtems_id sem;
@@ -366,7 +371,7 @@ struct rtems_libio_tt {
typedef struct {
rtems_libio_t *iop;
- off_t offset;
+ rtems_off64_t offset;
char *buffer;
uint32_t count;
uint32_t flags;
@@ -441,10 +446,10 @@ typedef int (*rtems_libio_ioctl_t)(
void *buffer
);
-typedef int (*rtems_libio_lseek_t)(
- int fd,
- off_t offset,
- int whence
+typedef rtems_off64_t (*rtems_libio_lseek_t)(
+ int fd,
+ rtems_off64_t offset,
+ int whence
);
/*
diff --git a/cpukit/libfs/src/dosfs/dosfs.h b/cpukit/libfs/src/dosfs/dosfs.h
index 3292b02dc4..cde67e38e3 100644
--- a/cpukit/libfs/src/dosfs/dosfs.h
+++ b/cpukit/libfs/src/dosfs/dosfs.h
@@ -32,6 +32,11 @@ extern rtems_filesystem_operations_table msdos_ops;
#define MSDOS_FMT_FAT16 2
#define MSDOS_FMT_FAT32 3
+#define MSDOS_FMT_INFO_LEVEL_NONE (0)
+#define MSDOS_FMT_INFO_LEVEL_INFO (1)
+#define MSDOS_FMT_INFO_LEVEL_DETAIL (2)
+#define MSDOS_FMT_INFO_LEVEL_DEBUG (3)
+
/*
* data to be filled out for formatter: parameters for format call
* any parameter set to 0 or NULL will be automatically detected/computed
@@ -51,6 +56,7 @@ typedef struct {
/* value. This can optimize clusters */
/* to be located at start of track */
/* or start of flash block */
+ int info_level; /* The amount of info to output */
} msdos_format_request_param_t;
/*=========================================================================*\
diff --git a/cpukit/libfs/src/dosfs/fat.h b/cpukit/libfs/src/dosfs/fat.h
index 83505922cc..74d0512fe5 100644
--- a/cpukit/libfs/src/dosfs/fat.h
+++ b/cpukit/libfs/src/dosfs/fat.h
@@ -250,7 +250,7 @@ extern "C" {
#define FAT_GET_FSINFO_TRAIL_SIGNATURE(x) FAT_GET_VAL32(x,508)
#define FAT_SET_FSINFO_TRAIL_SIGNATURE(x,val) FAT_SET_VAL32(x,508,val)
-#define FAT_FSINFO_TRAIL_SIGNATURE_VALUE (0x000055AA)
+#define FAT_FSINFO_TRAIL_SIGNATURE_VALUE (0xAA550000)
/*
* I read FSInfo sector from offset 484 to access the information, so offsets
* of these fields a relative
@@ -351,15 +351,31 @@ typedef struct fat_fs_info_s
} fat_fs_info_t;
/*
- * if the name we looking for is file we store not only first data cluster
- * number, but and cluster number and offset for directory entry for this
- * name
+ * FAT position is a the cluster and the offset into the
+ * cluster.
*/
-typedef struct fat_auxiliary_s
+typedef struct fat_pos_s
{
uint32_t cln;
uint32_t ofs;
-} fat_auxiliary_t;
+} fat_pos_t;
+
+/*
+ * If the name we looking for is file we store not only first data cluster
+ * number, but and cluster number and offset for directory entry for this
+ * name. We also add the LFN start offset so we can delete it the whole
+ * file name. We can then use this to delete the file.
+ */
+typedef struct fat_dir_pos_s
+{
+ fat_pos_t sname;
+ fat_pos_t lname;
+} fat_dir_pos_t;
+
+/*
+ * Set the long name entries to this value for a short file name.
+ */
+#define FAT_FILE_SHORT_NAME (0xffffffff)
#define FAT_FAT_OFFSET(fat_type, cln) \
((fat_type) & FAT_FAT12 ? ((cln) + ((cln) >> 1)) : \
@@ -380,6 +396,17 @@ typedef struct fat_auxiliary_s
#define FAT_OP_TYPE_READ 0x1
#define FAT_OP_TYPE_GET 0x2
+static inline void
+fat_dir_pos_init(
+ fat_dir_pos_t *dir_pos
+ )
+{
+ dir_pos->sname.cln = 0;
+ dir_pos->sname.ofs = 0;
+ dir_pos->lname.cln = FAT_FILE_SHORT_NAME;
+ dir_pos->lname.ofs = FAT_FILE_SHORT_NAME;
+}
+
static inline uint32_t
fat_cluster_num_to_sector_num(
rtems_filesystem_mount_table_entry_t *mt_entry,
diff --git a/cpukit/libfs/src/dosfs/fat_file.c b/cpukit/libfs/src/dosfs/fat_file.c
index 42204bacd7..b1a642f54b 100644
--- a/cpukit/libfs/src/dosfs/fat_file.c
+++ b/cpukit/libfs/src/dosfs/fat_file.c
@@ -33,20 +33,20 @@
#include "fat_file.h"
static inline void
-_hash_insert(Chain_Control *hash, uint32_t key1, uint32_t key2,
+_hash_insert(rtems_chain_control *hash, uint32_t key1, uint32_t key2,
fat_file_fd_t *el);
static inline void
-_hash_delete(Chain_Control *hash, uint32_t key1, uint32_t key2,
+_hash_delete(rtems_chain_control *hash, uint32_t key1, uint32_t key2,
fat_file_fd_t *el);
static inline int
_hash_search(
rtems_filesystem_mount_table_entry_t *mt_entry,
- Chain_Control *hash,
+ rtems_chain_control *hash,
uint32_t key1,
uint32_t key2,
- fat_file_fd_t **ret
+ fat_file_fd_t **ret
);
static off_t
@@ -75,8 +75,7 @@ fat_file_lseek(
*
* PARAMETERS:
* mt_entry - mount table entry
- * cln - cluster num of the node
- * ofs - offset of the node
+ * pos - cluster and offset of the node
* fat_fd - placeholder for returned fat-file descriptor
*
* RETURNS:
@@ -86,8 +85,7 @@ fat_file_lseek(
int
fat_file_open(
rtems_filesystem_mount_table_entry_t *mt_entry,
- uint32_t cln,
- uint32_t ofs,
+ fat_dir_pos_t *dir_pos,
fat_file_fd_t **fat_fd
)
{
@@ -97,7 +95,7 @@ fat_file_open(
uint32_t key = 0;
/* construct key */
- key = fat_construct_key(mt_entry, cln, ofs);
+ key = fat_construct_key(mt_entry, &dir_pos->sname);
/* access "valid" hash table */
rc = _hash_search(mt_entry, fs_info->vhash, key, 0, &lfat_fd);
@@ -116,10 +114,14 @@ fat_file_open(
if ( lfat_fd == NULL )
rtems_set_errno_and_return_minus_one( ENOMEM );
+ memset(lfat_fd, 0, sizeof(fat_file_fd_t));
+
lfat_fd->links_num = 1;
lfat_fd->flags &= ~FAT_FILE_REMOVED;
lfat_fd->map.last_cln = FAT_UNDEFINED_VALUE;
+ lfat_fd->dir_pos = *dir_pos;
+
if ( rc != RC_OK )
lfat_fd->ino = key;
else
@@ -138,7 +140,6 @@ fat_file_open(
}
_hash_insert(fs_info->vhash, key, lfat_fd->ino, lfat_fd);
-
/*
* other fields of fat-file descriptor will be initialized on upper
* level
@@ -203,7 +204,7 @@ fat_file_close(
return rc;
}
- key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
+ key = fat_construct_key(mt_entry, &fat_fd->dir_pos.sname);
if (fat_fd->flags & FAT_FILE_REMOVED)
{
@@ -582,6 +583,8 @@ fat_file_extend(
}
}
+ fat_fd->fat_file_size = new_length;
+
return RC_OK;
}
@@ -736,7 +739,7 @@ fat_file_mark_removed(
fat_fs_info_t *fs_info = mt_entry->fs_info;
uint32_t key = 0;
- key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
+ key = fat_construct_key(mt_entry, &fat_fd->dir_pos.sname);
_hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
@@ -869,10 +872,10 @@ fat_file_size(
* None
*/
static inline void
-_hash_insert(Chain_Control *hash, uint32_t key1, uint32_t key2,
+_hash_insert(rtems_chain_control *hash, uint32_t key1, uint32_t key2,
fat_file_fd_t *el)
{
- _Chain_Append((hash) + ((key1) % FAT_HASH_MODULE), &(el)->link);
+ rtems_chain_append((hash) + ((key1) % FAT_HASH_MODULE), &(el)->link);
}
@@ -889,10 +892,10 @@ _hash_insert(Chain_Control *hash, uint32_t key1, uint32_t key2,
* None
*/
static inline void
-_hash_delete(Chain_Control *hash, uint32_t key1, uint32_t key2,
+_hash_delete(rtems_chain_control *hash, uint32_t key1, uint32_t key2,
fat_file_fd_t *el)
{
- _Chain_Extract(&(el)->link);
+ rtems_chain_extract(&(el)->link);
}
/* _hash_search --
@@ -912,20 +915,19 @@ _hash_delete(Chain_Control *hash, uint32_t key1, uint32_t key2,
static inline int
_hash_search(
rtems_filesystem_mount_table_entry_t *mt_entry,
- Chain_Control *hash,
+ rtems_chain_control *hash,
uint32_t key1,
uint32_t key2,
fat_file_fd_t **ret
)
{
- uint32_t mod = (key1) % FAT_HASH_MODULE;
- Chain_Node *the_node = ((Chain_Control *)((hash) + mod))->first;
+ uint32_t mod = (key1) % FAT_HASH_MODULE;
+ rtems_chain_node *the_node = ((rtems_chain_control *)((hash) + mod))->first;
- for ( ; !_Chain_Is_tail((hash) + mod, the_node) ; )
+ for ( ; !rtems_chain_is_tail((hash) + mod, the_node) ; )
{
fat_file_fd_t *ffd = (fat_file_fd_t *)the_node;
- uint32_t ck =
- fat_construct_key(mt_entry, ffd->info_cln, ffd->info_ofs);
+ uint32_t ck = fat_construct_key(mt_entry, &ffd->dir_pos.sname);
if ( (key1) == ck)
{
diff --git a/cpukit/libfs/src/dosfs/fat_file.h b/cpukit/libfs/src/dosfs/fat_file.h
index 48b89c604e..01ab73ef98 100644
--- a/cpukit/libfs/src/dosfs/fat_file.h
+++ b/cpukit/libfs/src/dosfs/fat_file.h
@@ -20,6 +20,8 @@
#include <time.h>
+#include "fat.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -57,30 +59,27 @@ typedef struct fat_file_map_s
*/
typedef struct fat_file_fd_s
{
- Chain_Node link; /*
- * fat-file descriptors organized into hash;
- * collision lists are handled via link
- * field
- */
- uint32_t links_num; /*
- * the number of fat_file_open call on
- * this fat-file
- */
- uint32_t ino; /* inode, file serial number :)))) */
- fat_file_type_t fat_file_type;
- uint32_t size_limit;
- uint32_t fat_file_size; /* length */
- uint32_t info_cln;
- uint32_t cln;
- uint16_t info_ofs;
- unsigned char first_char;
- uint8_t flags;
- fat_file_map_t map;
- time_t mtime;
+ rtems_chain_node link; /*
+ * fat-file descriptors organized into hash;
+ * collision lists are handled via link
+ * field
+ */
+ uint32_t links_num; /*
+ * the number of fat_file_open call on
+ * this fat-file
+ */
+ uint32_t ino; /* inode, file serial number :)))) */
+ fat_file_type_t fat_file_type;
+ uint32_t size_limit;
+ uint32_t fat_file_size; /* length */
+ uint32_t cln;
+ fat_dir_pos_t dir_pos;
+ uint8_t flags;
+ fat_file_map_t map;
+ time_t mtime;
} fat_file_fd_t;
-
#define FAT_FILE_REMOVED 0x01
#define FAT_FILE_IS_REMOVED(p)\
@@ -101,8 +100,8 @@ typedef struct fat_file_fd_s
#define FAT_ROOTDIR_CLUSTER_NUM 0x01
#define FAT_FD_OF_ROOT_DIR(fat_fd) \
- ((fat_fd->info_cln == FAT_ROOTDIR_CLUSTER_NUM ) && \
- (fat_fd->info_ofs == 0))
+ ((fat_fd->dir_pos.sname.cln == FAT_ROOTDIR_CLUSTER_NUM) && \
+ (fat_fd->dir_pos.sname.ofs == 0))
#define FAT_EOF 0x00
@@ -122,19 +121,17 @@ typedef struct fat_file_fd_s
static inline uint32_t
fat_construct_key(
rtems_filesystem_mount_table_entry_t *mt_entry,
- uint32_t cl,
- uint32_t ofs)
+ fat_pos_t *pos)
{
- return ( ((fat_cluster_num_to_sector512_num(mt_entry, cl) +
- (ofs >> FAT_SECTOR512_BITS)) << 4) +
- ((ofs >> 5) & (FAT_DIRENTRIES_PER_SEC512 - 1)) );
+ return ( ((fat_cluster_num_to_sector512_num(mt_entry, pos->cln) +
+ (pos->ofs >> FAT_SECTOR512_BITS)) << 4) +
+ ((pos->ofs >> 5) & (FAT_DIRENTRIES_PER_SEC512 - 1)) );
}
/* Prototypes for "fat-file" operations */
int
fat_file_open(rtems_filesystem_mount_table_entry_t *mt_entry,
- uint32_t cln,
- uint32_t ofs,
+ fat_dir_pos_t *dir_pos,
fat_file_fd_t **fat_fd);
int
diff --git a/cpukit/libfs/src/dosfs/msdos.h b/cpukit/libfs/src/dosfs/msdos.h
index a1afcba8dc..374210d9b7 100644
--- a/cpukit/libfs/src/dosfs/msdos.h
+++ b/cpukit/libfs/src/dosfs/msdos.h
@@ -84,8 +84,10 @@ typedef rtems_filesystem_node_types_t msdos_node_type_t;
#define MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE 32 /* 32 bytes */
#define MSDOS_DIR_NAME(x) (char *)((x) + 0)
+#define MSDOS_DIR_ENTRY_TYPE(x) (uint8_t *)((x) + 0)
#define MSDOS_DIR_ATTR(x) (uint8_t *)((x) + 11)
#define MSDOS_DIR_NT_RES(x) (uint8_t *)((x) + 12)
+#define MSDOS_DIR_LFN_CHECKSUM(x) (uint8_t *)((x) + 13)
#define MSDOS_DIR_CRT_TIME_TENTH(x) (uint8_t *)((x) + 13)
#define MSDOS_DIR_CRT_TIME(x) (uint16_t *)((x) + 14)
#define MSDOS_DIR_CRT_DATE(x) (uint16_t *)((x) + 16)
@@ -121,6 +123,19 @@ typedef rtems_filesystem_node_types_t msdos_node_type_t;
#define MSDOS_ATTR_VOLUME_ID 0x08
#define MSDOS_ATTR_DIRECTORY 0x10
#define MSDOS_ATTR_ARCHIVE 0x20
+#define MSDOS_ATTR_LFN (MSDOS_ATTR_READ_ONLY | \
+ MSDOS_ATTR_HIDDEN | \
+ MSDOS_ATTR_SYSTEM | \
+ MSDOS_ATTR_VOLUME_ID)
+#define MSDOS_ATTR_LFN_MASK (MSDOS_ATTR_READ_ONLY | \
+ MSDOS_ATTR_HIDDEN | \
+ MSDOS_ATTR_SYSTEM | \
+ MSDOS_ATTR_VOLUME_ID | \
+ MSDOS_ATTR_DIRECTORY | \
+ MSDOS_ATTR_ARCHIVE)
+
+#define MSDOS_LAST_LONG_ENTRY 0x40
+#define MSDOS_LAST_LONG_ENTRY_MASK 0x3F
#define MSDOS_DT_2SECONDS_MASK 0x1F /* seconds divided by 2 */
#define MSDOS_DT_2SECONDS_SHIFT 0
@@ -144,22 +159,35 @@ typedef rtems_filesystem_node_types_t msdos_node_type_t;
#define MSDOS_THIS_DIR_ENTRY_EMPTY 0xE5
#define MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY 0x00
+/*
+ * Number of characters per directory entry for a long filename.
+ */
+#define MSDOS_LFN_LEN_PER_ENTRY (13)
/*
* Macros for names parsing and formatting
*/
-#define msdos_is_valid_name_char(_ch) (1)
#define msdos_is_separator(_ch) rtems_filesystem_is_separator(_ch)
#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_LNF_LEN (255)
#define MSDOS_NAME_MAX MSDOS_SHORT_NAME_LEN
#define MSDOS_NAME_MAX_WITH_DOT (MSDOS_NAME_MAX + 1)
+#define MSDOS_NAME_MAX_LFN_WITH_DOT (260)
-#define MSDOS_DOT_NAME ". " /* ".", padded to MSDOS_NAME chars */
-#define MSDOS_DOTDOT_NAME ".. " /* "..", padded to MSDOS_NAME chars */
+
+extern const char const* MSDOS_DOT_NAME; /* ".", padded to MSDOS_NAME chars */
+extern const char const* MSDOS_DOTDOT_NAME; /* ".", padded to MSDOS_NAME chars */
+
+typedef enum msdos_name_types_e
+{
+ MSDOS_NAME_INVALID = 0, /* Unknown name type. Has invalid characters. */
+ MSDOS_NAME_SHORT, /* Name can be short. */
+ MSDOS_NAME_LONG /* Name is long; cannot be short. */
+} msdos_name_type_t;
typedef enum msdos_token_types_e
{
@@ -258,9 +286,9 @@ ssize_t msdos_file_write(
size_t count /* IN */
);
-off_t msdos_file_lseek(
+rtems_off64_t msdos_file_lseek(
rtems_libio_t *iop, /* IN */
- off_t offset, /* IN */
+ rtems_off64_t offset, /* IN */
int whence /* IN */
);
@@ -272,7 +300,7 @@ int msdos_file_stat(
int
msdos_file_ftruncate(
rtems_libio_t *iop, /* IN */
- off_t length /* IN */
+ rtems_off64_t length /* IN */
);
int msdos_file_sync(rtems_libio_t *iop);
@@ -285,6 +313,12 @@ int msdos_file_ioctl(
void *buffer /* IN */
);
+int
+msdos_dir_chmod(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ mode_t mode /* IN */
+);
+
int msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc /* IN */);
int msdos_file_link(
@@ -308,12 +342,18 @@ ssize_t msdos_dir_read(
size_t count /* IN */
);
-off_t msdos_dir_lseek(
+rtems_off64_t msdos_dir_lseek(
rtems_libio_t *iop, /* IN */
- off_t offset, /* IN */
+ rtems_off64_t offset, /* IN */
int whence /* IN */
);
+int
+msdos_file_chmod(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ mode_t mode /* IN */
+);
+
int msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc /* IN */);
int msdos_dir_sync(rtems_libio_t *iop);
@@ -324,31 +364,39 @@ int msdos_dir_stat(
);
int msdos_creat_node(rtems_filesystem_location_info_t *parent_loc,
- msdos_node_type_t type,
- char *name,
- mode_t mode,
- const fat_file_fd_t *link_fd);
+ msdos_node_type_t type,
+ const char *name,
+ int name_len,
+ mode_t mode,
+ const fat_file_fd_t *link_fd);
/* Misc prototypes */
-msdos_token_types_t msdos_get_token(const char *path,
- char *token,
- int *token_len);
+msdos_token_types_t msdos_get_token(const char *path,
+ const char **token,
+ int *token_len);
int msdos_find_name(
rtems_filesystem_location_info_t *parent_loc,
- char *name
+ const char *name,
+ int name_len
);
int msdos_get_name_node(
rtems_filesystem_location_info_t *parent_loc,
- char *name,
- fat_auxiliary_t *paux,
+ bool create_node,
+ const char *name,
+ int name_len,
+ msdos_name_type_t name_type,
+ fat_dir_pos_t *dir_pos,
char *name_dir_entry
);
int msdos_dir_info_remove(rtems_filesystem_location_info_t *pathloc);
-int msdos_filename_unix2dos(char *un, int unlen, char *dn);
+msdos_name_type_t msdos_long_to_short(const char *lfn, int lfn_len,
+ char* sfn, int sfn_len);
+
+int msdos_filename_unix2dos(const char *un, int unlen, char *dn);
void msdos_date_unix2dos(
unsigned int tsp, unsigned short *ddp,
@@ -368,9 +416,8 @@ int msdos_set_file_size(
int msdos_set_first_char4file_name(
rtems_filesystem_mount_table_entry_t *mt_entry,
- uint32_t cl,
- uint32_t ofs,
- unsigned char first_char
+ fat_dir_pos_t *dir_pos,
+ unsigned char first_char
);
int msdos_set_dir_wrt_time_and_date(
@@ -388,8 +435,11 @@ int msdos_dir_is_empty(
int msdos_find_name_in_fat_file(
rtems_filesystem_mount_table_entry_t *mt_entry,
fat_file_fd_t *fat_fd,
- char *name,
- fat_auxiliary_t *paux,
+ bool create_node,
+ const char *name,
+ int name_len,
+ msdos_name_type_t name_type,
+ fat_dir_pos_t *dir_pos,
char *name_dir_entry
);
@@ -397,14 +447,14 @@ int msdos_find_node_by_cluster_num_in_fat_file(
rtems_filesystem_mount_table_entry_t *mt_entry,
fat_file_fd_t *fat_fd,
uint32_t cl4find,
- fat_auxiliary_t *paux,
+ fat_dir_pos_t *dir_pos,
char *dir_entry
);
int msdos_get_dotdot_dir_info_cluster_num_and_offset(
rtems_filesystem_mount_table_entry_t *mt_entry,
uint32_t cln,
- fat_auxiliary_t *paux,
+ fat_dir_pos_t *dir_pos,
char *dir_entry
);
diff --git a/cpukit/libfs/src/dosfs/msdos_conv.c b/cpukit/libfs/src/dosfs/msdos_conv.c
index b30822600b..bcc27539f9 100644
--- a/cpukit/libfs/src/dosfs/msdos_conv.c
+++ b/cpukit/libfs/src/dosfs/msdos_conv.c
@@ -169,6 +169,39 @@ msdos_date_dos2unix(unsigned int dd, unsigned int dt)
}
static const uint8_t msdos_map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 00-07 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 08-0f */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 10-17 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 18-1f */
+ 0, '!', 0, '#', '$', '%', '&', '\'', /* 20-27 */
+ '(', ')', 0, '+', 0, '-', 0, 0, /* 28-2f */
+ '0', '1', '2', '3', '4', '5', '6', '7', /* 30-37 */
+ '8', '9', 0, 0, 0, 0, 0, 0, /* 38-3f */
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40-47 */
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 48-4f */
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 50-57 */
+ 'X', 'Y', 'Z', 0, 0, 0, '^', '_', /* 58-5f */
+ '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 60-67 */
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 68-6f */
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 70-77 */
+ 'X', 'Y', 'Z', '{', 0, '}', '~', 0, /* 78-7f */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 80-87 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 88-8f */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 90-97 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 98-9f */
+ 0, 0xad, 0xbd, 0x9c, 0xcf, 0xbe, 0xdd, 0xf5, /* a0-a7 */
+ 0xf9, 0xb8, 0xa6, 0xae, 0xaa, 0xf0, 0xa9, 0xee, /* a8-af */
+ 0xf8, 0xf1, 0xfd, 0xfc, 0xef, 0xe6, 0xf4, 0xfa, /* b0-b7 */
+ 0xf7, 0xfb, 0xa7, 0xaf, 0xac, 0xab, 0xf3, 0xa8, /* b8-bf */
+ 0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* c0-c7 */
+ 0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* c8-cf */
+ 0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0x9e, /* d0-d7 */
+ 0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0xe1, /* d8-df */
+ 0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* e0-e7 */
+ 0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* e8-ef */
+ 0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0xf6, /* f0-f7 */
+ 0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0x98, /* f8-ff */
+#if OLD_TABLE
/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -201,13 +234,14 @@ static const uint8_t msdos_map[] = {
/* E8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* F8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+#endif
};
/*
* Convert a unix filename to a DOS filename. Return -1 if wrong name is
* supplied.
*/
int
-msdos_filename_unix2dos(char *un, int unlen, char *dn)
+msdos_filename_unix2dos(const char *un, int unlen, char *dn)
{
int i;
uint8_t c;
@@ -233,6 +267,14 @@ msdos_filename_unix2dos(char *un, int unlen, char *dn)
return 0;
}
+ /*
+ * Remove any dots from the start of a file name.
+ */
+ while (unlen && (*un == '.')) {
+ un++;
+ unlen--;
+ }
+
/*
* Copy the unix filename into the dos filename string upto the end
* of string, a '.', or 8 characters. Whichever happens first stops
@@ -240,8 +282,9 @@ msdos_filename_unix2dos(char *un, int unlen, char *dn)
* upper case.
*/
for (i = 0; i <= 7 && unlen && (c = *un) && c != '.'; i++) {
- if ((dn[i] = msdos_map[c]) == 0)
- return -1;
+ if (msdos_map[c] == 0)
+ break;
+ dn[i] = msdos_map[c];
un++;
unlen--;
}
@@ -264,8 +307,9 @@ msdos_filename_unix2dos(char *un, int unlen, char *dn)
* Filenames in this form are probably inaccessable under dos.
*/
for (i = 8; i <= 10 && unlen && (c = *un); i++) {
- if ((dn[i] = msdos_map[c]) == 0)
- return -1;
+ if (msdos_map[c] == 0)
+ break;
+ dn[i] = msdos_map[c];
un++;
unlen--;
}
diff --git a/cpukit/libfs/src/dosfs/msdos_create.c b/cpukit/libfs/src/dosfs/msdos_create.c
index c790dd740f..bbdf137600 100644
--- a/cpukit/libfs/src/dosfs/msdos_create.c
+++ b/cpukit/libfs/src/dosfs/msdos_create.c
@@ -17,6 +17,7 @@
#include <errno.h>
#include <assert.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rtems/libio_.h>
@@ -29,7 +30,14 @@
#include "msdos.h"
/* msdos_creat_node --
- * Create a new node. If a new node is file, FAT 32 Bytes Directory
+ * Create a new node. Determine if the name is a long name. If long we to
+ * scan the directory to create a short entry.
+ *
+ *
+
+
+
+ * If a new node is file, FAT 32 Bytes Directory
* Entry Structure is initialized, free space is found in parent
* directory and structure is written to the disk. In case of directory,
* all above steps present and also new cluster is allocated for a
@@ -48,52 +56,55 @@
*
*/
int
-msdos_creat_node(
- rtems_filesystem_location_info_t *parent_loc,
- msdos_node_type_t type,
- char *name,
- mode_t mode,
- const fat_file_fd_t *link_fd
- )
+msdos_creat_node(rtems_filesystem_location_info_t *parent_loc,
+ msdos_node_type_t type,
+ const char *name,
+ int name_len,
+ mode_t mode,
+ const fat_file_fd_t *link_fd)
{
- int rc = RC_OK;
- ssize_t ret = 0;
- msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
- fat_file_fd_t *parent_fat_fd = parent_loc->node_access;
- fat_file_fd_t *fat_fd = NULL;
- time_t time_ret = 0;
- uint16_t time_val = 0;
- uint16_t date = 0;
- fat_auxiliary_t aux;
- char new_node [MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
- char dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
- char link_node [MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
- uint32_t sec = 0;
- uint32_t byte = 0;
-
- memset(new_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+ int rc = RC_OK;
+ ssize_t ret = 0;
+ msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
+ fat_file_fd_t *parent_fat_fd = parent_loc->node_access;
+ fat_file_fd_t *fat_fd = NULL;
+ time_t time_ret = 0;
+ uint16_t time_val = 0;
+ uint16_t date = 0;
+ fat_dir_pos_t dir_pos;
+ msdos_name_type_t name_type;
+ char short_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+ char dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
+ char link_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+ uint32_t sec = 0;
+ uint32_t byte = 0;
+
+ fat_dir_pos_init(&dir_pos);
+
+ memset(short_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
memset(dot_dotdot, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2);
- /* set up name */
- strncpy(MSDOS_DIR_NAME(new_node), name, MSDOS_NAME_MAX);
+ name_type = msdos_long_to_short (name, name_len,
+ MSDOS_DIR_NAME(short_node),
+ MSDOS_NAME_MAX);
/* fill reserved field */
- *MSDOS_DIR_NT_RES(new_node) = MSDOS_RES_NT_VALUE;
+ *MSDOS_DIR_NT_RES(short_node) = MSDOS_RES_NT_VALUE;
/* set up last write date and time */
time_ret = time(NULL);
if ( time_ret == -1 )
return -1;
- msdos_date_unix2dos(time_ret, &time_val, &date);
- *MSDOS_DIR_WRITE_TIME(new_node) = CT_LE_W(time_val);
- *MSDOS_DIR_WRITE_DATE(new_node) = CT_LE_W(date);
+ msdos_date_unix2dos(time_ret, &date, &time_val);
+ *MSDOS_DIR_WRITE_TIME(short_node) = CT_LE_W(time_val);
+ *MSDOS_DIR_WRITE_DATE(short_node) = CT_LE_W(date);
/* initialize directory/file size */
- *MSDOS_DIR_FILE_SIZE(new_node) = MSDOS_INIT_DIR_SIZE;
+ *MSDOS_DIR_FILE_SIZE(short_node) = MSDOS_INIT_DIR_SIZE;
- if (type == MSDOS_DIRECTORY){
- *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_DIRECTORY;
+ if (type == MSDOS_DIRECTORY) {
+ *MSDOS_DIR_ATTR(short_node) |= MSDOS_ATTR_DIRECTORY;
}
else if (type == MSDOS_HARD_LINK) {
/*
@@ -105,51 +116,52 @@ msdos_creat_node(
* read the original directory entry
*/
sec = fat_cluster_num_to_sector_num(parent_loc->mt_entry,
- link_fd->info_cln);
- sec += (link_fd->info_ofs >> fs_info->fat.vol.sec_log2);
- byte = (link_fd->info_ofs & (fs_info->fat.vol.bps - 1));
+ link_fd->dir_pos.sname.cln);
+ sec += (link_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
+ byte = (link_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1));
ret = _fat_block_read(parent_loc->mt_entry,
- sec, byte, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
+ sec, byte, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
link_node);
if (ret < 0) {
- return -1;
+ return -1;
}
/*
* copy various attributes
*/
- *MSDOS_DIR_ATTR(new_node) =*MSDOS_DIR_ATTR(link_node);
- *MSDOS_DIR_CRT_TIME_TENTH(new_node)=*MSDOS_DIR_CRT_TIME_TENTH(link_node);
- *MSDOS_DIR_CRT_TIME(new_node) =*MSDOS_DIR_CRT_TIME(link_node);
- *MSDOS_DIR_CRT_DATE(new_node) =*MSDOS_DIR_CRT_DATE(link_node);
+ *MSDOS_DIR_ATTR(short_node) =*MSDOS_DIR_ATTR(link_node);
+ *MSDOS_DIR_CRT_TIME_TENTH(short_node)=*MSDOS_DIR_CRT_TIME_TENTH(link_node);
+ *MSDOS_DIR_CRT_TIME(short_node) =*MSDOS_DIR_CRT_TIME(link_node);
+ *MSDOS_DIR_CRT_DATE(short_node) =*MSDOS_DIR_CRT_DATE(link_node);
/*
* copy/set "file size", "first cluster"
*/
- *MSDOS_DIR_FILE_SIZE(new_node) =*MSDOS_DIR_FILE_SIZE(link_node);
+ *MSDOS_DIR_FILE_SIZE(short_node) =*MSDOS_DIR_FILE_SIZE(link_node);
- *MSDOS_DIR_FIRST_CLUSTER_LOW(new_node) =
+ *MSDOS_DIR_FIRST_CLUSTER_LOW(short_node) =
*MSDOS_DIR_FIRST_CLUSTER_LOW(link_node);
- *MSDOS_DIR_FIRST_CLUSTER_HI(new_node) =
+ *MSDOS_DIR_FIRST_CLUSTER_HI(short_node) =
*MSDOS_DIR_FIRST_CLUSTER_HI(link_node);
/*
* set "archive bit" due to changes
*/
- *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
+ *MSDOS_DIR_ATTR(short_node) |= MSDOS_ATTR_ARCHIVE;
/*
* set "last access" date to today
*/
- *MSDOS_DIR_LAST_ACCESS_DATE(new_node) = CT_LE_W(date);
+ *MSDOS_DIR_LAST_ACCESS_DATE(short_node) = CT_LE_W(date);
}
else { /* regular file... */
- *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
+ *MSDOS_DIR_ATTR(short_node) |= MSDOS_ATTR_ARCHIVE;
}
/*
* find free space in the parent directory and write new initialized
* FAT 32 Bytes Directory Entry Structure to the disk
*/
- rc = msdos_get_name_node(parent_loc, NULL, &aux, new_node);
+ rc = msdos_get_name_node(parent_loc, true, name, name_len,
+ name_type, &dir_pos, short_node);
if ( rc != RC_OK )
return rc;
@@ -160,7 +172,7 @@ msdos_creat_node(
if (type == MSDOS_DIRECTORY)
{
/* open new directory as fat-file */
- rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
+ rc = fat_file_open(parent_loc->mt_entry, &dir_pos, &fat_fd);
if (rc != RC_OK)
goto err;
@@ -168,8 +180,6 @@ msdos_creat_node(
* we opened fat-file for node we just created, so initialize fat-file
* descritor
*/
- fat_fd->info_cln = aux.cln;
- fat_fd->info_ofs = aux.ofs;
fat_fd->fat_file_size = 0;
fat_fd->fat_file_type = FAT_DIRECTORY;
fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
@@ -178,9 +188,9 @@ msdos_creat_node(
* dot and dotdot entries are identical to new node except the
* names
*/
- memcpy(DOT_NODE_P(dot_dotdot), new_node,
+ memcpy(DOT_NODE_P(dot_dotdot), short_node,
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
- memcpy(DOTDOT_NODE_P(dot_dotdot), new_node,
+ memcpy(DOTDOT_NODE_P(dot_dotdot), short_node,
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
memcpy(MSDOS_DIR_NAME(DOT_NODE_P(dot_dotdot)), MSDOS_DOT_NAME,
MSDOS_NAME_MAX);
@@ -253,9 +263,8 @@ error:
fat_file_close(parent_loc->mt_entry, fat_fd);
err:
- /* mark 32bytes structure on the disk as free */
- msdos_set_first_char4file_name(parent_loc->mt_entry, aux.cln, aux.ofs,
- 0xE5);
+ /* mark the used 32bytes structure on the disk as free */
+ msdos_set_first_char4file_name(parent_loc->mt_entry, &dir_pos, 0xE5);
return rc;
}
@@ -287,21 +296,21 @@ err:
*/
int
msdos_file_link(rtems_filesystem_location_info_t *to_loc,
- rtems_filesystem_location_info_t *par_loc,
- const char *token
+ rtems_filesystem_location_info_t *par_loc,
+ const char *name
)
{
int rc = RC_OK;
rtems_status_code sc = RTEMS_SUCCESSFUL;
msdos_fs_info_t *fs_info = to_loc->mt_entry->fs_info;
fat_file_fd_t *to_fat_fd = to_loc->node_access;
- char new_name[ MSDOS_NAME_MAX + 1 ];
+ const char *token;
int len;
/*
* check spelling and format new node name
*/
- if (MSDOS_NAME != msdos_get_token(token, new_name, &len)) {
+ if (MSDOS_NAME != msdos_get_token(name, &token, &len)) {
rtems_set_errno_and_return_minus_one(ENAMETOOLONG);
}
/*
@@ -324,8 +333,8 @@ msdos_file_link(rtems_filesystem_location_info_t *to_loc,
* create new directory entry as "hard link",
* copying relevant info from existing file
*/
- rc = msdos_creat_node(par_loc,MSDOS_HARD_LINK,new_name,S_IFREG,
- to_loc->node_access);
+ rc = msdos_creat_node(par_loc,MSDOS_HARD_LINK,name,len,S_IFREG,
+ to_loc->node_access);
/*
* set file size and first cluster number of old entry to 0
*/
diff --git a/cpukit/libfs/src/dosfs/msdos_dir.c b/cpukit/libfs/src/dosfs/msdos_dir.c
index 92dbf0435f..b897a192e3 100644
--- a/cpukit/libfs/src/dosfs/msdos_dir.c
+++ b/cpukit/libfs/src/dosfs/msdos_dir.c
@@ -14,6 +14,7 @@
#include "config.h"
#endif
+#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
@@ -145,7 +146,7 @@ msdos_format_dirent_with_dot(char *dst,const char *src)
src_tmp = src;
len = i;
while (i-- > 0) {
- *dst++ = *src_tmp++;
+ *dst++ = tolower(*src_tmp++);
}
/*
* find last non-blank character of extension
@@ -164,7 +165,7 @@ msdos_format_dirent_with_dot(char *dst,const char *src)
len += i + 1; /* extension + dot */
src_tmp = src + MSDOS_SHORT_BASE_LEN;
while (i-- > 0) {
- *dst++ = *src_tmp++;
+ *dst++ = tolower(*src_tmp++);
len++;
}
}
@@ -210,6 +211,9 @@ msdos_dir_read(rtems_libio_t *iop, void *buffer, size_t count)
uint32_t j = 0, i = 0;
uint32_t bts2rd = 0;
uint32_t cur_cln = 0;
+ uint32_t lfn_start = FAT_FILE_SHORT_NAME;
+ uint8_t lfn_checksum = 0;
+ int lfn_entries = 0;
/*
* cast start and count - protect against using sizes that are not exact
@@ -253,80 +257,211 @@ msdos_dir_read(rtems_libio_t *iop, void *buffer, size_t count)
for (i = 0; i < ret; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
{
- if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ char* entry = (char*) fs_info->cl_buf + i;
+
+ /*
+ * Is this directory from here on empty ?
+ */
+ if ((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
{
rtems_semaphore_release(fs_info->vol_sema);
return cmpltd;
}
- /* have to look at the DIR_NAME as "raw" 8-bit data */
- if ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
- MSDOS_THIS_DIR_ENTRY_EMPTY)
+ /* Is the directory entry empty */
+ if ((*MSDOS_DIR_ENTRY_TYPE(entry)) == MSDOS_THIS_DIR_ENTRY_EMPTY)
continue;
- /*
- * skip active entries until get the entry to start from
- */
- if (start)
- {
- start--;
+ /* Is the directory entry empty a volume label */
+ if (((*MSDOS_DIR_ATTR(entry)) & MSDOS_ATTR_VOLUME_ID) &&
+ ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) != MSDOS_ATTR_LFN))
continue;
- }
/*
- * Move the entry to the return buffer
- *
- * unfortunately there is no method to extract ino except to
- * open fat-file descriptor :( ... so, open it
+ * Check the attribute to see if the entry is for a long file
+ * name.
*/
-
- /* get number of cluster we are working with */
- rc = fat_file_ioctl(iop->pathinfo.mt_entry, fat_fd, F_CLU_NUM,
- j * bts2rd, &cur_cln);
- if (rc != RC_OK)
+ if ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) ==
+ MSDOS_ATTR_LFN)
{
- rtems_semaphore_release(fs_info->vol_sema);
- return rc;
+ int o;
+ char* p;
+ int q;
+
+ /*
+ * Is this is the first entry of a LFN ?
+ */
+ if (lfn_start == FAT_FILE_SHORT_NAME)
+ {
+ /*
+ * The first entry must have the last long entry flag set.
+ */
+ if ((*MSDOS_DIR_ENTRY_TYPE(entry) &
+ MSDOS_LAST_LONG_ENTRY) == 0)
+ continue;
+
+ /*
+ * Remember the start location of the long file name.
+ */
+ lfn_start =
+ ((j * bts2rd) + i) / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
+
+ /*
+ * Get the number of entries so we can count down and
+ * also the checksum of the short entry.
+ */
+ lfn_entries = (*MSDOS_DIR_ENTRY_TYPE(entry) &
+ MSDOS_LAST_LONG_ENTRY_MASK);
+ lfn_checksum = *MSDOS_DIR_LFN_CHECKSUM(entry);
+ memset (tmp_dirent.d_name, 0, sizeof(tmp_dirent.d_name));
+ }
+
+ /*
+ * If the entry number or the check sum do not match
+ * forget this series of long directory entries. These could
+ * be orphaned entries depending on the history of the
+ * disk.
+ */
+ if ((lfn_entries != (*MSDOS_DIR_ENTRY_TYPE(entry) &
+ MSDOS_LAST_LONG_ENTRY_MASK)) ||
+ (lfn_checksum != *MSDOS_DIR_LFN_CHECKSUM(entry)))
+ {
+ lfn_start = FAT_FILE_SHORT_NAME;
+ continue;
+ }
+
+ /*
+ * Extract the file name into the directory entry. The data is
+ * stored in UNICODE characters (16bit). No translation is
+ * currently supported.
+ *
+ * The DOS maximum length is 255 characters without the
+ * trailing nul character. We need to range check the length to
+ * fit in the directory entry name field.
+ */
+
+ lfn_entries--;
+ p = entry + 1;
+ o = lfn_entries * MSDOS_LFN_LEN_PER_ENTRY;
+
+ for (q = 0; q < MSDOS_LFN_LEN_PER_ENTRY; q++)
+ {
+ if (o >= (sizeof(tmp_dirent.d_name) - 1))
+ break;
+
+ tmp_dirent.d_name[o++] = *p;
+
+ if (*p == '\0')
+ break;
+
+ switch (q)
+ {
+ case 4:
+ p += 5;
+ break;
+ case 10:
+ p += 4;
+ break;
+ default:
+ p += 2;
+ break;
+ }
+ }
}
-
- rc = fat_file_open(iop->pathinfo.mt_entry, cur_cln, i,
- &tmp_fat_fd);
- if (rc != RC_OK)
+ else
{
- rtems_semaphore_release(fs_info->vol_sema);
- return rc;
+ fat_dir_pos_t dir_pos;
+
+ /*
+ * Skip active entries until get the entry to start from.
+ */
+ if (start)
+ {
+ lfn_start = FAT_FILE_SHORT_NAME;
+ start--;
+ continue;
+ }
+
+ /*
+ * Move the entry to the return buffer
+ *
+ * unfortunately there is no method to extract ino except to
+ * open fat-file descriptor :( ... so, open it
+ */
+
+ /* get number of cluster we are working with */
+ rc = fat_file_ioctl(iop->pathinfo.mt_entry, fat_fd, F_CLU_NUM,
+ j * bts2rd, &cur_cln);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ fat_dir_pos_init(&dir_pos);
+ dir_pos.sname.cln = cur_cln;
+ dir_pos.sname.ofs = i;
+ rc = fat_file_open(iop->pathinfo.mt_entry, &dir_pos, &tmp_fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ /* fill in dirent structure */
+ /* XXX: from what and in what d_off should be computed ?! */
+ tmp_dirent.d_off = start + cmpltd;
+ tmp_dirent.d_reclen = sizeof(struct dirent);
+ tmp_dirent.d_ino = tmp_fat_fd->ino;
+
+ /*
+ * If a long file name check if the correct number of
+ * entries have been found and if the checksum is correct.
+ * If not return the short file name.
+ */
+ if (lfn_start != FAT_FILE_SHORT_NAME)
+ {
+ uint8_t cs = 0;
+ uint8_t* p = (uint8_t*) entry;
+ int i;
+
+ for (i = 0; i < 11; i++, p++)
+ cs = ((cs & 1) ? 0x80 : 0) + (cs >> 1) + *p;
+
+ if (lfn_entries || (lfn_checksum != cs))
+ lfn_start = FAT_FILE_SHORT_NAME;
+ }
+
+ if (lfn_start == FAT_FILE_SHORT_NAME)
+ {
+ /*
+ * 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, entry); /* src text */
+ }
+ else
+ {
+ tmp_dirent.d_namlen = strlen(tmp_dirent.d_name);
+ }
+
+ memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
+
+ iop->offset = iop->offset + sizeof(struct dirent);
+ cmpltd += (sizeof(struct dirent));
+ count -= (sizeof(struct dirent));
+
+ /* inode number extracted, close fat-file */
+ rc = fat_file_close(iop->pathinfo.mt_entry, tmp_fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
}
-
- tmp_fat_fd->info_cln = cur_cln;
- tmp_fat_fd->info_ofs = i;
-
- /* fill in dirent structure */
- /* XXX: from what and in what d_off should be computed ?! */
- tmp_dirent.d_off = start + cmpltd;
- tmp_dirent.d_reclen = sizeof(struct dirent);
- tmp_dirent.d_ino = tmp_fat_fd->ino;
- /*
- * 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,
- (char *) fs_info->cl_buf + i); /* src text */
- memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
-
- iop->offset = iop->offset + sizeof(struct dirent);
- cmpltd += (sizeof(struct dirent));
- count -= (sizeof(struct dirent));
-
- /* inode number extracted, close fat-file */
- rc = fat_file_close(iop->pathinfo.mt_entry, tmp_fat_fd);
- if (rc != RC_OK)
- {
- rtems_semaphore_release(fs_info->vol_sema);
- return rc;
- }
-
+
if (count <= 0)
break;
}
@@ -363,8 +498,8 @@ msdos_dir_read(rtems_libio_t *iop, void *buffer, size_t count)
* RC_OK on success, or -1 if error occured (errno
* set apropriately).
*/
-off_t
-msdos_dir_lseek(rtems_libio_t *iop, off_t offset, int whence)
+rtems_off64_t
+msdos_dir_lseek(rtems_libio_t *iop, rtems_off64_t offset, int whence)
{
switch (whence)
{
@@ -471,6 +606,24 @@ msdos_dir_sync(rtems_libio_t *iop)
return rc;
}
+/* msdos_dir_chmod --
+ * Change the attributes of the directory. This currently does
+ * nothing and returns no error.
+ *
+ * PARAMETERS:
+ * pathloc - node description
+ * mode - the new mode
+ *
+ * RETURNS:
+ * RC_OK always
+ */
+int
+msdos_dir_chmod(rtems_filesystem_location_info_t *pathloc,
+ mode_t mode)
+{
+ return RC_OK;
+}
+
/* msdos_dir_rmnod --
* Remove directory node.
*
@@ -498,7 +651,7 @@ msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc)
rtems_set_errno_and_return_minus_one(EIO);
/*
- * We deny attemp to delete open directory (if directory is current
+ * We deny attempts to delete open directory (if directory is current
* directory we assume it is open one)
*/
if (fat_fd->links_num > 1)
@@ -538,8 +691,7 @@ msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc)
*/
/* mark file removed */
- rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
- fat_fd->info_ofs,
+ rc = msdos_set_first_char4file_name(pathloc->mt_entry, &fat_fd->dir_pos,
MSDOS_THIS_DIR_ENTRY_EMPTY);
if (rc != RC_OK)
{
diff --git a/cpukit/libfs/src/dosfs/msdos_eval.c b/cpukit/libfs/src/dosfs/msdos_eval.c
index 81cae010ad..5eabedb2a4 100644
--- a/cpukit/libfs/src/dosfs/msdos_eval.c
+++ b/cpukit/libfs/src/dosfs/msdos_eval.c
@@ -82,9 +82,9 @@ msdos_eval_path(
fat_file_fd_t *fat_fd = NULL;
rtems_filesystem_location_info_t newloc;
int i = 0;
- int len = 0;
+ int token_len = 0;
msdos_token_types_t type = MSDOS_CURRENT_DIR;
- char token[MSDOS_NAME_MAX + 1];
+ const char *token;
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
@@ -106,8 +106,8 @@ msdos_eval_path(
while ((type != MSDOS_NO_MORE_PATH) && (type != MSDOS_INVALID_TOKEN))
{
- type = msdos_get_token(&pathname[i], token, &len);
- i += len;
+ type = msdos_get_token(&pathname[i], &token, &token_len);
+ i += token_len;
fat_fd = pathloc->node_access;
@@ -149,13 +149,13 @@ msdos_eval_path(
goto err;
rtems_semaphore_release(fs_info->vol_sema);
- return (*pathloc->ops->evalpath_h)(&(pathname[i-len]),
+ return (*pathloc->ops->evalpath_h)(&(pathname[i-token_len]),
flags, pathloc);
}
}
else
{
- rc = msdos_find_name(pathloc, token);
+ rc = msdos_find_name(pathloc, token, token_len);
if (rc != RC_OK)
{
if (rc == MSDOS_NAME_NOT_FOUND_ERR)
@@ -183,7 +183,7 @@ msdos_eval_path(
* Otherwise find the token name in the present location and
* set the node access to the point we have found.
*/
- rc = msdos_find_name(pathloc, token);
+ rc = msdos_find_name(pathloc, token, token_len);
if (rc != RC_OK)
{
if (rc == MSDOS_NAME_NOT_FOUND_ERR)
@@ -264,8 +264,8 @@ msdos_eval4make(
rtems_filesystem_location_info_t newloc;
msdos_token_types_t type;
int i = 0;
- int len;
- char token[ MSDOS_NAME_MAX + 1 ];
+ int token_len;
+ const char *token;
bool done = false;
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
@@ -288,8 +288,8 @@ msdos_eval4make(
while (!done)
{
- type = msdos_get_token(&path[i], token, &len);
- i += len;
+ type = msdos_get_token(&path[i], &token, &token_len);
+ i += token_len;
fat_fd = pathloc->node_access;
switch (type)
@@ -330,13 +330,13 @@ msdos_eval4make(
goto err;
rtems_semaphore_release(fs_info->vol_sema);
- return (*pathloc->ops->evalformake_h)(&path[i-len],
+ return (*pathloc->ops->evalformake_h)(&path[i-token_len],
pathloc, name);
}
}
else
{
- rc = msdos_find_name(pathloc, token);
+ rc = msdos_find_name(pathloc, token, token_len);
if (rc != RC_OK)
{
if (rc == MSDOS_NAME_NOT_FOUND_ERR)
@@ -361,10 +361,10 @@ msdos_eval4make(
}
/*
- * Otherwise find the token name in the present location and
+ * Otherwise find the token name in the present location and
* set the node access to the point we have found.
*/
- rc = msdos_find_name(pathloc, token);
+ rc = msdos_find_name(pathloc, token, token_len);
if (rc)
{
if (rc != MSDOS_NAME_NOT_FOUND_ERR)
@@ -396,7 +396,7 @@ msdos_eval4make(
}
}
- *name = &path[i - len];
+ *name = &path[i - token_len];
/*
* We have evaluated the path as far as we can.
diff --git a/cpukit/libfs/src/dosfs/msdos_file.c b/cpukit/libfs/src/dosfs/msdos_file.c
index 471d4a04dc..817897f845 100644
--- a/cpukit/libfs/src/dosfs/msdos_file.c
+++ b/cpukit/libfs/src/dosfs/msdos_file.c
@@ -223,8 +223,8 @@ msdos_file_write(rtems_libio_t *iop,const void *buffer, size_t count)
* new offset on success, or -1 if error occured (errno set
* appropriately).
*/
-off_t
-msdos_file_lseek(rtems_libio_t *iop, off_t offset, int whence)
+rtems_off64_t
+msdos_file_lseek(rtems_libio_t *iop, rtems_off64_t offset, int whence)
{
int rc = RC_OK;
rtems_status_code sc = RTEMS_SUCCESSFUL;
@@ -302,7 +302,7 @@ msdos_file_stat(
* RC_OK on success, or -1 if error occured (errno set appropriately).
*/
int
-msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
+msdos_file_ftruncate(rtems_libio_t *iop, rtems_off64_t length)
{
int rc = RC_OK;
rtems_status_code sc = RTEMS_SUCCESSFUL;
@@ -444,6 +444,24 @@ msdos_file_ioctl(rtems_libio_t *iop,uint32_t command, void *buffer)
return rc;
}
+/* msdos_file_chmod --
+ * Change the attributes of the file. This currently does
+ * nothing and returns no error.
+ *
+ * PARAMETERS:
+ * pathloc - node description
+ * mode - the new mode
+ *
+ * RETURNS:
+ * RC_OK always
+ */
+int
+msdos_file_chmod(rtems_filesystem_location_info_t *pathloc,
+ mode_t mode)
+{
+ return RC_OK;
+}
+
/* msdos_file_rmnod --
* Remove node associated with a file - set up first name character to
* predefined value(and write it to the disk), and mark fat-file which
@@ -469,8 +487,8 @@ msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc)
rtems_set_errno_and_return_minus_one(EIO);
/* mark file removed */
- rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
- fat_fd->info_ofs,
+ rc = msdos_set_first_char4file_name(pathloc->mt_entry,
+ &fat_fd->dir_pos,
MSDOS_THIS_DIR_ENTRY_EMPTY);
if (rc != RC_OK)
{
diff --git a/cpukit/libfs/src/dosfs/msdos_format.c b/cpukit/libfs/src/dosfs/msdos_format.c
index 1d012c29f5..7e72b5e089 100644
--- a/cpukit/libfs/src/dosfs/msdos_format.c
+++ b/cpukit/libfs/src/dosfs/msdos_format.c
@@ -31,6 +31,7 @@
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
+#include <stdio.h>
#include <ctype.h>
#include <assert.h>
@@ -65,6 +66,58 @@ typedef struct {
uint32_t vol_id;
} msdos_format_param_t;
+/*
+ * Formatted output.
+ */
+static void
+msdos_format_printf (const msdos_format_request_param_t *rqdata,
+ int info_level,
+ const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ if (rqdata->info_level >= info_level)
+ {
+ vfprintf (stdout, format, args);
+ fflush (stdout);
+ }
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static int msdos_format_read_sec
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| function to read a sector |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ int fd, /* file descriptor index */
+ uint32_t start_sector, /* sector number to write to */
+ uint32_t sector_size, /* size of sector */
+ char *buffer /* buffer with read data into */
+ )
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0, if success, -1 and errno if failed |
+\*=========================================================================*/
+{
+ int ret_val = 0;
+
+ if (0 > lseek(fd,((off_t)start_sector)*sector_size,SEEK_SET)) {
+ ret_val = -1;
+ }
+ if (ret_val == 0) {
+ if (0 > read(fd,buffer,sector_size)) {
+ ret_val = -1;
+ }
+ }
+
+ return ret_val;
+}
+
/*=========================================================================*\
| Function: |
\*-------------------------------------------------------------------------*/
@@ -100,7 +153,7 @@ static int msdos_format_write_sec
return ret_val;
}
-/*=========================================================================*\
+/*=========================================================================* \
| Function: |
\*-------------------------------------------------------------------------*/
static int msdos_format_fill_sectors
@@ -111,6 +164,7 @@ static int msdos_format_fill_sectors
+---------------------------------------------------------------------------+
| Input Parameters: |
\*-------------------------------------------------------------------------*/
+ const msdos_format_request_param_t *rqdata,
int fd, /* file descriptor index */
uint32_t start_sector, /* sector number to fill to */
uint32_t sector_cnt, /* number of sectors to fill to */
@@ -124,7 +178,9 @@ static int msdos_format_fill_sectors
{
int ret_val = 0;
char *fill_buffer = NULL;
-
+ uint32_t total_sectors = sector_cnt;
+ int last_percent = -1;
+
/*
* allocate and fill buffer
*/
@@ -138,15 +194,31 @@ static int msdos_format_fill_sectors
memset(fill_buffer,fill_byte,sector_size);
}
}
+
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+ "Filling : ");
/*
* write to consecutive sectors
*/
while ((ret_val == 0) &&
(sector_cnt > 0)) {
+ int percent = (sector_cnt * 100) / total_sectors;
+ if (percent != last_percent) {
+ if ((percent & 1) == 0)
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL, ".");
+ last_percent = percent;
+ }
ret_val = msdos_format_write_sec(fd,start_sector,sector_size,fill_buffer);
start_sector++;
sector_cnt--;
}
+
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL, "\n");
+
+ if (ret_val)
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_INFO,
+ "filling error on sector: %d\n", start_sector);
+
/*
* cleanup
*/
@@ -311,7 +383,8 @@ static int msdos_format_determine_fmt_params
uint32_t fatdata_sect_cnt;
uint32_t onebit;
uint32_t sectors_per_cluster_adj = 0;
-
+ uint64_t total_size = 0;
+
memset(fmt_params,0,sizeof(*fmt_params));
/*
* this one is fixed in this implementation.
@@ -320,6 +393,10 @@ static int msdos_format_determine_fmt_params
if (ret_val == 0) {
fmt_params->bytes_per_sector = dd->block_size;
fmt_params->totl_sector_cnt = dd->size;
+ total_size = dd->block_size * dd->size;
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+ "bytes per sector: %d\ntotal sectors: %d\ntotal size: %lu\n",
+ dd->block_size, dd->size, total_size);
}
/*
* determine number of FATs
@@ -336,6 +413,11 @@ static int msdos_format_determine_fmt_params
ret_val = EINVAL;
}
}
+
+ if (ret_val == 0)
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+ "number of fats: %d\n", fmt_params->fat_num);
+
/*
* Now we get sort of a loop when determining things:
* The FAT type (FAT12/16/32) is determined ONLY from the
@@ -396,21 +478,26 @@ static int msdos_format_determine_fmt_params
* are a compromise concerning capacity and efficency
*/
if (fmt_params->totl_sector_cnt
- < ((uint32_t)FAT_FAT12_MAX_CLN)*8) {
- fmt_params->fattype = FAT_FAT12;
- /* start trying with small clusters */
- fmt_params->sectors_per_cluster = 2;
+ < ((uint32_t)FAT_FAT12_MAX_CLN)*8) {
+ fmt_params->fattype = FAT_FAT12;
+ /* start trying with small clusters */
+ fmt_params->sectors_per_cluster = 2;
}
else if (fmt_params->totl_sector_cnt
- < ((uint32_t)FAT_FAT16_MAX_CLN)*32) {
- fmt_params->fattype = FAT_FAT16;
- /* start trying with small clusters */
- fmt_params->sectors_per_cluster = 2;
+ < ((uint32_t)FAT_FAT16_MAX_CLN)*32) {
+ fmt_params->fattype = FAT_FAT16;
+ /* start trying with small clusters */
+ fmt_params->sectors_per_cluster = 2;
}
else {
- fmt_params->fattype = FAT_FAT32;
- /* start trying with small clusters... */
- fmt_params->sectors_per_cluster = 1;
+ uint32_t gigs = (total_size + (1024 * 1024 * 1024)) / (1024 * 1024 * 1024);
+ int b;
+ fmt_params->fattype = FAT_FAT32;
+ /* scale with the size of disk... */
+ for (b = 31; b > 0; b--)
+ if ((gigs & (1 << b)) != 0)
+ break;
+ fmt_params->sectors_per_cluster = 1 << b;
}
}
/*
@@ -428,7 +515,7 @@ static int msdos_format_determine_fmt_params
* sectors_per_cluster*bytes_per_sector must not be bigger than 32K
*/
for (onebit = 128;onebit >= 1;onebit = onebit>>1) {
- if (fmt_params->sectors_per_cluster > onebit) {
+ if (fmt_params->sectors_per_cluster >= onebit) {
fmt_params->sectors_per_cluster = onebit;
if (fmt_params->sectors_per_cluster
<= 32768L/fmt_params->bytes_per_sector) {
@@ -440,6 +527,9 @@ static int msdos_format_determine_fmt_params
}
if (ret_val == 0) {
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+ "sectors per cluster: %d\n", fmt_params->sectors_per_cluster);
+
if (fmt_params->fattype == FAT_FAT32) {
/* recommended: for FAT32, always set reserved sector count to 32 */
fmt_params->rsvd_sector_cnt = 32;
@@ -649,9 +739,15 @@ static int msdos_format_gen_mbr
total_sectors_num32 = fmt_params->totl_sector_cnt;
}
/*
- * finally we are there: let's fill in the values into the MBR
+ * finally we are there: let's fill in the values into the MBR
+ * but first clear the MRB leaving the partition table.
*/
- memset(mbr,0,FAT_TOTAL_MBR_SIZE);
+#define RTEMS_IDE_PARTITION_TABLE_OFFSET 0x1be
+#define RTEMS_IDE_PARTITION_TABLE_SIZE (4 * 16)
+ memset(mbr,0,RTEMS_IDE_PARTITION_TABLE_OFFSET);
+ memset(mbr + RTEMS_IDE_PARTITION_TABLE_OFFSET + RTEMS_IDE_PARTITION_TABLE_SIZE,
+ 0,
+ FAT_TOTAL_MBR_SIZE - (RTEMS_IDE_PARTITION_TABLE_OFFSET + RTEMS_IDE_PARTITION_TABLE_SIZE));
/*
* FIXME: fill jmpBoot and Boot code...
* with 0xEB,....
@@ -672,9 +768,9 @@ static int msdos_format_gen_mbr
FAT_SET_BR_TOTAL_SECTORS_NUM16(mbr , total_sectors_num16);
FAT_SET_BR_MEDIA(mbr , fmt_params->media_code);
- FAT_SET_BR_SECTORS_PER_TRACK(mbr , 0); /* only needed for INT13... */
- FAT_SET_BR_NUMBER_OF_HEADS(mbr , 0); /* only needed for INT13... */
- FAT_SET_BR_HIDDEN_SECTORS(mbr , 0); /* only needed for INT13... */
+ FAT_SET_BR_SECTORS_PER_TRACK(mbr , 255); /* only needed for INT13... */
+ FAT_SET_BR_NUMBER_OF_HEADS(mbr , 6); /* only needed for INT13... */
+ FAT_SET_BR_HIDDEN_SECTORS(mbr , 1); /* only needed for INT13... */
FAT_SET_BR_TOTAL_SECTORS_NUM32(mbr , total_sectors_num32);
if (fmt_params->fattype != FAT_FAT32) {
@@ -749,7 +845,6 @@ static int msdos_format_gen_fsinfo
| 0, if success, -1 and errno if failed |
\*=========================================================================*/
{
-
/*
* clear fsinfo sector data
*/
@@ -760,9 +855,9 @@ static int msdos_format_gen_fsinfo
FAT_SET_FSINFO_LEAD_SIGNATURE (fsinfo,FAT_FSINFO_LEAD_SIGNATURE_VALUE );
FAT_SET_FSINFO_STRUC_SIGNATURE(fsinfo,FAT_FSINFO_STRUC_SIGNATURE_VALUE);
FAT_SET_FSINFO_TRAIL_SIGNATURE(fsinfo,FAT_FSINFO_TRAIL_SIGNATURE_VALUE);
-/*
- * write "empty" values for free cluster count and next cluster number
- */
+ /*
+ * write "empty" values for free cluster count and next cluster number
+ */
FAT_SET_FSINFO_FREE_CLUSTER_COUNT(fsinfo+FAT_FSI_INFO,
0xffffffff);
FAT_SET_FSINFO_NEXT_FREE_CLUSTER (fsinfo+FAT_FSI_INFO,
@@ -800,9 +895,13 @@ int msdos_format
int i;
msdos_format_param_t fmt_params;
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_INFO,
+ "formating: %s\n", devname);
/*
* sanity check on device
*/
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+ "stat check: %s\n", devname);
if (ret_val == 0) {
rc = stat(devname, &stat_buf);
ret_val = rc;
@@ -828,7 +927,9 @@ int msdos_format
* open device for writing
*/
if (ret_val == 0) {
- fd = open(devname, O_WRONLY);
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+ "open device\n");
+ fd = open(devname, O_RDWR);
if (fd == -1)
{
ret_val= -1;
@@ -848,7 +949,8 @@ int msdos_format
(rqdata != NULL) &&
!(rqdata->quick_format)) {
ret_val = msdos_format_fill_sectors
- (fd,
+ (rqdata,
+ fd,
0, /* start sector */
fmt_params.totl_sector_cnt, /* sector count */
fmt_params.bytes_per_sector,
@@ -858,27 +960,45 @@ int msdos_format
* create master boot record
*/
if (ret_val == 0) {
- ret_val = msdos_format_gen_mbr(tmp_sec,&fmt_params);
- }
- /*
- * write master boot record to disk
- * also write copy of MBR to disk
- */
- if (ret_val == 0) {
- ret_val = msdos_format_write_sec(fd,
- 0,
- fmt_params.bytes_per_sector,
- tmp_sec);
- }
- if ((ret_val == 0) &&
- (fmt_params.mbr_copy_sec != 0)) {
/*
- * write copy of MBR
+ * Read the current MBR to obtain the partition table.
*/
- ret_val = msdos_format_write_sec(fd,
- fmt_params.mbr_copy_sec ,
- fmt_params.bytes_per_sector,
- tmp_sec);
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+ "read MRB sector\n");
+ ret_val = msdos_format_read_sec(fd,
+ 0,
+ fmt_params.bytes_per_sector,
+ tmp_sec);
+ if (ret_val == 0) {
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+ "generate MRB sector\n");
+ ret_val = msdos_format_gen_mbr(tmp_sec,&fmt_params);
+ }
+
+ /*
+ * write master boot record to disk
+ * also write copy of MBR to disk
+ */
+ if (ret_val == 0) {
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+ "write MRB sector\n");
+ ret_val = msdos_format_write_sec(fd,
+ 0,
+ fmt_params.bytes_per_sector,
+ tmp_sec);
+ }
+ if ((ret_val == 0) &&
+ (fmt_params.mbr_copy_sec != 0)) {
+ /*
+ * write copy of MBR
+ */
+ msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+ "write back up MRB sector\n");
+ ret_val = msdos_format_write_sec(fd,
+ fmt_params.mbr_copy_sec ,
+ fmt_params.bytes_per_sector,
+ tmp_sec);
+ }
}
/*
* for FAT32: initialize info sector on disk
@@ -903,7 +1023,8 @@ int msdos_format
*/
if (ret_val == 0) {
ret_val = msdos_format_fill_sectors
- (fd,
+ (rqdata,
+ fd,
fmt_params.rsvd_sector_cnt, /* start sector */
fmt_params.fat_num*fmt_params.sectors_per_fat,/* sector count */
fmt_params.bytes_per_sector,
@@ -915,7 +1036,8 @@ int msdos_format
*/
if (ret_val == 0) {
ret_val = msdos_format_fill_sectors
- (fd,
+ (rqdata,
+ fd,
fmt_params.root_dir_start_sec, /* start sector */
fmt_params.root_dir_fmt_sec_cnt, /* sector count */
fmt_params.bytes_per_sector,
diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_dir.c b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
index e42f72ab16..66e4e8c531 100644
--- a/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
+++ b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
@@ -26,7 +26,7 @@ const rtems_filesystem_file_handlers_r msdos_dir_handlers = {
NULL, /* msdos_dir_ioctl */
msdos_dir_lseek,
msdos_dir_stat,
- NULL,
+ msdos_dir_chmod,
NULL, /* msdos_dir_ftruncate */
NULL,
msdos_dir_sync,
diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_file.c b/cpukit/libfs/src/dosfs/msdos_handlers_file.c
index 6ad6d1850d..5dd89849c7 100644
--- a/cpukit/libfs/src/dosfs/msdos_handlers_file.c
+++ b/cpukit/libfs/src/dosfs/msdos_handlers_file.c
@@ -26,7 +26,7 @@ const rtems_filesystem_file_handlers_r msdos_file_handlers = {
msdos_file_ioctl,
msdos_file_lseek,
msdos_file_stat,
- NULL,
+ msdos_file_chmod,
msdos_file_ftruncate,
NULL,
msdos_file_sync,
diff --git a/cpukit/libfs/src/dosfs/msdos_init.c b/cpukit/libfs/src/dosfs/msdos_init.c
index 8642cead0a..1af639c286 100644
--- a/cpukit/libfs/src/dosfs/msdos_init.c
+++ b/cpukit/libfs/src/dosfs/msdos_init.c
@@ -42,7 +42,8 @@ const rtems_filesystem_operations_table msdos_ops = {
};
/* msdos_initialize --
- * MSDOS filesystem initialization
+ * MSDOS filesystem initialization. Called when mounting an
+ * MSDOS filesystem.
*
* PARAMETERS:
* temp_mt_entry - mount table entry
diff --git a/cpukit/libfs/src/dosfs/msdos_initsupp.c b/cpukit/libfs/src/dosfs/msdos_initsupp.c
index 42495c7622..72e762d081 100644
--- a/cpukit/libfs/src/dosfs/msdos_initsupp.c
+++ b/cpukit/libfs/src/dosfs/msdos_initsupp.c
@@ -57,6 +57,7 @@ msdos_initialize_support(
rtems_status_code sc = RTEMS_SUCCESSFUL;
msdos_fs_info_t *fs_info = NULL;
fat_file_fd_t *fat_fd = NULL;
+ fat_dir_pos_t root_pos;
uint32_t cl_buf_size;
fs_info = (msdos_fs_info_t *)calloc(1, sizeof(msdos_fs_info_t));
@@ -79,7 +80,9 @@ msdos_initialize_support(
* open fat-file which correspondes to root directory
* (so inode number 0x00000010 is always used for root directory)
*/
- rc = fat_file_open(temp_mt_entry, FAT_ROOTDIR_CLUSTER_NUM, 0, &fat_fd);
+ fat_dir_pos_init(&root_pos);
+ root_pos.sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
+ rc = fat_file_open(temp_mt_entry, &root_pos, &fat_fd);
if (rc != RC_OK)
{
fat_shutdown_drive(temp_mt_entry);
@@ -90,8 +93,6 @@ msdos_initialize_support(
/* again: unfortunately "fat-file" is just almost fat file :( */
fat_fd->fat_file_type = FAT_DIRECTORY;
fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
- fat_fd->info_cln = FAT_ROOTDIR_CLUSTER_NUM;
- fat_fd->info_ofs = 0;
fat_fd->cln = fs_info->fat.vol.rdir_cl;
fat_fd->map.file_cln = 0;
diff --git a/cpukit/libfs/src/dosfs/msdos_misc.c b/cpukit/libfs/src/dosfs/msdos_misc.c
index abf5eedbd4..17928077e4 100644
--- a/cpukit/libfs/src/dosfs/msdos_misc.c
+++ b/cpukit/libfs/src/dosfs/msdos_misc.c
@@ -18,6 +18,7 @@
#endif
#include <stdlib.h>
+#include <ctype.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
@@ -30,6 +31,189 @@
#include "msdos.h"
+
+#include <stdio.h>
+
+/*
+ * External strings. Saves spave this way.
+ */
+const char const* MSDOS_DOT_NAME = ". ";
+const char const* MSDOS_DOTDOT_NAME = ".. ";
+
+/* msdos_is_valid_name_char --
+ * Routine to check the character in a file or directory name.
+ * The characters support in the short file name are letters,
+ * digits, or characters with code points values greater than
+ * 127 (not sure what this last is) plus the following special
+ * characters "$%'-_@~`!(){}^#&". The must be uppercase.
+ *
+ * The following 6 characters are allowed in a long names,
+ * " +,;=[]" including a space and lower case letters.
+ *
+ * PARAMETERS:
+ * ch - character to check.
+ *
+ * RETURNS:
+ * MSDOS_NAME_INVALID - Not valid in a long or short name.
+ * MSDOS_NAME_SHORT - Valid in a short name or long name.
+ * MSDOS_NAME_LONG - Valid in a long name only.
+ *
+ */
+static msdos_name_type_t
+msdos_is_valid_name_char(const char ch)
+{
+ if (strchr(" +,;=[]", ch) != NULL)
+ return MSDOS_NAME_LONG;
+
+ if ((ch == '.') || isalnum(ch) ||
+ (strchr("$%'-_@~`!(){}^#&", ch) != NULL))
+ return MSDOS_NAME_SHORT;
+
+ return MSDOS_NAME_INVALID;
+}
+
+/* msdos_short_hex_number --
+ * Routine to set the hex number in the SFN.
+ *
+ * PARAMETERS:
+ * name - name to change
+ * num - number to set
+ *
+ * RETURNS:
+ * nothing
+ *
+ */
+static void
+msdos_short_name_hex(char* sfn, int num)
+{
+ static const char* hex = "0123456789ABCDEF";
+ char* c = MSDOS_DIR_NAME(sfn);
+ int i;
+ for (i = 0; i < 3; i++, c++)
+ if ((*c == ' ') || (*c == '.'))
+ *c = '~';
+ *c++ = '~';
+ for (i = 0; i < 4; i++, c++)
+ *c = hex[(num >> ((3 - i) * 4)) & 0xf];
+}
+
+/* msdos_name_type --
+ * Routine the type of file name.
+ *
+ * PARAMETERS:
+ * name - name to check
+ *
+ * RETURNS:
+ * true the name is long, else the name is short.
+ *
+ */
+static msdos_name_type_t
+msdos_name_type(const char *name, int name_len)
+{
+ bool dot = false;
+ bool lowercase = false;
+ bool uppercase = false;
+ int dot_at = 0;
+ int count = 0;
+
+ while (*name && (count < name_len))
+ {
+ msdos_name_type_t type = msdos_is_valid_name_char(*name);
+
+ if ((type == MSDOS_NAME_INVALID) || (type == MSDOS_NAME_LONG))
+ return type;
+
+ if (dot)
+ {
+ if ((*name == '.') || ((count - dot_at) > 3))
+ return MSDOS_NAME_LONG;
+ }
+ else
+ {
+ if (count >= 8)
+ return MSDOS_NAME_LONG;
+ }
+
+ if (*name == '.')
+ {
+ dot = true;
+ dot_at = count;
+ }
+ else if ((*name >= 'A') && (*name <= 'Z'))
+ uppercase = true;
+ else if ((*name >= 'a') && (*name <= 'z'))
+ lowercase = true;
+
+ count++;
+ name++;
+ }
+
+ if (lowercase && uppercase)
+ return MSDOS_NAME_LONG;
+
+ return MSDOS_NAME_SHORT;
+}
+
+/* msdos_long_to_short --
+ * Routine to creates a short name from a long. Start the end of the
+ *
+ * PARAMETERS:
+ * name - name to check
+ *
+ * RETURNS:
+ * true the name is long, else the name is short.
+ *
+ */
+msdos_name_type_t
+msdos_long_to_short(const char *lfn, int lfn_len, char* sfn, int sfn_len)
+{
+ msdos_name_type_t type;
+ int i;
+
+ /*
+ * Fill with spaces. This is how a short directory entry is padded.
+ */
+ memset (sfn, ' ', sfn_len);
+
+ /*
+ * Handle '.' and '..' specially.
+ */
+ if ((lfn[0] == '.') && (lfn_len == 1))
+ {
+ sfn[0] = '.';
+ return MSDOS_NAME_SHORT;
+ }
+
+ if ((lfn[0] == '.') && (lfn[1] == '.') && (lfn_len == 2))
+ {
+ sfn[0] = sfn[1] = '.';
+ return MSDOS_NAME_SHORT;
+ }
+
+ /*
+ * Filenames with only blanks and dots are not allowed!
+ */
+ for (i = 0; i < lfn_len; i++)
+ if ((lfn[i] != ' ') && (lfn[i] == '.'))
+ break;
+
+ if (i > lfn_len)
+ return MSDOS_NAME_INVALID;
+
+ /*
+ * Is this a short name ?
+ */
+
+ type = msdos_name_type (lfn, lfn_len);
+
+ if (type == MSDOS_NAME_INVALID)
+ return MSDOS_NAME_INVALID;
+
+ msdos_filename_unix2dos (lfn, lfn_len, sfn);
+
+ return type;
+}
+
/* msdos_get_token --
* Routine to get a token (name or separator) from the path.
*
@@ -43,35 +227,34 @@
*
*/
msdos_token_types_t
-msdos_get_token(const char *path, char *ret_token, int *token_len)
+msdos_get_token(const char *path, const char **ret_token, int *ret_token_len)
{
- int rc = RC_OK;
- register int i = 0;
msdos_token_types_t type = MSDOS_NAME;
- char token[MSDOS_NAME_MAX_WITH_DOT+1];
- register char c;
+ int i = 0;
+
+ *ret_token = NULL;
+ *ret_token_len = 0;
/*
- * Copy a name into token. (Remember NULL is a token.)
+ * Check for a separator.
*/
- c = path[i];
- while ( (!msdos_is_separator(c)) && (i <= MSDOS_NAME_MAX_WITH_DOT) )
+ while (!msdos_is_separator(path[i]))
{
- token[i] = c;
- if ( i == MSDOS_NAME_MAX_WITH_DOT )
+ if ( !msdos_is_valid_name_char(path[i]) )
return MSDOS_INVALID_TOKEN;
- if ( !msdos_is_valid_name_char(c) )
+ ++i;
+ if ( i == MSDOS_NAME_MAX_LFN_WITH_DOT )
return MSDOS_INVALID_TOKEN;
- c = path [++i];
}
+ *ret_token = path;
+
/*
- * Copy a seperator into token.
+ * If it is just a separator then it is the current dir.
*/
if ( i == 0 )
{
- token[i] = c;
- if ( token[i] != '\0' )
+ if ( *path != '\0' )
{
i++;
type = MSDOS_CURRENT_DIR;
@@ -79,13 +262,11 @@ msdos_get_token(const char *path, char *ret_token, int *token_len)
else
type = MSDOS_NO_MORE_PATH;
}
- else if (token[ i-1 ] != '\0')
- token[i] = '\0';
/*
- * Set token_len to the number of characters copied.
+ * Set the token and token_len to the token start and length.
*/
- *token_len = i;
+ *ret_token_len = i;
/*
* If we copied something that was not a seperator see if
@@ -93,25 +274,19 @@ msdos_get_token(const char *path, char *ret_token, int *token_len)
*/
if ( type == MSDOS_NAME )
{
- if ( strcmp( token, "..") == 0 )
+ if ((i == 2) && ((*ret_token)[0] == '.') && ((*ret_token)[1] == '.'))
{
- strcpy(ret_token, MSDOS_DOTDOT_NAME);
type = MSDOS_UP_DIR;
return type;
}
- if ( strcmp( token, "." ) == 0 )
+ if ((i == 1) && ((*ret_token)[0] == '.'))
{
- strcpy(ret_token, MSDOS_DOT_NAME);
type = MSDOS_CURRENT_DIR;
return type;
}
-
- rc = msdos_filename_unix2dos(token, *token_len, ret_token);
- if ( rc != RC_OK )
- return MSDOS_INVALID_TOKEN;
}
- ret_token[MSDOS_NAME_MAX] = '\0';
+
return type;
}
@@ -133,50 +308,61 @@ msdos_get_token(const char *path, char *ret_token, int *token_len)
int
msdos_find_name(
rtems_filesystem_location_info_t *parent_loc,
- char *name
+ const char *name,
+ int name_len
)
{
- int rc = RC_OK;
- msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
- fat_file_fd_t *fat_fd = NULL;
- fat_auxiliary_t aux;
- unsigned short time_val = 0;
- unsigned short date = 0;
- char node_entry[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+ int rc = RC_OK;
+ msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = NULL;
+ msdos_name_type_t name_type;
+ fat_dir_pos_t dir_pos;
+ unsigned short time_val = 0;
+ unsigned short date = 0;
+ char node_entry[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
memset(node_entry, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+ name_type = msdos_long_to_short (name,
+ name_len,
+ MSDOS_DIR_NAME(node_entry),
+ MSDOS_NAME_MAX);
+
/*
* find the node which correspondes to the name in the directory pointed by
* 'parent_loc'
*/
- rc = msdos_get_name_node(parent_loc, name, &aux, node_entry);
+ rc = msdos_get_name_node(parent_loc, false, name, name_len, name_type,
+ &dir_pos, node_entry);
if (rc != RC_OK)
return rc;
+ if (((*MSDOS_DIR_ATTR(node_entry)) & MSDOS_ATTR_VOLUME_ID) ||
+ ((*MSDOS_DIR_ATTR(node_entry) & MSDOS_ATTR_LFN_MASK) == MSDOS_ATTR_LFN))
+ return MSDOS_NAME_NOT_FOUND_ERR;
+
/* open fat-file corresponded to the found node */
- rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
+ rc = fat_file_open(parent_loc->mt_entry, &dir_pos, &fat_fd);
if (rc != RC_OK)
return rc;
+ fat_fd->dir_pos = dir_pos;
+
/*
- * I don't like this if, but: we should do it , or should write new file
+ * I don't like this if, but: we should do it, or should write new file
* size and first cluster num to the disk after each write operation
- * (even if one byte is written - that is TOO non-optimize) because
+ * (even if one byte is written - that is TOO slow) because
* otherwise real values of these fields stored in fat-file descriptor
- * may be accidentely rewritten with wrong values stored on the disk
+ * may be accidentally rewritten with wrong values stored on the disk
*/
if (fat_fd->links_num == 1)
{
- fat_fd->info_cln = aux.cln;
- fat_fd->info_ofs = aux.ofs;
fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(node_entry);
- fat_fd->first_char = *MSDOS_DIR_NAME(node_entry);
time_val = *MSDOS_DIR_WRITE_TIME(node_entry);
date = *MSDOS_DIR_WRITE_DATE(node_entry);
- fat_fd->mtime = msdos_date_dos2unix(CF_LE_W(time_val), CF_LE_W(date));
+ fat_fd->mtime = msdos_date_dos2unix(CF_LE_W(date), CF_LE_W(time_val));
if ((*MSDOS_DIR_ATTR(node_entry)) & MSDOS_ATTR_DIRECTORY)
{
@@ -227,7 +413,7 @@ msdos_find_name(
}
/* msdos_get_name_node --
- * This routine is used in two ways: for a new mode creation (a) or for
+ * This routine is used in two ways: for a new node creation (a) or for
* search the node which correspondes to the name parameter (b).
* In case (a) 'name' should be set up to NULL and 'name_dir_entry' should
* point to initialized 32 bytes structure described a new node.
@@ -247,7 +433,7 @@ msdos_find_name(
* name - NULL or name to find
* paux - identify a node location on the disk -
* cluster num and offset inside the cluster
- * name_dir_entry - node to create/placeholder for found node (IN/OUT)
+ * short_dir_entry - node to create/placeholder for found node (IN/OUT)
*
* RETURNS:
* RC_OK, filled aux_struct_ptr and name_dir_entry on success, or -1 if
@@ -257,90 +443,63 @@ msdos_find_name(
int
msdos_get_name_node(
rtems_filesystem_location_info_t *parent_loc,
- char *name,
- fat_auxiliary_t *paux,
+ bool create_node,
+ const char *name,
+ int name_len,
+ msdos_name_type_t name_type,
+ fat_dir_pos_t *dir_pos,
char *name_dir_entry
)
{
int rc = RC_OK;
- ssize_t ret = 0;
- msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
fat_file_fd_t *fat_fd = parent_loc->node_access;
uint32_t dotdot_cln = 0;
- /* find name in fat-file which correspondes to the directory */
- rc = msdos_find_name_in_fat_file(parent_loc->mt_entry, fat_fd, name, paux,
- name_dir_entry);
+ /* find name in fat-file which corresponds to the directory */
+ rc = msdos_find_name_in_fat_file(parent_loc->mt_entry, fat_fd,
+ create_node, name, name_len, name_type,
+ dir_pos, name_dir_entry);
if ((rc != RC_OK) && (rc != MSDOS_NAME_NOT_FOUND_ERR))
return rc;
- /* if we search for valid name and name not found -> return */
- if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name != NULL))
- return rc;
-
- /*
- * if we try to create new entry and the directory is not big enough
- * currently - try to enlarge directory
- */
- if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name == NULL))
+ if (!create_node)
{
- ret = fat_file_write(parent_loc->mt_entry, fat_fd,
- fat_fd->fat_file_size,
- MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
- (uint8_t *)name_dir_entry);
- if (ret == -1)
- return -1;
-
- /* on success directory is enlarged by a new cluster */
- fat_fd->fat_file_size += fs_info->fat.vol.bpc;
-
- /* get cluster num where a new node located */
- rc = fat_file_ioctl(parent_loc->mt_entry, fat_fd, F_CLU_NUM,
- fat_fd->fat_file_size - 1, &paux->cln);
-
- if (rc != RC_OK)
+ /* if we search for valid name and name not found -> return */
+ if (rc == MSDOS_NAME_NOT_FOUND_ERR)
return rc;
/*
- * if new cluster allocated succesfully then new node is at very
- * beginning of the cluster (offset is computed in bytes)
+ * if we have deal with ".." - it is a special case :(((
+ *
+ * Really, we should return cluster num and offset not of ".." slot, but
+ * slot which correspondes to real directory name.
*/
- paux->ofs = 0;
- return RC_OK;
- }
-
- /*
- * if we have deal with ".." - it is a special case :(((
- *
- * Really, we should return cluster num and offset not of ".." slot, but
- * slot which correspondes to real directory name.
- */
- if ((rc == RC_OK) && (name != NULL))
- {
- if (strncmp(name, MSDOS_DOTDOT_NAME, MSDOS_SHORT_NAME_LEN) == 0)
+ if (rc == RC_OK)
{
- dotdot_cln = MSDOS_EXTRACT_CLUSTER_NUM((name_dir_entry));
-
- /* are we right under root dir ? */
- if (dotdot_cln == 0)
- {
- /*
- * we can relax about first_char field - it never should be
- * used for root dir
- */
- paux->cln = FAT_ROOTDIR_CLUSTER_NUM;
- paux->ofs = 0;
- }
- else
+ if (strncmp(name, "..", 2) == 0)
{
- rc = msdos_get_dotdot_dir_info_cluster_num_and_offset(
- parent_loc->mt_entry,
- dotdot_cln,
- paux,
- name_dir_entry
- );
- if (rc != RC_OK)
- return rc;
+ dotdot_cln = MSDOS_EXTRACT_CLUSTER_NUM((name_dir_entry));
+
+ /* are we right under root dir ? */
+ if (dotdot_cln == 0)
+ {
+ /*
+ * we can relax about first_char field - it never should be
+ * used for root dir
+ */
+ fat_dir_pos_init(dir_pos);
+ dir_pos->sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
+ }
+ else
+ {
+ rc =
+ msdos_get_dotdot_dir_info_cluster_num_and_offset(parent_loc->mt_entry,
+ dotdot_cln,
+ dir_pos,
+ name_dir_entry);
+ if (rc != RC_OK)
+ return rc;
+ }
}
}
}
@@ -380,7 +539,7 @@ int
msdos_get_dotdot_dir_info_cluster_num_and_offset(
rtems_filesystem_mount_table_entry_t *mt_entry,
uint32_t cln,
- fat_auxiliary_t *paux,
+ fat_dir_pos_t *dir_pos,
char *dir_entry
)
{
@@ -391,18 +550,13 @@ msdos_get_dotdot_dir_info_cluster_num_and_offset(
char dotdot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
uint32_t cl4find = 0;
- memset(dot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
- memset(dotdot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
-
/*
* open fat-file corresponded to ".."
*/
- rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd);
+ rc = fat_file_open(mt_entry, dir_pos, &fat_fd);
if (rc != RC_OK)
return rc;
- fat_fd->info_cln = paux->cln;
- fat_fd->info_ofs = paux->ofs;
fat_fd->cln = cln;
fat_fd->fat_file_type = FAT_DIRECTORY;
fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
@@ -418,8 +572,10 @@ msdos_get_dotdot_dir_info_cluster_num_and_offset(
}
/* find "." node in opened directory */
- rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOT_NAME, paux,
- dot_node);
+ memset(dot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+ msdos_long_to_short(".", 1, dot_node, MSDOS_SHORT_NAME_LEN);
+ rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, false, ".", 1,
+ MSDOS_NAME_SHORT, dir_pos, dot_node);
if (rc != RC_OK)
{
@@ -428,7 +584,10 @@ msdos_get_dotdot_dir_info_cluster_num_and_offset(
}
/* find ".." node in opened directory */
- rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOTDOT_NAME, paux,
+ memset(dotdot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+ msdos_long_to_short("..", 2, dotdot_node, MSDOS_SHORT_NAME_LEN);
+ rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, false, "..", 2,
+ MSDOS_NAME_SHORT, dir_pos,
dotdot_node);
if (rc != RC_OK)
@@ -450,18 +609,15 @@ msdos_get_dotdot_dir_info_cluster_num_and_offset(
* we handle root dir for all FAT types in the same way with the
* ordinary directories ( through fat_file_* calls )
*/
- paux->cln = FAT_ROOTDIR_CLUSTER_NUM;
- paux->ofs = 0;
+ fat_dir_pos_init(dir_pos);
+ dir_pos->sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
}
/* open fat-file corresponded to second ".." */
- rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd);
+ rc = fat_file_open(mt_entry, dir_pos, &fat_fd);
if (rc != RC_OK)
return rc;
- fat_fd->info_cln = paux->cln;
- fat_fd->info_ofs = paux->ofs;
-
if ((MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node)) == 0)
fat_fd->cln = fs_info->fat.vol.rdir_cl;
else
@@ -482,7 +638,7 @@ msdos_get_dotdot_dir_info_cluster_num_and_offset(
/* in this directory find slot with specified cluster num */
rc = msdos_find_node_by_cluster_num_in_fat_file(mt_entry, fat_fd, cl4find,
- paux, dir_entry);
+ dir_pos, dir_entry);
if (rc != RC_OK)
{
fat_file_close(mt_entry, fat_fd);
@@ -518,16 +674,16 @@ msdos_set_dir_wrt_time_and_date(
uint32_t sec = 0;
uint32_t byte = 0;
- msdos_date_unix2dos(fat_fd->mtime, &time_val, &date);
+ msdos_date_unix2dos(fat_fd->mtime, &date, &time_val);
/*
* calculate input for _fat_block_write: convert (cluster num, offset) to
* (sector num, new offset)
*/
- sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln);
- sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2);
+ sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->dir_pos.sname.cln);
+ sec += (fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
/* byte points to start of 32bytes structure */
- byte = fat_fd->info_ofs & (fs_info->fat.vol.bps - 1);
+ byte = fat_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1);
time_val = CT_LE_W(time_val);
ret1 = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_WTIME_OFFSET,
@@ -572,10 +728,10 @@ msdos_set_first_cluster_num(
* calculate input for _fat_block_write: convert (cluster num, offset) to
* (sector num, new offset)
*/
- sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln);
- sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2);
+ sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->dir_pos.sname.cln);
+ sec += (fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
/* byte from points to start of 32bytes structure */
- byte = fat_fd->info_ofs & (fs_info->fat.vol.bps - 1);
+ byte = fat_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1);
le_cl_low = CT_LE_W((uint16_t )(new_cln & 0x0000FFFF));
ret1 = _fat_block_write(mt_entry, sec,
@@ -615,9 +771,9 @@ msdos_set_file_size(
uint32_t sec = 0;
uint32_t byte = 0;
- sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln);
- sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2);
- byte = (fat_fd->info_ofs & (fs_info->fat.vol.bps - 1));
+ sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->dir_pos.sname.cln);
+ sec += (fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
+ byte = (fat_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1));
le_new_length = CT_LE_L((fat_fd->fat_file_size));
ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_SIZE_OFFSET, 4,
@@ -650,25 +806,58 @@ msdos_set_file_size(
int
msdos_set_first_char4file_name(
rtems_filesystem_mount_table_entry_t *mt_entry,
- uint32_t cl,
- uint32_t ofs,
+ fat_dir_pos_t *dir_pos,
unsigned char fchar
)
{
- ssize_t ret = 0;
+ ssize_t ret;
msdos_fs_info_t *fs_info = mt_entry->fs_info;
- uint32_t sec = 0;
- uint32_t byte = 0;
+ uint32_t dir_block_size;
+ fat_pos_t start = dir_pos->lname;
+ fat_pos_t end = dir_pos->sname;
- sec = fat_cluster_num_to_sector_num(mt_entry, cl);
- sec += (ofs >> fs_info->fat.vol.sec_log2);
- byte = (ofs & (fs_info->fat.vol.bps - 1));
+ if ((end.cln == fs_info->fat.vol.rdir_cl) &&
+ (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
+ dir_block_size = fs_info->fat.vol.rdir_size;
+ else
+ dir_block_size = fs_info->fat.vol.bpc;
+
+ if (dir_pos->lname.cln == FAT_FILE_SHORT_NAME)
+ start = dir_pos->sname;
- ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_NAME_OFFSET, 1,
- &fchar);
- if ( ret < 0)
+ /*
+ * We handle the changes directly due the way the short file
+ * name code was written rather than use the fat_file_write
+ * interface.
+ */
+ while (true)
+ {
+ uint32_t sec = (fat_cluster_num_to_sector_num(mt_entry, start.cln) +
+ (start.ofs >> fs_info->fat.vol.sec_log2));
+ uint32_t byte = (start.ofs & (fs_info->fat.vol.bps - 1));;
+
+ ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_NAME_OFFSET, 1,
+ &fchar);
+ if (ret < 0)
return -1;
+ if ((start.cln == end.cln) && (start.ofs == end.ofs))
+ break;
+
+ start.ofs += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
+ if (start.ofs >= dir_block_size)
+ {
+ int rc;
+ if ((end.cln == fs_info->fat.vol.rdir_cl) &&
+ (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
+ break;
+ rc = fat_get_fat_cluster(mt_entry, start.cln, &start.cln);
+ if ( rc != RC_OK )
+ return rc;
+ start.ofs = 0;
+ }
+ }
+
return RC_OK;
}
@@ -713,21 +902,39 @@ msdos_dir_is_empty(
i < fs_info->fat.vol.bps;
i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
{
- if (((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ char* entry = (char*) fs_info->cl_buf + i;
+
+ /*
+ * If the entry is empty, a long file name entry, or '.' or '..'
+ * then consider it as empty.
+ *
+ * Just ignore long file name entries. They must have a short entry to
+ * be valid.
+ */
+ if (((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
MSDOS_THIS_DIR_ENTRY_EMPTY) ||
- (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), MSDOS_DOT_NAME,
+ ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) ==
+ MSDOS_ATTR_LFN) ||
+ (strncmp(MSDOS_DIR_NAME((entry)), MSDOS_DOT_NAME,
MSDOS_SHORT_NAME_LEN) == 0) ||
- (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)),
+ (strncmp(MSDOS_DIR_NAME((entry)),
MSDOS_DOTDOT_NAME,
MSDOS_SHORT_NAME_LEN) == 0))
continue;
- if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ /*
+ * Nothing more to look at.
+ */
+ if ((*MSDOS_DIR_NAME(entry)) ==
MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
{
*ret_val = true;
return RC_OK;
}
+
+ /*
+ * Short file name entries mean not empty.
+ */
return RC_OK;
}
j++;
@@ -736,20 +943,15 @@ msdos_dir_is_empty(
return RC_OK;
}
-
-/* msdos_find_name_in_fat_file --
- * This routine is used in two ways: for a new mode creation (a) or for
- * search the node which correspondes to the 'name' parameter (b).
- * In case (a) name should be set up to NULL and 'name_dir_entry' should
- * point to initialized 32 bytes structure described a new node.
- * In case (b) 'name' should contain a valid string.
+/* msdos_create_name_in_fat_file --
+ * This routine creates an entry in the fat file for the file name
+ * provided by the user. The directory entry passed is the short
+ * file name and is added as it. If the file name is long a long
+ * file name set of entries is added.
*
- * (a): reading fat-file corresponded to directory we are going to create
- * node in. If found free slot write contents of name_dir_entry into
- * it.
- *
- * (b): reading fat-file corresponded to directory and trying to find slot
- * with the name field == name parameter
+ * Scan the directory for the file and if not found add the new entry.
+ * When scanning remember the offset in the file where the directory
+ * entry can be added.
*
* PARAMETERS:
* mt_entry - mount table entry
@@ -764,111 +966,610 @@ msdos_dir_is_empty(
* appropriately)
*
*/
+#define MSDOS_FIND_PRINT 0
int msdos_find_name_in_fat_file(
rtems_filesystem_mount_table_entry_t *mt_entry,
fat_file_fd_t *fat_fd,
- char *name,
- fat_auxiliary_t *paux,
+ bool create_node,
+ const char *name,
+ int name_len,
+ msdos_name_type_t name_type,
+ fat_dir_pos_t *dir_pos,
char *name_dir_entry
- )
+ )
{
- int rc = RC_OK;
ssize_t ret = 0;
msdos_fs_info_t *fs_info = mt_entry->fs_info;
- uint32_t i = 0, j = 0;
+ uint32_t dir_offset = 0;
+ uint32_t dir_entry = 0;
uint32_t bts2rd = 0;
-
+ fat_pos_t lfn_start;
+ bool lfn_matched = false;
+ uint8_t lfn_checksum = 0;
+ int lfn_entries = 0;
+ int lfn_entry = 0;
+ uint32_t empty_space_offset = 0;
+ uint32_t empty_space_entry = 0;
+ uint32_t empty_space_count = 0;
+ bool empty_space_found = false;
+ uint32_t entries_per_block;
+ bool read_cluster = false;
+
+ assert(name_len > 0);
+
+ fat_dir_pos_init(dir_pos);
+
+ lfn_start.cln = lfn_start.ofs = FAT_FILE_SHORT_NAME;
+
+ /*
+ * If the file name is long how many short directory
+ * entries are needed ?
+ */
+ if (name_type == MSDOS_NAME_LONG)
+ lfn_entries = ((name_len - 1) + MSDOS_LFN_LEN_PER_ENTRY) / MSDOS_LFN_LEN_PER_ENTRY;
+
if (FAT_FD_OF_ROOT_DIR(fat_fd) &&
- (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
+ (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
bts2rd = fat_fd->fat_file_size;
else
bts2rd = fs_info->fat.vol.bpc;
- while ((ret = fat_file_read(mt_entry, fat_fd, (j * bts2rd), bts2rd,
- fs_info->cl_buf)) != FAT_EOF)
+ entries_per_block = bts2rd / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
+
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[1] cn:%i ebp:%li bts2rd:%li lfne:%d nl:%i n:%s\n",
+ create_node, entries_per_block, bts2rd, lfn_entries, name_len, name);
+#endif
+ /*
+ * Scan the directory seeing if the file is present. While
+ * doing this see if a suitable location can be found to
+ * create the entry if the name is not found.
+ */
+ while ((ret = fat_file_read(mt_entry, fat_fd, (dir_offset * bts2rd),
+ bts2rd, fs_info->cl_buf)) != FAT_EOF)
{
+ bool remainder_empty = false;
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[2] dir_offset:%li\n", dir_offset);
+#endif
+
if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
rtems_set_errno_and_return_minus_one(EIO);
assert(ret == bts2rd);
/* have to look at the DIR_NAME as "raw" 8-bit data */
- for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
+ for (dir_entry = 0;
+ dir_entry < bts2rd;
+ dir_entry += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
{
- /* is the entry empty ? */
- if (((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
- MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY) ||
- ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
- MSDOS_THIS_DIR_ENTRY_EMPTY))
+ char* entry = (char*) fs_info->cl_buf + dir_entry;
+
+ /*
+ * See if the entry is empty or the remainder of the directory is
+ * empty ? Localise to make the code read better.
+ */
+ bool entry_empty = (*MSDOS_DIR_ENTRY_TYPE(entry) ==
+ MSDOS_THIS_DIR_ENTRY_EMPTY);
+ remainder_empty = (*MSDOS_DIR_ENTRY_TYPE(entry) ==
+ MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY);
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[3] re:%i ee:%i do:%li de:%li(%ld)\n",
+ remainder_empty, entry_empty, dir_offset,
+ dir_entry, (dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE));
+#endif
+ /*
+ * Remember where the we are, ie the start, so we can come back
+ * to here and write the long file name if this is the start of
+ * a series of empty entries. If empty_space_count is 0 then
+ * we are currently not inside an empty series of entries. It
+ * is a count of empty entries.
+ */
+ if (empty_space_count == 0)
{
- /* whether we are looking for an empty entry */
- if (name == NULL)
- {
- /* get current cluster number */
- rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
- j * bts2rd, &paux->cln);
- if (rc != RC_OK)
- return rc;
-
- /* offset is computed in bytes */
- paux->ofs = i;
-
- /* write new node entry */
- ret = fat_file_write(mt_entry, fat_fd, j * bts2rd + i,
- MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
- (uint8_t *)name_dir_entry);
- if (ret != MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
- return -1;
-
- /*
- * we don't update fat_file_size here - it should not
- * increase
- */
- return RC_OK;
- }
+ empty_space_entry = dir_entry;
+ empty_space_offset = dir_offset;
+ }
+ if (remainder_empty)
+ {
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[3.1] cn:%i esf:%i\n", create_node, empty_space_found);
+#endif
/*
- * if name != NULL and there is no more entries in the
+ * If just looking and there is no more entries in the
* directory - return name-not-found
*/
- if (((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
- MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY))
+ if (!create_node)
return MSDOS_NAME_NOT_FOUND_ERR;
+
+ /*
+ * Lets go and write the directory entries. If we have not found
+ * any available space add the remaining number of entries to any that
+ * we may have already found that are just before this entry. If more
+ * are needed FAT_EOF is returned by the read and we extend the file.
+ */
+ if (!empty_space_found)
+ {
+ empty_space_count +=
+ entries_per_block - (dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+ empty_space_found = true;
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[3.2] esf:%i esc%i\n", empty_space_found, empty_space_count);
+#endif
+ }
+ break;
+ }
+ else if (entry_empty)
+ {
+ if (create_node)
+ {
+ /*
+ * Remainder is not empty so is this entry empty ?
+ */
+ empty_space_count++;
+
+ if (empty_space_count == (lfn_entries + 1))
+ empty_space_found = true;
+ }
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[4.1] esc:%li esf:%i\n",
+ empty_space_count, empty_space_found);
+#endif
}
else
{
- /* entry not empty and name != NULL -> compare names */
- if (name != NULL)
+ /*
+ * A valid entry so handle it.
+ *
+ * If empty space has not been found we need to start the
+ * count again.
+ */
+ if (create_node && !empty_space_found)
+ {
+ empty_space_entry = 0;
+ empty_space_count = 0;
+ }
+
+ /*
+ * Check the attribute to see if the entry is for a long
+ * file name.
+ */
+ if ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) ==
+ MSDOS_ATTR_LFN)
{
- if (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), name,
- MSDOS_SHORT_NAME_LEN) == 0)
+ char* p;
+ int o;
+ int i;
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[4.2] lfn:%c entry:%i checksum:%i\n",
+ lfn_start.cln == FAT_FILE_SHORT_NAME ? 't' : 'f',
+ *MSDOS_DIR_ENTRY_TYPE(entry) & MSDOS_LAST_LONG_ENTRY_MASK,
+ *MSDOS_DIR_LFN_CHECKSUM(entry));
+#endif
+ /*
+ * If we are not already processing a LFN see if this is
+ * the first entry of a LFN ?
+ */
+ if (lfn_start.cln == FAT_FILE_SHORT_NAME)
{
+ lfn_matched = false;
+
+ /*
+ * The first entry must have the last long entry
+ * flag set.
+ */
+ if ((*MSDOS_DIR_ENTRY_TYPE(entry) &
+ MSDOS_LAST_LONG_ENTRY) == 0)
+ continue;
+
+ /*
+ * Does the number of entries in the LFN directory
+ * entry match the number we expect for this
+ * file name. Note we do not know the number of
+ * characters in the entry so this is check further
+ * on when the characters are checked.
+ */
+ if (lfn_entries != (*MSDOS_DIR_ENTRY_TYPE(entry) &
+ MSDOS_LAST_LONG_ENTRY_MASK))
+ continue;
+
/*
- * we get the entry we looked for - fill auxiliary
- * structure and copy all 32 bytes of the entry
+ * Get the checksum of the short entry.
*/
- rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
- j * bts2rd, &paux->cln);
+ lfn_start.cln = dir_offset;
+ lfn_start.ofs = dir_entry;
+ lfn_entry = lfn_entries;
+ lfn_checksum = *MSDOS_DIR_LFN_CHECKSUM(entry);
+
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[4.3] lfn_checksum:%i\n",
+ *MSDOS_DIR_LFN_CHECKSUM(entry));
+#endif
+ }
+
+ /*
+ * If the entry number or the check sum do not match
+ * forget this series of long directory entries. These
+ * could be orphaned entries depending on the history
+ * of the disk.
+ */
+ if ((lfn_entry != (*MSDOS_DIR_ENTRY_TYPE(entry) &
+ MSDOS_LAST_LONG_ENTRY_MASK)) ||
+ (lfn_checksum != *MSDOS_DIR_LFN_CHECKSUM(entry)))
+ {
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[4.4] no match\n");
+#endif
+ lfn_start.cln = FAT_FILE_SHORT_NAME;
+ continue;
+ }
+
+ lfn_entry--;
+ o = lfn_entry * MSDOS_LFN_LEN_PER_ENTRY;
+ p = entry + 1;
+
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[5] lfne:%i\n", lfn_entry);
+#endif
+ for (i = 0; i < MSDOS_LFN_LEN_PER_ENTRY; i++)
+ {
+#if MSDOS_FIND_PRINT > 1
+ printf ("MSFS:[6] o:%i i:%i *p:%c(%02x) name[o + i]:%c(%02x)\n",
+ o, i, *p, *p, name[o + i], name[o + i]);
+#endif
+ if (*p == '\0')
+ {
+ /*
+ * If this is the first entry, ie the last part of the
+ * long file name and the length does not match then
+ * the file names do not match.
+ */
+ if (((lfn_entry + 1) == lfn_entries) &&
+ ((o + i) != name_len))
+ lfn_start.cln = FAT_FILE_SHORT_NAME;
+ break;
+ }
+
+ if (((o + i) >= name_len) || (*p != name[o + i]))
+ {
+ lfn_start.cln = FAT_FILE_SHORT_NAME;
+ break;
+ }
+
+ switch (i)
+ {
+ case 4:
+ p += 5;
+ break;
+ case 10:
+ p += 4;
+ break;
+ default:
+ p += 2;
+ break;
+ }
+ }
+
+ lfn_matched = ((lfn_entry == 0) &&
+ (lfn_start.cln != FAT_FILE_SHORT_NAME));
+
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[8.1] lfn_matched:%i\n", lfn_matched);
+#endif
+ }
+ else
+ {
+ /*
+ * SFN entry found.
+ *
+ * If a LFN has been found and it matched check the
+ * entries have all been found and the checksum is
+ * correct. If this is the case return the short file
+ * name entry.
+ */
+ if (lfn_matched)
+ {
+ uint8_t cs = 0;
+ uint8_t* p = (uint8_t*) MSDOS_DIR_NAME(entry);
+ int i;
+
+ for (i = 0; i < MSDOS_SHORT_NAME_LEN; i++, p++)
+ cs = ((cs & 1) ? 0x80 : 0) + (cs >> 1) + *p;
+
+ if (lfn_entry || (lfn_checksum != cs))
+ lfn_matched = false;
+ }
+
+ /*
+ * If the long file names matched or the file name is
+ * short and they match then we have the entry. We will not
+ * match a long file name against a short file name because
+ * a long file name that generates a matching short file
+ * name is not a long file name.
+ */
+ if (lfn_matched ||
+ ((name_type == MSDOS_NAME_SHORT) &&
+ (lfn_start.cln == FAT_FILE_SHORT_NAME) &&
+ (memcmp(MSDOS_DIR_NAME(entry),
+ MSDOS_DIR_NAME(name_dir_entry),
+ MSDOS_SHORT_NAME_LEN) == 0)))
+ {
+ /*
+ * We get the entry we looked for - fill the position
+ * structure and the 32 bytes of the short entry
+ */
+ int rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
+ dir_offset * bts2rd,
+ &dir_pos->sname.cln);
if (rc != RC_OK)
return rc;
- /* offset is computed in bytes */
- paux->ofs = i;
- memcpy(name_dir_entry,(fs_info->cl_buf + i),
+ dir_pos->sname.ofs = dir_entry;
+
+ if (lfn_start.cln != FAT_FILE_SHORT_NAME)
+ {
+ rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
+ lfn_start.cln * bts2rd,
+ &lfn_start.cln);
+ if (rc != RC_OK)
+ return rc;
+ }
+
+ dir_pos->lname.cln = lfn_start.cln;
+ dir_pos->lname.ofs = lfn_start.ofs;
+
+ memcpy(name_dir_entry, entry,
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
return RC_OK;
}
+
+ lfn_start.cln = FAT_FILE_SHORT_NAME;
+ lfn_matched = false;
}
}
}
- j++;
+
+ if (remainder_empty)
+ break;
+
+ dir_offset++;
}
- return MSDOS_NAME_NOT_FOUND_ERR;
+
+ /*
+ * If we are not to create the entry return a not found error.
+ */
+ if (!create_node)
+ return MSDOS_NAME_NOT_FOUND_ERR;
+
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[8.1] WRITE do:%ld esc:%ld eso:%ld ese:%ld\n",
+ dir_offset, empty_space_count, empty_space_offset, empty_space_entry);
+#endif
+
+ /*
+ * If a long file name calculate the checksum of the short file name
+ * data to place in each long file name entry. First set the short
+ * file name to the slot of the SFN entry. This will mean no clashes
+ * in this directory.
+ */
+ lfn_checksum = 0;
+ if (name_type == MSDOS_NAME_LONG)
+ {
+ uint8_t* p = (uint8_t*) MSDOS_DIR_NAME(name_dir_entry);
+ int i;
+ int slot = (((empty_space_offset * bts2rd) + empty_space_entry) /
+ MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) + lfn_entries + 1;
+
+ msdos_short_name_hex(MSDOS_DIR_NAME(name_dir_entry), slot);
+
+ for (i = 0; i < 11; i++, p++)
+ lfn_checksum =
+ ((lfn_checksum & 1) ? 0x80 : 0) + (lfn_checksum >> 1) + *p;
+ }
+
+ /*
+ * If there is no space available then extend the file. The
+ * empty_space_count is a count of empty entries in the currently
+ * read cluster so if 0 there is no space. Note, dir_offset will
+ * be at the next cluster so we can just make empty_space_offset
+ * that value.
+ */
+ if (empty_space_count == 0)
+ {
+ read_cluster = true;
+ empty_space_offset = dir_offset;
+ empty_space_entry = 0;
+ }
+
+ /*
+ * Have we read past the empty block ? If so go back and read it again.
+ */
+ if (dir_offset != empty_space_offset)
+ read_cluster = true;
+
+ /*
+ * Handle the entry writes.
+ */
+ lfn_start.cln = lfn_start.ofs = FAT_FILE_SHORT_NAME;
+ lfn_entry = 0;
+
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[9] read_cluster:%d eso:%ld ese:%ld\n",
+ read_cluster, empty_space_offset, empty_space_entry);
+#endif
+
+ /*
+ * The one more is the short entry.
+ */
+ while (lfn_entry < (lfn_entries + 1))
+ {
+ int length = 0;
+
+ if (read_cluster)
+ {
+ uint32_t new_length;
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[9.1] eso:%li\n", empty_space_offset);
+#endif
+ ret = fat_file_read(mt_entry, fat_fd,
+ (empty_space_offset * bts2rd), bts2rd,
+ fs_info->cl_buf);
+
+ if (ret != bts2rd)
+ {
+ if (ret != FAT_EOF)
+ rtems_set_errno_and_return_minus_one(EIO);
+
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[9.2] extending file:%li\n", empty_space_offset);
+#endif
+ ret = fat_file_extend (mt_entry, fat_fd, empty_space_offset * bts2rd,
+ &new_length);
+
+ if (ret != RC_OK)
+ return ret;
+
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[9.3] extended: %d <-> %d\n", new_length, empty_space_offset * bts2rd);
+#endif
+ if (new_length != (empty_space_offset * bts2rd))
+ rtems_set_errno_and_return_minus_one(EIO);
+
+ memset(fs_info->cl_buf, 0, bts2rd);
+
+ ret = fat_file_write(mt_entry, fat_fd,
+ empty_space_offset * bts2rd,
+ bts2rd, fs_info->cl_buf);
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[9.4] clear write: %d\n", ret);
+#endif
+ if (ret != bts2rd)
+ rtems_set_errno_and_return_minus_one(EIO);
+ }
+ }
+
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[10] eso:%li\n", empty_space_offset);
+#endif
+
+ for (dir_entry = empty_space_entry;
+ dir_entry < bts2rd;
+ dir_entry += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
+ {
+ char* entry = (char*) fs_info->cl_buf + dir_entry;
+ char* p;
+ const char* n;
+ int i;
+
+ length += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
+ lfn_entry++;
+
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[10] de:%li(%li) length:%i lfn_entry:%i\n",
+ dir_entry, (dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE),
+ length, lfn_entry);
+#endif
+ /*
+ * Time to write the short file name entry.
+ */
+ if (lfn_entry == (lfn_entries + 1))
+ {
+ /* get current cluster number */
+ int rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
+ empty_space_offset * bts2rd,
+ &dir_pos->sname.cln);
+ if (rc != RC_OK)
+ return rc;
+
+ dir_pos->sname.ofs = dir_entry;
+
+ if (lfn_start.cln != FAT_FILE_SHORT_NAME)
+ {
+ rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
+ lfn_start.cln * bts2rd,
+ &lfn_start.cln);
+ if (rc != RC_OK)
+ return rc;
+ }
+
+ dir_pos->lname.cln = lfn_start.cln;
+ dir_pos->lname.ofs = lfn_start.ofs;
+
+ /* write new node entry */
+ memcpy (entry, (uint8_t *) name_dir_entry,
+ MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+ break;
+ }
+
+ /*
+ * This is a long file name and we need to write
+ * a long file name entry. See if this is the
+ * first entry written and if so remember the
+ * the location of the long file name.
+ */
+ if (lfn_start.cln == FAT_FILE_SHORT_NAME)
+ {
+ lfn_start.cln = empty_space_offset;
+ lfn_start.ofs = dir_entry;
+ }
+
+ /*
+ * Clear the entry before loading the data.
+ */
+ memset (entry, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+
+ *MSDOS_DIR_LFN_CHECKSUM(entry) = lfn_checksum;
+
+ p = entry + 1;
+ n = name + (lfn_entries - lfn_entry) * MSDOS_LFN_LEN_PER_ENTRY;
+
+ for (i = 0; i < MSDOS_LFN_LEN_PER_ENTRY; i++)
+ {
+ *p = *n;
+ if (*n != 0)
+ n++;
+
+ switch (i)
+ {
+ case 4:
+ p += 5;
+ break;
+ case 10:
+ p += 4;
+ break;
+ default:
+ p += 2;
+ break;
+ }
+ }
+
+ *MSDOS_DIR_ENTRY_TYPE(entry) = (lfn_entries - lfn_entry) + 1;
+ if (lfn_entry == 1)
+ *MSDOS_DIR_ENTRY_TYPE(entry) |= MSDOS_LAST_LONG_ENTRY;
+ *MSDOS_DIR_ATTR(entry) |= MSDOS_ATTR_LFN;
+ }
+
+ ret = fat_file_write(mt_entry, fat_fd,
+ (empty_space_offset * bts2rd) + empty_space_entry,
+ length, fs_info->cl_buf + empty_space_entry);
+ if (ret != length)
+ rtems_set_errno_and_return_minus_one(EIO);
+
+ empty_space_offset++;
+ empty_space_entry = 0;
+ read_cluster = true;
+ }
+
+ return 0;
}
/* msdos_find_node_by_cluster_num_in_fat_file --
* Find node with specified number of cluster in fat-file.
*
+ * Note, not updated in the LFN change because it is only used
+ * for . and .. entries and these are always short.
+ *
* PARAMETERS:
* mt_entry - mount table entry
* fat_fd - fat-file descriptor
@@ -885,7 +1586,7 @@ int msdos_find_node_by_cluster_num_in_fat_file(
rtems_filesystem_mount_table_entry_t *mt_entry,
fat_file_fd_t *fat_fd,
uint32_t cl4find,
- fat_auxiliary_t *paux,
+ fat_dir_pos_t *dir_pos,
char *dir_entry
)
{
@@ -911,28 +1612,32 @@ int msdos_find_node_by_cluster_num_in_fat_file(
for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
{
+ char* entry = (char*) fs_info->cl_buf + i;
+
/* if this and all rest entries are empty - return not-found */
- if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ if ((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
return MSDOS_NAME_NOT_FOUND_ERR;
- /* have to look at the DIR_NAME as "raw" 8-bit data */
/* if this entry is empty - skip it */
- if ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ if ((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
MSDOS_THIS_DIR_ENTRY_EMPTY)
continue;
/* if get a non-empty entry - compare clusters num */
- if (MSDOS_EXTRACT_CLUSTER_NUM((fs_info->cl_buf + i)) == cl4find)
+ if (MSDOS_EXTRACT_CLUSTER_NUM(entry) == cl4find)
{
/* on success fill aux structure and copy all 32 bytes */
rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM, j * bts2rd,
- &paux->cln);
+ &dir_pos->sname.cln);
if (rc != RC_OK)
return rc;
- paux->ofs = i;
- memcpy(dir_entry, fs_info->cl_buf + i,
+ dir_pos->sname.ofs = i;
+ dir_pos->lname.cln = FAT_FILE_SHORT_NAME;
+ dir_pos->lname.ofs = FAT_FILE_SHORT_NAME;
+
+ memcpy(dir_entry, entry,
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
return RC_OK;
}
diff --git a/cpukit/libfs/src/dosfs/msdos_mknod.c b/cpukit/libfs/src/dosfs/msdos_mknod.c
index ac2a142cce..421d873136 100644
--- a/cpukit/libfs/src/dosfs/msdos_mknod.c
+++ b/cpukit/libfs/src/dosfs/msdos_mknod.c
@@ -36,7 +36,7 @@
* determines type of the node to be created and creates it.
*
* PARAMETERS:
- * token - non-formatted name of a new node
+ * name - file name to create
* mode - node type
* dev - dev
* pathloc - parent directory description
@@ -46,7 +46,7 @@
*
*/
int msdos_mknod(
- const char *token,
+ const char *name,
mode_t mode,
dev_t dev,
rtems_filesystem_location_info_t *pathloc
@@ -56,12 +56,7 @@ int msdos_mknod(
rtems_status_code sc = RTEMS_SUCCESSFUL;
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
msdos_token_types_t type = 0;
- char new_name[ MSDOS_NAME_MAX + 1 ];
- int len;
-
- /* check spelling and format new node name */
- msdos_get_token(token, new_name, &len);
-
+
/*
* Figure out what type of msdos node this is.
*/
@@ -82,7 +77,7 @@ int msdos_mknod(
rtems_set_errno_and_return_minus_one(EIO);
/* Create an MSDOS node */
- rc = msdos_creat_node(pathloc, type, new_name, mode, NULL);
+ rc = msdos_creat_node(pathloc, type, name, strlen(name), mode, NULL);
rtems_semaphore_release(fs_info->vol_sema);
return rc;
diff --git a/cpukit/libfs/src/imfs/deviceio.c b/cpukit/libfs/src/imfs/deviceio.c
index 62b1381233..70cb936425 100644
--- a/cpukit/libfs/src/imfs/deviceio.c
+++ b/cpukit/libfs/src/imfs/deviceio.c
@@ -206,12 +206,14 @@ int device_ioctl(
/*
* device_lseek
*
- * This handler eats all lseek() operations.
+ * This handler eats all lseek() operations and does not create
+ * an error. It assumes all devices can handle the seek. The
+ * writes fail.
*/
-off_t device_lseek(
+rtems_off64_t device_lseek(
rtems_libio_t *iop,
- off_t offset,
+ rtems_off64_t offset,
int whence
)
{
@@ -232,7 +234,7 @@ off_t device_lseek(
int device_ftruncate(
rtems_libio_t *iop,
- off_t length
+ rtems_off64_t length
)
{
return 0;
diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h
index 808a6f0cb7..355e494248 100644
--- a/cpukit/libfs/src/imfs/imfs.h
+++ b/cpukit/libfs/src/imfs/imfs.h
@@ -98,15 +98,15 @@ typedef uint8_t *block_p;
typedef block_p *block_ptr;
typedef struct {
- off_t size; /* size of file in bytes */
- block_ptr indirect; /* array of 128 data blocks pointers */
- block_ptr doubly_indirect; /* 128 indirect blocks */
- block_ptr triply_indirect; /* 128 doubly indirect blocks */
+ rtems_off64_t size; /* size of file in bytes */
+ block_ptr indirect; /* array of 128 data blocks pointers */
+ block_ptr doubly_indirect; /* 128 indirect blocks */
+ block_ptr triply_indirect; /* 128 doubly indirect blocks */
} IMFS_memfile_t;
typedef struct {
- off_t size; /* size of file in bytes */
- block_p direct; /* pointer to file image */
+ rtems_off64_t size; /* size of file in bytes */
+ block_p direct; /* pointer to file image */
} IMFS_linearfile_t;
/*
@@ -380,7 +380,7 @@ extern int IMFS_memfile_remove(
extern int memfile_ftruncate(
rtems_libio_t *iop, /* IN */
- off_t length /* IN */
+ rtems_off64_t length /* IN */
);
extern int imfs_dir_open(
@@ -400,9 +400,9 @@ extern ssize_t imfs_dir_read(
size_t count /* IN */
);
-extern off_t imfs_dir_lseek(
+extern rtems_off64_t imfs_dir_lseek(
rtems_libio_t *iop, /* IN */
- off_t offset, /* IN */
+ rtems_off64_t offset, /* IN */
int whence /* IN */
);
@@ -444,9 +444,9 @@ extern int memfile_ioctl(
void *buffer /* IN */
);
-extern off_t memfile_lseek(
+extern rtems_off64_t memfile_lseek(
rtems_libio_t *iop, /* IN */
- off_t offset, /* IN */
+ rtems_off64_t offset, /* IN */
int whence /* IN */
);
@@ -483,15 +483,15 @@ extern int device_ioctl(
void *buffer /* IN */
);
-extern off_t device_lseek(
+extern rtems_off64_t device_lseek(
rtems_libio_t *iop, /* IN */
- off_t offset, /* IN */
+ rtems_off64_t offset, /* IN */
int whence /* IN */
);
extern int device_ftruncate(
rtems_libio_t *iop, /* IN */
- off_t length /* IN */
+ rtems_off64_t length /* IN */
);
extern int IMFS_utime(
diff --git a/cpukit/libfs/src/imfs/imfs_directory.c b/cpukit/libfs/src/imfs/imfs_directory.c
index 519d534fe0..1107da9221 100644
--- a/cpukit/libfs/src/imfs/imfs_directory.c
+++ b/cpukit/libfs/src/imfs/imfs_directory.c
@@ -182,9 +182,9 @@ int imfs_dir_close(
* SEEK_END - N/A --> This will cause an assert.
*/
-off_t imfs_dir_lseek(
+rtems_off64_t imfs_dir_lseek(
rtems_libio_t *iop,
- off_t offset,
+ rtems_off64_t offset,
int whence
)
{
diff --git a/cpukit/libfs/src/imfs/imfs_fifo.c b/cpukit/libfs/src/imfs/imfs_fifo.c
index 5d3cf466c6..f02cfd31c6 100644
--- a/cpukit/libfs/src/imfs/imfs_fifo.c
+++ b/cpukit/libfs/src/imfs/imfs_fifo.c
@@ -119,10 +119,10 @@ int IMFS_fifo_ioctl(
IMFS_FIFO_RETURN(err);
}
-off_t IMFS_fifo_lseek(
+rtems_off64_t IMFS_fifo_lseek(
rtems_libio_t *iop,
- off_t offset,
- int whence
+ rtems_off64_t offset,
+ int whence
)
{
off_t err = pipe_lseek(LIBIO2PIPE(iop), offset, whence, iop);
diff --git a/cpukit/libfs/src/imfs/memfile.c b/cpukit/libfs/src/imfs/memfile.c
index 51ad8669bb..e9b4d70f97 100644
--- a/cpukit/libfs/src/imfs/memfile.c
+++ b/cpukit/libfs/src/imfs/memfile.c
@@ -214,9 +214,9 @@ int memfile_ioctl(
* This routine processes the lseek() system call.
*/
-off_t memfile_lseek(
+rtems_off64_t memfile_lseek(
rtems_libio_t *iop,
- off_t offset,
+ rtems_off64_t offset,
int whence
)
{
@@ -251,7 +251,7 @@ off_t memfile_lseek(
int memfile_ftruncate(
rtems_libio_t *iop,
- off_t length
+ rtems_off64_t length
)
{
IMFS_jnode_t *the_jnode;
diff --git a/cpukit/libfs/src/nfsclient/src/nfs.c b/cpukit/libfs/src/nfsclient/src/nfs.c
index 78c592a363..daafac8c87 100644
--- a/cpukit/libfs/src/nfsclient/src/nfs.c
+++ b/cpukit/libfs/src/nfsclient/src/nfs.c
@@ -2737,9 +2737,9 @@ static int nfs_file_ioctl(
#define nfs_link_ioctl 0
#endif
-static off_t nfs_file_lseek(
+static rtems_off64_t nfs_file_lseek(
rtems_libio_t *iop,
- off_t length,
+ rtems_off64_t length,
int whence
)
{
@@ -2770,9 +2770,9 @@ static off_t nfs_file_lseek(
return iop->offset;
}
-static off_t nfs_dir_lseek(
+static rtems_off64_t nfs_dir_lseek(
rtems_libio_t *iop,
- off_t length,
+ rtems_off64_t length,
int whence
)
{
@@ -2818,29 +2818,29 @@ struct fattr {
struct stat
{
- dev_t st_dev;
- ino_t st_ino;
- mode_t st_mode;
- nlink_t st_nlink;
- uid_t st_uid;
- gid_t st_gid;
- dev_t st_rdev;
- off_t st_size;
+ dev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ rtems_off64_t st_size;
/* SysV/sco doesn't have the rest... But Solaris, eabi does. */
#if defined(__svr4__) && !defined(__PPC__) && !defined(__sun__)
- time_t st_atime;
- time_t st_mtime;
- time_t st_ctime;
+ time_t st_atime;
+ time_t st_mtime;
+ time_t st_ctime;
#else
- time_t st_atime;
- long st_spare1;
- time_t st_mtime;
- long st_spare2;
- time_t st_ctime;
- long st_spare3;
- long st_blksize;
- long st_blocks;
- long st_spare4[2];
+ time_t st_atime;
+ long st_spare1;
+ time_t st_mtime;
+ long st_spare2;
+ time_t st_ctime;
+ long st_spare3;
+ long st_blksize;
+ long st_blocks;
+ long st_spare4[2];
#endif
};
#endif
@@ -3009,7 +3009,7 @@ sattr arg;
*/
static int nfs_file_ftruncate(
rtems_libio_t *iop,
- off_t length
+ rtems_off64_t length
)
{
sattr arg;
diff --git a/cpukit/libmisc/shell/main_msdosfmt.c b/cpukit/libmisc/shell/main_msdosfmt.c
index 12ba79e8c8..65e6e73a75 100644
--- a/cpukit/libmisc/shell/main_msdosfmt.c
+++ b/cpukit/libmisc/shell/main_msdosfmt.c
@@ -42,7 +42,8 @@ int rtems_shell_main_msdos_format(
fattype: MSDOS_FMT_FATANY,
media: 0,
quick_format: TRUE,
- cluster_align: 0
+ cluster_align: 0,
+ info_level: 0
};
const char* driver = NULL;
@@ -51,7 +52,7 @@ int rtems_shell_main_msdos_format(
for (arg = 1; arg < argc; arg++) {
if (argv[arg][0] == '-') {
switch (argv[arg][1]) {
- case 'v':
+ case 'V':
arg++;
if (arg == argc) {
fprintf (stderr, "error: no volume label.\n");
@@ -59,6 +60,15 @@ int rtems_shell_main_msdos_format(
}
rqdata.VolLabel = argv[arg];
break;
+
+ case 's':
+ arg++;
+ if (arg == argc) {
+ fprintf (stderr, "error: sectors per cluster count.\n");
+ return 1;
+ }
+ rqdata.sectors_per_cluster = rtems_shell_str2int(argv[arg]);
+ break;
case 'r':
arg++;
@@ -90,6 +100,10 @@ int rtems_shell_main_msdos_format(
}
break;
+ case 'v':
+ rqdata.info_level++;
+ break;
+
default:
fprintf (stderr, "error: invalid option: %s\n", argv[arg]);
return 1;
@@ -111,6 +125,19 @@ int rtems_shell_main_msdos_format(
}
printf ("msdos format: %s\n", driver);
+
+ if (rqdata.info_level)
+ {
+ printf (" %-20s: %s\n", "OEMName", "RTEMS");
+ printf (" %-20s: %s\n", "VolLabel", "RTEMSDisk");
+ printf (" %-20s: %i\n", "sectors per cluster", rqdata.sectors_per_cluster);
+ printf (" %-20s: %i\n", "fats", rqdata.fat_num);
+ printf (" %-20s: %i\n", "files per root dir", rqdata.files_per_root_dir);
+ printf (" %-20s: %i\n", "fat type", rqdata.fattype);
+ printf (" %-20s: %d\n", "media", rqdata.media);
+ printf (" %-20s: %d\n", "quick_format", rqdata.quick_format);
+ printf (" %-20s: %i\n", "cluster align", rqdata.cluster_align);
+ }
if (msdos_format (driver, &rqdata) < 0) {
fprintf (stderr, "error: format failed: %s\n", strerror (errno));
diff --git a/cpukit/libnetworking/lib/ftpfs.c b/cpukit/libnetworking/lib/ftpfs.c
index f73c6acff3..82e23dc287 100644
--- a/cpukit/libnetworking/lib/ftpfs.c
+++ b/cpukit/libnetworking/lib/ftpfs.c
@@ -986,7 +986,7 @@ static int rtems_ftpfs_close( rtems_libio_t *iop)
}
/* Dummy version to let fopen( *,"w") work properly */
-static int rtems_ftpfs_ftruncate( rtems_libio_t *iop, off_t count)
+static int rtems_ftpfs_ftruncate( rtems_libio_t *iop, rtems_off64_t count)
{
return 0;
}
diff --git a/cpukit/libnetworking/lib/tftpDriver.c b/cpukit/libnetworking/lib/tftpDriver.c
index 734d0bda35..ecb46c6c0f 100644
--- a/cpukit/libnetworking/lib/tftpDriver.c
+++ b/cpukit/libnetworking/lib/tftpDriver.c
@@ -984,7 +984,7 @@ static ssize_t rtems_tftp_write(
*/
static int rtems_tftp_ftruncate(
rtems_libio_t *iop __attribute__((unused)),
- off_t count __attribute__((unused))
+ rtems_off64_t count __attribute__((unused))
)
{
return 0;