dosfs: Support ctime and mtime

Implement ctime and mtime updates according to POSIX.  The ctime is
mapped to the FAT create time and date.  The mtime is mapped to the FAT
last modified time and date.  For the atime use the mtime for
simplicity.
This commit is contained in:
Sebastian Huber
2014-10-20 09:33:34 +02:00
parent 040ed0b4cd
commit a7eaaae85b
9 changed files with 170 additions and 133 deletions

View File

@@ -165,6 +165,38 @@ fat_file_reopen(fat_file_fd_t *fat_fd)
return RC_OK;
}
int
fat_file_update(fat_fs_info_t *fs_info, fat_file_fd_t *fat_fd)
{
int ret_rc = RC_OK;
/*
* if fat-file descriptor is not marked as "removed", synchronize
* size, first cluster number, write time and date fields of the file
*/
if (!FAT_FILE_IS_REMOVED(fat_fd))
{
int rc;
if (fat_fd->fat_file_type == FAT_FILE)
{
rc = fat_file_write_first_cluster_num(fs_info, fat_fd);
if (rc != RC_OK)
ret_rc = rc;
rc = fat_file_write_file_size(fs_info, fat_fd);
if (rc != RC_OK)
ret_rc = rc;
}
rc = fat_file_write_time_and_date(fs_info, fat_fd);
if (rc != RC_OK)
ret_rc = rc;
}
return ret_rc;
}
/* fat_file_close --
* Close fat-file. If count of links to fat-file
* descriptor is greater than 1 (i.e. somebody esle holds pointer
@@ -204,6 +236,8 @@ fat_file_close(
{
uint32_t key = fat_construct_key(fs_info, &fat_fd->dir_pos.sname);
fat_file_update(fs_info, fat_fd);
if (fat_fd->flags & FAT_FILE_REMOVED)
{
rc = fat_file_truncate(fs_info, fat_fd, 0);

View File

@@ -88,6 +88,7 @@ typedef struct fat_file_fd_s
fat_dir_pos_t dir_pos;
uint8_t flags;
fat_file_map_t map;
time_t ctime;
time_t mtime;
} fat_file_fd_t;
@@ -139,6 +140,22 @@ fat_construct_key(
((pos->ofs >> 5) & (FAT_DIRENTRIES_PER_SEC512 - 1)) );
}
static inline void fat_file_set_ctime(fat_file_fd_t *fat_fd, time_t t)
{
fat_fd->ctime = t;
}
static inline void fat_file_set_mtime(fat_file_fd_t *fat_fd, time_t t)
{
fat_fd->mtime = t;
}
static inline void fat_file_set_ctime_mtime(fat_file_fd_t *fat_fd, time_t t)
{
fat_fd->ctime = t;
fat_fd->mtime = t;
}
/* Prototypes for "fat-file" operations */
int
fat_file_open(fat_fs_info_t *fs_info,
@@ -192,6 +209,26 @@ void
fat_file_mark_removed(fat_fs_info_t *fs_info,
fat_file_fd_t *fat_fd);
int
fat_file_size(fat_fs_info_t *fs_info,
fat_file_fd_t *fat_fd);
int
fat_file_write_first_cluster_num(fat_fs_info_t *fs_info,
fat_file_fd_t *fat_fd);
int
fat_file_write_file_size(fat_fs_info_t *fs_info,
fat_file_fd_t *fat_fd);
int
fat_file_write_time_and_date(fat_fs_info_t *fs_info,
fat_file_fd_t *fat_fd);
int
fat_file_update(fat_fs_info_t *fs_info,
fat_file_fd_t *fat_fd);
#ifdef __cplusplus
}
#endif

View File

@@ -134,6 +134,8 @@ typedef rtems_filesystem_node_types_t msdos_node_type_t;
#define MSDOS_FILE_WDATE_OFFSET 24
#define MSDOS_FILE_WTIME_OFFSET 22
#define MSDOS_FILE_ADATE_OFFSET 18
#define MSDOS_FILE_CDATE_OFFSET 16
#define MSDOS_FILE_CTIME_OFFSET 14
/*
* Possible values of DIR_Attr field of 32 bytes long FAT Directory Entry
@@ -333,8 +335,6 @@ int msdos_initialize_support(
rtems_dosfs_convert_control *converter
);
int msdos_file_close(rtems_libio_t *iop /* IN */);
ssize_t msdos_file_read(
rtems_libio_t *iop, /* IN */
void *buffer, /* IN */
@@ -360,8 +360,6 @@ msdos_file_ftruncate(
int msdos_file_sync(rtems_libio_t *iop);
int msdos_file_datasync(rtems_libio_t *iop);
ssize_t msdos_dir_read(
rtems_libio_t *iop, /* IN */
void *buffer, /* IN */
@@ -461,28 +459,12 @@ void msdos_date_unix2dos(
unsigned int msdos_date_dos2unix(unsigned int dd, unsigned int dt);
int msdos_set_first_cluster_num(
rtems_filesystem_mount_table_entry_t *mt_entry,
fat_file_fd_t *fat_fd
);
int msdos_set_file_size(
rtems_filesystem_mount_table_entry_t *mt_entry,
fat_file_fd_t *fat_fd
);
int msdos_set_first_char4file_name(
rtems_filesystem_mount_table_entry_t *mt_entry,
fat_dir_pos_t *dir_pos,
unsigned char first_char
);
int msdos_set_dir_wrt_time_and_date(
rtems_filesystem_mount_table_entry_t *mt_entry,
fat_file_fd_t *fat_fd
);
int msdos_dir_is_empty(
rtems_filesystem_mount_table_entry_t *mt_entry,
fat_file_fd_t *fat_fd,

View File

@@ -70,7 +70,7 @@ msdos_creat_node(const rtems_filesystem_location_info_t *parent_loc,
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;
time_t now;
uint16_t time_val = 0;
uint16_t date = 0;
fat_dir_pos_t dir_pos;
@@ -102,11 +102,10 @@ msdos_creat_node(const rtems_filesystem_location_info_t *parent_loc,
*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;
now = time(NULL);
fat_file_set_ctime_mtime(parent_fat_fd, now);
msdos_date_unix2dos(time_ret, &date, &time_val);
msdos_date_unix2dos(now, &date, &time_val);
*MSDOS_DIR_CRT_TIME(short_node) = CT_LE_W(time_val);
*MSDOS_DIR_CRT_DATE(short_node) = CT_LE_W(date);
*MSDOS_DIR_WRITE_TIME(short_node) = CT_LE_W(time_val);
@@ -192,6 +191,7 @@ msdos_creat_node(const rtems_filesystem_location_info_t *parent_loc,
fat_fd->fat_file_size = 0;
fat_fd->fat_file_type = FAT_DIRECTORY;
fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
fat_file_set_ctime_mtime(fat_fd, now);
/*
* dot and dotdot entries are identical to new node except the
@@ -260,7 +260,7 @@ msdos_creat_node(const rtems_filesystem_location_info_t *parent_loc,
}
/* write first cluster num of a new directory to disk */
rc = msdos_set_first_cluster_num(parent_loc->mt_entry, fat_fd);
rc = fat_file_write_first_cluster_num(&fs_info->fat, fat_fd);
if (rc != RC_OK)
goto error;

View File

@@ -403,6 +403,8 @@ msdos_dir_stat(
buf->st_size = fat_fd->fat_file_size;
buf->st_blocks = fat_fd->fat_file_size >> FAT_SECTOR512_BITS;
buf->st_blksize = fs_info->fat.vol.bps;
buf->st_atime = fat_fd->mtime;
buf->st_ctime = fat_fd->ctime;
buf->st_mtime = fat_fd->mtime;
rtems_semaphore_release(fs_info->vol_sema);

View File

@@ -30,70 +30,6 @@
#include "msdos.h"
static int
msdos_file_update(rtems_libio_t *iop)
{
int rc = RC_OK;
fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
/*
* if fat-file descriptor is not marked as "removed", synchronize
* size, first cluster number, write time and date fields of the file
*/
if (!FAT_FILE_IS_REMOVED(fat_fd))
{
rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd);
if (rc != RC_OK)
{
return rc;
}
rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
if (rc != RC_OK)
{
return rc;
}
rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
if (rc != RC_OK)
{
return rc;
}
}
return rc;
}
/* msdos_file_close --
* Close fat-file which correspondes to the file. If fat-file descriptor
* which correspondes to the file is not marked "removed", synchronize
* size, first cluster number, write time and date fields of the file.
*
* PARAMETERS:
* iop - file control block
*
* RETURNS:
* RC_OK, if file closed successfully, or -1 if error occured (errno set
* appropriately)
*/
int
msdos_file_close(rtems_libio_t *iop)
{
int rc = RC_OK;
rtems_status_code sc = RTEMS_SUCCESSFUL;
msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
rtems_set_errno_and_return_minus_one(EIO);
rc = msdos_file_update(iop);
rtems_semaphore_release(fs_info->vol_sema);
return rc;
}
/* msdos_file_read --
* This routine read from file pointed to by file control block into
* the specified data buffer provided by user
@@ -174,6 +110,9 @@ msdos_file_write(rtems_libio_t *iop,const void *buffer, size_t count)
if (iop->offset > fat_fd->fat_file_size)
fat_fd->fat_file_size = iop->offset;
if (ret > 0)
fat_file_set_ctime_mtime(fat_fd, time(NULL));
rtems_semaphore_release(fs_info->vol_sema);
return ret;
}
@@ -211,6 +150,8 @@ msdos_file_stat(
buf->st_blocks = ((fat_fd->fat_file_size + cl_mask) & ~cl_mask)
>> FAT_SECTOR512_BITS;
buf->st_blksize = fs_info->fat.vol.bpc;
buf->st_atime = fat_fd->mtime;
buf->st_ctime = fat_fd->ctime;
buf->st_mtime = fat_fd->mtime;
rtems_semaphore_release(fs_info->vol_sema);
@@ -259,8 +200,10 @@ msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
}
}
if (rc == RC_OK) {
if (rc == RC_OK)
{
fat_fd->fat_file_size = length;
fat_file_set_ctime_mtime(fat_fd, time(NULL));
}
rtems_semaphore_release(fs_info->vol_sema);
@@ -284,13 +227,14 @@ msdos_file_sync(rtems_libio_t *iop)
int rc = RC_OK;
rtems_status_code sc = RTEMS_SUCCESSFUL;
msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
rtems_set_errno_and_return_minus_one(EIO);
rc = msdos_file_update(iop);
rc = fat_file_update(&fs_info->fat, fat_fd);
if (rc != RC_OK)
{
rtems_semaphore_release(fs_info->vol_sema);

View File

@@ -23,7 +23,7 @@
const rtems_filesystem_file_handlers_r msdos_file_handlers = {
.open_h = rtems_filesystem_default_open,
.close_h = msdos_file_close,
.close_h = rtems_filesystem_default_close,
.read_h = msdos_file_read,
.write_h = msdos_file_write,
.ioctl_h = rtems_filesystem_default_ioctl,

View File

@@ -35,6 +35,22 @@ static int msdos_clone_node_info(rtems_filesystem_location_info_t *loc)
return fat_file_reopen(fat_fd);
}
static int msdos_utime(
const rtems_filesystem_location_info_t *loc,
time_t actime,
time_t modtime
)
{
fat_file_fd_t *fat_fd = loc->node_access;
if (actime != modtime)
rtems_set_errno_and_return_minus_one( ENOTSUP );
fat_file_set_mtime(fat_fd, modtime);
return RC_OK;
}
const rtems_filesystem_operations_table msdos_ops = {
.lock_h = msdos_lock,
.unlock_h = msdos_unlock,
@@ -52,7 +68,7 @@ const rtems_filesystem_operations_table msdos_ops = {
.fsmount_me_h = rtems_dosfs_initialize,
.unmount_h = rtems_filesystem_default_unmount,
.fsunmount_me_h = msdos_shut_down,
.utime_h = rtems_filesystem_default_utime,
.utime_h = msdos_utime,
.symlink_h = rtems_filesystem_default_symlink,
.readlink_h = rtems_filesystem_default_readlink,
.rename_h = msdos_rename,

View File

@@ -380,6 +380,11 @@ msdos_find_name(
fat_fd->mtime = msdos_date_dos2unix(CF_LE_W(date), CF_LE_W(time_val));
time_val = *MSDOS_DIR_CRT_TIME(node_entry);
date = *MSDOS_DIR_CRT_DATE(node_entry);
fat_fd->ctime = msdos_date_dos2unix(CF_LE_W(date), CF_LE_W(time_val));
if ((*MSDOS_DIR_ATTR(node_entry)) & MSDOS_ATTR_DIRECTORY)
{
fat_fd->fat_file_type = FAT_DIRECTORY;
@@ -670,12 +675,12 @@ msdos_get_dotdot_dir_info_cluster_num_and_offset(
}
/* msdos_set_dir_wrt_time_and_date --
/* fat_file_write_time_and_date --
* Write last write date and time for a file to the disk (to corresponded
* 32bytes node)
*
* PARAMETERS:
* mt_entry - mount table entry
* fs_info - fat fs info
* fat_fd - fat-file descriptor
*
* RETURNS:
@@ -683,50 +688,69 @@ msdos_get_dotdot_dir_info_cluster_num_and_offset(
*
*/
int
msdos_set_dir_wrt_time_and_date(
rtems_filesystem_mount_table_entry_t *mt_entry,
fat_file_write_time_and_date(
fat_fs_info_t *fs_info,
fat_file_fd_t *fat_fd
)
{
ssize_t ret1 = 0, ret2 = 0, ret3 = 0;
msdos_fs_info_t *fs_info = mt_entry->fs_info;
int rc = RC_OK;
ssize_t ret;
uint16_t time_val;
uint16_t date;
uint32_t sec = 0;
uint32_t byte = 0;
msdos_date_unix2dos(fat_fd->mtime, &date, &time_val);
/*
* calculate input for fat_sector_write: convert (cluster num, offset) to
* (sector num, new offset)
*/
sec = fat_cluster_num_to_sector_num(&fs_info->fat, fat_fd->dir_pos.sname.cln);
sec += (fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
sec = fat_cluster_num_to_sector_num(fs_info, fat_fd->dir_pos.sname.cln);
sec += (fat_fd->dir_pos.sname.ofs >> fs_info->vol.sec_log2);
/* byte points to start of 32bytes structure */
byte = fat_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1);
byte = fat_fd->dir_pos.sname.ofs & (fs_info->vol.bps - 1);
msdos_date_unix2dos(fat_fd->mtime, &date, &time_val);
time_val = CT_LE_W(time_val);
ret1 = fat_sector_write(&fs_info->fat, sec, byte + MSDOS_FILE_WTIME_OFFSET,
2, (char *)(&time_val));
ret = fat_sector_write(fs_info, sec, byte + MSDOS_FILE_WTIME_OFFSET,
2, (char *)(&time_val));
if ( ret < 0 )
rc = -1;
date = CT_LE_W(date);
ret2 = fat_sector_write(&fs_info->fat, sec, byte + MSDOS_FILE_WDATE_OFFSET,
2, (char *)(&date));
ret3 = fat_sector_write(&fs_info->fat, sec, byte + MSDOS_FILE_ADATE_OFFSET,
2, (char *)(&date));
ret = fat_sector_write(fs_info, sec, byte + MSDOS_FILE_WDATE_OFFSET,
2, (char *)(&date));
if ( ret < 0 )
rc = -1;
if ( (ret1 < 0) || (ret2 < 0) || (ret3 < 0) )
return -1;
ret = fat_sector_write(fs_info, sec, byte + MSDOS_FILE_ADATE_OFFSET,
2, (char *)(&date));
if ( ret < 0 )
rc = -1;
return RC_OK;
msdos_date_unix2dos(fat_fd->ctime, &date, &time_val);
time_val = CT_LE_W(time_val);
ret = fat_sector_write(fs_info, sec, byte + MSDOS_FILE_CTIME_OFFSET,
2, (char *)(&time_val));
if ( ret < 0 )
rc = -1;
date = CT_LE_W(date);
ret = fat_sector_write(fs_info, sec, byte + MSDOS_FILE_CDATE_OFFSET,
2, (char *)(&date));
if ( ret < 0 )
rc = -1;
return rc;
}
/* msdos_set_first_cluster_num --
/* fat_set_first_cluster_num --
* Write number of first cluster of the file to the disk (to corresponded
* 32bytes slot)
*
* PARAMETERS:
* mt_entry - mount table entry
* fs_info - fat fs info
* fat_fd - fat-file descriptor
*
* RETURNS:
@@ -734,13 +758,12 @@ msdos_set_dir_wrt_time_and_date(
*
*/
int
msdos_set_first_cluster_num(
rtems_filesystem_mount_table_entry_t *mt_entry,
fat_file_write_first_cluster_num(
fat_fs_info_t *fs_info,
fat_file_fd_t *fat_fd
)
{
ssize_t ret1 = 0, ret2 = 0;
msdos_fs_info_t *fs_info = mt_entry->fs_info;
uint32_t new_cln = fat_fd->cln;
uint16_t le_cl_low = 0;
uint16_t le_cl_hi = 0;
@@ -751,17 +774,17 @@ msdos_set_first_cluster_num(
* calculate input for fat_sector_write: convert (cluster num, offset) to
* (sector num, new offset)
*/
sec = fat_cluster_num_to_sector_num(&fs_info->fat, fat_fd->dir_pos.sname.cln);
sec += (fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
sec = fat_cluster_num_to_sector_num(fs_info, fat_fd->dir_pos.sname.cln);
sec += (fat_fd->dir_pos.sname.ofs >> fs_info->vol.sec_log2);
/* byte from points to start of 32bytes structure */
byte = fat_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1);
byte = fat_fd->dir_pos.sname.ofs & (fs_info->vol.bps - 1);
le_cl_low = CT_LE_W((uint16_t )(new_cln & 0x0000FFFF));
ret1 = fat_sector_write(&fs_info->fat, sec,
ret1 = fat_sector_write(fs_info, sec,
byte + MSDOS_FIRST_CLUSTER_LOW_OFFSET, 2,
(char *)(&le_cl_low));
le_cl_hi = CT_LE_W((uint16_t )((new_cln & 0xFFFF0000) >> 16));
ret2 = fat_sector_write(&fs_info->fat, sec,
ret2 = fat_sector_write(fs_info, sec,
byte + MSDOS_FIRST_CLUSTER_HI_OFFSET, 2,
(char *)(&le_cl_hi));
if ( (ret1 < 0) || (ret2 < 0) )
@@ -771,11 +794,11 @@ msdos_set_first_cluster_num(
}
/* msdos_set_file size --
/* fat_set_file size --
* Write file size of the file to the disk (to corresponded 32bytes slot)
*
* PARAMETERS:
* mt_entry - mount table entry
* fs_info - fat fs info
* fat_fd - fat-file descriptor
*
* RETURNS:
@@ -783,23 +806,22 @@ msdos_set_first_cluster_num(
*
*/
int
msdos_set_file_size(
rtems_filesystem_mount_table_entry_t *mt_entry,
fat_file_write_file_size(
fat_fs_info_t *fs_info,
fat_file_fd_t *fat_fd
)
{
ssize_t ret = 0;
msdos_fs_info_t *fs_info = mt_entry->fs_info;
uint32_t le_new_length = 0;
uint32_t sec = 0;
uint32_t byte = 0;
sec = fat_cluster_num_to_sector_num(&fs_info->fat, 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));
sec = fat_cluster_num_to_sector_num(fs_info, fat_fd->dir_pos.sname.cln);
sec += (fat_fd->dir_pos.sname.ofs >> fs_info->vol.sec_log2);
byte = (fat_fd->dir_pos.sname.ofs & (fs_info->vol.bps - 1));
le_new_length = CT_LE_L((fat_fd->fat_file_size));
ret = fat_sector_write(&fs_info->fat, sec, byte + MSDOS_FILE_SIZE_OFFSET, 4,
ret = fat_sector_write(fs_info, sec, byte + MSDOS_FILE_SIZE_OFFSET, 4,
(char *)(&le_new_length));
if ( ret < 0 )
return -1;