forked from Imagelibrary/rtems
2002-02-28 Victor V. Vengerov <vvv@oktet.ru>
* DOS filesystem including FAT12, FAT16, and FAT32 support submitted. * src/dosfs, src/dosfs/Makefile.am, src/dosfs/stamp-h2.in, src/dosfs/config.h.in, src/dosfs/dosfs.h, src/dosfs/fat.c, src/dosfs/fat.h, src/dosfs/fat_fat_operations.c, src/dosfs/fat_fat_operations.h, src/dosfs/fat_file.c, src/dosfs/fat_file.h, src/dosfs/msdos.h, src/dosfs/msdos_create.c, src/dosfs/msdos_dir.c, src/dosfs/msdos_eval.c, src/dosfs/msdos_file.c, src/dosfs/msdos_free.c, src/dosfs/msdos_fsunmount.c, src/dosfs/msdos_handlers_dir.c, src/dosfs/msdos_handlers_file.c, src/dosfs/msdos_init.c, src/dosfs/msdos_initsupp.c, src/dosfs/msdos_misc.c, src/dosfs/msdos_mknod.c, src/dosfs/msdos_node_type.c, src/dosfs/.cvsignore: New files. * configure.ac, src/Makefile.am, wrapup/Makefile.am: Modified to reflect addition.
This commit is contained in:
@@ -1,3 +1,20 @@
|
|||||||
|
2002-02-28 Victor V. Vengerov <vvv@oktet.ru>
|
||||||
|
|
||||||
|
* DOS filesystem including FAT12, FAT16, and FAT32 support submitted.
|
||||||
|
* src/dosfs, src/dosfs/Makefile.am, src/dosfs/stamp-h2.in,
|
||||||
|
src/dosfs/config.h.in, src/dosfs/dosfs.h, src/dosfs/fat.c,
|
||||||
|
src/dosfs/fat.h, src/dosfs/fat_fat_operations.c,
|
||||||
|
src/dosfs/fat_fat_operations.h, src/dosfs/fat_file.c,
|
||||||
|
src/dosfs/fat_file.h, src/dosfs/msdos.h, src/dosfs/msdos_create.c,
|
||||||
|
src/dosfs/msdos_dir.c, src/dosfs/msdos_eval.c, src/dosfs/msdos_file.c,
|
||||||
|
src/dosfs/msdos_free.c, src/dosfs/msdos_fsunmount.c,
|
||||||
|
src/dosfs/msdos_handlers_dir.c, src/dosfs/msdos_handlers_file.c,
|
||||||
|
src/dosfs/msdos_init.c, src/dosfs/msdos_initsupp.c,
|
||||||
|
src/dosfs/msdos_misc.c, src/dosfs/msdos_mknod.c,
|
||||||
|
src/dosfs/msdos_node_type.c, src/dosfs/.cvsignore: New files.
|
||||||
|
* configure.ac, src/Makefile.am, wrapup/Makefile.am: Modified to
|
||||||
|
reflect addition.
|
||||||
|
|
||||||
2002-01-07 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
2002-01-07 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
||||||
|
|
||||||
* src/imfs/imfs_load_tar.c: Add include <sys/types.h>.
|
* src/imfs/imfs_load_tar.c: Add include <sys/types.h>.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
AC_PREREQ(2.52)
|
AC_PREREQ(2.52)
|
||||||
AC_INIT
|
AC_INIT
|
||||||
AC_CONFIG_SRCDIR([src/imfs/imfs.h])
|
AC_CONFIG_SRCDIR([src/imfs/imfs.h])
|
||||||
|
AC_CONFIG_SRCDIR([src/dosfs/dosfs.h])
|
||||||
RTEMS_TOP(../../..)
|
RTEMS_TOP(../../..)
|
||||||
AC_CONFIG_AUX_DIR(../../..)
|
AC_CONFIG_AUX_DIR(../../..)
|
||||||
|
|
||||||
@@ -27,11 +28,13 @@ RTEMS_CANONICALIZE_TOOLS
|
|||||||
|
|
||||||
AM_CONDITIONAL(UNIX,test x"$RTEMS_CPU" = x"unix")
|
AM_CONDITIONAL(UNIX,test x"$RTEMS_CPU" = x"unix")
|
||||||
AM_CONFIG_HEADER(src/imfs/config.h)
|
AM_CONFIG_HEADER(src/imfs/config.h)
|
||||||
|
AM_CONFIG_HEADER(src/dosfs/config.h)
|
||||||
|
|
||||||
# Explicitly list all Makefiles here
|
# Explicitly list all Makefiles here
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
src/imfs/Makefile
|
src/imfs/Makefile
|
||||||
|
src/dosfs/Makefile
|
||||||
wrapup/Makefile
|
wrapup/Makefile
|
||||||
])
|
])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
AUTOMAKE_OPTIONS = foreign 1.4
|
AUTOMAKE_OPTIONS = foreign 1.4
|
||||||
|
|
||||||
SUBDIRS = imfs
|
SUBDIRS = imfs dosfs
|
||||||
|
|
||||||
include $(top_srcdir)/../../../automake/subdirs.am
|
include $(top_srcdir)/../../../automake/subdirs.am
|
||||||
include $(top_srcdir)/../../../automake/local.am
|
include $(top_srcdir)/../../../automake/local.am
|
||||||
|
|||||||
6
c/src/exec/libfs/src/dosfs/.cvsignore
Normal file
6
c/src/exec/libfs/src/dosfs/.cvsignore
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
config.h
|
||||||
|
config.h.in
|
||||||
|
stamp-h
|
||||||
|
stamp-h.in
|
||||||
80
c/src/exec/libfs/src/dosfs/Makefile.am
Normal file
80
c/src/exec/libfs/src/dosfs/Makefile.am
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
##
|
||||||
|
## $Id$
|
||||||
|
##
|
||||||
|
|
||||||
|
AUTOMAKE_OPTIONS = foreign 1.4
|
||||||
|
|
||||||
|
INCLUDES = -I.
|
||||||
|
|
||||||
|
LIBNAME = libdosfs
|
||||||
|
LIB = ${ARCH}/${LIBNAME}.a
|
||||||
|
|
||||||
|
FATFS_C_FILES = fat.c fat_fat_operations.c fat_file.c
|
||||||
|
|
||||||
|
DOSFS_C_FILES = msdos_create.c msdos_dir.c msdos_eval.c msdos_file.c \
|
||||||
|
msdos_free.c msdos_fsunmount.c msdos_handlers_dir.c \
|
||||||
|
msdos_handlers_file.c msdos_init.c msdos_initsupp.c \
|
||||||
|
msdos_misc.c msdos_mknod.c msdos_node_type.c
|
||||||
|
|
||||||
|
|
||||||
|
UNIX_C_FILES = msdos_unixstub.c
|
||||||
|
|
||||||
|
EMBEDDED_C_FILES = $(FATFS_C_FILES) $(DOSFS_C_FILES)
|
||||||
|
|
||||||
|
COMMON_C_FILES =
|
||||||
|
|
||||||
|
if UNIX
|
||||||
|
C_FILES = $(COMMON_C_FILES) $(UNIX_C_FILES)
|
||||||
|
else
|
||||||
|
C_FILES = $(COMMON_C_FILES) $(EMBEDDED_C_FILES)
|
||||||
|
endif
|
||||||
|
C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o)
|
||||||
|
|
||||||
|
include_HEADERS = fat.h fat_fat_operations.h \
|
||||||
|
fat_file.h msdos.h dosfs.h
|
||||||
|
SYS_H_FILES =
|
||||||
|
RTEMS_H_FILES =
|
||||||
|
noinst_HEADERS =
|
||||||
|
|
||||||
|
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||||
|
include $(top_srcdir)/../../../automake/compile.am
|
||||||
|
include $(top_srcdir)/../../../automake/lib.am
|
||||||
|
|
||||||
|
PREINSTALL_FILES = $(PROJECT_INCLUDE) $(PROJECT_INCLUDE)/rtems \
|
||||||
|
$(PROJECT_INCLUDE)/sys $(include_HEADERS:%=$(PROJECT_INCLUDE)/%) \
|
||||||
|
$(RTEMS_H_FILES:%=$(PROJECT_INCLUDE)/rtems/%) \
|
||||||
|
$(SYS_H_FILES:%=$(PROJECT_INCLUDE)/sys/%)
|
||||||
|
|
||||||
|
$(PROJECT_INCLUDE):
|
||||||
|
@$(mkinstalldirs) $@
|
||||||
|
$(PROJECT_INCLUDE)/rtems:
|
||||||
|
@$(mkinstalldirs) $@
|
||||||
|
$(PROJECT_INCLUDE)/sys:
|
||||||
|
@$(mkinstalldirs) $@
|
||||||
|
|
||||||
|
$(PROJECT_INCLUDE)/%.h: %.h
|
||||||
|
$(INSTALL_DATA) $< $@
|
||||||
|
$(PROJECT_INCLUDE)/rtems/%.h: %.h
|
||||||
|
$(INSTALL_DATA) $< $@
|
||||||
|
$(PROJECT_INCLUDE)/sys/%.h: %.h
|
||||||
|
$(INSTALL_DATA) $< $@
|
||||||
|
|
||||||
|
OBJS = $(C_O_FILES)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add local stuff here using +=
|
||||||
|
#
|
||||||
|
|
||||||
|
AM_CFLAGS += $(LIBC_DEFINES)
|
||||||
|
|
||||||
|
all-local: ${ARCH} $(LIB)
|
||||||
|
|
||||||
|
$(LIB): ${OBJS}
|
||||||
|
$(make-library)
|
||||||
|
|
||||||
|
DOC_FILES =
|
||||||
|
|
||||||
|
EXTRA_DIST = $(DOC_FILES) $(COMMON_C_FILES) $(EMBEDDED_C_FILES) \
|
||||||
|
$(UNIX_C_FILES) $(RTEMS_H_FILES) $(SYS_H_FILES)
|
||||||
|
|
||||||
|
include $(top_srcdir)/../../../automake/local.am
|
||||||
31
c/src/exec/libfs/src/dosfs/dosfs.h
Normal file
31
c/src/exec/libfs/src/dosfs/dosfs.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* dosfs.h
|
||||||
|
*
|
||||||
|
* Application interface to MSDOS filesystem.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#ifndef __DOSFS_DOSFS_H__
|
||||||
|
#define __DOSFS_DOSFS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
|
||||||
|
extern rtems_filesystem_operations_table msdos_ops;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_DOSFS_H__ */
|
||||||
695
c/src/exec/libfs/src/dosfs/fat.c
Normal file
695
c/src/exec/libfs/src/dosfs/fat.c
Normal file
@@ -0,0 +1,695 @@
|
|||||||
|
/*
|
||||||
|
* fat.c
|
||||||
|
*
|
||||||
|
* Low-level operations on a volume with FAT filesystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
|
||||||
|
/* _fat_block_read --
|
||||||
|
* This function reads 'count' bytes from device filesystem is mounted on,
|
||||||
|
* starts at 'start+offset' position where 'start' computed in sectors
|
||||||
|
* and 'offset' is offset inside sector (reading may cross sectors
|
||||||
|
* boundary; in this case assumed we want to read sequential sector(s))
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* start - sector num to start read from
|
||||||
|
* offset - offset inside sector 'start'
|
||||||
|
* count - count of bytes to read
|
||||||
|
* buff - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* bytes read on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
_fat_block_read(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 offset,
|
||||||
|
unsigned32 count,
|
||||||
|
void *buff
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
ssize_t cmpltd = 0;
|
||||||
|
unsigned32 blk = start;
|
||||||
|
unsigned32 ofs = offset;
|
||||||
|
bdbuf_buffer *block = NULL;
|
||||||
|
unsigned32 c = 0;
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
c = MIN(count, (fs_info->vol.bps - ofs));
|
||||||
|
memcpy((buff + cmpltd), (block->buffer + ofs), c);
|
||||||
|
|
||||||
|
count -= c;
|
||||||
|
cmpltd += c;
|
||||||
|
blk++;
|
||||||
|
ofs = 0;
|
||||||
|
}
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _fat_block_write --
|
||||||
|
* This function write 'count' bytes to device filesystem is mounted on,
|
||||||
|
* starts at 'start+offset' position where 'start' computed in sectors
|
||||||
|
* and 'offset' is offset inside sector (writing may cross sectors
|
||||||
|
* boundary; in this case assumed we want to write sequential sector(s))
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* start - sector num to start read from
|
||||||
|
* offset - offset inside sector 'start'
|
||||||
|
* count - count of bytes to write
|
||||||
|
* buff - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* bytes written on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
_fat_block_write(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 offset,
|
||||||
|
unsigned32 count,
|
||||||
|
const void *buff)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
ssize_t cmpltd = 0;
|
||||||
|
unsigned32 blk = start;
|
||||||
|
unsigned32 ofs = offset;
|
||||||
|
bdbuf_buffer *block = NULL;
|
||||||
|
unsigned32 c = 0;
|
||||||
|
|
||||||
|
while(count > 0)
|
||||||
|
{
|
||||||
|
c = MIN(count, (fs_info->vol.bps - ofs));
|
||||||
|
|
||||||
|
if (c == fs_info->vol.bps)
|
||||||
|
rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_GET, &block);
|
||||||
|
else
|
||||||
|
rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
memcpy((block->buffer + ofs), (buff + cmpltd), c);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
|
||||||
|
count -= c;
|
||||||
|
cmpltd +=c;
|
||||||
|
blk++;
|
||||||
|
ofs = 0;
|
||||||
|
}
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* fat_cluster_read --
|
||||||
|
* wrapper for reading a whole cluster at once
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - number of cluster to read
|
||||||
|
* buff - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* bytes read on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
fat_cluster_read(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
void *buff
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 fsec = 0;
|
||||||
|
|
||||||
|
fsec = fat_cluster_num_to_sector_num(mt_entry, cln);
|
||||||
|
|
||||||
|
return _fat_block_read(mt_entry, fsec, 0,
|
||||||
|
fs_info->vol.spc << fs_info->vol.sec_log2, buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_cluster_write --
|
||||||
|
* wrapper for writting a whole cluster at once
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - number of cluster to write
|
||||||
|
* buff - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* bytes written on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
fat_cluster_write(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
const void *buff
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 fsec = 0;
|
||||||
|
|
||||||
|
fsec = fat_cluster_num_to_sector_num(mt_entry, cln);
|
||||||
|
|
||||||
|
return _fat_block_write(mt_entry, fsec, 0,
|
||||||
|
fs_info->vol.spc << fs_info->vol.sec_log2, buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_init_volume_info --
|
||||||
|
* Get inforamtion about volume on which filesystem is mounted on
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
register fat_vol_t *vol = &fs_info->vol;
|
||||||
|
unsigned32 data_secs = 0;
|
||||||
|
char boot_rec[FAT_MAX_BPB_SIZE];
|
||||||
|
char fs_info_sector[FAT_USEFUL_INFO_SIZE];
|
||||||
|
ssize_t ret = 0;
|
||||||
|
int fd;
|
||||||
|
struct stat stat_buf;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
rc = stat(mt_entry->dev, &stat_buf);
|
||||||
|
if (rc == -1)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* rtmes feature: no block devices, all are character devices */
|
||||||
|
if (!S_ISCHR(stat_buf.st_mode))
|
||||||
|
set_errno_and_return_minus_one(ENOTBLK);
|
||||||
|
|
||||||
|
/* check that device is registred as block device and lock it */
|
||||||
|
vol->dd = rtems_disk_lookup(stat_buf.st_dev);
|
||||||
|
if (vol->dd == NULL)
|
||||||
|
set_errno_and_return_minus_one(ENOTBLK);
|
||||||
|
|
||||||
|
vol->dev = stat_buf.st_dev;
|
||||||
|
|
||||||
|
fd = open(mt_entry->dev, O_RDONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = read(fd, (void *)boot_rec, FAT_MAX_BPB_SIZE);
|
||||||
|
if ( ret != FAT_MAX_BPB_SIZE )
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
vol->bps = FAT_BR_BYTES_PER_SECTOR(boot_rec);
|
||||||
|
|
||||||
|
if ( (vol->bps != 512) &&
|
||||||
|
(vol->bps != 1024) &&
|
||||||
|
(vol->bps != 2048) &&
|
||||||
|
(vol->bps != 4096))
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( EINVAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0;
|
||||||
|
i >>= 1, vol->sec_mul++);
|
||||||
|
for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0;
|
||||||
|
i >>= 1, vol->sec_log2++);
|
||||||
|
|
||||||
|
vol->spc = FAT_BR_SECTORS_PER_CLUSTER(boot_rec);
|
||||||
|
for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0;
|
||||||
|
i >>= 1, vol->spc_log2++);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* According to M$ White Paper "bytes per cluster" value
|
||||||
|
* greater than 32K is invalid
|
||||||
|
*/
|
||||||
|
if ((vol->bpc = vol->bps << vol->spc_log2) > MS_BYTES_PER_CLUSTER_LIMIT)
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0;
|
||||||
|
i >>= 1, vol->bpc_log2++);
|
||||||
|
|
||||||
|
vol->fats = FAT_BR_FAT_NUM(boot_rec);
|
||||||
|
vol->fat_loc = FAT_BR_RESERVED_SECTORS_NUM(boot_rec);
|
||||||
|
|
||||||
|
vol->rdir_entrs = FAT_BR_FILES_PER_ROOT_DIR(boot_rec);
|
||||||
|
|
||||||
|
/* calculate the count of sectors occupied by the root directory */
|
||||||
|
vol->rdir_secs = ((vol->rdir_entrs * FAT_DIRENTRY_SIZE) + (vol->bps - 1)) /
|
||||||
|
vol->bps;
|
||||||
|
|
||||||
|
vol->rdir_size = vol->rdir_secs << vol->sec_log2;
|
||||||
|
|
||||||
|
if ( (FAT_BR_SECTORS_PER_FAT(boot_rec)) != 0)
|
||||||
|
vol->fat_length = FAT_BR_SECTORS_PER_FAT(boot_rec);
|
||||||
|
else
|
||||||
|
vol->fat_length = FAT_BR_SECTORS_PER_FAT32(boot_rec);
|
||||||
|
|
||||||
|
vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length +
|
||||||
|
vol->rdir_secs;
|
||||||
|
|
||||||
|
/* for FAT12/16 root dir starts at(sector) */
|
||||||
|
vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length;
|
||||||
|
|
||||||
|
if ( (FAT_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0)
|
||||||
|
vol->tot_secs = FAT_BR_TOTAL_SECTORS_NUM16(boot_rec);
|
||||||
|
else
|
||||||
|
vol->tot_secs = FAT_BR_TOTAL_SECTORS_NUM32(boot_rec);
|
||||||
|
|
||||||
|
data_secs = vol->tot_secs - vol->data_fsec;
|
||||||
|
|
||||||
|
vol->data_cls = data_secs / vol->spc;
|
||||||
|
|
||||||
|
/* determine FAT type at least */
|
||||||
|
if ( vol->data_cls < FAT_FAT12_MAX_CLN)
|
||||||
|
{
|
||||||
|
vol->type = FAT_FAT12;
|
||||||
|
vol->mask = FAT_FAT12_MASK;
|
||||||
|
vol->eoc_val = FAT_FAT12_EOC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( vol->data_cls < FAT_FAT16_MAX_CLN)
|
||||||
|
{
|
||||||
|
vol->type = FAT_FAT16;
|
||||||
|
vol->mask = FAT_FAT16_MASK;
|
||||||
|
vol->eoc_val = FAT_FAT16_EOC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vol->type = FAT_FAT32;
|
||||||
|
vol->mask = FAT_FAT32_MASK;
|
||||||
|
vol->eoc_val = FAT_FAT32_EOC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vol->type == FAT_FAT32)
|
||||||
|
{
|
||||||
|
vol->rdir_cl = FAT_BR_FAT32_ROOT_CLUSTER(boot_rec);
|
||||||
|
|
||||||
|
vol->mirror = FAT_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR;
|
||||||
|
if (vol->mirror)
|
||||||
|
vol->afat = FAT_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM;
|
||||||
|
else
|
||||||
|
vol->afat = 0;
|
||||||
|
|
||||||
|
vol->info_sec = FAT_BR_FAT32_FS_INFO_SECTOR(boot_rec);
|
||||||
|
if( vol->info_sec == 0 )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( EINVAL );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = _fat_block_read(mt_entry, vol->info_sec , 0,
|
||||||
|
FAT_FSI_LEADSIG_SIZE, fs_info_sector);
|
||||||
|
if ( ret < 0 )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAT_FSINFO_LEAD_SIGNATURE(fs_info_sector) !=
|
||||||
|
FAT_FSINFO_LEAD_SIGNATURE_VALUE)
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( EINVAL );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = _fat_block_read(mt_entry, vol->info_sec , FAT_FSI_INFO,
|
||||||
|
FAT_USEFUL_INFO_SIZE, fs_info_sector);
|
||||||
|
if ( ret < 0 )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vol->free_cls = FAT_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector);
|
||||||
|
vol->next_cl = FAT_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector);
|
||||||
|
rc = fat_fat32_update_fsinfo_sector(mt_entry, 0xFFFFFFFF,
|
||||||
|
0xFFFFFFFF);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vol->rdir_cl = 0;
|
||||||
|
vol->mirror = 0;
|
||||||
|
vol->afat = 0;
|
||||||
|
vol->free_cls = 0xFFFFFFFF;
|
||||||
|
vol->next_cl = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat;
|
||||||
|
|
||||||
|
/* set up collection of fat-files fd */
|
||||||
|
fs_info->vhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control));
|
||||||
|
if ( fs_info->vhash == NULL )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < FAT_HASH_SIZE; i++)
|
||||||
|
_Chain_Initialize_empty(fs_info->vhash + i);
|
||||||
|
|
||||||
|
fs_info->rhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control));
|
||||||
|
if ( fs_info->rhash == NULL )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
free(fs_info->vhash);
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
for (i = 0; i < FAT_HASH_SIZE; i++)
|
||||||
|
_Chain_Initialize_empty(fs_info->rhash + i);
|
||||||
|
|
||||||
|
fs_info->uino_pool_size = FAT_UINO_POOL_INIT_SIZE;
|
||||||
|
fs_info->uino_base = (vol->tot_secs << vol->sec_mul) << 4;
|
||||||
|
fs_info->index = 0;
|
||||||
|
fs_info->uino = (char *)calloc(fs_info->uino_pool_size, sizeof(char));
|
||||||
|
if ( fs_info->uino == NULL )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
free(fs_info->vhash);
|
||||||
|
free(fs_info->rhash);
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
fs_info->sec_buf = (char *)calloc(vol->bps, sizeof(char));
|
||||||
|
if (fs_info->sec_buf == NULL)
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
free(fs_info->vhash);
|
||||||
|
free(fs_info->rhash);
|
||||||
|
free(fs_info->uino);
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_shutdown_drive --
|
||||||
|
* Free all allocated resources and synchronize all necessary data
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_shutdown_drive(rtems_filesystem_mount_table_entry_t *mt_entry)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (fs_info->vol.type & FAT_FAT32)
|
||||||
|
{
|
||||||
|
rc = fat_fat32_update_fsinfo_sector(mt_entry, fs_info->vol.free_cls,
|
||||||
|
fs_info->vol.next_cl);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
|
||||||
|
if (rtems_bdbuf_syncdev(fs_info->vol.dev) != RTEMS_SUCCESSFUL)
|
||||||
|
rc = -1;
|
||||||
|
|
||||||
|
for (i = 0; i < FAT_HASH_SIZE; i++)
|
||||||
|
{
|
||||||
|
Chain_Node *node = NULL;
|
||||||
|
Chain_Control *the_chain = fs_info->vhash + i;
|
||||||
|
|
||||||
|
while ( (node = _Chain_Get(the_chain)) != NULL )
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < FAT_HASH_SIZE; i++)
|
||||||
|
{
|
||||||
|
Chain_Node *node = NULL;
|
||||||
|
Chain_Control *the_chain = fs_info->rhash + i;
|
||||||
|
|
||||||
|
while ( (node = _Chain_Get(the_chain)) != NULL )
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fs_info->vhash);
|
||||||
|
free(fs_info->rhash);
|
||||||
|
|
||||||
|
free(fs_info->uino);
|
||||||
|
free(fs_info->sec_buf);
|
||||||
|
rtems_disk_release(fs_info->vol.dd);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
errno = EIO;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_init_clusters_chain --
|
||||||
|
* Zeroing contents of all clusters in the chain
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* start_cluster_num - num of first cluster in the chain
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_init_clusters_chain(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start_cln
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
ssize_t ret = 0;
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = start_cln;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
buf = calloc(fs_info->vol.bpc, sizeof(char));
|
||||||
|
if ( buf == NULL )
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
||||||
|
{
|
||||||
|
ret = fat_cluster_write(mt_entry, cur_cln, buf);
|
||||||
|
if ( ret == -1 )
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FAT_UNIQ_INO_BASE 0x0FFFFF00
|
||||||
|
|
||||||
|
#define FAT_UNIQ_INO_IS_BUSY(index, arr) \
|
||||||
|
(((arr)[((index)>>3)]>>((index) & (8-1))) & 0x01)
|
||||||
|
|
||||||
|
#define FAT_SET_UNIQ_INO_BUSY(index, arr) \
|
||||||
|
((arr)[((index)>>3)] |= (0x01<<((index) & (8-1))))
|
||||||
|
|
||||||
|
#define FAT_SET_UNIQ_INO_FREE(index, arr) \
|
||||||
|
((arr)[((index)>>3)] &= (~(0x01<<((index) & (8-1)))))
|
||||||
|
|
||||||
|
/* fat_get_unique_ino --
|
||||||
|
* Allocate unique ino from unique ino pool
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* unique inode number on success, or 0 if there is no free unique inode
|
||||||
|
* number in the pool
|
||||||
|
*
|
||||||
|
* ATTENTION:
|
||||||
|
* 0 means FAILED !!!
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
unsigned32
|
||||||
|
fat_get_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry)
|
||||||
|
{
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 j = 0;
|
||||||
|
rtems_boolean resrc_unsuff = FALSE;
|
||||||
|
|
||||||
|
while (!resrc_unsuff)
|
||||||
|
{
|
||||||
|
for (j = 0; j < fs_info->uino_pool_size; j++)
|
||||||
|
{
|
||||||
|
if (!FAT_UNIQ_INO_IS_BUSY(fs_info->index, fs_info->uino))
|
||||||
|
{
|
||||||
|
FAT_SET_UNIQ_INO_BUSY(fs_info->index, fs_info->uino);
|
||||||
|
return (fs_info->uino_base + fs_info->index);
|
||||||
|
}
|
||||||
|
fs_info->index++;
|
||||||
|
if (fs_info->index >= fs_info->uino_pool_size)
|
||||||
|
fs_info->index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fs_info->uino_pool_size << 1) < (0x0FFFFFFF - fs_info->uino_base))
|
||||||
|
{
|
||||||
|
fs_info->uino_pool_size <<= 1;
|
||||||
|
fs_info->uino = realloc(fs_info->uino, fs_info->uino_pool_size);
|
||||||
|
if (fs_info->uino != NULL)
|
||||||
|
fs_info->index = fs_info->uino_pool_size;
|
||||||
|
else
|
||||||
|
resrc_unsuff = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
resrc_unsuff = TRUE;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_free_unique_ino --
|
||||||
|
* Return unique ino to unique ino pool
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* ino - inode number to free
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fat_free_unique_ino(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 ino
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
|
||||||
|
FAT_SET_UNIQ_INO_FREE((ino - fs_info->uino_base), fs_info->uino);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_ino_is_unique --
|
||||||
|
* Test whether ino is from unique ino pool
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* ino - ino to be tested
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* TRUE if ino is allocated from unique ino pool, FALSE otherwise
|
||||||
|
*/
|
||||||
|
inline rtems_boolean
|
||||||
|
fat_ino_is_unique(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 ino
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
|
||||||
|
return (ino >= fs_info->uino_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_fat32_update_fsinfo_sector --
|
||||||
|
* Synchronize fsinfo sector for FAT32 volumes
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* free_count - count of free clusters
|
||||||
|
* next_free - the next free cluster num
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_fat32_update_fsinfo_sector(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 free_count,
|
||||||
|
unsigned32 next_free
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ssize_t ret1 = 0, ret2 = 0;
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 le_free_count = 0;
|
||||||
|
unsigned32 le_next_free = 0;
|
||||||
|
|
||||||
|
le_free_count = CT_LE_L(free_count);
|
||||||
|
le_next_free = CT_LE_L(next_free);
|
||||||
|
|
||||||
|
ret1 = _fat_block_write(mt_entry,
|
||||||
|
fs_info->vol.info_sec,
|
||||||
|
FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET,
|
||||||
|
4,
|
||||||
|
(char *)(&le_free_count));
|
||||||
|
|
||||||
|
ret2 = _fat_block_write(mt_entry,
|
||||||
|
fs_info->vol.info_sec,
|
||||||
|
FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET,
|
||||||
|
4,
|
||||||
|
(char *)(&le_next_free));
|
||||||
|
|
||||||
|
if ( (ret1 < 0) || (ret2 < 0) )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
489
c/src/exec/libfs/src/dosfs/fat.h
Normal file
489
c/src/exec/libfs/src/dosfs/fat.h
Normal file
@@ -0,0 +1,489 @@
|
|||||||
|
/*
|
||||||
|
* fat.h
|
||||||
|
*
|
||||||
|
* Constants/data structures/prototypes for low-level operations on a volume
|
||||||
|
* with FAT filesystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DOSFS_FAT_H__
|
||||||
|
#define __DOSFS_FAT_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems/seterr.h>
|
||||||
|
|
||||||
|
/* XXX: temporary hack :(( */
|
||||||
|
#ifndef set_errno_and_return_minus_one
|
||||||
|
#define set_errno_and_return_minus_one rtems_set_errno_and_return_minus_one
|
||||||
|
#endif /* set_errno_and_return_minus_one */
|
||||||
|
|
||||||
|
#include <rtems/score/cpu.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <rtems/bdbuf.h>
|
||||||
|
|
||||||
|
#define DBG1(x) x
|
||||||
|
#define DBG2(x) x
|
||||||
|
|
||||||
|
#ifndef RC_OK
|
||||||
|
#define RC_OK 0x00000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remember that all FAT file system on disk data structure is
|
||||||
|
* "little endian"!
|
||||||
|
* (derived from linux)
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Conversion from and to little-endian byte order. (no-op on i386/i486)
|
||||||
|
*
|
||||||
|
* Naming: Ca_b_c, where a: F = from, T = to, b: LE = little-endian,
|
||||||
|
* BE = big-endian, c: W = word (16 bits), L = longword (32 bits)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (CPU_BIG_ENDIAN == TRUE)
|
||||||
|
# define CF_LE_W(v) CPU_swap_u16(v)
|
||||||
|
# define CF_LE_L(v) CPU_swap_u32(v)
|
||||||
|
# define CT_LE_W(v) CPU_swap_u16(v)
|
||||||
|
# define CT_LE_L(v) CPU_swap_u32(v)
|
||||||
|
#else
|
||||||
|
# define CF_LE_W(v) (v)
|
||||||
|
# define CF_LE_L(v) (v)
|
||||||
|
# define CT_LE_W(v) (v)
|
||||||
|
# define CT_LE_L(v) (v)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
#define FAT_HASH_SIZE 2
|
||||||
|
#define FAT_HASH_MODULE FAT_HASH_SIZE
|
||||||
|
|
||||||
|
|
||||||
|
#define FAT_SECTOR512_SIZE 512 /* sector size (bytes) */
|
||||||
|
#define FAT_SECTOR512_BITS 9 /* log2(SECTOR_SIZE) */
|
||||||
|
|
||||||
|
/* maximum + 1 number of clusters for FAT12 */
|
||||||
|
#define FAT_FAT12_MAX_CLN 4085
|
||||||
|
|
||||||
|
/* maximum + 1 number of clusters for FAT16 */
|
||||||
|
#define FAT_FAT16_MAX_CLN 65525
|
||||||
|
|
||||||
|
#define FAT_FAT12 0x01
|
||||||
|
#define FAT_FAT16 0x02
|
||||||
|
#define FAT_FAT32 0x04
|
||||||
|
|
||||||
|
#define FAT_UNDEFINED_VALUE 0xFFFFFFFF
|
||||||
|
|
||||||
|
#define FAT_FAT12_EOC 0x0FFF
|
||||||
|
#define FAT_FAT16_EOC 0xFFFF
|
||||||
|
#define FAT_FAT32_EOC 0x0FFFFFFF
|
||||||
|
|
||||||
|
#define FAT_FAT12_FREE 0x0000
|
||||||
|
#define FAT_FAT16_FREE 0x0000
|
||||||
|
#define FAT_FAT32_FREE 0x00000000
|
||||||
|
|
||||||
|
#define FAT_GENFAT_EOC 0xFFFFFFFF
|
||||||
|
#define FAT_GENFAT_FREE 0x00000000
|
||||||
|
|
||||||
|
#define FAT_FAT12_SHIFT 0x04
|
||||||
|
|
||||||
|
#define FAT_FAT12_MASK 0x00000FFF
|
||||||
|
#define FAT_FAT16_MASK 0x0000FFFF
|
||||||
|
#define FAT_FAT32_MASK 0x0FFFFFFF
|
||||||
|
|
||||||
|
#define FAT_MAX_BPB_SIZE 90
|
||||||
|
|
||||||
|
/* size of useful information in FSInfo sector */
|
||||||
|
#define FAT_USEFUL_INFO_SIZE 12
|
||||||
|
|
||||||
|
#define FAT_VAL8(x, ofs) (unsigned8)(*((unsigned8 *)(x) + (ofs)))
|
||||||
|
|
||||||
|
#define FAT_VAL16(x, ofs) \
|
||||||
|
(unsigned16)( (*((unsigned8 *)(x) + (ofs))) | \
|
||||||
|
((*((unsigned8 *)(x) + (ofs) + 1)) << 8) )
|
||||||
|
|
||||||
|
#define FAT_VAL32(x, ofs) \
|
||||||
|
(unsigned32)( (*((unsigned8 *)(x) + (ofs))) | \
|
||||||
|
((*((unsigned8 *)(x) + (ofs) + 1)) << 8) | \
|
||||||
|
((*((unsigned8 *)(x) + (ofs) + 2)) << 16) | \
|
||||||
|
((*((unsigned8 *)(x) + (ofs) + 3)) << 24) )
|
||||||
|
|
||||||
|
/* macros to access boot sector fields */
|
||||||
|
#define FAT_BR_BYTES_PER_SECTOR(x) FAT_VAL16(x, 11)
|
||||||
|
#define FAT_BR_SECTORS_PER_CLUSTER(x) FAT_VAL8(x, 13)
|
||||||
|
#define FAT_BR_RESERVED_SECTORS_NUM(x) FAT_VAL16(x, 14)
|
||||||
|
#define FAT_BR_FAT_NUM(x) FAT_VAL8(x, 16)
|
||||||
|
#define FAT_BR_FILES_PER_ROOT_DIR(x) FAT_VAL16(x, 17)
|
||||||
|
#define FAT_BR_TOTAL_SECTORS_NUM16(x) FAT_VAL16(x, 19)
|
||||||
|
#define FAT_BR_MEDIA(x) FAT_VAL8(x, 21)
|
||||||
|
#define FAT_BR_SECTORS_PER_FAT(x) FAT_VAL16(x, 22)
|
||||||
|
#define FAT_BR_TOTAL_SECTORS_NUM32(x) FAT_VAL32(x, 32)
|
||||||
|
#define FAT_BR_SECTORS_PER_FAT32(x) FAT_VAL32(x, 36)
|
||||||
|
#define FAT_BR_EXT_FLAGS(x) FAT_VAL16(x, 40)
|
||||||
|
#define FAT_BR_FAT32_ROOT_CLUSTER(x) FAT_VAL32(x, 44)
|
||||||
|
#define FAT_BR_FAT32_FS_INFO_SECTOR(x) FAT_VAL16(x, 48)
|
||||||
|
#define FAT_FSINFO_LEAD_SIGNATURE(x) FAT_VAL32(x, 0)
|
||||||
|
/*
|
||||||
|
* I read FSInfo sector from offset 484 to access the information, so offsets
|
||||||
|
* of these fields a relative
|
||||||
|
*/
|
||||||
|
#define FAT_FSINFO_FREE_CLUSTER_COUNT(x) FAT_VAL32(x, 4)
|
||||||
|
#define FAT_FSINFO_NEXT_FREE_CLUSTER(x) FAT_VAL32(x, 8)
|
||||||
|
|
||||||
|
#define FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET 488
|
||||||
|
|
||||||
|
#define FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET 492
|
||||||
|
|
||||||
|
#define FAT_RSRVD_CLN 0x02
|
||||||
|
|
||||||
|
#define FAT_FSINFO_LEAD_SIGNATURE_VALUE 0x41615252
|
||||||
|
|
||||||
|
#define FAT_FSI_LEADSIG_SIZE 0x04
|
||||||
|
|
||||||
|
#define FAT_FSI_INFO 484
|
||||||
|
|
||||||
|
#define MS_BYTES_PER_CLUSTER_LIMIT 0x8000 /* 32K */
|
||||||
|
|
||||||
|
#define FAT_BR_EXT_FLAGS_MIRROR 0x0080
|
||||||
|
|
||||||
|
#define FAT_BR_EXT_FLAGS_FAT_NUM 0x000F
|
||||||
|
|
||||||
|
|
||||||
|
#define FAT_DIRENTRY_SIZE 32
|
||||||
|
|
||||||
|
#define FAT_DIRENTRIES_PER_SEC512 16
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Volume descriptor
|
||||||
|
* Description of the volume the FAT filesystem is located on - generally
|
||||||
|
* the fields of the structure corresponde to Boot Sector and BPB Srtucture
|
||||||
|
* (see M$ White Paper) fields
|
||||||
|
*/
|
||||||
|
typedef struct fat_vol_s
|
||||||
|
{
|
||||||
|
unsigned16 bps; /* bytes per sector */
|
||||||
|
unsigned8 sec_log2; /* log2 of bps */
|
||||||
|
unsigned8 sec_mul; /* log2 of 512bts sectors number per sector */
|
||||||
|
unsigned8 spc; /* sectors per cluster */
|
||||||
|
unsigned8 spc_log2; /* log2 of spc */
|
||||||
|
unsigned16 bpc; /* bytes per cluster */
|
||||||
|
unsigned8 bpc_log2; /* log2 of bytes per cluster */
|
||||||
|
unsigned8 fats; /* number of FATs */
|
||||||
|
unsigned8 type; /* FAT type */
|
||||||
|
unsigned32 mask;
|
||||||
|
unsigned32 eoc_val;
|
||||||
|
unsigned16 fat_loc; /* FAT start */
|
||||||
|
unsigned32 fat_length; /* sectors per FAT */
|
||||||
|
unsigned32 rdir_loc; /* root directory start */
|
||||||
|
unsigned16 rdir_entrs; /* files per root directory */
|
||||||
|
unsigned32 rdir_secs; /* sectors per root directory */
|
||||||
|
unsigned32 rdir_size; /* root directory size in bytes */
|
||||||
|
unsigned32 tot_secs; /* total count of sectors */
|
||||||
|
unsigned32 data_fsec; /* first data sector */
|
||||||
|
unsigned32 data_cls; /* count of data clusters */
|
||||||
|
unsigned32 rdir_cl; /* first cluster of the root directory */
|
||||||
|
unsigned16 info_sec; /* FSInfo Sector Structure location */
|
||||||
|
unsigned32 free_cls; /* last known free clusters count */
|
||||||
|
unsigned32 next_cl; /* next free cluster number */
|
||||||
|
unsigned8 mirror; /* mirroring enabla/disable */
|
||||||
|
unsigned32 afat_loc; /* active FAT location */
|
||||||
|
unsigned8 afat; /* the number of active FAT */
|
||||||
|
dev_t dev; /* device ID */
|
||||||
|
disk_device *dd; /* disk device (see libblock) */
|
||||||
|
void *private_data; /* reserved */
|
||||||
|
} fat_vol_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct fat_cache_s
|
||||||
|
{
|
||||||
|
unsigned32 blk_num;
|
||||||
|
rtems_boolean modified;
|
||||||
|
unsigned8 state;
|
||||||
|
bdbuf_buffer *buf;
|
||||||
|
} fat_cache_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This structure identifies the instance of the filesystem on the FAT
|
||||||
|
* ("fat-file") level.
|
||||||
|
*/
|
||||||
|
typedef struct fat_fs_info_s
|
||||||
|
{
|
||||||
|
fat_vol_t vol; /* volume descriptor */
|
||||||
|
Chain_Control *vhash; /* "vhash" of fat-file descriptors */
|
||||||
|
Chain_Control *rhash; /* "rhash" of fat-file descriptors */
|
||||||
|
char *uino; /* array of unique ino numbers */
|
||||||
|
unsigned32 index;
|
||||||
|
unsigned32 uino_pool_size; /* size */
|
||||||
|
unsigned32 uino_base;
|
||||||
|
fat_cache_t c; /* cache */
|
||||||
|
unsigned8 *sec_buf; /* just placeholder for anything */
|
||||||
|
} 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
|
||||||
|
*/
|
||||||
|
typedef struct fat_auxiliary_s
|
||||||
|
{
|
||||||
|
unsigned32 cln;
|
||||||
|
unsigned32 ofs;
|
||||||
|
} fat_auxiliary_t;
|
||||||
|
|
||||||
|
#define FAT_FAT_OFFSET(fat_type, cln) \
|
||||||
|
((fat_type) & FAT_FAT12 ? ((cln) + ((cln) >> 1)) : \
|
||||||
|
(fat_type) & FAT_FAT16 ? ((cln) << 1) : \
|
||||||
|
((cln) << 2))
|
||||||
|
|
||||||
|
#define FAT_CLUSTER_IS_ODD(n) ((n) & 0x0001)
|
||||||
|
|
||||||
|
#define FAT12_SHIFT 0x4 /* half of a byte */
|
||||||
|
|
||||||
|
/* initial size of array of unique ino */
|
||||||
|
#define FAT_UINO_POOL_INIT_SIZE 0x100
|
||||||
|
|
||||||
|
/* cache support */
|
||||||
|
#define FAT_CACHE_EMPTY 0x0
|
||||||
|
#define FAT_CACHE_ACTUAL 0x1
|
||||||
|
|
||||||
|
#define FAT_OP_TYPE_READ 0x1
|
||||||
|
#define FAT_OP_TYPE_GET 0x2
|
||||||
|
|
||||||
|
static inline unsigned32
|
||||||
|
fat_cluster_num_to_sector_num(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln
|
||||||
|
)
|
||||||
|
{
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
|
||||||
|
if ( (cln == 0) && (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)) )
|
||||||
|
return fs_info->vol.rdir_loc;
|
||||||
|
|
||||||
|
return (((cln - FAT_RSRVD_CLN) << fs_info->vol.spc_log2) +
|
||||||
|
fs_info->vol.data_fsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned32
|
||||||
|
fat_cluster_num_to_sector512_num(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
|
||||||
|
if (cln == 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return (fat_cluster_num_to_sector_num(mt_entry, cln) <<
|
||||||
|
fs_info->vol.sec_mul);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
fat_buf_access(fat_fs_info_t *fs_info, unsigned32 blk, int op_type,
|
||||||
|
bdbuf_buffer **buf)
|
||||||
|
{
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
unsigned8 i;
|
||||||
|
rtems_boolean sec_of_fat;
|
||||||
|
|
||||||
|
|
||||||
|
if (fs_info->c.state == FAT_CACHE_EMPTY)
|
||||||
|
{
|
||||||
|
if (op_type == FAT_OP_TYPE_READ)
|
||||||
|
sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
|
||||||
|
else
|
||||||
|
sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
fs_info->c.blk_num = blk;
|
||||||
|
fs_info->c.state = FAT_CACHE_ACTUAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
|
||||||
|
(fs_info->c.blk_num < fs_info->vol.rdir_loc));
|
||||||
|
|
||||||
|
if (fs_info->c.blk_num != blk)
|
||||||
|
{
|
||||||
|
if (fs_info->c.modified)
|
||||||
|
{
|
||||||
|
if (sec_of_fat && !fs_info->vol.mirror)
|
||||||
|
memcpy(fs_info->sec_buf, fs_info->c.buf->buffer,
|
||||||
|
fs_info->vol.bps);
|
||||||
|
|
||||||
|
sc = rtems_bdbuf_release_modified(fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
fs_info->c.modified = 0;
|
||||||
|
|
||||||
|
if (sec_of_fat && !fs_info->vol.mirror)
|
||||||
|
{
|
||||||
|
bdbuf_buffer *b;
|
||||||
|
|
||||||
|
for (i = 1; i < fs_info->vol.fats; i++)
|
||||||
|
{
|
||||||
|
sc = rtems_bdbuf_get(fs_info->vol.dev,
|
||||||
|
fs_info->c.blk_num +
|
||||||
|
fs_info->vol.fat_length * i,
|
||||||
|
&b);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
|
||||||
|
sc = rtems_bdbuf_release_modified(b);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sc = rtems_bdbuf_release(fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (op_type == FAT_OP_TYPE_READ)
|
||||||
|
sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
|
||||||
|
else
|
||||||
|
sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
fs_info->c.blk_num = blk;
|
||||||
|
}
|
||||||
|
*buf = fs_info->c.buf;
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
fat_buf_release(fat_fs_info_t *fs_info)
|
||||||
|
{
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
unsigned8 i;
|
||||||
|
rtems_boolean sec_of_fat;
|
||||||
|
|
||||||
|
if (fs_info->c.state == FAT_CACHE_EMPTY)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
|
||||||
|
(fs_info->c.blk_num < fs_info->vol.rdir_loc));
|
||||||
|
|
||||||
|
if (fs_info->c.modified)
|
||||||
|
{
|
||||||
|
if (sec_of_fat && !fs_info->vol.mirror)
|
||||||
|
memcpy(fs_info->sec_buf, fs_info->c.buf->buffer, fs_info->vol.bps);
|
||||||
|
|
||||||
|
sc = rtems_bdbuf_release_modified(fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
fs_info->c.modified = 0;
|
||||||
|
|
||||||
|
if (sec_of_fat && !fs_info->vol.mirror)
|
||||||
|
{
|
||||||
|
bdbuf_buffer *b;
|
||||||
|
|
||||||
|
for (i = 1; i < fs_info->vol.fats; i++)
|
||||||
|
{
|
||||||
|
sc = rtems_bdbuf_get(fs_info->vol.dev,
|
||||||
|
fs_info->c.blk_num +
|
||||||
|
fs_info->vol.fat_length * i,
|
||||||
|
&b);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
|
||||||
|
sc = rtems_bdbuf_release_modified(b);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sc = rtems_bdbuf_release(fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
}
|
||||||
|
fs_info->c.state = FAT_CACHE_EMPTY;
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
fat_buf_mark_modified(fat_fs_info_t *fs_info)
|
||||||
|
{
|
||||||
|
fs_info->c.modified = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
_fat_block_read(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 offset,
|
||||||
|
unsigned32 count,
|
||||||
|
void *buff);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
_fat_block_write(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 offset,
|
||||||
|
unsigned32 count,
|
||||||
|
const void *buff);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
fat_cluster_read(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
void *buff);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
fat_cluster_write(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
const void *buff);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_init_clusters_chain(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start_cln);
|
||||||
|
|
||||||
|
unsigned32
|
||||||
|
fat_cluster_num_to_sector_num(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_shutdown_drive(rtems_filesystem_mount_table_entry_t *mt_entry);
|
||||||
|
|
||||||
|
|
||||||
|
unsigned32
|
||||||
|
fat_get_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry);
|
||||||
|
|
||||||
|
rtems_boolean
|
||||||
|
fat_ino_is_unique(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 ino);
|
||||||
|
|
||||||
|
void
|
||||||
|
fat_free_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 ino);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_fat32_update_fsinfo_sector(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 free_count,
|
||||||
|
unsigned32 next_free
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_FAT_H__ */
|
||||||
445
c/src/exec/libfs/src/dosfs/fat_fat_operations.c
Normal file
445
c/src/exec/libfs/src/dosfs/fat_fat_operations.c
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
/*
|
||||||
|
* fat_fat_operations.c
|
||||||
|
*
|
||||||
|
* General operations on File Allocation Table
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
|
||||||
|
/* fat_scan_fat_for_free_clusters --
|
||||||
|
* Allocate chain of free clusters from Files Allocation Table
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* chain - the number of the first allocated cluster (first cluster
|
||||||
|
* in the chain)
|
||||||
|
* count - count of clusters to allocate (chain length)
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or error code if error occured (errno set
|
||||||
|
* appropriately)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_scan_fat_for_free_clusters(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 *chain,
|
||||||
|
unsigned32 count,
|
||||||
|
unsigned32 *cls_added,
|
||||||
|
unsigned32 *last_cl
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cl4find = 2;
|
||||||
|
unsigned32 next_cln = 0;
|
||||||
|
unsigned32 save_cln = 0;
|
||||||
|
unsigned32 data_cls_val = fs_info->vol.data_cls + 2;
|
||||||
|
unsigned32 i = 2;
|
||||||
|
|
||||||
|
*cls_added = 0;
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if ((fs_info->vol.type & FAT_FAT32) &&
|
||||||
|
(fs_info->vol.next_cl != FAT_UNDEFINED_VALUE))
|
||||||
|
cl4find = fs_info->vol.next_cl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fs_info->vol.data_cls is exactly the count of data clusters
|
||||||
|
* starting at cluster 2, so the maximum valid cluster number is
|
||||||
|
* (fs_info->vol.data_cls + 1)
|
||||||
|
*/
|
||||||
|
while (i < data_cls_val)
|
||||||
|
{
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cl4find, &next_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
if (*cls_added != 0)
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, (*chain));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((next_cln & fs_info->vol.mask) == FAT_GENFAT_FREE)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We are enforced to process allocation of the first free cluster
|
||||||
|
* by separate 'if' statement because otherwise undo function
|
||||||
|
* wouldn't work properly
|
||||||
|
*/
|
||||||
|
if (*cls_added == 0)
|
||||||
|
{
|
||||||
|
*chain = cl4find;
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_EOC);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* this is the first cluster we tried to allocate so no
|
||||||
|
* cleanup activity needed
|
||||||
|
*/
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* set EOC value to new allocated cluster */
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_EOC);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
/* cleanup activity */
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, (*chain));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, save_cln, cl4find);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
/* cleanup activity */
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, (*chain));
|
||||||
|
/* trying to save last allocated cluster for future use */
|
||||||
|
fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_FREE);
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
save_cln = cl4find;
|
||||||
|
(*cls_added)++;
|
||||||
|
|
||||||
|
/* have we satisfied request ? */
|
||||||
|
if (*cls_added == count)
|
||||||
|
{
|
||||||
|
if (fs_info->vol.type & FAT_FAT32)
|
||||||
|
{
|
||||||
|
fs_info->vol.next_cl = save_cln;
|
||||||
|
if (fs_info->vol.free_cls != 0xFFFFFFFF)
|
||||||
|
fs_info->vol.free_cls -= (*cls_added);
|
||||||
|
}
|
||||||
|
*last_cl = save_cln;
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
cl4find++;
|
||||||
|
if (cl4find >= data_cls_val)
|
||||||
|
cl4find = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs_info->vol.type & FAT_FAT32)
|
||||||
|
{
|
||||||
|
fs_info->vol.next_cl = save_cln;
|
||||||
|
if (fs_info->vol.free_cls != 0xFFFFFFFF)
|
||||||
|
fs_info->vol.free_cls -= (*cls_added);
|
||||||
|
}
|
||||||
|
*last_cl = save_cln;
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_free_fat_clusters_chain --
|
||||||
|
* Free chain of clusters in Files Allocation Table.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* chain - number of the first cluster in the chain
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_free_fat_clusters_chain(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 chain
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK, rc1 = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = chain;
|
||||||
|
unsigned32 next_cln = 0;
|
||||||
|
unsigned32 freed_cls_cnt = 0;
|
||||||
|
|
||||||
|
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
||||||
|
{
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &next_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
if ((fs_info->vol.type & FAT_FAT32) &&
|
||||||
|
(fs_info->vol.free_cls != FAT_UNDEFINED_VALUE))
|
||||||
|
fs_info->vol.free_cls += freed_cls_cnt;
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, cur_cln, FAT_GENFAT_FREE);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
rc1 = rc;
|
||||||
|
|
||||||
|
freed_cls_cnt++;
|
||||||
|
cur_cln = next_cln;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs_info->vol.type & FAT_FAT32)
|
||||||
|
{
|
||||||
|
fs_info->vol.next_cl = chain;
|
||||||
|
if (fs_info->vol.free_cls != FAT_UNDEFINED_VALUE)
|
||||||
|
fs_info->vol.free_cls += freed_cls_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
if (rc1 != RC_OK)
|
||||||
|
return rc1;
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_get_fat_cluster --
|
||||||
|
* Fetches the contents of the cluster (link to next cluster in the chain)
|
||||||
|
* from Files Allocation Table.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - number of cluster to fetch the contents from
|
||||||
|
* ret_val - contents of the cluster 'cln' (link to next cluster in
|
||||||
|
* the chain)
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_get_fat_cluster(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 *ret_val
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
bdbuf_buffer *block0 = NULL;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 ofs = 0;
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
|
||||||
|
fs_info->vol.afat_loc;
|
||||||
|
ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
switch ( fs_info->vol.type )
|
||||||
|
{
|
||||||
|
case FAT_FAT12:
|
||||||
|
/*
|
||||||
|
* we are enforced in complex computations for FAT12 to escape CPU
|
||||||
|
* align problems for some architectures
|
||||||
|
*/
|
||||||
|
*ret_val = (*((unsigned8 *)(block0->buffer + ofs)));
|
||||||
|
if ( ofs == (fs_info->vol.bps - 1) )
|
||||||
|
{
|
||||||
|
rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
|
||||||
|
&block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*ret_val |= (*((unsigned8 *)(block0->buffer)))<<8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ret_val |= (*((unsigned8 *)(block0->buffer + ofs + 1)))<<8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( FAT_CLUSTER_IS_ODD(cln) )
|
||||||
|
*ret_val = (*ret_val) >> FAT12_SHIFT;
|
||||||
|
else
|
||||||
|
*ret_val = (*ret_val) & FAT_FAT12_MASK;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT_FAT16:
|
||||||
|
*ret_val = *((unsigned16 *)(block0->buffer + ofs));
|
||||||
|
*ret_val = CF_LE_W(*ret_val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT_FAT32:
|
||||||
|
*ret_val = *((unsigned32 *)(block0->buffer + ofs));
|
||||||
|
*ret_val = CF_LE_L(*ret_val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_set_fat_cluster --
|
||||||
|
* Set the contents of the cluster (link to next cluster in the chain)
|
||||||
|
* from Files Allocation Table.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - number of cluster to set contents to
|
||||||
|
* in_val - value to set
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_set_fat_cluster(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 in_val
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 ofs = 0;
|
||||||
|
unsigned16 fat16_clv = 0;
|
||||||
|
unsigned32 fat32_clv = 0;
|
||||||
|
bdbuf_buffer *block0 = NULL;
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
|
||||||
|
fs_info->vol.afat_loc;
|
||||||
|
ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
switch ( fs_info->vol.type )
|
||||||
|
{
|
||||||
|
case FAT_FAT12:
|
||||||
|
if ( FAT_CLUSTER_IS_ODD(cln) )
|
||||||
|
{
|
||||||
|
fat16_clv = CT_LE_W((((unsigned16)in_val) << FAT_FAT12_SHIFT));
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs))) & 0x0F;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs))) |
|
||||||
|
(unsigned8)(fat16_clv & 0x00FF);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
|
||||||
|
if ( ofs == (fs_info->vol.bps - 1) )
|
||||||
|
{
|
||||||
|
rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
|
||||||
|
&block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer)) &= 0x00;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer))) |
|
||||||
|
(unsigned8)((fat16_clv & 0xFF00)>>8);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs + 1)) &= 0x00;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs + 1)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs + 1))) |
|
||||||
|
(unsigned8)((fat16_clv & 0xFF00)>>8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fat16_clv = CT_LE_W((((unsigned16)in_val) & FAT_FAT12_MASK));
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs)) &= 0x00;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs))) |
|
||||||
|
(unsigned8)(fat16_clv & 0x00FF);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
|
||||||
|
if ( ofs == (fs_info->vol.bps - 1) )
|
||||||
|
{
|
||||||
|
rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
|
||||||
|
&block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer))) & 0xF0;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer))) |
|
||||||
|
(unsigned8)((fat16_clv & 0xFF00)>>8);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs + 1)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs + 1))) & 0xF0;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs+1)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs+1))) |
|
||||||
|
(unsigned8)((fat16_clv & 0xFF00)>>8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT_FAT16:
|
||||||
|
*((unsigned16 *)(block0->buffer + ofs)) =
|
||||||
|
(unsigned16)(CT_LE_W(in_val));
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT_FAT32:
|
||||||
|
fat32_clv = CT_LE_L((in_val & FAT_FAT32_MASK));
|
||||||
|
|
||||||
|
*((unsigned32 *)(block0->buffer + ofs)) =
|
||||||
|
(*((unsigned32 *)(block0->buffer + ofs))) & (CT_LE_L(0xF0000000));
|
||||||
|
|
||||||
|
*((unsigned32 *)(block0->buffer + ofs)) =
|
||||||
|
fat32_clv | (*((unsigned32 *)(block0->buffer + ofs)));
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
58
c/src/exec/libfs/src/dosfs/fat_fat_operations.h
Normal file
58
c/src/exec/libfs/src/dosfs/fat_fat_operations.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* fat_fat_operations.h
|
||||||
|
*
|
||||||
|
* Constants/data structures/prototypes for operations on Files Allocation
|
||||||
|
* Table
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#ifndef __DOSFS_FAT_FAT_OPERATIONS_H__
|
||||||
|
#define __DOSFS_FAT_FAT_OPERATIONS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include <rtems/bdbuf.h>
|
||||||
|
#include "fat.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_get_fat_cluster(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 *ret_val);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_set_fat_cluster(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 in_val);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_scan_fat_for_free_clusters(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 *chain,
|
||||||
|
unsigned32 count,
|
||||||
|
unsigned32 *cls_added,
|
||||||
|
unsigned32 *last_cl
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_free_fat_clusters_chain(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 chain
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_FAT_FAT_OPERATIONS_H__ */
|
||||||
979
c/src/exec/libfs/src/dosfs/fat_file.c
Normal file
979
c/src/exec/libfs/src/dosfs/fat_file.c
Normal file
@@ -0,0 +1,979 @@
|
|||||||
|
/*
|
||||||
|
* fat_file.c
|
||||||
|
*
|
||||||
|
* General operations on "fat-file"
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <bsp.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_hash_insert(Chain_Control *hash, unsigned32 key1, unsigned32 key2,
|
||||||
|
fat_file_fd_t *el);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_hash_delete(Chain_Control *hash, unsigned32 key1, unsigned32 key2,
|
||||||
|
fat_file_fd_t *el);
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
_hash_search(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
Chain_Control *hash,
|
||||||
|
unsigned32 key1,
|
||||||
|
unsigned32 key2,
|
||||||
|
void **ret
|
||||||
|
);
|
||||||
|
|
||||||
|
static int
|
||||||
|
fat_file_lseek(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 file_cln,
|
||||||
|
unsigned32 *disk_cln
|
||||||
|
);
|
||||||
|
|
||||||
|
/* fat_file_open --
|
||||||
|
* Open fat-file. Two hash tables are accessed by key
|
||||||
|
* constructed from cluster num and offset of the node (i.e.
|
||||||
|
* files/directories are distinguished by location on the disk).
|
||||||
|
* First, hash table("vhash") consists of fat-file descriptors corresponded
|
||||||
|
* to "valid" files is accessed. Search is made by 2 fields equal to key
|
||||||
|
* constructed. If descriptor is found in the "vhash" - return it.
|
||||||
|
* Otherwise search is made in hash table("rhash") consits of fat-file
|
||||||
|
* descriptors corresponded to "removed-but-still-open" files with the
|
||||||
|
* same keys.
|
||||||
|
* If search failed, new fat-file descriptor is added to "vhash"
|
||||||
|
* with both key fields equal to constructed key. Otherwise new fat-file
|
||||||
|
* descriptor is added to "vhash" with first key field equal to key
|
||||||
|
* constructed and the second equal to an unique (unique among all values
|
||||||
|
* of second key fields) value.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - cluster num of the node
|
||||||
|
* ofs - offset of the node
|
||||||
|
* fat_fd - placeholder for returned fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and pointer to opened descriptor on success, or -1 if error
|
||||||
|
* occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_open(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 ofs,
|
||||||
|
fat_file_fd_t **fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *lfat_fd = NULL;
|
||||||
|
unsigned32 key = 0;
|
||||||
|
|
||||||
|
/* construct key */
|
||||||
|
key = fat_construct_key(mt_entry, cln, ofs);
|
||||||
|
|
||||||
|
/* access "valid" hash table */
|
||||||
|
rc = _hash_search(mt_entry, fs_info->vhash, key, 0, (void **)&lfat_fd);
|
||||||
|
if ( rc == RC_OK )
|
||||||
|
{
|
||||||
|
/* return pointer to fat_file_descriptor allocated before */
|
||||||
|
(*fat_fd) = lfat_fd;
|
||||||
|
lfat_fd->links_num++;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* access "removed-but-still-open" hash table */
|
||||||
|
rc = _hash_search(mt_entry, fs_info->rhash, key, key, (void **)&lfat_fd);
|
||||||
|
|
||||||
|
lfat_fd = (*fat_fd) = (fat_file_fd_t*)malloc(sizeof(fat_file_fd_t));
|
||||||
|
if ( lfat_fd == NULL )
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
|
||||||
|
lfat_fd->links_num = 1;
|
||||||
|
lfat_fd->flags &= ~FAT_FILE_REMOVED;
|
||||||
|
lfat_fd->map.last_cln = FAT_UNDEFINED_VALUE;
|
||||||
|
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
lfat_fd->ino = key;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lfat_fd->ino = fat_get_unique_ino(mt_entry);
|
||||||
|
|
||||||
|
if ( lfat_fd->ino == 0 )
|
||||||
|
{
|
||||||
|
free((*fat_fd));
|
||||||
|
/*
|
||||||
|
* XXX: kernel resource is unsufficient, but not the memory,
|
||||||
|
* but there is no suitable errno :(
|
||||||
|
*/
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_hash_insert(fs_info->vhash, key, lfat_fd->ino, lfat_fd);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* other fields of fat-file descriptor will be initialized on upper
|
||||||
|
* level
|
||||||
|
*/
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* fat_file_reopen --
|
||||||
|
* Increment by 1 number of links
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_reopen(fat_file_fd_t *fat_fd)
|
||||||
|
{
|
||||||
|
fat_fd->links_num++;
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_close --
|
||||||
|
* Close fat-file. If count of links to fat-file
|
||||||
|
* descriptor is greater than 1 (i.e. somebody esle holds pointer
|
||||||
|
* to this descriptor) just decrement it. Otherwise
|
||||||
|
* do the following. If this descriptor corresponded to removed fat-file
|
||||||
|
* then free clusters contained fat-file data, delete descriptor from
|
||||||
|
* "rhash" table and free memory allocated by descriptor. If descriptor
|
||||||
|
* correspondes to non-removed fat-file and 'ino' field has value from
|
||||||
|
* unique inode numbers pool then set count of links to descriptor to zero
|
||||||
|
* and leave it in hash, otherwise delete descriptor from "vhash" and free
|
||||||
|
* memory allocated by the descriptor
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_close(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 key = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if links_num field of fat-file descriptor is greater than 1
|
||||||
|
* decrement the count of links and return
|
||||||
|
*/
|
||||||
|
if (fat_fd->links_num > 1)
|
||||||
|
{
|
||||||
|
fat_fd->links_num--;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
|
||||||
|
|
||||||
|
if (fat_fd->flags & FAT_FILE_REMOVED)
|
||||||
|
{
|
||||||
|
rc = fat_file_truncate(mt_entry, fat_fd, 0);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
_hash_delete(fs_info->rhash, key, fat_fd->ino, fat_fd);
|
||||||
|
|
||||||
|
if ( fat_ino_is_unique(mt_entry, fat_fd->ino) )
|
||||||
|
fat_free_unique_ino(mt_entry, fat_fd->ino);
|
||||||
|
|
||||||
|
free(fat_fd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fat_ino_is_unique(mt_entry, fat_fd->ino))
|
||||||
|
{
|
||||||
|
fat_fd->links_num = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
|
||||||
|
free(fat_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_read --
|
||||||
|
* Read 'count' bytes from 'start' position from fat-file. This
|
||||||
|
* interface hides the architecture of fat-file, represents it as
|
||||||
|
* linear file
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* start - offset in fat-file (in bytes) to read from
|
||||||
|
* count - count of bytes to read
|
||||||
|
* buf - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* the number of bytes read on success, or -1 if error occured (errno
|
||||||
|
* set appropriately)
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
fat_file_read(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 count,
|
||||||
|
char *buf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
ssize_t ret = 0;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cmpltd = 0;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
unsigned32 cl_start = 0;
|
||||||
|
unsigned32 save_cln = 0;
|
||||||
|
unsigned32 ofs = 0;
|
||||||
|
unsigned32 save_ofs;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 byte = 0;
|
||||||
|
unsigned32 c = 0;
|
||||||
|
|
||||||
|
/* it couldn't be removed - otherwise cache update will be broken */
|
||||||
|
if (count == 0)
|
||||||
|
return cmpltd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* >= because start is offset and computed from 0 and file_size
|
||||||
|
* computed from 1
|
||||||
|
*/
|
||||||
|
if ( start >= fat_fd->fat_file_size )
|
||||||
|
return FAT_EOF;
|
||||||
|
|
||||||
|
if ((count > fat_fd->fat_file_size) ||
|
||||||
|
(start > fat_fd->fat_file_size - count))
|
||||||
|
count = fat_fd->fat_file_size - start;
|
||||||
|
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
{
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->cln);
|
||||||
|
sec += (start >> fs_info->vol.sec_log2);
|
||||||
|
byte = start & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
ret = _fat_block_read(mt_entry, sec, byte, count, buf);
|
||||||
|
if ( ret < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl_start = start >> fs_info->vol.bpc_log2;
|
||||||
|
save_ofs = ofs = start & (fs_info->vol.bpc - 1);
|
||||||
|
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
c = MIN(count, (fs_info->vol.bpc - ofs));
|
||||||
|
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
|
||||||
|
sec += (ofs >> fs_info->vol.sec_log2);
|
||||||
|
byte = ofs & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
ret = _fat_block_read(mt_entry, sec, byte, c, buf + cmpltd);
|
||||||
|
if ( ret < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
count -= c;
|
||||||
|
cmpltd += c;
|
||||||
|
save_cln = cur_cln;
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
ofs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update cache */
|
||||||
|
/* XXX: check this - I'm not sure :( */
|
||||||
|
fat_fd->map.file_cln = cl_start +
|
||||||
|
((save_ofs + cmpltd - 1) >> fs_info->vol.bpc_log2);
|
||||||
|
fat_fd->map.disk_cln = save_cln;
|
||||||
|
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_write --
|
||||||
|
* Write 'count' bytes of data from user supplied buffer to fat-file
|
||||||
|
* starting at offset 'start'. This interface hides the architecture
|
||||||
|
* of fat-file, represents it as linear file
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* start - offset(in bytes) to write from
|
||||||
|
* count - count
|
||||||
|
* buf - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* number of bytes actually written to the file on success, or -1 if
|
||||||
|
* error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
fat_file_write(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 count,
|
||||||
|
char *buf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
ssize_t ret = 0;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cmpltd = 0;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
unsigned32 save_cln;
|
||||||
|
unsigned32 cl_start = 0;
|
||||||
|
unsigned32 ofs = 0;
|
||||||
|
unsigned32 save_ofs;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 byte = 0;
|
||||||
|
unsigned32 c = 0;
|
||||||
|
|
||||||
|
if ( count == 0 )
|
||||||
|
return cmpltd;
|
||||||
|
|
||||||
|
if ( start > fat_fd->fat_file_size )
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
if ((count > fat_fd->size_limit) ||
|
||||||
|
(start > fat_fd->size_limit - count))
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
rc = fat_file_extend(mt_entry, fat_fd, start + count, &c);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check whether there was enough room on device to locate
|
||||||
|
* file of 'start + count' bytes
|
||||||
|
*/
|
||||||
|
if (c != (start + count))
|
||||||
|
count = c - start;
|
||||||
|
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
{
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->cln);
|
||||||
|
sec += (start >> fs_info->vol.sec_log2);
|
||||||
|
byte = start & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
ret = _fat_block_write(mt_entry, sec, byte, count, buf);
|
||||||
|
if ( ret < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl_start = start >> fs_info->vol.bpc_log2;
|
||||||
|
save_ofs = ofs = start & (fs_info->vol.bpc - 1);
|
||||||
|
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
c = MIN(count, (fs_info->vol.bpc - ofs));
|
||||||
|
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
|
||||||
|
sec += (ofs >> fs_info->vol.sec_log2);
|
||||||
|
byte = ofs & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
ret = _fat_block_write(mt_entry, sec, byte, c, buf + cmpltd);
|
||||||
|
if ( ret < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
count -= c;
|
||||||
|
cmpltd += c;
|
||||||
|
save_cln = cur_cln;
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
ofs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update cache */
|
||||||
|
/* XXX: check this - I'm not sure :( */
|
||||||
|
fat_fd->map.file_cln = cl_start +
|
||||||
|
((save_ofs + cmpltd - 1) >> fs_info->vol.bpc_log2);
|
||||||
|
fat_fd->map.disk_cln = save_cln;
|
||||||
|
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_extend --
|
||||||
|
* Extend fat-file. If new length less than current fat-file size -
|
||||||
|
* do nothing. Otherwise calculate necessary count of clusters to add,
|
||||||
|
* allocate it and add new clusters chain to the end of
|
||||||
|
* existing clusters chain.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* new_length - new length
|
||||||
|
* a_length - placeholder for result - actual new length of file
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and new length of file on success, or -1 if error occured (errno
|
||||||
|
* set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_extend(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 new_length,
|
||||||
|
unsigned32 *a_length
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 chain = 0;
|
||||||
|
unsigned32 bytes2add = 0;
|
||||||
|
unsigned32 cls2add = 0;
|
||||||
|
unsigned32 old_last_cl;
|
||||||
|
unsigned32 last_cl = 0;
|
||||||
|
unsigned32 bytes_remain = 0;
|
||||||
|
unsigned32 cls_added;
|
||||||
|
|
||||||
|
*a_length = new_length;
|
||||||
|
|
||||||
|
if (new_length <= fat_fd->fat_file_size)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
set_errno_and_return_minus_one( ENOSPC );
|
||||||
|
|
||||||
|
bytes_remain = (fs_info->vol.bpc -
|
||||||
|
(fat_fd->fat_file_size & (fs_info->vol.bpc - 1))) &
|
||||||
|
(fs_info->vol.bpc - 1);
|
||||||
|
|
||||||
|
bytes2add = new_length - fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
if (bytes2add > bytes_remain)
|
||||||
|
bytes2add -= bytes_remain;
|
||||||
|
else
|
||||||
|
bytes2add = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if in last cluster allocated for the file there is enough room to
|
||||||
|
* handle extention (hence we don't need to add even one cluster to the
|
||||||
|
* file ) - return
|
||||||
|
*/
|
||||||
|
if (bytes2add == 0)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
cls2add = ((bytes2add - 1) >> fs_info->vol.bpc_log2) + 1;
|
||||||
|
|
||||||
|
rc = fat_scan_fat_for_free_clusters(mt_entry, &chain, cls2add,
|
||||||
|
&cls_added, &last_cl);
|
||||||
|
|
||||||
|
/* this means that low level I/O error occured */
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* this means that no space left on device */
|
||||||
|
if ((cls_added == 0) && (bytes_remain == 0))
|
||||||
|
set_errno_and_return_minus_one(ENOSPC);
|
||||||
|
|
||||||
|
/* check wether we satisfied request for 'cls2add' clusters */
|
||||||
|
if (cls2add != cls_added)
|
||||||
|
*a_length = new_length -
|
||||||
|
((cls2add - cls_added - 1) << fs_info->vol.bpc_log2) -
|
||||||
|
(bytes2add & (fs_info->vol.bpc - 1));
|
||||||
|
|
||||||
|
/* add new chain to the end of existed */
|
||||||
|
if ( fat_fd->fat_file_size == 0 )
|
||||||
|
{
|
||||||
|
fat_fd->map.disk_cln = fat_fd->cln = chain;
|
||||||
|
fat_fd->map.file_cln = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fat_fd->map.last_cln != FAT_UNDEFINED_VALUE)
|
||||||
|
{
|
||||||
|
old_last_cl = fat_fd->map.last_cln;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
|
||||||
|
(fat_fd->fat_file_size - 1), &old_last_cl);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, chain);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, old_last_cl, chain);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, chain);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update number of the last cluster of the file if it changed */
|
||||||
|
if (cls_added != 0)
|
||||||
|
{
|
||||||
|
fat_fd->map.last_cln = last_cl;
|
||||||
|
if (fat_fd->fat_file_type == FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
rc = fat_init_clusters_chain(mt_entry, chain);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, chain);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_truncate --
|
||||||
|
* Truncate fat-file. If new length greater than current fat-file size -
|
||||||
|
* do nothing. Otherwise find first cluster to free and free all clusters
|
||||||
|
* in the chain starting from this cluster.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* new_length - new length
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_truncate(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 new_length
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
unsigned32 cl_start = 0;
|
||||||
|
unsigned32 new_last_cln = FAT_UNDEFINED_VALUE;
|
||||||
|
|
||||||
|
|
||||||
|
if ( new_length >= fat_fd->fat_file_size )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
assert(fat_fd->fat_file_size);
|
||||||
|
|
||||||
|
cl_start = (new_length + fs_info->vol.bpc - 1) >> fs_info->vol.bpc_log2;
|
||||||
|
|
||||||
|
if ((cl_start << fs_info->vol.bpc_log2) >= fat_fd->fat_file_size)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
if (cl_start != 0)
|
||||||
|
{
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start - 1, &new_last_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = fat_free_fat_clusters_chain(mt_entry, cur_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (cl_start != 0)
|
||||||
|
{
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, new_last_cln, FAT_GENFAT_EOC);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
fat_fd->map.file_cln = cl_start - 1;
|
||||||
|
fat_fd->map.disk_cln = new_last_cln;
|
||||||
|
fat_fd->map.last_cln = new_last_cln;
|
||||||
|
}
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_ioctl --
|
||||||
|
* F_CLU_NUM:
|
||||||
|
* make mapping between serial number of the cluster in fat-file and
|
||||||
|
* its real number on the volume
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cmd - command
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_ioctl(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
int cmd,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
unsigned32 cl_start = 0;
|
||||||
|
unsigned32 pos = 0;
|
||||||
|
unsigned32 *ret;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, cmd);
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case F_CLU_NUM:
|
||||||
|
pos = va_arg(ap, int);
|
||||||
|
ret = va_arg(ap, int *);
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
if ( pos >= fat_fd->fat_file_size )
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
{
|
||||||
|
/* cluster 0 (zero) reserved for root dir */
|
||||||
|
*ret = 0;
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl_start = pos >> fs_info->vol.bpc_log2;
|
||||||
|
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*ret = cur_cln;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
rc = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_mark_removed --
|
||||||
|
* Remove the fat-file descriptor from "valid" hash table, insert it
|
||||||
|
* into "removed-but-still-open" hash table and set up "removed" bit.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fat_file_mark_removed(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 key = 0;
|
||||||
|
|
||||||
|
key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
|
||||||
|
|
||||||
|
_hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
|
||||||
|
|
||||||
|
_hash_insert(fs_info->rhash, key, fat_fd->ino, fat_fd);
|
||||||
|
|
||||||
|
fat_fd->flags |= FAT_FILE_REMOVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_datasync --
|
||||||
|
* Synchronize fat-file - flush all buffered data to the media.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_datasync(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = fat_fd->cln;
|
||||||
|
bdbuf_buffer *block = NULL;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 i = 0;
|
||||||
|
|
||||||
|
if (fat_fd->fat_file_size == 0)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we can use only one bdbuf :( and we also know that cache is useless
|
||||||
|
* for sync operation, so don't use it
|
||||||
|
*/
|
||||||
|
rc = fat_buf_release(fs_info);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* for each cluster of the file ... */
|
||||||
|
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
||||||
|
{
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
|
||||||
|
/* for each sector in cluster ... */
|
||||||
|
for ( i = 0; i < fs_info->vol.spc; i++ )
|
||||||
|
{
|
||||||
|
/* ... sync it */
|
||||||
|
sc = rtems_bdbuf_read(fs_info->vol.dev, (sec + i), &block);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
sc = rtems_bdbuf_sync(block);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL )
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_size --
|
||||||
|
* Calculate fat-file size - fat-file is nothing that clusters chain, so
|
||||||
|
* go through all clusters in the chain and count it. Only
|
||||||
|
* special case is root directory for FAT12/16 volumes.
|
||||||
|
* This function is used only for directories which are fat-files with
|
||||||
|
* non-zero length, hence 'fat_fd->cln' always contains valid data.
|
||||||
|
* Calculated size is stored in 'fat_file_size' field of fat-file
|
||||||
|
* descriptor.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_size(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = fat_fd->cln;
|
||||||
|
unsigned32 save_cln = 0;
|
||||||
|
|
||||||
|
/* Have we requested root dir size for FAT12/16? */
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
{
|
||||||
|
fat_fd->fat_file_size = fs_info->vol.rdir_size;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_fd->fat_file_size = 0;
|
||||||
|
|
||||||
|
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
||||||
|
{
|
||||||
|
save_cln = cur_cln;
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
fat_fd->fat_file_size += fs_info->vol.bpc;
|
||||||
|
}
|
||||||
|
fat_fd->map.last_cln = save_cln;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hash support routines */
|
||||||
|
|
||||||
|
/* _hash_insert --
|
||||||
|
* Insert elemnt into hash based on key 'key1'
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* hash - hash element will be inserted into
|
||||||
|
* key1 - key on which insertion is based on
|
||||||
|
* key2 - not used during insertion
|
||||||
|
* el - element to insert
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
_hash_insert(Chain_Control *hash, unsigned32 key1, unsigned32 key2,
|
||||||
|
fat_file_fd_t *el)
|
||||||
|
{
|
||||||
|
_Chain_Append((hash) + ((key1) % FAT_HASH_MODULE), &(el)->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* _hash_delete --
|
||||||
|
* Remove element from hash
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* hash - hash element will be removed from
|
||||||
|
* key1 - not used
|
||||||
|
* key2 - not used
|
||||||
|
* el - element to delete
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
_hash_delete(Chain_Control *hash, unsigned32 key1, unsigned32 key2,
|
||||||
|
fat_file_fd_t *el)
|
||||||
|
{
|
||||||
|
_Chain_Extract(&(el)->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _hash_search --
|
||||||
|
* Search element in hash. If both keys match pointer to found element
|
||||||
|
* is returned
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* hash - hash element will be removed from
|
||||||
|
* key1 - search key
|
||||||
|
* key2 - search key
|
||||||
|
* ret - placeholder for result
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* 0 and pointer to found element on success, -1 otherwise
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
_hash_search(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
Chain_Control *hash,
|
||||||
|
unsigned32 key1,
|
||||||
|
unsigned32 key2,
|
||||||
|
void **ret
|
||||||
|
)
|
||||||
|
{
|
||||||
|
unsigned32 mod = (key1) % FAT_HASH_MODULE;
|
||||||
|
Chain_Node *the_node = ((Chain_Control *)((hash) + mod))->first;
|
||||||
|
|
||||||
|
for ( ; !_Chain_Is_tail((hash) + mod, the_node) ; )
|
||||||
|
{
|
||||||
|
fat_file_fd_t *ffd = (fat_file_fd_t *)the_node;
|
||||||
|
unsigned32 ck =
|
||||||
|
fat_construct_key(mt_entry, ffd->info_cln, ffd->info_ofs);
|
||||||
|
|
||||||
|
if ( (key1) == ck)
|
||||||
|
{
|
||||||
|
if ( ((key2) == 0) || ((key2) == ffd->ino) )
|
||||||
|
{
|
||||||
|
*ret = (void *)the_node;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
the_node = the_node->next;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
fat_file_lseek(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 file_cln,
|
||||||
|
unsigned32 *disk_cln
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
/*
|
||||||
|
assert(fat_fd->fat_file_size);
|
||||||
|
*/
|
||||||
|
if (file_cln == fat_fd->map.file_cln)
|
||||||
|
*disk_cln = fat_fd->map.disk_cln;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned32 cur_cln;
|
||||||
|
unsigned32 count;
|
||||||
|
unsigned32 i;
|
||||||
|
|
||||||
|
if (file_cln > fat_fd->map.file_cln)
|
||||||
|
{
|
||||||
|
cur_cln = fat_fd->map.disk_cln;
|
||||||
|
count = file_cln - fat_fd->map.file_cln;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur_cln = fat_fd->cln;
|
||||||
|
count = file_cln;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip over the clusters */
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update cache */
|
||||||
|
fat_fd->map.file_cln = file_cln;
|
||||||
|
fat_fd->map.disk_cln = cur_cln;
|
||||||
|
|
||||||
|
*disk_cln = cur_cln;
|
||||||
|
}
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
195
c/src/exec/libfs/src/dosfs/fat_file.h
Normal file
195
c/src/exec/libfs/src/dosfs/fat_file.h
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* fat_file.h
|
||||||
|
*
|
||||||
|
* Constants/data structures/prototypes for operations on "fat-file"
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#ifndef __DOSFS_FAT_FILE_H__
|
||||||
|
#define __DOSFS_FAT_FILE_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/* "fat-file" representation
|
||||||
|
*
|
||||||
|
* the idea is: fat-file is nothing but a cluster chain, any open fat-file is
|
||||||
|
* represented in system by fat-file descriptor and has well-known
|
||||||
|
* file interface:
|
||||||
|
*
|
||||||
|
* fat_file_open()
|
||||||
|
* fat_file_close()
|
||||||
|
* fat_file_read()
|
||||||
|
* fat_file_write()
|
||||||
|
*
|
||||||
|
* Such interface hides the architecture of fat-file and represents it like
|
||||||
|
* linear file
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef rtems_filesystem_node_types_t fat_file_type_t;
|
||||||
|
|
||||||
|
#define FAT_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
|
||||||
|
#define FAT_FILE RTEMS_FILESYSTEM_MEMORY_FILE
|
||||||
|
|
||||||
|
typedef struct fat_file_map_s
|
||||||
|
{
|
||||||
|
unsigned32 file_cln;
|
||||||
|
unsigned32 disk_cln;
|
||||||
|
unsigned32 last_cln;
|
||||||
|
} fat_file_map_t;
|
||||||
|
/*
|
||||||
|
* descriptor of a fat-file
|
||||||
|
*
|
||||||
|
* To each particular clusters chain
|
||||||
|
*/
|
||||||
|
typedef struct fat_file_fd_s
|
||||||
|
{
|
||||||
|
Chain_Node link; /*
|
||||||
|
* fat-file descriptors organized into hash;
|
||||||
|
* collision lists are handled via link
|
||||||
|
* field
|
||||||
|
*/
|
||||||
|
unsigned32 links_num; /*
|
||||||
|
* the number of fat_file_open call on
|
||||||
|
* this fat-file
|
||||||
|
*/
|
||||||
|
unsigned32 ino; /* inode, file serial number :)))) */
|
||||||
|
fat_file_type_t fat_file_type;
|
||||||
|
unsigned32 size_limit;
|
||||||
|
unsigned32 fat_file_size; /* length */
|
||||||
|
unsigned32 info_cln;
|
||||||
|
unsigned32 cln;
|
||||||
|
unsigned16 info_ofs;
|
||||||
|
unsigned char first_char;
|
||||||
|
unsigned8 flags;
|
||||||
|
fat_file_map_t map;
|
||||||
|
time_t mtime;
|
||||||
|
|
||||||
|
} fat_file_fd_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define FAT_FILE_REMOVED 0x01
|
||||||
|
|
||||||
|
#define FAT_FILE_IS_REMOVED(p)\
|
||||||
|
(((p)->flags & FAT_FILE_REMOVED) ? 1 : 0)
|
||||||
|
|
||||||
|
/* ioctl macros */
|
||||||
|
#define F_CLU_NUM 0x01
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each file and directory on a MSDOS volume is unique identified by it
|
||||||
|
* location, i.e. location of it 32 Bytes Directory Entry Structure. We can
|
||||||
|
* distinguish them by cluster number it locates on and offset inside this
|
||||||
|
* cluster. But root directory on any volumes (FAT12/16/32) has no 32 Bytes
|
||||||
|
* Directory Entry Structure corresponded to it. So we assume 32 Bytes
|
||||||
|
* Directory Entry Structure of root directory locates at cluster 1 (invalid
|
||||||
|
* cluaster number) and offset 0
|
||||||
|
*/
|
||||||
|
#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))
|
||||||
|
|
||||||
|
#define FAT_EOF 0x00
|
||||||
|
|
||||||
|
/* fat_construct_key --
|
||||||
|
* Construct key for hash access: convert (cluster num, offset) to
|
||||||
|
* (sector512 num, new offset) and than construct key as
|
||||||
|
* key = (sector512 num) << 4 | (new offset)
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* cl - cluster number
|
||||||
|
* ofs - offset inside cluster 'cl'
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* constructed key
|
||||||
|
*/
|
||||||
|
static inline unsigned32
|
||||||
|
fat_construct_key(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cl,
|
||||||
|
unsigned32 ofs)
|
||||||
|
{
|
||||||
|
return ( ((fat_cluster_num_to_sector512_num(mt_entry, cl) +
|
||||||
|
(ofs >> FAT_SECTOR512_BITS)) << 4) +
|
||||||
|
((ofs >> 5) & (FAT_DIRENTRIES_PER_SEC512 - 1)) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prototypes for "fat-file" operations */
|
||||||
|
int
|
||||||
|
fat_file_open(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 ofs,
|
||||||
|
fat_file_fd_t **fat_fd);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_reopen(fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_close(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
fat_file_read(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 count,
|
||||||
|
char *buf);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
fat_file_write(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 count,
|
||||||
|
char *buf);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_extend(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 new_length,
|
||||||
|
unsigned32 *a_length);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_truncate(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 new_length);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_datasync(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_ioctl(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
int cmd,
|
||||||
|
...);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_size(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
void
|
||||||
|
fat_file_mark_removed(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_FAT_FILE_H__ */
|
||||||
408
c/src/exec/libfs/src/dosfs/msdos.h
Normal file
408
c/src/exec/libfs/src/dosfs/msdos.h
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
/*
|
||||||
|
* msdos.h
|
||||||
|
*
|
||||||
|
* The MSDOS filesystem constants/data structures/prototypes
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#ifndef __DOSFS_MSDOS_H__
|
||||||
|
#define __DOSFS_MSDOS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#ifndef RC_OK
|
||||||
|
#define RC_OK 0x00000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MSDOS_NAME_NOT_FOUND_ERR 0xDD000001
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This structure identifies the instance of the filesystem on the MSDOS
|
||||||
|
* level.
|
||||||
|
*/
|
||||||
|
typedef struct msdos_fs_info_s
|
||||||
|
{
|
||||||
|
fat_fs_info_t fat; /*
|
||||||
|
* volume
|
||||||
|
* description
|
||||||
|
*/
|
||||||
|
rtems_filesystem_file_handlers_r *directory_handlers; /*
|
||||||
|
* a set of routines
|
||||||
|
* that handles the
|
||||||
|
* nodes of directory
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
rtems_filesystem_file_handlers_r *file_handlers; /*
|
||||||
|
* a set of routines
|
||||||
|
* that handles the
|
||||||
|
* nodes of file
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
rtems_id vol_sema; /*
|
||||||
|
* semaphore
|
||||||
|
* associated with
|
||||||
|
* the volume
|
||||||
|
*/
|
||||||
|
unsigned8 *cl_buf; /*
|
||||||
|
* just placeholder
|
||||||
|
* for anything
|
||||||
|
*/
|
||||||
|
} msdos_fs_info_t;
|
||||||
|
|
||||||
|
/* a set of routines that handle the nodes which are directories */
|
||||||
|
extern rtems_filesystem_file_handlers_r msdos_dir_handlers;
|
||||||
|
|
||||||
|
/* a set of routines that handle the nodes which are files */
|
||||||
|
extern rtems_filesystem_file_handlers_r msdos_file_handlers;
|
||||||
|
|
||||||
|
/* Volume semaphore timeout value */
|
||||||
|
#define MSDOS_VOLUME_SEMAPHORE_TIMEOUT 100
|
||||||
|
|
||||||
|
/* Node types */
|
||||||
|
#define MSDOS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
|
||||||
|
#define MSDOS_REGULAR_FILE RTEMS_FILESYSTEM_MEMORY_FILE
|
||||||
|
|
||||||
|
typedef rtems_filesystem_node_types_t msdos_node_type_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros for fetching fields from 32 bytes long FAT Directory Entry
|
||||||
|
* Structure (see M$ White Paper)
|
||||||
|
*/
|
||||||
|
#define MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE 32 /* 32 bytes */
|
||||||
|
|
||||||
|
#define MSDOS_DIR_NAME(x) (unsigned8 *)((x) + 0)
|
||||||
|
#define MSDOS_DIR_ATTR(x) (unsigned8 *)((x) + 11)
|
||||||
|
#define MSDOS_DIR_NT_RES(x) (unsigned8 *)((x) + 12)
|
||||||
|
#define MSDOS_DIR_CRT_TIME_TENTH(x) (unsigned8 *)((x) + 13)
|
||||||
|
#define MSDOS_DIR_CRT_TIME(x) (unsigned16 *)((x) + 14)
|
||||||
|
#define MSDOS_DIR_CRT_DATE(x) (unsigned16 *)((x) + 16)
|
||||||
|
#define MSDOS_DIR_LAST_ACCESS_DATE(x) (unsigned16 *)((x) + 18)
|
||||||
|
#define MSDOS_DIR_FIRST_CLUSTER_HI(x) (unsigned16 *)((x) + 20)
|
||||||
|
#define MSDOS_DIR_WRITE_TIME(x) (unsigned16 *)((x) + 22)
|
||||||
|
#define MSDOS_DIR_WRITE_DATE(x) (unsigned16 *)((x) + 24)
|
||||||
|
#define MSDOS_DIR_FIRST_CLUSTER_LOW(x) (unsigned16 *)((x) + 26)
|
||||||
|
#define MSDOS_DIR_FILE_SIZE(x) (unsigned32 *)((x) + 28)
|
||||||
|
|
||||||
|
#define MSDOS_EXTRACT_CLUSTER_NUM(p) \
|
||||||
|
(unsigned32)( (CF_LE_W(*MSDOS_DIR_FIRST_CLUSTER_LOW(p))) | \
|
||||||
|
((CF_LE_W((*MSDOS_DIR_FIRST_CLUSTER_HI(p))))<<16) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fields offset in 32 bytes long FAT Directory Entry
|
||||||
|
* Structure (see M$ White Paper)
|
||||||
|
*/
|
||||||
|
#define MSDOS_FILE_SIZE_OFFSET 28
|
||||||
|
#define MSDOS_FILE_NAME_OFFSET 0
|
||||||
|
#define MSDOS_FIRST_CLUSTER_HI_OFFSET 20
|
||||||
|
#define MSDOS_FIRST_CLUSTER_LOW_OFFSET 26
|
||||||
|
#define MSDOS_FILE_WDATE_OFFSET 24
|
||||||
|
#define MSDOS_FILE_WTIME_OFFSET 22
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possible values of DIR_Attr field of 32 bytes long FAT Directory Entry
|
||||||
|
* Structure (see M$ White Paper)
|
||||||
|
*/
|
||||||
|
#define MSDOS_ATTR_READ_ONLY 0x01
|
||||||
|
#define MSDOS_ATTR_HIDDEN 0x02
|
||||||
|
#define MSDOS_ATTR_SYSTEM 0x04
|
||||||
|
#define MSDOS_ATTR_VOLUME_ID 0x08
|
||||||
|
#define MSDOS_ATTR_DIRECTORY 0x10
|
||||||
|
#define MSDOS_ATTR_ARCHIVE 0x20
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possible values of DIR_Name[0] field of 32 bytes long FAT Directory Entry
|
||||||
|
* Structure (see M$ White Paper)
|
||||||
|
*/
|
||||||
|
#define MSDOS_THIS_DIR_ENTRY_EMPTY 0xE5
|
||||||
|
#define MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY 0x00
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_NAME_LEN 11 /* 11 characters */
|
||||||
|
#define MSDOS_NAME_MAX MSDOS_SHORT_NAME_LEN
|
||||||
|
#define MSDOS_NAME_MAX_WITH_DOT (MSDOS_NAME_MAX + 1)
|
||||||
|
|
||||||
|
#define MSDOS_DOT_NAME ". " /* ".", padded to MSDOS_NAME chars */
|
||||||
|
#define MSDOS_DOTDOT_NAME ".. " /* "..", padded to MSDOS_NAME chars */
|
||||||
|
|
||||||
|
typedef enum msdos_token_types_e
|
||||||
|
{
|
||||||
|
MSDOS_NO_MORE_PATH,
|
||||||
|
MSDOS_CURRENT_DIR,
|
||||||
|
MSDOS_UP_DIR,
|
||||||
|
MSDOS_NAME,
|
||||||
|
MSDOS_INVALID_TOKEN
|
||||||
|
} msdos_token_types_t;
|
||||||
|
|
||||||
|
/* Others macros */
|
||||||
|
#define MSDOS_RES_NT_VALUE 0x00
|
||||||
|
#define MSDOS_INIT_DIR_SIZE 0x00
|
||||||
|
|
||||||
|
/* "dot" entry offset in a directory */
|
||||||
|
#define MSDOS_DOT_DIR_ENTRY_OFFSET 0x00 /* first entry in directory */
|
||||||
|
|
||||||
|
/* "dotdot" entry offset in a directory */
|
||||||
|
#define MSDOS_DOTDOT_DIR_ENTRY_OFFSET 0x20 /* second entry in directory */
|
||||||
|
|
||||||
|
/* 'p' should be char* */
|
||||||
|
#define DOT_NODE_P(p) ((char *)(p))
|
||||||
|
#define DOTDOT_NODE_P(p) ((char *)((p) + MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE))
|
||||||
|
|
||||||
|
/* Size limits for files and directories (see M$ White Paper) */
|
||||||
|
#define MSDOS_MAX_DIR_LENGHT 0x200000 /* 2,097,152 bytes */
|
||||||
|
#define MSDOS_MAX_FILE_SIZE 0xFFFFFFFF /* 4 Gb */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of 32 bytes long FAT Directory Entry
|
||||||
|
* Structures per 512 bytes sector
|
||||||
|
*/
|
||||||
|
#define MSDOS_DPS512_NUM 16
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
int
|
||||||
|
msdos_initialize(rtems_filesystem_mount_table_entry_t *temp_mt_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_eval_path(const char *pathname, /* IN */
|
||||||
|
int flags, /* IN */
|
||||||
|
rtems_filesystem_location_info_t *pathloc /* IN/OUT */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_eval4make(const char *path, /* IN */
|
||||||
|
rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
|
||||||
|
const char **name /* OUT */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_unlink(rtems_filesystem_location_info_t *pathloc /* IN */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_free_node_info(rtems_filesystem_location_info_t *pathloc /* IN */);
|
||||||
|
|
||||||
|
rtems_filesystem_node_types_t
|
||||||
|
msdos_node_type(rtems_filesystem_location_info_t *pathloc);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_mknod(const char *path, /* IN */
|
||||||
|
mode_t mode, /* IN */
|
||||||
|
dev_t dev, /* IN */
|
||||||
|
rtems_filesystem_location_info_t *pathloc /* IN/OUT */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_utime(rtems_filesystem_location_info_t *pathloc, /* IN */
|
||||||
|
time_t actime, /* IN */
|
||||||
|
time_t modtime /* IN */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_initialize_support(
|
||||||
|
rtems_filesystem_mount_table_entry_t *temp_mt_entry,
|
||||||
|
rtems_filesystem_operations_table *op_table,
|
||||||
|
rtems_filesystem_file_handlers_r *file_handlers,
|
||||||
|
rtems_filesystem_file_handlers_r *directory_handlers
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_open(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
const char *pathname, /* IN */
|
||||||
|
unsigned32 flag, /* IN */
|
||||||
|
unsigned32 mode /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_close(rtems_libio_t *iop /* IN */);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
msdos_file_read(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
void *buffer, /* IN */
|
||||||
|
unsigned32 count /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
msdos_file_write(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
const void *buffer, /* IN */
|
||||||
|
unsigned32 count /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_lseek(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
off_t offset, /* IN */
|
||||||
|
int whence /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_stat(rtems_filesystem_location_info_t *loc, /* IN */
|
||||||
|
struct stat *buf /* OUT */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_ftruncate(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
off_t length /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_sync(rtems_libio_t *iop);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_datasync(rtems_libio_t *iop);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_ioctl(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
unsigned32 command, /* IN */
|
||||||
|
void *buffer /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc /* IN */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_open(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
const char *pathname, /* IN */
|
||||||
|
unsigned32 flag, /* IN */
|
||||||
|
unsigned32 mode /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_close(rtems_libio_t *iop /* IN */);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
msdos_dir_read(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
void *buffer, /* IN */
|
||||||
|
unsigned32 count /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_lseek(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
off_t offset, /* IN */
|
||||||
|
int whence /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc /* IN */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_sync(rtems_libio_t *iop);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_stat(
|
||||||
|
rtems_filesystem_location_info_t *loc, /* IN */
|
||||||
|
struct stat *buf /* OUT */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_creat_node(rtems_filesystem_location_info_t *parent_loc,
|
||||||
|
msdos_node_type_t type,
|
||||||
|
char *name,
|
||||||
|
mode_t mode);
|
||||||
|
|
||||||
|
/* Misc prototypes */
|
||||||
|
msdos_token_types_t msdos_get_token(const char *path,
|
||||||
|
char *token,
|
||||||
|
int *token_len);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_find_name(rtems_filesystem_location_info_t *parent_loc,
|
||||||
|
char *name);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_get_name_node(rtems_filesystem_location_info_t *parent_loc,
|
||||||
|
char *name,
|
||||||
|
fat_auxiliary_t *paux,
|
||||||
|
char *name_dir_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_info_remove(rtems_filesystem_location_info_t *pathloc);
|
||||||
|
|
||||||
|
void
|
||||||
|
msdos_date_unix2dos(int unix_date,
|
||||||
|
unsigned short *time_val,
|
||||||
|
unsigned short *date);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
msdos_date_dos2unix(unsigned short time_val, unsigned short date);
|
||||||
|
|
||||||
|
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,
|
||||||
|
unsigned32 cl,
|
||||||
|
unsigned32 ofs,
|
||||||
|
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,
|
||||||
|
rtems_boolean *ret_val);
|
||||||
|
|
||||||
|
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,
|
||||||
|
char *name_dir_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_find_node_by_cluster_num_in_fat_file(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 cl4find,
|
||||||
|
fat_auxiliary_t *paux,
|
||||||
|
char *dir_entry
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_get_dotdot_dir_info_cluster_num_and_offset(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
fat_auxiliary_t *paux,
|
||||||
|
char *dir_entry
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_MSDOS_H__ */
|
||||||
208
c/src/exec/libfs/src/dosfs/msdos_create.c
Normal file
208
c/src/exec/libfs/src/dosfs/msdos_create.c
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* Routine to create a new MSDOS filesystem node
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_creat_node --
|
||||||
|
* Create a new node. If a new node is file, FAT 32 Bytes Directory
|
||||||
|
* Entry Structure (see M$ White Paper) 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 new directory and dot and dotdot nodes are created
|
||||||
|
* in alloceted cluster.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* parent_loc - parent (directory we are going to create node in)
|
||||||
|
* type - new node type (file or directory)
|
||||||
|
* name - new node name
|
||||||
|
* mode - mode
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_creat_node(
|
||||||
|
rtems_filesystem_location_info_t *parent_loc,
|
||||||
|
msdos_node_type_t type,
|
||||||
|
char *name,
|
||||||
|
mode_t mode
|
||||||
|
)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
unsigned16 time_val = 0;
|
||||||
|
unsigned16 date = 0;
|
||||||
|
fat_auxiliary_t aux;
|
||||||
|
unsigned char new_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
|
||||||
|
unsigned char dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
|
||||||
|
|
||||||
|
memset(new_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);
|
||||||
|
|
||||||
|
/* fill reserved field */
|
||||||
|
*MSDOS_DIR_NT_RES(new_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);
|
||||||
|
|
||||||
|
/* initialize directory/file size */
|
||||||
|
*MSDOS_DIR_FILE_SIZE(new_node) = MSDOS_INIT_DIR_SIZE;
|
||||||
|
|
||||||
|
if (type == MSDOS_DIRECTORY)
|
||||||
|
*MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_DIRECTORY;
|
||||||
|
else
|
||||||
|
*MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find free space in the parent directory and write new initialized
|
||||||
|
* FAT 32 Bytes Directory Entry Structure (see M$ White Paper)
|
||||||
|
* to the disk
|
||||||
|
*/
|
||||||
|
rc = msdos_get_name_node(parent_loc, NULL, &aux, new_node);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if we create a new file we are done, if directory there are more steps
|
||||||
|
* to do
|
||||||
|
*/
|
||||||
|
if (type == MSDOS_DIRECTORY)
|
||||||
|
{
|
||||||
|
/* open new directory as fat-file */
|
||||||
|
rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dot and dotdot entries are identical to new node except the
|
||||||
|
* names
|
||||||
|
*/
|
||||||
|
memcpy(DOT_NODE_P(dot_dotdot), new_node,
|
||||||
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
|
||||||
|
memcpy(DOTDOT_NODE_P(dot_dotdot), new_node,
|
||||||
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
|
||||||
|
memcpy(MSDOS_DIR_NAME(DOT_NODE_P(dot_dotdot)), MSDOS_DOT_NAME,
|
||||||
|
MSDOS_NAME_MAX);
|
||||||
|
memcpy(MSDOS_DIR_NAME(DOTDOT_NODE_P(dot_dotdot)), MSDOS_DOTDOT_NAME,
|
||||||
|
MSDOS_NAME_MAX);
|
||||||
|
|
||||||
|
/* set up cluster num for dotdot entry */
|
||||||
|
/*
|
||||||
|
* here we can ommit FAT32 condition because for all FAT types dirs
|
||||||
|
* right under root dir should contain 0 in dotdot entry but for
|
||||||
|
* FAT12/16 parent_fat_fd->cluster_num always contains such value
|
||||||
|
*/
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(parent_fat_fd)) &&
|
||||||
|
(fs_info->fat.vol.type & FAT_FAT32))
|
||||||
|
{
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_LOW(DOTDOT_NODE_P(dot_dotdot)) = 0x0000;
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_HI(DOTDOT_NODE_P(dot_dotdot)) = 0x0000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_LOW(DOTDOT_NODE_P(dot_dotdot)) =
|
||||||
|
CT_LE_W((unsigned16)((parent_fat_fd->cln) & 0x0000FFFF));
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_HI(DOTDOT_NODE_P(dot_dotdot)) =
|
||||||
|
CT_LE_W((unsigned16)(((parent_fat_fd->cln) & 0xFFFF0000)>>16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* write dot and dotdot entries to new fat-file: currently fat-file
|
||||||
|
* correspondes to a new node is zero length, so it will be extended
|
||||||
|
* by one cluster and entries will be written
|
||||||
|
*/
|
||||||
|
ret = fat_file_write(parent_loc->mt_entry, fat_fd, 0,
|
||||||
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2,
|
||||||
|
dot_dotdot);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* increment fat-file size by cluster size */
|
||||||
|
fat_fd->fat_file_size += fs_info->fat.vol.bpc;
|
||||||
|
|
||||||
|
/* set up cluster num for dot entry */
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_LOW(DOT_NODE_P(dot_dotdot)) =
|
||||||
|
CT_LE_W((unsigned16)((fat_fd->cln) & 0x0000FFFF));
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_HI(DOT_NODE_P(dot_dotdot)) =
|
||||||
|
CT_LE_W((unsigned16)(((fat_fd->cln) & 0xFFFF0000) >> 16));
|
||||||
|
|
||||||
|
/* rewrite dot entry */
|
||||||
|
ret = fat_file_write(parent_loc->mt_entry, fat_fd, 0,
|
||||||
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
|
||||||
|
DOT_NODE_P(dot_dotdot));
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write first cluster num of a new directory to disk */
|
||||||
|
rc = msdos_set_first_cluster_num(parent_loc->mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
fat_file_close(parent_loc->mt_entry, fat_fd);
|
||||||
|
}
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
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);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
483
c/src/exec/libfs/src/dosfs/msdos_dir.c
Normal file
483
c/src/exec/libfs/src/dosfs/msdos_dir.c
Normal file
@@ -0,0 +1,483 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS directory handlers implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_dir_open --
|
||||||
|
* Open fat-file which correspondes to the directory being opened and
|
||||||
|
* set offset field of file control block to zero.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* pathname - name
|
||||||
|
* flag - flags
|
||||||
|
* mode - mode
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, if directory opened successfully, or -1 if error occured (errno
|
||||||
|
* set apropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_open(rtems_libio_t *iop, const char *pathname, unsigned32 flag,
|
||||||
|
unsigned32 mode)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
rc = fat_file_reopen(fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
iop->offset = 0;
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_close --
|
||||||
|
* Close fat-file which correspondes to the directory being closed
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, if directory closed successfully, or -1 if error occured (errno
|
||||||
|
* set apropriately.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_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;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_read --
|
||||||
|
* This routine will read the next directory entry based on the directory
|
||||||
|
* offset. The offset should be equal to -n- time the size of an
|
||||||
|
* individual dirent structure. If n is not an integer multiple of the
|
||||||
|
* sizeof a dirent structure, an integer division will be performed to
|
||||||
|
* determine directory entry that will be returned in the buffer. Count
|
||||||
|
* should reflect -m- times the sizeof dirent bytes to be placed in the
|
||||||
|
* buffer.
|
||||||
|
* If there are not -m- dirent elements from the current directory
|
||||||
|
* position to the end of the exisiting file, the remaining entries will
|
||||||
|
* be placed in the buffer and the returned value will be equal to
|
||||||
|
* -m actual- times the size of a directory entry.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* buffer - buffer provided by user
|
||||||
|
* count - count of bytes to read
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* the number of bytes read on success, or -1 if error occured (errno
|
||||||
|
* set apropriately).
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
msdos_dir_read(rtems_libio_t *iop, void *buffer, unsigned32 count)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
fat_file_fd_t *tmp_fat_fd = NULL;
|
||||||
|
struct dirent tmp_dirent;
|
||||||
|
unsigned32 start = 0;
|
||||||
|
ssize_t ret = 0;
|
||||||
|
unsigned32 cmpltd = 0;
|
||||||
|
unsigned32 j = 0, i = 0;
|
||||||
|
unsigned32 bts2rd = 0;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cast start and count - protect against using sizes that are not exact
|
||||||
|
* multiples of the -dirent- size. These could result in unexpected
|
||||||
|
* results
|
||||||
|
*/
|
||||||
|
start = iop->offset / sizeof(struct dirent);
|
||||||
|
count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* optimization: we know that root directory for FAT12/16 volumes is
|
||||||
|
* sequential set of sectors and any cluster is sequential set of sectors
|
||||||
|
* too, so read such set of sectors is quick operation for low-level IO
|
||||||
|
* layer.
|
||||||
|
*/
|
||||||
|
bts2rd = (FAT_FD_OF_ROOT_DIR(fat_fd) &&
|
||||||
|
(fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) ?
|
||||||
|
fat_fd->fat_file_size :
|
||||||
|
fs_info->fat.vol.bpc;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* fat-file is already opened by open call, so read it
|
||||||
|
* Always read directory fat-file from the beggining because of MSDOS
|
||||||
|
* directories feature :( - we should count elements currently
|
||||||
|
* present in the directory because there may be holes :)
|
||||||
|
*/
|
||||||
|
ret = fat_file_read(iop->pathinfo.mt_entry, fat_fd, (j * bts2rd),
|
||||||
|
bts2rd, fs_info->cl_buf);
|
||||||
|
if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ret; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
|
||||||
|
{
|
||||||
|
if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
|
||||||
|
MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
|
||||||
|
MSDOS_THIS_DIR_ENTRY_EMPTY)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* skip active entries until get the entry to start from
|
||||||
|
*/
|
||||||
|
if (start)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_file_open(iop->pathinfo.mt_entry, cur_cln, i,
|
||||||
|
&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;
|
||||||
|
tmp_dirent.d_namlen = MSDOS_SHORT_NAME_LEN;
|
||||||
|
memcpy(tmp_dirent.d_name, MSDOS_DIR_NAME((fs_info->cl_buf + i)),
|
||||||
|
MSDOS_SHORT_NAME_LEN);
|
||||||
|
|
||||||
|
/* d_name is null-terminated */
|
||||||
|
tmp_dirent.d_name[MSDOS_SHORT_NAME_LEN] = 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_write --
|
||||||
|
* no write for directory
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* msdos_dir_lseek --
|
||||||
|
*
|
||||||
|
* This routine will behave in one of three ways based on the state of
|
||||||
|
* argument whence. Based on the state of its value the offset argument will
|
||||||
|
* be interpreted using one of the following methods:
|
||||||
|
*
|
||||||
|
* SEEK_SET - offset is the absolute byte offset from the start of the
|
||||||
|
* logical start of the dirent sequence that represents the
|
||||||
|
* directory
|
||||||
|
* SEEK_CUR - offset is used as the relative byte offset from the current
|
||||||
|
* directory position index held in the iop structure
|
||||||
|
* SEEK_END - N/A --> This will cause an assert.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* offset - offset
|
||||||
|
* whence - predefine directive
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno
|
||||||
|
* set apropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_lseek(rtems_libio_t *iop, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
switch (whence)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
case SEEK_CUR:
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
* Movement past the end of the directory via lseek is not a
|
||||||
|
* permitted operation
|
||||||
|
*/
|
||||||
|
case SEEK_END:
|
||||||
|
default:
|
||||||
|
set_errno_and_return_minus_one( EINVAL );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_stat --
|
||||||
|
*
|
||||||
|
* This routine will obtain the following information concerning the current
|
||||||
|
* directory:
|
||||||
|
* st_dev device id
|
||||||
|
* st_ino node serial number :)
|
||||||
|
* st_mode mode extracted from the node
|
||||||
|
* st_size total size in bytes
|
||||||
|
* st_blksize blocksize for filesystem I/O
|
||||||
|
* st_blocks number of blocks allocated
|
||||||
|
* stat_mtime time of last modification
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* loc - this directory
|
||||||
|
* buf - stat buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and filled stat buffer on success, or -1 if error occured (errno
|
||||||
|
* set apropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_stat(
|
||||||
|
rtems_filesystem_location_info_t *loc,
|
||||||
|
struct stat *buf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = loc->node_access;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
buf->st_dev = fs_info->fat.vol.dev;
|
||||||
|
buf->st_ino = fat_fd->ino;
|
||||||
|
buf->st_mode = S_IFDIR;
|
||||||
|
buf->st_rdev = 0ll;
|
||||||
|
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_mtime = fat_fd->mtime;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_truncate --
|
||||||
|
* No truncate for directory.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* msdos_dir_sync --
|
||||||
|
* The following routine does a syncronization on a MSDOS directory node.
|
||||||
|
* DIR_WrtTime, DIR_WrtDate and DIR_fileSize fields of 32 Bytes Directory
|
||||||
|
* Entry Structure(see M$ White Paper) should not be updated for
|
||||||
|
* directories, so only call to corresponding fat-file routine.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set apropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_sync(rtems_libio_t *iop)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
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)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_rmnod --
|
||||||
|
* Remove directory node.
|
||||||
|
*
|
||||||
|
* Check that this directory node is not opened as fat-file, is empty and
|
||||||
|
* not filesystem root node. If all this conditions met then delete.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathloc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set apropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = pathloc->node_access;
|
||||||
|
rtems_boolean is_empty = FALSE;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We deny attemp to delete open directory (if directory is current
|
||||||
|
* directory we assume it is open one)
|
||||||
|
*/
|
||||||
|
if (fat_fd->links_num > 1)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
set_errno_and_return_minus_one(EBUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You cannot remove a node that still has children
|
||||||
|
*/
|
||||||
|
rc = msdos_dir_is_empty(pathloc->mt_entry, fat_fd, &is_empty);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_empty)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
set_errno_and_return_minus_one(ENOTEMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You cannot remove the file system root node.
|
||||||
|
*/
|
||||||
|
if (pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
set_errno_and_return_minus_one(EBUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You cannot remove a mountpoint.
|
||||||
|
* not used - mount() not implemenetd yet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* mark file removed */
|
||||||
|
rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
|
||||||
|
fat_fd->info_ofs,
|
||||||
|
MSDOS_THIS_DIR_ENTRY_EMPTY);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_file_mark_removed(pathloc->mt_entry, fat_fd);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
435
c/src/exec/libfs/src/dosfs/msdos_eval.c
Normal file
435
c/src/exec/libfs/src/dosfs/msdos_eval.c
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS evaluation routines
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_set_handlers --
|
||||||
|
* Set handlers for the node with specified type(i.e. handlers for file
|
||||||
|
* or directory).
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* loc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
msdos_set_handlers(rtems_filesystem_location_info_t *loc)
|
||||||
|
{
|
||||||
|
msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = loc->node_access;
|
||||||
|
|
||||||
|
if (fat_fd->fat_file_type == FAT_DIRECTORY)
|
||||||
|
loc->handlers = fs_info->directory_handlers;
|
||||||
|
else
|
||||||
|
loc->handlers = fs_info->file_handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_eval_path --
|
||||||
|
*
|
||||||
|
* The following routine evaluate path for a node that wishes to be
|
||||||
|
* accessed. Structure 'pathloc' is returned with a pointer to the
|
||||||
|
* node to be accessed.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathname - path for evaluation
|
||||||
|
* flags - flags
|
||||||
|
* pathloc - node description (IN/OUT)
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and filled pathloc on success, or -1 if error occured
|
||||||
|
* (errno set appropriately)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_eval_path(
|
||||||
|
const char *pathname,
|
||||||
|
int flags,
|
||||||
|
rtems_filesystem_location_info_t *pathloc
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = NULL;
|
||||||
|
rtems_filesystem_location_info_t newloc;
|
||||||
|
int i = 0;
|
||||||
|
int len = 0;
|
||||||
|
msdos_token_types_t type = MSDOS_CURRENT_DIR;
|
||||||
|
char token[MSDOS_NAME_MAX + 1];
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
if (!pathloc->node_access)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
rc = fat_file_reopen(fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
while ((type != MSDOS_NO_MORE_PATH) && (type != MSDOS_INVALID_TOKEN))
|
||||||
|
{
|
||||||
|
type = msdos_get_token(&pathname[i], token, &len);
|
||||||
|
i += len;
|
||||||
|
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case MSDOS_UP_DIR:
|
||||||
|
/*
|
||||||
|
* Only a directory can be decended into.
|
||||||
|
*/
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Am I at the root of this mounted filesystem?
|
||||||
|
*/
|
||||||
|
if (pathloc->node_access ==
|
||||||
|
pathloc->mt_entry->mt_fs_root.node_access)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Am I at the root of all filesystems?
|
||||||
|
* XXX: MSDOS is not supposed to be base fs.
|
||||||
|
*/
|
||||||
|
if (pathloc->node_access ==
|
||||||
|
rtems_filesystem_root.node_access)
|
||||||
|
{
|
||||||
|
break; /* Throw out the .. in this case */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newloc = pathloc->mt_entry->mt_point_node;
|
||||||
|
*pathloc = newloc;
|
||||||
|
|
||||||
|
rc = fat_file_close(pathloc->mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return (*pathloc->ops->evalpath_h)(&(pathname[i-len]),
|
||||||
|
flags, pathloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = msdos_find_name(pathloc, token);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
if (rc == MSDOS_NAME_NOT_FOUND_ERR)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_NAME:
|
||||||
|
/*
|
||||||
|
* Only a directory can be decended into.
|
||||||
|
*/
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
if (rc == MSDOS_NAME_NOT_FOUND_ERR)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_NO_MORE_PATH:
|
||||||
|
case MSDOS_CURRENT_DIR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_INVALID_TOKEN:
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Always return the root node.
|
||||||
|
*
|
||||||
|
* If we are at a node that is a mount point. Set loc to the
|
||||||
|
* new fs root node and let let the mounted filesystem set the handlers.
|
||||||
|
*
|
||||||
|
* NOTE: The behavior of stat() on a mount point appears to be
|
||||||
|
* questionable.
|
||||||
|
* NOTE: MSDOS filesystem currently doesn't support mount functionality ->
|
||||||
|
* action not implemented
|
||||||
|
*/
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
msdos_set_handlers(pathloc);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
fat_file_close(pathloc->mt_entry, fat_fd);
|
||||||
|
|
||||||
|
err:
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_eval4make --
|
||||||
|
* The following routine evaluate path for a new node to be created.
|
||||||
|
* 'pathloc' is returned with a pointer to the parent of the new node.
|
||||||
|
* 'name' is returned with a pointer to the first character in the
|
||||||
|
* new node name. The parent node is verified to be a directory.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* path - path for evaluation
|
||||||
|
* pathloc - IN/OUT (start point for evaluation/parent directory for
|
||||||
|
* creation)
|
||||||
|
* name - new node name
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, filled pathloc for parent directory and name of new node on
|
||||||
|
* success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_eval4make(
|
||||||
|
const char *path,
|
||||||
|
rtems_filesystem_location_info_t *pathloc,
|
||||||
|
const char **name
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = NULL;
|
||||||
|
rtems_filesystem_location_info_t newloc;
|
||||||
|
msdos_token_types_t type;
|
||||||
|
int i = 0;
|
||||||
|
int len;
|
||||||
|
char token[ MSDOS_NAME_MAX + 1 ];
|
||||||
|
rtems_boolean done = 0;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
if (!pathloc->node_access)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
rc = fat_file_reopen(fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
type = msdos_get_token(&path[i], token, &len);
|
||||||
|
i += len;
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case MSDOS_UP_DIR:
|
||||||
|
/*
|
||||||
|
* Only a directory can be decended into.
|
||||||
|
*/
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Am I at the root of this mounted filesystem?
|
||||||
|
*/
|
||||||
|
if (pathloc->node_access ==
|
||||||
|
pathloc->mt_entry->mt_fs_root.node_access)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Am I at the root of all filesystems?
|
||||||
|
* XXX: MSDOS is not supposed to be base fs.
|
||||||
|
*/
|
||||||
|
if (pathloc->node_access ==
|
||||||
|
rtems_filesystem_root.node_access)
|
||||||
|
{
|
||||||
|
break; /* Throw out the .. in this case */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newloc = pathloc->mt_entry->mt_point_node;
|
||||||
|
*pathloc = newloc;
|
||||||
|
|
||||||
|
rc = fat_file_close(pathloc->mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return (*pathloc->ops->evalformake_h)(&path[i-len],
|
||||||
|
pathloc, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = msdos_find_name(pathloc, token);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
if (rc == MSDOS_NAME_NOT_FOUND_ERR)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_NAME:
|
||||||
|
/*
|
||||||
|
* Only a directory can be decended into.
|
||||||
|
*/
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
if (rc != MSDOS_NAME_NOT_FOUND_ERR)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
done = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_NO_MORE_PATH:
|
||||||
|
errno = EEXIST;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_CURRENT_DIR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_INVALID_TOKEN:
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*name = &path[i - len];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have evaluated the path as far as we can.
|
||||||
|
* Verify there is not any invalid stuff at the end of the name.
|
||||||
|
*/
|
||||||
|
for( ; path[i] != '\0'; i++)
|
||||||
|
{
|
||||||
|
if (!msdos_is_separator(path[i]))
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
msdos_set_handlers(pathloc);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
fat_file_close(pathloc->mt_entry, fat_fd);
|
||||||
|
|
||||||
|
err:
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
485
c/src/exec/libfs/src/dosfs/msdos_file.c
Normal file
485
c/src/exec/libfs/src/dosfs/msdos_file.c
Normal file
@@ -0,0 +1,485 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS file handlers implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_file_open --
|
||||||
|
* Open fat-file which correspondes to the file
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* pathname - name
|
||||||
|
* flag - flags
|
||||||
|
* mode - mode
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, if file opened successfully, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_open(rtems_libio_t *iop, const char *pathname, unsigned32 flag,
|
||||||
|
unsigned32 mode)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_reopen(fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iop->flags & LIBIO_FLAGS_APPEND)
|
||||||
|
iop->offset = fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
iop->size = fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* buffer - buffer provided by user
|
||||||
|
* count - the number of bytes to read
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* the number of bytes read on success, or -1 if error occured (errno set
|
||||||
|
* appropriately)
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
msdos_file_read(rtems_libio_t *iop, void *buffer, unsigned32 count)
|
||||||
|
{
|
||||||
|
ssize_t ret = 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->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
ret = fat_file_read(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
|
||||||
|
buffer);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_write --
|
||||||
|
* This routine writes the specified data buffer into the file pointed to
|
||||||
|
* by file control block.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* buffer - data to write
|
||||||
|
* count - count of bytes to write
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* the number of bytes written on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
msdos_file_write(rtems_libio_t *iop,const void *buffer, unsigned32 count)
|
||||||
|
{
|
||||||
|
ssize_t ret = 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->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
ret = fat_file_write(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
|
||||||
|
buffer);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* update file size in both fat-file descriptor and file control block if
|
||||||
|
* file was extended
|
||||||
|
*/
|
||||||
|
if (iop->offset + ret > fat_fd->fat_file_size)
|
||||||
|
fat_fd->fat_file_size = iop->offset + ret;
|
||||||
|
|
||||||
|
iop->size = fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_lseek --
|
||||||
|
* Process lseek call to the file: extend file if lseek is up to the end
|
||||||
|
* of the file.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* offset - new offset
|
||||||
|
* whence - predefine directive
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* new offset on success, or -1 if error occured (errno set
|
||||||
|
* appropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_lseek(rtems_libio_t *iop, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
unsigned32 real_size = 0;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_extend(iop->pathinfo.mt_entry, fat_fd, iop->offset,
|
||||||
|
&real_size);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (real_size > fat_fd->fat_file_size)
|
||||||
|
fat_fd->fat_file_size = iop->offset = real_size;
|
||||||
|
|
||||||
|
iop->size = fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return iop->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_stat --
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* loc - node description
|
||||||
|
* buf - stat buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_stat(
|
||||||
|
rtems_filesystem_location_info_t *loc,
|
||||||
|
struct stat *buf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = loc->node_access;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
buf->st_dev = fs_info->fat.vol.dev;
|
||||||
|
buf->st_ino = fat_fd->ino;
|
||||||
|
buf->st_mode = S_IFREG;
|
||||||
|
buf->st_rdev = 0ll;
|
||||||
|
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_mtime = fat_fd->mtime;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_ftruncate --
|
||||||
|
* Truncate the file (if new length is greater then current do nothing).
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* length - new length
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
|
||||||
|
if (length >= fat_fd->fat_file_size)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_truncate(iop->pathinfo.mt_entry, fat_fd, length);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fat_file_truncate do nothing if new length >= fat-file size, so update
|
||||||
|
* file size only if length < fat-file size
|
||||||
|
*/
|
||||||
|
if (length < fat_fd->fat_file_size)
|
||||||
|
iop->size = fat_fd->fat_file_size = length;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_sync --
|
||||||
|
* Synchronize file - synchronize file data and if file is not removed
|
||||||
|
* synchronize file metadata.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_sync(rtems_libio_t *iop)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
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)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/* synchronize file data */
|
||||||
|
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if fat-file descriptor is not marked "removed" - synchronize file
|
||||||
|
* metadata
|
||||||
|
*/
|
||||||
|
if (!FAT_FILE_IS_REMOVED(fat_fd))
|
||||||
|
{
|
||||||
|
rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_datasync --
|
||||||
|
* Synchronize file - synchronize only file data (metadata is letf intact).
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_datasync(rtems_libio_t *iop)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
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)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/* synchronize file data */
|
||||||
|
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* msdos_file_ioctl --
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_ioctl(rtems_libio_t *iop,unsigned32 command, void *buffer)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* correspondes to the file as "removed"
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathloc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
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,
|
||||||
|
MSDOS_THIS_DIR_ENTRY_EMPTY);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_file_mark_removed(pathloc->mt_entry, fat_fd);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
56
c/src/exec/libfs/src/dosfs/msdos_free.c
Normal file
56
c/src/exec/libfs/src/dosfs/msdos_free.c
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Free node handler implementation for the filesystem
|
||||||
|
* operations table.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_free_node_info --
|
||||||
|
* Call fat-file close routine.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathloc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 code if error occured
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_free_node_info(rtems_filesystem_location_info_t *pathloc)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_close(pathloc->mt_entry, pathloc->node_access);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
71
c/src/exec/libfs/src/dosfs/msdos_fsunmount.c
Normal file
71
c/src/exec/libfs/src/dosfs/msdos_fsunmount.c
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS shut down handler implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_shut_down --
|
||||||
|
* Shut down MSDOS filesystem - free all allocated resources (don't
|
||||||
|
* return if deallocation of some resource failed - free as much as
|
||||||
|
* possible).
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* temp_mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set apropriately).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
msdos_fs_info_t *fs_info = temp_mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = temp_mt_entry->mt_fs_root.node_access;
|
||||||
|
|
||||||
|
/* close fat-file which correspondes to root directory */
|
||||||
|
if (fat_file_close(temp_mt_entry, fat_fd) != RC_OK)
|
||||||
|
{
|
||||||
|
/* no return - try to free as much as possible */
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fat_shutdown_drive(temp_mt_entry) != RC_OK)
|
||||||
|
{
|
||||||
|
/* no return - try to free as much as possible */
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_semaphore_delete(fs_info->vol_sema);
|
||||||
|
free(fs_info->cl_buf);
|
||||||
|
free(temp_mt_entry->fs_info);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
36
c/src/exec/libfs/src/dosfs/msdos_handlers_dir.c
Normal file
36
c/src/exec/libfs/src/dosfs/msdos_handlers_dir.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Directory Handlers Table for MSDOS filesystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
rtems_filesystem_file_handlers_r msdos_dir_handlers = {
|
||||||
|
msdos_dir_open,
|
||||||
|
msdos_dir_close,
|
||||||
|
msdos_dir_read,
|
||||||
|
NULL, /* msdos_dir_write */
|
||||||
|
NULL, /* msdos_dir_ioctl */
|
||||||
|
msdos_dir_lseek,
|
||||||
|
msdos_dir_stat,
|
||||||
|
NULL,
|
||||||
|
NULL, /* msdos_dir_ftruncate */
|
||||||
|
NULL,
|
||||||
|
msdos_dir_sync,
|
||||||
|
msdos_dir_sync,
|
||||||
|
NULL, /* msdos_dir_fcntl */
|
||||||
|
msdos_dir_rmnod
|
||||||
|
};
|
||||||
36
c/src/exec/libfs/src/dosfs/msdos_handlers_file.c
Normal file
36
c/src/exec/libfs/src/dosfs/msdos_handlers_file.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* File Operations Table for MSDOS filesystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
rtems_filesystem_file_handlers_r msdos_file_handlers = {
|
||||||
|
msdos_file_open,
|
||||||
|
msdos_file_close,
|
||||||
|
msdos_file_read,
|
||||||
|
msdos_file_write,
|
||||||
|
msdos_file_ioctl,
|
||||||
|
msdos_file_lseek,
|
||||||
|
msdos_file_stat,
|
||||||
|
NULL,
|
||||||
|
msdos_file_ftruncate,
|
||||||
|
NULL,
|
||||||
|
msdos_file_sync,
|
||||||
|
msdos_file_datasync,
|
||||||
|
NULL, /* msdos_file_fcntl */
|
||||||
|
msdos_file_rmnod
|
||||||
|
};
|
||||||
60
c/src/exec/libfs/src/dosfs/msdos_init.c
Normal file
60
c/src/exec/libfs/src/dosfs/msdos_init.c
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Init routine for MSDOS
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
rtems_filesystem_operations_table msdos_ops = {
|
||||||
|
msdos_eval_path,
|
||||||
|
msdos_eval4make,
|
||||||
|
NULL, /* msdos_link */
|
||||||
|
msdos_file_rmnod,
|
||||||
|
msdos_node_type,
|
||||||
|
msdos_mknod,
|
||||||
|
NULL, /* msdos_chown */
|
||||||
|
msdos_free_node_info,
|
||||||
|
NULL,
|
||||||
|
msdos_initialize,
|
||||||
|
NULL,
|
||||||
|
msdos_shut_down, /* msdos_shut_down */
|
||||||
|
NULL, /* msdos_utime */
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* msdos_initialize --
|
||||||
|
* MSDOS filesystem initialization
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* temp_mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set apropriately).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_initialize(rtems_filesystem_mount_table_entry_t *temp_mt_entry)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
|
||||||
|
rc = msdos_initialize_support(temp_mt_entry,
|
||||||
|
&msdos_ops,
|
||||||
|
&msdos_file_handlers,
|
||||||
|
&msdos_dir_handlers);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
149
c/src/exec/libfs/src/dosfs/msdos_initsupp.c
Normal file
149
c/src/exec/libfs/src/dosfs/msdos_initsupp.c
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS Initialization support routine implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_initialize_support --
|
||||||
|
* MSDOS filesystem initialization
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* temp_mt_entry - mount table entry
|
||||||
|
* op_table - filesystem operations table
|
||||||
|
* file_handlers - file operations table
|
||||||
|
* directory_handlers - directory operations table
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and filled temp_mt_entry on success, or -1 if error occured
|
||||||
|
* (errno set apropriately)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_initialize_support(
|
||||||
|
rtems_filesystem_mount_table_entry_t *temp_mt_entry,
|
||||||
|
rtems_filesystem_operations_table *op_table,
|
||||||
|
rtems_filesystem_file_handlers_r *file_handlers,
|
||||||
|
rtems_filesystem_file_handlers_r *directory_handlers
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = NULL;
|
||||||
|
fat_file_fd_t *fat_fd = NULL;
|
||||||
|
unsigned32 cl_buf_size;
|
||||||
|
|
||||||
|
fs_info = (msdos_fs_info_t *)calloc(1, sizeof(msdos_fs_info_t));
|
||||||
|
if (!fs_info)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
|
||||||
|
temp_mt_entry->fs_info = fs_info;
|
||||||
|
|
||||||
|
rc = fat_init_volume_info(temp_mt_entry);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
free(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs_info->file_handlers = file_handlers;
|
||||||
|
fs_info->directory_handlers = directory_handlers;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
fat_shutdown_drive(temp_mt_entry);
|
||||||
|
free(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
fat_fd->map.disk_cln = fat_fd->cln;
|
||||||
|
|
||||||
|
/* if we have FAT12/16 */
|
||||||
|
if ( fat_fd->cln == 0 )
|
||||||
|
{
|
||||||
|
fat_fd->fat_file_size = fs_info->fat.vol.rdir_size;
|
||||||
|
cl_buf_size = (fs_info->fat.vol.bpc > fs_info->fat.vol.rdir_size) ?
|
||||||
|
fs_info->fat.vol.bpc :
|
||||||
|
fs_info->fat.vol.rdir_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = fat_file_size(temp_mt_entry, fat_fd);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
fat_file_close(temp_mt_entry, fat_fd);
|
||||||
|
fat_shutdown_drive(temp_mt_entry);
|
||||||
|
free(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
cl_buf_size = fs_info->fat.vol.bpc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs_info->cl_buf = (char *)calloc(cl_buf_size, sizeof(char));
|
||||||
|
if (fs_info->cl_buf == NULL)
|
||||||
|
{
|
||||||
|
fat_file_close(temp_mt_entry, fat_fd);
|
||||||
|
fat_shutdown_drive(temp_mt_entry);
|
||||||
|
free(fs_info);
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
sc = rtems_semaphore_create(3,
|
||||||
|
1,
|
||||||
|
RTEMS_BINARY_SEMAPHORE | RTEMS_FIFO,
|
||||||
|
RTEMS_INHERIT_PRIORITY,
|
||||||
|
&fs_info->vol_sema);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
{
|
||||||
|
fat_file_close(temp_mt_entry, fat_fd);
|
||||||
|
fat_shutdown_drive(temp_mt_entry);
|
||||||
|
free(fs_info->cl_buf);
|
||||||
|
free(fs_info);
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
}
|
||||||
|
|
||||||
|
temp_mt_entry->mt_fs_root.node_access = fat_fd;
|
||||||
|
temp_mt_entry->mt_fs_root.handlers = directory_handlers;
|
||||||
|
temp_mt_entry->mt_fs_root.ops = op_table;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
1087
c/src/exec/libfs/src/dosfs/msdos_misc.c
Normal file
1087
c/src/exec/libfs/src/dosfs/msdos_misc.c
Normal file
File diff suppressed because it is too large
Load Diff
90
c/src/exec/libfs/src/dosfs/msdos_mknod.c
Normal file
90
c/src/exec/libfs/src/dosfs/msdos_mknod.c
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Routine for node creation in MSDOS filesystem.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_mknod --
|
||||||
|
* The following function checks spelling and formats name for a new node,
|
||||||
|
* determines type of the node to be created and creates it.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* token - non-formatted name of a new node
|
||||||
|
* mode - node type
|
||||||
|
* dev - dev
|
||||||
|
* pathloc - parent directory description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on succes, or -1 if error occured and set errno
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_mknod(
|
||||||
|
const char *token,
|
||||||
|
mode_t mode,
|
||||||
|
dev_t dev,
|
||||||
|
rtems_filesystem_location_info_t *pathloc
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
if (S_ISDIR(mode))
|
||||||
|
{
|
||||||
|
type = MSDOS_DIRECTORY;
|
||||||
|
}
|
||||||
|
else if (S_ISREG(mode))
|
||||||
|
{
|
||||||
|
type = MSDOS_REGULAR_FILE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
set_errno_and_return_minus_one(EINVAL);
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/* Create an MSDOS node */
|
||||||
|
rc = msdos_creat_node(pathloc, type, new_name, mode);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
58
c/src/exec/libfs/src/dosfs/msdos_node_type.c
Normal file
58
c/src/exec/libfs/src/dosfs/msdos_node_type.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* The following returns the type of node that the loc refers to.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_node_type --
|
||||||
|
* Determine type of the node that the pathloc refers to.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathloc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* node type
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
rtems_filesystem_node_types_t
|
||||||
|
msdos_node_type(rtems_filesystem_location_info_t *pathloc)
|
||||||
|
{
|
||||||
|
fat_file_fd_t *fat_fd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we don't need to obtain the volume semaphore here because node_type_h
|
||||||
|
* call always follows evalpath_h call(hence link increment occured) and
|
||||||
|
* hence node_access memory can't be freed during processing node_type_h
|
||||||
|
* call
|
||||||
|
*/
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
return fat_fd->fat_file_type;
|
||||||
|
}
|
||||||
@@ -13,7 +13,9 @@ include $(top_srcdir)/../../../automake/lib.am
|
|||||||
|
|
||||||
IMFSLIB = ../src/imfs/$(ARCH)/libimfs.a
|
IMFSLIB = ../src/imfs/$(ARCH)/libimfs.a
|
||||||
|
|
||||||
TMP_LIBS = $(IMFSLIB)
|
DOSFSLIB = ../src/dosfs/$(ARCH)/libdosfs.a
|
||||||
|
|
||||||
|
TMP_LIBS = $(IMFSLIB) $(DOSFSLIB)
|
||||||
|
|
||||||
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB)
|
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB)
|
||||||
$(INSTALL_DATA) $< $@
|
$(INSTALL_DATA) $< $@
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
2002-02-28 Victor V. Vengerov <vvv@oktet.ru>
|
||||||
|
|
||||||
|
* DOS filesystem including FAT12, FAT16, and FAT32 support submitted.
|
||||||
|
* src/dosfs, src/dosfs/Makefile.am, src/dosfs/stamp-h2.in,
|
||||||
|
src/dosfs/config.h.in, src/dosfs/dosfs.h, src/dosfs/fat.c,
|
||||||
|
src/dosfs/fat.h, src/dosfs/fat_fat_operations.c,
|
||||||
|
src/dosfs/fat_fat_operations.h, src/dosfs/fat_file.c,
|
||||||
|
src/dosfs/fat_file.h, src/dosfs/msdos.h, src/dosfs/msdos_create.c,
|
||||||
|
src/dosfs/msdos_dir.c, src/dosfs/msdos_eval.c, src/dosfs/msdos_file.c,
|
||||||
|
src/dosfs/msdos_free.c, src/dosfs/msdos_fsunmount.c,
|
||||||
|
src/dosfs/msdos_handlers_dir.c, src/dosfs/msdos_handlers_file.c,
|
||||||
|
src/dosfs/msdos_init.c, src/dosfs/msdos_initsupp.c,
|
||||||
|
src/dosfs/msdos_misc.c, src/dosfs/msdos_mknod.c,
|
||||||
|
src/dosfs/msdos_node_type.c, src/dosfs/.cvsignore: New files.
|
||||||
|
* configure.ac, src/Makefile.am, wrapup/Makefile.am: Modified to
|
||||||
|
reflect addition.
|
||||||
|
|
||||||
2002-01-07 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
2002-01-07 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
||||||
|
|
||||||
* src/imfs/imfs_load_tar.c: Add include <sys/types.h>.
|
* src/imfs/imfs_load_tar.c: Add include <sys/types.h>.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
AC_PREREQ(2.52)
|
AC_PREREQ(2.52)
|
||||||
AC_INIT
|
AC_INIT
|
||||||
AC_CONFIG_SRCDIR([src/imfs/imfs.h])
|
AC_CONFIG_SRCDIR([src/imfs/imfs.h])
|
||||||
|
AC_CONFIG_SRCDIR([src/dosfs/dosfs.h])
|
||||||
RTEMS_TOP(../../..)
|
RTEMS_TOP(../../..)
|
||||||
AC_CONFIG_AUX_DIR(../../..)
|
AC_CONFIG_AUX_DIR(../../..)
|
||||||
|
|
||||||
@@ -27,11 +28,13 @@ RTEMS_CANONICALIZE_TOOLS
|
|||||||
|
|
||||||
AM_CONDITIONAL(UNIX,test x"$RTEMS_CPU" = x"unix")
|
AM_CONDITIONAL(UNIX,test x"$RTEMS_CPU" = x"unix")
|
||||||
AM_CONFIG_HEADER(src/imfs/config.h)
|
AM_CONFIG_HEADER(src/imfs/config.h)
|
||||||
|
AM_CONFIG_HEADER(src/dosfs/config.h)
|
||||||
|
|
||||||
# Explicitly list all Makefiles here
|
# Explicitly list all Makefiles here
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
src/imfs/Makefile
|
src/imfs/Makefile
|
||||||
|
src/dosfs/Makefile
|
||||||
wrapup/Makefile
|
wrapup/Makefile
|
||||||
])
|
])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
AUTOMAKE_OPTIONS = foreign 1.4
|
AUTOMAKE_OPTIONS = foreign 1.4
|
||||||
|
|
||||||
SUBDIRS = imfs
|
SUBDIRS = imfs dosfs
|
||||||
|
|
||||||
include $(top_srcdir)/../../../automake/subdirs.am
|
include $(top_srcdir)/../../../automake/subdirs.am
|
||||||
include $(top_srcdir)/../../../automake/local.am
|
include $(top_srcdir)/../../../automake/local.am
|
||||||
|
|||||||
6
c/src/libfs/src/dosfs/.cvsignore
Normal file
6
c/src/libfs/src/dosfs/.cvsignore
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
config.h
|
||||||
|
config.h.in
|
||||||
|
stamp-h
|
||||||
|
stamp-h.in
|
||||||
80
c/src/libfs/src/dosfs/Makefile.am
Normal file
80
c/src/libfs/src/dosfs/Makefile.am
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
##
|
||||||
|
## $Id$
|
||||||
|
##
|
||||||
|
|
||||||
|
AUTOMAKE_OPTIONS = foreign 1.4
|
||||||
|
|
||||||
|
INCLUDES = -I.
|
||||||
|
|
||||||
|
LIBNAME = libdosfs
|
||||||
|
LIB = ${ARCH}/${LIBNAME}.a
|
||||||
|
|
||||||
|
FATFS_C_FILES = fat.c fat_fat_operations.c fat_file.c
|
||||||
|
|
||||||
|
DOSFS_C_FILES = msdos_create.c msdos_dir.c msdos_eval.c msdos_file.c \
|
||||||
|
msdos_free.c msdos_fsunmount.c msdos_handlers_dir.c \
|
||||||
|
msdos_handlers_file.c msdos_init.c msdos_initsupp.c \
|
||||||
|
msdos_misc.c msdos_mknod.c msdos_node_type.c
|
||||||
|
|
||||||
|
|
||||||
|
UNIX_C_FILES = msdos_unixstub.c
|
||||||
|
|
||||||
|
EMBEDDED_C_FILES = $(FATFS_C_FILES) $(DOSFS_C_FILES)
|
||||||
|
|
||||||
|
COMMON_C_FILES =
|
||||||
|
|
||||||
|
if UNIX
|
||||||
|
C_FILES = $(COMMON_C_FILES) $(UNIX_C_FILES)
|
||||||
|
else
|
||||||
|
C_FILES = $(COMMON_C_FILES) $(EMBEDDED_C_FILES)
|
||||||
|
endif
|
||||||
|
C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o)
|
||||||
|
|
||||||
|
include_HEADERS = fat.h fat_fat_operations.h \
|
||||||
|
fat_file.h msdos.h dosfs.h
|
||||||
|
SYS_H_FILES =
|
||||||
|
RTEMS_H_FILES =
|
||||||
|
noinst_HEADERS =
|
||||||
|
|
||||||
|
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||||
|
include $(top_srcdir)/../../../automake/compile.am
|
||||||
|
include $(top_srcdir)/../../../automake/lib.am
|
||||||
|
|
||||||
|
PREINSTALL_FILES = $(PROJECT_INCLUDE) $(PROJECT_INCLUDE)/rtems \
|
||||||
|
$(PROJECT_INCLUDE)/sys $(include_HEADERS:%=$(PROJECT_INCLUDE)/%) \
|
||||||
|
$(RTEMS_H_FILES:%=$(PROJECT_INCLUDE)/rtems/%) \
|
||||||
|
$(SYS_H_FILES:%=$(PROJECT_INCLUDE)/sys/%)
|
||||||
|
|
||||||
|
$(PROJECT_INCLUDE):
|
||||||
|
@$(mkinstalldirs) $@
|
||||||
|
$(PROJECT_INCLUDE)/rtems:
|
||||||
|
@$(mkinstalldirs) $@
|
||||||
|
$(PROJECT_INCLUDE)/sys:
|
||||||
|
@$(mkinstalldirs) $@
|
||||||
|
|
||||||
|
$(PROJECT_INCLUDE)/%.h: %.h
|
||||||
|
$(INSTALL_DATA) $< $@
|
||||||
|
$(PROJECT_INCLUDE)/rtems/%.h: %.h
|
||||||
|
$(INSTALL_DATA) $< $@
|
||||||
|
$(PROJECT_INCLUDE)/sys/%.h: %.h
|
||||||
|
$(INSTALL_DATA) $< $@
|
||||||
|
|
||||||
|
OBJS = $(C_O_FILES)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add local stuff here using +=
|
||||||
|
#
|
||||||
|
|
||||||
|
AM_CFLAGS += $(LIBC_DEFINES)
|
||||||
|
|
||||||
|
all-local: ${ARCH} $(LIB)
|
||||||
|
|
||||||
|
$(LIB): ${OBJS}
|
||||||
|
$(make-library)
|
||||||
|
|
||||||
|
DOC_FILES =
|
||||||
|
|
||||||
|
EXTRA_DIST = $(DOC_FILES) $(COMMON_C_FILES) $(EMBEDDED_C_FILES) \
|
||||||
|
$(UNIX_C_FILES) $(RTEMS_H_FILES) $(SYS_H_FILES)
|
||||||
|
|
||||||
|
include $(top_srcdir)/../../../automake/local.am
|
||||||
1
c/src/libfs/src/dosfs/config.h.in
Normal file
1
c/src/libfs/src/dosfs/config.h.in
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/* src/dosfs/config.h.in. Generated automatically from configure.in by autoheader. */
|
||||||
31
c/src/libfs/src/dosfs/dosfs.h
Normal file
31
c/src/libfs/src/dosfs/dosfs.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* dosfs.h
|
||||||
|
*
|
||||||
|
* Application interface to MSDOS filesystem.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#ifndef __DOSFS_DOSFS_H__
|
||||||
|
#define __DOSFS_DOSFS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
|
||||||
|
extern rtems_filesystem_operations_table msdos_ops;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_DOSFS_H__ */
|
||||||
695
c/src/libfs/src/dosfs/fat.c
Normal file
695
c/src/libfs/src/dosfs/fat.c
Normal file
@@ -0,0 +1,695 @@
|
|||||||
|
/*
|
||||||
|
* fat.c
|
||||||
|
*
|
||||||
|
* Low-level operations on a volume with FAT filesystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
|
||||||
|
/* _fat_block_read --
|
||||||
|
* This function reads 'count' bytes from device filesystem is mounted on,
|
||||||
|
* starts at 'start+offset' position where 'start' computed in sectors
|
||||||
|
* and 'offset' is offset inside sector (reading may cross sectors
|
||||||
|
* boundary; in this case assumed we want to read sequential sector(s))
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* start - sector num to start read from
|
||||||
|
* offset - offset inside sector 'start'
|
||||||
|
* count - count of bytes to read
|
||||||
|
* buff - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* bytes read on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
_fat_block_read(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 offset,
|
||||||
|
unsigned32 count,
|
||||||
|
void *buff
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
ssize_t cmpltd = 0;
|
||||||
|
unsigned32 blk = start;
|
||||||
|
unsigned32 ofs = offset;
|
||||||
|
bdbuf_buffer *block = NULL;
|
||||||
|
unsigned32 c = 0;
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
c = MIN(count, (fs_info->vol.bps - ofs));
|
||||||
|
memcpy((buff + cmpltd), (block->buffer + ofs), c);
|
||||||
|
|
||||||
|
count -= c;
|
||||||
|
cmpltd += c;
|
||||||
|
blk++;
|
||||||
|
ofs = 0;
|
||||||
|
}
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _fat_block_write --
|
||||||
|
* This function write 'count' bytes to device filesystem is mounted on,
|
||||||
|
* starts at 'start+offset' position where 'start' computed in sectors
|
||||||
|
* and 'offset' is offset inside sector (writing may cross sectors
|
||||||
|
* boundary; in this case assumed we want to write sequential sector(s))
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* start - sector num to start read from
|
||||||
|
* offset - offset inside sector 'start'
|
||||||
|
* count - count of bytes to write
|
||||||
|
* buff - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* bytes written on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
_fat_block_write(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 offset,
|
||||||
|
unsigned32 count,
|
||||||
|
const void *buff)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
ssize_t cmpltd = 0;
|
||||||
|
unsigned32 blk = start;
|
||||||
|
unsigned32 ofs = offset;
|
||||||
|
bdbuf_buffer *block = NULL;
|
||||||
|
unsigned32 c = 0;
|
||||||
|
|
||||||
|
while(count > 0)
|
||||||
|
{
|
||||||
|
c = MIN(count, (fs_info->vol.bps - ofs));
|
||||||
|
|
||||||
|
if (c == fs_info->vol.bps)
|
||||||
|
rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_GET, &block);
|
||||||
|
else
|
||||||
|
rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
memcpy((block->buffer + ofs), (buff + cmpltd), c);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
|
||||||
|
count -= c;
|
||||||
|
cmpltd +=c;
|
||||||
|
blk++;
|
||||||
|
ofs = 0;
|
||||||
|
}
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* fat_cluster_read --
|
||||||
|
* wrapper for reading a whole cluster at once
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - number of cluster to read
|
||||||
|
* buff - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* bytes read on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
fat_cluster_read(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
void *buff
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 fsec = 0;
|
||||||
|
|
||||||
|
fsec = fat_cluster_num_to_sector_num(mt_entry, cln);
|
||||||
|
|
||||||
|
return _fat_block_read(mt_entry, fsec, 0,
|
||||||
|
fs_info->vol.spc << fs_info->vol.sec_log2, buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_cluster_write --
|
||||||
|
* wrapper for writting a whole cluster at once
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - number of cluster to write
|
||||||
|
* buff - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* bytes written on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
fat_cluster_write(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
const void *buff
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 fsec = 0;
|
||||||
|
|
||||||
|
fsec = fat_cluster_num_to_sector_num(mt_entry, cln);
|
||||||
|
|
||||||
|
return _fat_block_write(mt_entry, fsec, 0,
|
||||||
|
fs_info->vol.spc << fs_info->vol.sec_log2, buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_init_volume_info --
|
||||||
|
* Get inforamtion about volume on which filesystem is mounted on
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
register fat_vol_t *vol = &fs_info->vol;
|
||||||
|
unsigned32 data_secs = 0;
|
||||||
|
char boot_rec[FAT_MAX_BPB_SIZE];
|
||||||
|
char fs_info_sector[FAT_USEFUL_INFO_SIZE];
|
||||||
|
ssize_t ret = 0;
|
||||||
|
int fd;
|
||||||
|
struct stat stat_buf;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
rc = stat(mt_entry->dev, &stat_buf);
|
||||||
|
if (rc == -1)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* rtmes feature: no block devices, all are character devices */
|
||||||
|
if (!S_ISCHR(stat_buf.st_mode))
|
||||||
|
set_errno_and_return_minus_one(ENOTBLK);
|
||||||
|
|
||||||
|
/* check that device is registred as block device and lock it */
|
||||||
|
vol->dd = rtems_disk_lookup(stat_buf.st_dev);
|
||||||
|
if (vol->dd == NULL)
|
||||||
|
set_errno_and_return_minus_one(ENOTBLK);
|
||||||
|
|
||||||
|
vol->dev = stat_buf.st_dev;
|
||||||
|
|
||||||
|
fd = open(mt_entry->dev, O_RDONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = read(fd, (void *)boot_rec, FAT_MAX_BPB_SIZE);
|
||||||
|
if ( ret != FAT_MAX_BPB_SIZE )
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
vol->bps = FAT_BR_BYTES_PER_SECTOR(boot_rec);
|
||||||
|
|
||||||
|
if ( (vol->bps != 512) &&
|
||||||
|
(vol->bps != 1024) &&
|
||||||
|
(vol->bps != 2048) &&
|
||||||
|
(vol->bps != 4096))
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( EINVAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0;
|
||||||
|
i >>= 1, vol->sec_mul++);
|
||||||
|
for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0;
|
||||||
|
i >>= 1, vol->sec_log2++);
|
||||||
|
|
||||||
|
vol->spc = FAT_BR_SECTORS_PER_CLUSTER(boot_rec);
|
||||||
|
for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0;
|
||||||
|
i >>= 1, vol->spc_log2++);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* According to M$ White Paper "bytes per cluster" value
|
||||||
|
* greater than 32K is invalid
|
||||||
|
*/
|
||||||
|
if ((vol->bpc = vol->bps << vol->spc_log2) > MS_BYTES_PER_CLUSTER_LIMIT)
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0;
|
||||||
|
i >>= 1, vol->bpc_log2++);
|
||||||
|
|
||||||
|
vol->fats = FAT_BR_FAT_NUM(boot_rec);
|
||||||
|
vol->fat_loc = FAT_BR_RESERVED_SECTORS_NUM(boot_rec);
|
||||||
|
|
||||||
|
vol->rdir_entrs = FAT_BR_FILES_PER_ROOT_DIR(boot_rec);
|
||||||
|
|
||||||
|
/* calculate the count of sectors occupied by the root directory */
|
||||||
|
vol->rdir_secs = ((vol->rdir_entrs * FAT_DIRENTRY_SIZE) + (vol->bps - 1)) /
|
||||||
|
vol->bps;
|
||||||
|
|
||||||
|
vol->rdir_size = vol->rdir_secs << vol->sec_log2;
|
||||||
|
|
||||||
|
if ( (FAT_BR_SECTORS_PER_FAT(boot_rec)) != 0)
|
||||||
|
vol->fat_length = FAT_BR_SECTORS_PER_FAT(boot_rec);
|
||||||
|
else
|
||||||
|
vol->fat_length = FAT_BR_SECTORS_PER_FAT32(boot_rec);
|
||||||
|
|
||||||
|
vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length +
|
||||||
|
vol->rdir_secs;
|
||||||
|
|
||||||
|
/* for FAT12/16 root dir starts at(sector) */
|
||||||
|
vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length;
|
||||||
|
|
||||||
|
if ( (FAT_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0)
|
||||||
|
vol->tot_secs = FAT_BR_TOTAL_SECTORS_NUM16(boot_rec);
|
||||||
|
else
|
||||||
|
vol->tot_secs = FAT_BR_TOTAL_SECTORS_NUM32(boot_rec);
|
||||||
|
|
||||||
|
data_secs = vol->tot_secs - vol->data_fsec;
|
||||||
|
|
||||||
|
vol->data_cls = data_secs / vol->spc;
|
||||||
|
|
||||||
|
/* determine FAT type at least */
|
||||||
|
if ( vol->data_cls < FAT_FAT12_MAX_CLN)
|
||||||
|
{
|
||||||
|
vol->type = FAT_FAT12;
|
||||||
|
vol->mask = FAT_FAT12_MASK;
|
||||||
|
vol->eoc_val = FAT_FAT12_EOC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( vol->data_cls < FAT_FAT16_MAX_CLN)
|
||||||
|
{
|
||||||
|
vol->type = FAT_FAT16;
|
||||||
|
vol->mask = FAT_FAT16_MASK;
|
||||||
|
vol->eoc_val = FAT_FAT16_EOC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vol->type = FAT_FAT32;
|
||||||
|
vol->mask = FAT_FAT32_MASK;
|
||||||
|
vol->eoc_val = FAT_FAT32_EOC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vol->type == FAT_FAT32)
|
||||||
|
{
|
||||||
|
vol->rdir_cl = FAT_BR_FAT32_ROOT_CLUSTER(boot_rec);
|
||||||
|
|
||||||
|
vol->mirror = FAT_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR;
|
||||||
|
if (vol->mirror)
|
||||||
|
vol->afat = FAT_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM;
|
||||||
|
else
|
||||||
|
vol->afat = 0;
|
||||||
|
|
||||||
|
vol->info_sec = FAT_BR_FAT32_FS_INFO_SECTOR(boot_rec);
|
||||||
|
if( vol->info_sec == 0 )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( EINVAL );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = _fat_block_read(mt_entry, vol->info_sec , 0,
|
||||||
|
FAT_FSI_LEADSIG_SIZE, fs_info_sector);
|
||||||
|
if ( ret < 0 )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAT_FSINFO_LEAD_SIGNATURE(fs_info_sector) !=
|
||||||
|
FAT_FSINFO_LEAD_SIGNATURE_VALUE)
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( EINVAL );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = _fat_block_read(mt_entry, vol->info_sec , FAT_FSI_INFO,
|
||||||
|
FAT_USEFUL_INFO_SIZE, fs_info_sector);
|
||||||
|
if ( ret < 0 )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vol->free_cls = FAT_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector);
|
||||||
|
vol->next_cl = FAT_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector);
|
||||||
|
rc = fat_fat32_update_fsinfo_sector(mt_entry, 0xFFFFFFFF,
|
||||||
|
0xFFFFFFFF);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vol->rdir_cl = 0;
|
||||||
|
vol->mirror = 0;
|
||||||
|
vol->afat = 0;
|
||||||
|
vol->free_cls = 0xFFFFFFFF;
|
||||||
|
vol->next_cl = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat;
|
||||||
|
|
||||||
|
/* set up collection of fat-files fd */
|
||||||
|
fs_info->vhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control));
|
||||||
|
if ( fs_info->vhash == NULL )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < FAT_HASH_SIZE; i++)
|
||||||
|
_Chain_Initialize_empty(fs_info->vhash + i);
|
||||||
|
|
||||||
|
fs_info->rhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control));
|
||||||
|
if ( fs_info->rhash == NULL )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
free(fs_info->vhash);
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
for (i = 0; i < FAT_HASH_SIZE; i++)
|
||||||
|
_Chain_Initialize_empty(fs_info->rhash + i);
|
||||||
|
|
||||||
|
fs_info->uino_pool_size = FAT_UINO_POOL_INIT_SIZE;
|
||||||
|
fs_info->uino_base = (vol->tot_secs << vol->sec_mul) << 4;
|
||||||
|
fs_info->index = 0;
|
||||||
|
fs_info->uino = (char *)calloc(fs_info->uino_pool_size, sizeof(char));
|
||||||
|
if ( fs_info->uino == NULL )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
free(fs_info->vhash);
|
||||||
|
free(fs_info->rhash);
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
fs_info->sec_buf = (char *)calloc(vol->bps, sizeof(char));
|
||||||
|
if (fs_info->sec_buf == NULL)
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
free(fs_info->vhash);
|
||||||
|
free(fs_info->rhash);
|
||||||
|
free(fs_info->uino);
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_shutdown_drive --
|
||||||
|
* Free all allocated resources and synchronize all necessary data
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_shutdown_drive(rtems_filesystem_mount_table_entry_t *mt_entry)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (fs_info->vol.type & FAT_FAT32)
|
||||||
|
{
|
||||||
|
rc = fat_fat32_update_fsinfo_sector(mt_entry, fs_info->vol.free_cls,
|
||||||
|
fs_info->vol.next_cl);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
|
||||||
|
if (rtems_bdbuf_syncdev(fs_info->vol.dev) != RTEMS_SUCCESSFUL)
|
||||||
|
rc = -1;
|
||||||
|
|
||||||
|
for (i = 0; i < FAT_HASH_SIZE; i++)
|
||||||
|
{
|
||||||
|
Chain_Node *node = NULL;
|
||||||
|
Chain_Control *the_chain = fs_info->vhash + i;
|
||||||
|
|
||||||
|
while ( (node = _Chain_Get(the_chain)) != NULL )
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < FAT_HASH_SIZE; i++)
|
||||||
|
{
|
||||||
|
Chain_Node *node = NULL;
|
||||||
|
Chain_Control *the_chain = fs_info->rhash + i;
|
||||||
|
|
||||||
|
while ( (node = _Chain_Get(the_chain)) != NULL )
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fs_info->vhash);
|
||||||
|
free(fs_info->rhash);
|
||||||
|
|
||||||
|
free(fs_info->uino);
|
||||||
|
free(fs_info->sec_buf);
|
||||||
|
rtems_disk_release(fs_info->vol.dd);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
errno = EIO;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_init_clusters_chain --
|
||||||
|
* Zeroing contents of all clusters in the chain
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* start_cluster_num - num of first cluster in the chain
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_init_clusters_chain(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start_cln
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
ssize_t ret = 0;
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = start_cln;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
buf = calloc(fs_info->vol.bpc, sizeof(char));
|
||||||
|
if ( buf == NULL )
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
||||||
|
{
|
||||||
|
ret = fat_cluster_write(mt_entry, cur_cln, buf);
|
||||||
|
if ( ret == -1 )
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FAT_UNIQ_INO_BASE 0x0FFFFF00
|
||||||
|
|
||||||
|
#define FAT_UNIQ_INO_IS_BUSY(index, arr) \
|
||||||
|
(((arr)[((index)>>3)]>>((index) & (8-1))) & 0x01)
|
||||||
|
|
||||||
|
#define FAT_SET_UNIQ_INO_BUSY(index, arr) \
|
||||||
|
((arr)[((index)>>3)] |= (0x01<<((index) & (8-1))))
|
||||||
|
|
||||||
|
#define FAT_SET_UNIQ_INO_FREE(index, arr) \
|
||||||
|
((arr)[((index)>>3)] &= (~(0x01<<((index) & (8-1)))))
|
||||||
|
|
||||||
|
/* fat_get_unique_ino --
|
||||||
|
* Allocate unique ino from unique ino pool
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* unique inode number on success, or 0 if there is no free unique inode
|
||||||
|
* number in the pool
|
||||||
|
*
|
||||||
|
* ATTENTION:
|
||||||
|
* 0 means FAILED !!!
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
unsigned32
|
||||||
|
fat_get_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry)
|
||||||
|
{
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 j = 0;
|
||||||
|
rtems_boolean resrc_unsuff = FALSE;
|
||||||
|
|
||||||
|
while (!resrc_unsuff)
|
||||||
|
{
|
||||||
|
for (j = 0; j < fs_info->uino_pool_size; j++)
|
||||||
|
{
|
||||||
|
if (!FAT_UNIQ_INO_IS_BUSY(fs_info->index, fs_info->uino))
|
||||||
|
{
|
||||||
|
FAT_SET_UNIQ_INO_BUSY(fs_info->index, fs_info->uino);
|
||||||
|
return (fs_info->uino_base + fs_info->index);
|
||||||
|
}
|
||||||
|
fs_info->index++;
|
||||||
|
if (fs_info->index >= fs_info->uino_pool_size)
|
||||||
|
fs_info->index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fs_info->uino_pool_size << 1) < (0x0FFFFFFF - fs_info->uino_base))
|
||||||
|
{
|
||||||
|
fs_info->uino_pool_size <<= 1;
|
||||||
|
fs_info->uino = realloc(fs_info->uino, fs_info->uino_pool_size);
|
||||||
|
if (fs_info->uino != NULL)
|
||||||
|
fs_info->index = fs_info->uino_pool_size;
|
||||||
|
else
|
||||||
|
resrc_unsuff = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
resrc_unsuff = TRUE;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_free_unique_ino --
|
||||||
|
* Return unique ino to unique ino pool
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* ino - inode number to free
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fat_free_unique_ino(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 ino
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
|
||||||
|
FAT_SET_UNIQ_INO_FREE((ino - fs_info->uino_base), fs_info->uino);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_ino_is_unique --
|
||||||
|
* Test whether ino is from unique ino pool
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* ino - ino to be tested
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* TRUE if ino is allocated from unique ino pool, FALSE otherwise
|
||||||
|
*/
|
||||||
|
inline rtems_boolean
|
||||||
|
fat_ino_is_unique(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 ino
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
|
||||||
|
return (ino >= fs_info->uino_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_fat32_update_fsinfo_sector --
|
||||||
|
* Synchronize fsinfo sector for FAT32 volumes
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* free_count - count of free clusters
|
||||||
|
* next_free - the next free cluster num
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_fat32_update_fsinfo_sector(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 free_count,
|
||||||
|
unsigned32 next_free
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ssize_t ret1 = 0, ret2 = 0;
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 le_free_count = 0;
|
||||||
|
unsigned32 le_next_free = 0;
|
||||||
|
|
||||||
|
le_free_count = CT_LE_L(free_count);
|
||||||
|
le_next_free = CT_LE_L(next_free);
|
||||||
|
|
||||||
|
ret1 = _fat_block_write(mt_entry,
|
||||||
|
fs_info->vol.info_sec,
|
||||||
|
FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET,
|
||||||
|
4,
|
||||||
|
(char *)(&le_free_count));
|
||||||
|
|
||||||
|
ret2 = _fat_block_write(mt_entry,
|
||||||
|
fs_info->vol.info_sec,
|
||||||
|
FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET,
|
||||||
|
4,
|
||||||
|
(char *)(&le_next_free));
|
||||||
|
|
||||||
|
if ( (ret1 < 0) || (ret2 < 0) )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
489
c/src/libfs/src/dosfs/fat.h
Normal file
489
c/src/libfs/src/dosfs/fat.h
Normal file
@@ -0,0 +1,489 @@
|
|||||||
|
/*
|
||||||
|
* fat.h
|
||||||
|
*
|
||||||
|
* Constants/data structures/prototypes for low-level operations on a volume
|
||||||
|
* with FAT filesystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DOSFS_FAT_H__
|
||||||
|
#define __DOSFS_FAT_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems/seterr.h>
|
||||||
|
|
||||||
|
/* XXX: temporary hack :(( */
|
||||||
|
#ifndef set_errno_and_return_minus_one
|
||||||
|
#define set_errno_and_return_minus_one rtems_set_errno_and_return_minus_one
|
||||||
|
#endif /* set_errno_and_return_minus_one */
|
||||||
|
|
||||||
|
#include <rtems/score/cpu.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <rtems/bdbuf.h>
|
||||||
|
|
||||||
|
#define DBG1(x) x
|
||||||
|
#define DBG2(x) x
|
||||||
|
|
||||||
|
#ifndef RC_OK
|
||||||
|
#define RC_OK 0x00000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remember that all FAT file system on disk data structure is
|
||||||
|
* "little endian"!
|
||||||
|
* (derived from linux)
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Conversion from and to little-endian byte order. (no-op on i386/i486)
|
||||||
|
*
|
||||||
|
* Naming: Ca_b_c, where a: F = from, T = to, b: LE = little-endian,
|
||||||
|
* BE = big-endian, c: W = word (16 bits), L = longword (32 bits)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (CPU_BIG_ENDIAN == TRUE)
|
||||||
|
# define CF_LE_W(v) CPU_swap_u16(v)
|
||||||
|
# define CF_LE_L(v) CPU_swap_u32(v)
|
||||||
|
# define CT_LE_W(v) CPU_swap_u16(v)
|
||||||
|
# define CT_LE_L(v) CPU_swap_u32(v)
|
||||||
|
#else
|
||||||
|
# define CF_LE_W(v) (v)
|
||||||
|
# define CF_LE_L(v) (v)
|
||||||
|
# define CT_LE_W(v) (v)
|
||||||
|
# define CT_LE_L(v) (v)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
#define FAT_HASH_SIZE 2
|
||||||
|
#define FAT_HASH_MODULE FAT_HASH_SIZE
|
||||||
|
|
||||||
|
|
||||||
|
#define FAT_SECTOR512_SIZE 512 /* sector size (bytes) */
|
||||||
|
#define FAT_SECTOR512_BITS 9 /* log2(SECTOR_SIZE) */
|
||||||
|
|
||||||
|
/* maximum + 1 number of clusters for FAT12 */
|
||||||
|
#define FAT_FAT12_MAX_CLN 4085
|
||||||
|
|
||||||
|
/* maximum + 1 number of clusters for FAT16 */
|
||||||
|
#define FAT_FAT16_MAX_CLN 65525
|
||||||
|
|
||||||
|
#define FAT_FAT12 0x01
|
||||||
|
#define FAT_FAT16 0x02
|
||||||
|
#define FAT_FAT32 0x04
|
||||||
|
|
||||||
|
#define FAT_UNDEFINED_VALUE 0xFFFFFFFF
|
||||||
|
|
||||||
|
#define FAT_FAT12_EOC 0x0FFF
|
||||||
|
#define FAT_FAT16_EOC 0xFFFF
|
||||||
|
#define FAT_FAT32_EOC 0x0FFFFFFF
|
||||||
|
|
||||||
|
#define FAT_FAT12_FREE 0x0000
|
||||||
|
#define FAT_FAT16_FREE 0x0000
|
||||||
|
#define FAT_FAT32_FREE 0x00000000
|
||||||
|
|
||||||
|
#define FAT_GENFAT_EOC 0xFFFFFFFF
|
||||||
|
#define FAT_GENFAT_FREE 0x00000000
|
||||||
|
|
||||||
|
#define FAT_FAT12_SHIFT 0x04
|
||||||
|
|
||||||
|
#define FAT_FAT12_MASK 0x00000FFF
|
||||||
|
#define FAT_FAT16_MASK 0x0000FFFF
|
||||||
|
#define FAT_FAT32_MASK 0x0FFFFFFF
|
||||||
|
|
||||||
|
#define FAT_MAX_BPB_SIZE 90
|
||||||
|
|
||||||
|
/* size of useful information in FSInfo sector */
|
||||||
|
#define FAT_USEFUL_INFO_SIZE 12
|
||||||
|
|
||||||
|
#define FAT_VAL8(x, ofs) (unsigned8)(*((unsigned8 *)(x) + (ofs)))
|
||||||
|
|
||||||
|
#define FAT_VAL16(x, ofs) \
|
||||||
|
(unsigned16)( (*((unsigned8 *)(x) + (ofs))) | \
|
||||||
|
((*((unsigned8 *)(x) + (ofs) + 1)) << 8) )
|
||||||
|
|
||||||
|
#define FAT_VAL32(x, ofs) \
|
||||||
|
(unsigned32)( (*((unsigned8 *)(x) + (ofs))) | \
|
||||||
|
((*((unsigned8 *)(x) + (ofs) + 1)) << 8) | \
|
||||||
|
((*((unsigned8 *)(x) + (ofs) + 2)) << 16) | \
|
||||||
|
((*((unsigned8 *)(x) + (ofs) + 3)) << 24) )
|
||||||
|
|
||||||
|
/* macros to access boot sector fields */
|
||||||
|
#define FAT_BR_BYTES_PER_SECTOR(x) FAT_VAL16(x, 11)
|
||||||
|
#define FAT_BR_SECTORS_PER_CLUSTER(x) FAT_VAL8(x, 13)
|
||||||
|
#define FAT_BR_RESERVED_SECTORS_NUM(x) FAT_VAL16(x, 14)
|
||||||
|
#define FAT_BR_FAT_NUM(x) FAT_VAL8(x, 16)
|
||||||
|
#define FAT_BR_FILES_PER_ROOT_DIR(x) FAT_VAL16(x, 17)
|
||||||
|
#define FAT_BR_TOTAL_SECTORS_NUM16(x) FAT_VAL16(x, 19)
|
||||||
|
#define FAT_BR_MEDIA(x) FAT_VAL8(x, 21)
|
||||||
|
#define FAT_BR_SECTORS_PER_FAT(x) FAT_VAL16(x, 22)
|
||||||
|
#define FAT_BR_TOTAL_SECTORS_NUM32(x) FAT_VAL32(x, 32)
|
||||||
|
#define FAT_BR_SECTORS_PER_FAT32(x) FAT_VAL32(x, 36)
|
||||||
|
#define FAT_BR_EXT_FLAGS(x) FAT_VAL16(x, 40)
|
||||||
|
#define FAT_BR_FAT32_ROOT_CLUSTER(x) FAT_VAL32(x, 44)
|
||||||
|
#define FAT_BR_FAT32_FS_INFO_SECTOR(x) FAT_VAL16(x, 48)
|
||||||
|
#define FAT_FSINFO_LEAD_SIGNATURE(x) FAT_VAL32(x, 0)
|
||||||
|
/*
|
||||||
|
* I read FSInfo sector from offset 484 to access the information, so offsets
|
||||||
|
* of these fields a relative
|
||||||
|
*/
|
||||||
|
#define FAT_FSINFO_FREE_CLUSTER_COUNT(x) FAT_VAL32(x, 4)
|
||||||
|
#define FAT_FSINFO_NEXT_FREE_CLUSTER(x) FAT_VAL32(x, 8)
|
||||||
|
|
||||||
|
#define FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET 488
|
||||||
|
|
||||||
|
#define FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET 492
|
||||||
|
|
||||||
|
#define FAT_RSRVD_CLN 0x02
|
||||||
|
|
||||||
|
#define FAT_FSINFO_LEAD_SIGNATURE_VALUE 0x41615252
|
||||||
|
|
||||||
|
#define FAT_FSI_LEADSIG_SIZE 0x04
|
||||||
|
|
||||||
|
#define FAT_FSI_INFO 484
|
||||||
|
|
||||||
|
#define MS_BYTES_PER_CLUSTER_LIMIT 0x8000 /* 32K */
|
||||||
|
|
||||||
|
#define FAT_BR_EXT_FLAGS_MIRROR 0x0080
|
||||||
|
|
||||||
|
#define FAT_BR_EXT_FLAGS_FAT_NUM 0x000F
|
||||||
|
|
||||||
|
|
||||||
|
#define FAT_DIRENTRY_SIZE 32
|
||||||
|
|
||||||
|
#define FAT_DIRENTRIES_PER_SEC512 16
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Volume descriptor
|
||||||
|
* Description of the volume the FAT filesystem is located on - generally
|
||||||
|
* the fields of the structure corresponde to Boot Sector and BPB Srtucture
|
||||||
|
* (see M$ White Paper) fields
|
||||||
|
*/
|
||||||
|
typedef struct fat_vol_s
|
||||||
|
{
|
||||||
|
unsigned16 bps; /* bytes per sector */
|
||||||
|
unsigned8 sec_log2; /* log2 of bps */
|
||||||
|
unsigned8 sec_mul; /* log2 of 512bts sectors number per sector */
|
||||||
|
unsigned8 spc; /* sectors per cluster */
|
||||||
|
unsigned8 spc_log2; /* log2 of spc */
|
||||||
|
unsigned16 bpc; /* bytes per cluster */
|
||||||
|
unsigned8 bpc_log2; /* log2 of bytes per cluster */
|
||||||
|
unsigned8 fats; /* number of FATs */
|
||||||
|
unsigned8 type; /* FAT type */
|
||||||
|
unsigned32 mask;
|
||||||
|
unsigned32 eoc_val;
|
||||||
|
unsigned16 fat_loc; /* FAT start */
|
||||||
|
unsigned32 fat_length; /* sectors per FAT */
|
||||||
|
unsigned32 rdir_loc; /* root directory start */
|
||||||
|
unsigned16 rdir_entrs; /* files per root directory */
|
||||||
|
unsigned32 rdir_secs; /* sectors per root directory */
|
||||||
|
unsigned32 rdir_size; /* root directory size in bytes */
|
||||||
|
unsigned32 tot_secs; /* total count of sectors */
|
||||||
|
unsigned32 data_fsec; /* first data sector */
|
||||||
|
unsigned32 data_cls; /* count of data clusters */
|
||||||
|
unsigned32 rdir_cl; /* first cluster of the root directory */
|
||||||
|
unsigned16 info_sec; /* FSInfo Sector Structure location */
|
||||||
|
unsigned32 free_cls; /* last known free clusters count */
|
||||||
|
unsigned32 next_cl; /* next free cluster number */
|
||||||
|
unsigned8 mirror; /* mirroring enabla/disable */
|
||||||
|
unsigned32 afat_loc; /* active FAT location */
|
||||||
|
unsigned8 afat; /* the number of active FAT */
|
||||||
|
dev_t dev; /* device ID */
|
||||||
|
disk_device *dd; /* disk device (see libblock) */
|
||||||
|
void *private_data; /* reserved */
|
||||||
|
} fat_vol_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct fat_cache_s
|
||||||
|
{
|
||||||
|
unsigned32 blk_num;
|
||||||
|
rtems_boolean modified;
|
||||||
|
unsigned8 state;
|
||||||
|
bdbuf_buffer *buf;
|
||||||
|
} fat_cache_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This structure identifies the instance of the filesystem on the FAT
|
||||||
|
* ("fat-file") level.
|
||||||
|
*/
|
||||||
|
typedef struct fat_fs_info_s
|
||||||
|
{
|
||||||
|
fat_vol_t vol; /* volume descriptor */
|
||||||
|
Chain_Control *vhash; /* "vhash" of fat-file descriptors */
|
||||||
|
Chain_Control *rhash; /* "rhash" of fat-file descriptors */
|
||||||
|
char *uino; /* array of unique ino numbers */
|
||||||
|
unsigned32 index;
|
||||||
|
unsigned32 uino_pool_size; /* size */
|
||||||
|
unsigned32 uino_base;
|
||||||
|
fat_cache_t c; /* cache */
|
||||||
|
unsigned8 *sec_buf; /* just placeholder for anything */
|
||||||
|
} 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
|
||||||
|
*/
|
||||||
|
typedef struct fat_auxiliary_s
|
||||||
|
{
|
||||||
|
unsigned32 cln;
|
||||||
|
unsigned32 ofs;
|
||||||
|
} fat_auxiliary_t;
|
||||||
|
|
||||||
|
#define FAT_FAT_OFFSET(fat_type, cln) \
|
||||||
|
((fat_type) & FAT_FAT12 ? ((cln) + ((cln) >> 1)) : \
|
||||||
|
(fat_type) & FAT_FAT16 ? ((cln) << 1) : \
|
||||||
|
((cln) << 2))
|
||||||
|
|
||||||
|
#define FAT_CLUSTER_IS_ODD(n) ((n) & 0x0001)
|
||||||
|
|
||||||
|
#define FAT12_SHIFT 0x4 /* half of a byte */
|
||||||
|
|
||||||
|
/* initial size of array of unique ino */
|
||||||
|
#define FAT_UINO_POOL_INIT_SIZE 0x100
|
||||||
|
|
||||||
|
/* cache support */
|
||||||
|
#define FAT_CACHE_EMPTY 0x0
|
||||||
|
#define FAT_CACHE_ACTUAL 0x1
|
||||||
|
|
||||||
|
#define FAT_OP_TYPE_READ 0x1
|
||||||
|
#define FAT_OP_TYPE_GET 0x2
|
||||||
|
|
||||||
|
static inline unsigned32
|
||||||
|
fat_cluster_num_to_sector_num(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln
|
||||||
|
)
|
||||||
|
{
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
|
||||||
|
if ( (cln == 0) && (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)) )
|
||||||
|
return fs_info->vol.rdir_loc;
|
||||||
|
|
||||||
|
return (((cln - FAT_RSRVD_CLN) << fs_info->vol.spc_log2) +
|
||||||
|
fs_info->vol.data_fsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned32
|
||||||
|
fat_cluster_num_to_sector512_num(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
|
||||||
|
if (cln == 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return (fat_cluster_num_to_sector_num(mt_entry, cln) <<
|
||||||
|
fs_info->vol.sec_mul);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
fat_buf_access(fat_fs_info_t *fs_info, unsigned32 blk, int op_type,
|
||||||
|
bdbuf_buffer **buf)
|
||||||
|
{
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
unsigned8 i;
|
||||||
|
rtems_boolean sec_of_fat;
|
||||||
|
|
||||||
|
|
||||||
|
if (fs_info->c.state == FAT_CACHE_EMPTY)
|
||||||
|
{
|
||||||
|
if (op_type == FAT_OP_TYPE_READ)
|
||||||
|
sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
|
||||||
|
else
|
||||||
|
sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
fs_info->c.blk_num = blk;
|
||||||
|
fs_info->c.state = FAT_CACHE_ACTUAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
|
||||||
|
(fs_info->c.blk_num < fs_info->vol.rdir_loc));
|
||||||
|
|
||||||
|
if (fs_info->c.blk_num != blk)
|
||||||
|
{
|
||||||
|
if (fs_info->c.modified)
|
||||||
|
{
|
||||||
|
if (sec_of_fat && !fs_info->vol.mirror)
|
||||||
|
memcpy(fs_info->sec_buf, fs_info->c.buf->buffer,
|
||||||
|
fs_info->vol.bps);
|
||||||
|
|
||||||
|
sc = rtems_bdbuf_release_modified(fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
fs_info->c.modified = 0;
|
||||||
|
|
||||||
|
if (sec_of_fat && !fs_info->vol.mirror)
|
||||||
|
{
|
||||||
|
bdbuf_buffer *b;
|
||||||
|
|
||||||
|
for (i = 1; i < fs_info->vol.fats; i++)
|
||||||
|
{
|
||||||
|
sc = rtems_bdbuf_get(fs_info->vol.dev,
|
||||||
|
fs_info->c.blk_num +
|
||||||
|
fs_info->vol.fat_length * i,
|
||||||
|
&b);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
|
||||||
|
sc = rtems_bdbuf_release_modified(b);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sc = rtems_bdbuf_release(fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (op_type == FAT_OP_TYPE_READ)
|
||||||
|
sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
|
||||||
|
else
|
||||||
|
sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
fs_info->c.blk_num = blk;
|
||||||
|
}
|
||||||
|
*buf = fs_info->c.buf;
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
fat_buf_release(fat_fs_info_t *fs_info)
|
||||||
|
{
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
unsigned8 i;
|
||||||
|
rtems_boolean sec_of_fat;
|
||||||
|
|
||||||
|
if (fs_info->c.state == FAT_CACHE_EMPTY)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
|
||||||
|
(fs_info->c.blk_num < fs_info->vol.rdir_loc));
|
||||||
|
|
||||||
|
if (fs_info->c.modified)
|
||||||
|
{
|
||||||
|
if (sec_of_fat && !fs_info->vol.mirror)
|
||||||
|
memcpy(fs_info->sec_buf, fs_info->c.buf->buffer, fs_info->vol.bps);
|
||||||
|
|
||||||
|
sc = rtems_bdbuf_release_modified(fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
fs_info->c.modified = 0;
|
||||||
|
|
||||||
|
if (sec_of_fat && !fs_info->vol.mirror)
|
||||||
|
{
|
||||||
|
bdbuf_buffer *b;
|
||||||
|
|
||||||
|
for (i = 1; i < fs_info->vol.fats; i++)
|
||||||
|
{
|
||||||
|
sc = rtems_bdbuf_get(fs_info->vol.dev,
|
||||||
|
fs_info->c.blk_num +
|
||||||
|
fs_info->vol.fat_length * i,
|
||||||
|
&b);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
|
||||||
|
sc = rtems_bdbuf_release_modified(b);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sc = rtems_bdbuf_release(fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
}
|
||||||
|
fs_info->c.state = FAT_CACHE_EMPTY;
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
fat_buf_mark_modified(fat_fs_info_t *fs_info)
|
||||||
|
{
|
||||||
|
fs_info->c.modified = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
_fat_block_read(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 offset,
|
||||||
|
unsigned32 count,
|
||||||
|
void *buff);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
_fat_block_write(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 offset,
|
||||||
|
unsigned32 count,
|
||||||
|
const void *buff);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
fat_cluster_read(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
void *buff);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
fat_cluster_write(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
const void *buff);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_init_clusters_chain(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start_cln);
|
||||||
|
|
||||||
|
unsigned32
|
||||||
|
fat_cluster_num_to_sector_num(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_shutdown_drive(rtems_filesystem_mount_table_entry_t *mt_entry);
|
||||||
|
|
||||||
|
|
||||||
|
unsigned32
|
||||||
|
fat_get_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry);
|
||||||
|
|
||||||
|
rtems_boolean
|
||||||
|
fat_ino_is_unique(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 ino);
|
||||||
|
|
||||||
|
void
|
||||||
|
fat_free_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 ino);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_fat32_update_fsinfo_sector(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 free_count,
|
||||||
|
unsigned32 next_free
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_FAT_H__ */
|
||||||
445
c/src/libfs/src/dosfs/fat_fat_operations.c
Normal file
445
c/src/libfs/src/dosfs/fat_fat_operations.c
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
/*
|
||||||
|
* fat_fat_operations.c
|
||||||
|
*
|
||||||
|
* General operations on File Allocation Table
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
|
||||||
|
/* fat_scan_fat_for_free_clusters --
|
||||||
|
* Allocate chain of free clusters from Files Allocation Table
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* chain - the number of the first allocated cluster (first cluster
|
||||||
|
* in the chain)
|
||||||
|
* count - count of clusters to allocate (chain length)
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or error code if error occured (errno set
|
||||||
|
* appropriately)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_scan_fat_for_free_clusters(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 *chain,
|
||||||
|
unsigned32 count,
|
||||||
|
unsigned32 *cls_added,
|
||||||
|
unsigned32 *last_cl
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cl4find = 2;
|
||||||
|
unsigned32 next_cln = 0;
|
||||||
|
unsigned32 save_cln = 0;
|
||||||
|
unsigned32 data_cls_val = fs_info->vol.data_cls + 2;
|
||||||
|
unsigned32 i = 2;
|
||||||
|
|
||||||
|
*cls_added = 0;
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if ((fs_info->vol.type & FAT_FAT32) &&
|
||||||
|
(fs_info->vol.next_cl != FAT_UNDEFINED_VALUE))
|
||||||
|
cl4find = fs_info->vol.next_cl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fs_info->vol.data_cls is exactly the count of data clusters
|
||||||
|
* starting at cluster 2, so the maximum valid cluster number is
|
||||||
|
* (fs_info->vol.data_cls + 1)
|
||||||
|
*/
|
||||||
|
while (i < data_cls_val)
|
||||||
|
{
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cl4find, &next_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
if (*cls_added != 0)
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, (*chain));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((next_cln & fs_info->vol.mask) == FAT_GENFAT_FREE)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We are enforced to process allocation of the first free cluster
|
||||||
|
* by separate 'if' statement because otherwise undo function
|
||||||
|
* wouldn't work properly
|
||||||
|
*/
|
||||||
|
if (*cls_added == 0)
|
||||||
|
{
|
||||||
|
*chain = cl4find;
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_EOC);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* this is the first cluster we tried to allocate so no
|
||||||
|
* cleanup activity needed
|
||||||
|
*/
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* set EOC value to new allocated cluster */
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_EOC);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
/* cleanup activity */
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, (*chain));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, save_cln, cl4find);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
/* cleanup activity */
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, (*chain));
|
||||||
|
/* trying to save last allocated cluster for future use */
|
||||||
|
fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_FREE);
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
save_cln = cl4find;
|
||||||
|
(*cls_added)++;
|
||||||
|
|
||||||
|
/* have we satisfied request ? */
|
||||||
|
if (*cls_added == count)
|
||||||
|
{
|
||||||
|
if (fs_info->vol.type & FAT_FAT32)
|
||||||
|
{
|
||||||
|
fs_info->vol.next_cl = save_cln;
|
||||||
|
if (fs_info->vol.free_cls != 0xFFFFFFFF)
|
||||||
|
fs_info->vol.free_cls -= (*cls_added);
|
||||||
|
}
|
||||||
|
*last_cl = save_cln;
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
cl4find++;
|
||||||
|
if (cl4find >= data_cls_val)
|
||||||
|
cl4find = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs_info->vol.type & FAT_FAT32)
|
||||||
|
{
|
||||||
|
fs_info->vol.next_cl = save_cln;
|
||||||
|
if (fs_info->vol.free_cls != 0xFFFFFFFF)
|
||||||
|
fs_info->vol.free_cls -= (*cls_added);
|
||||||
|
}
|
||||||
|
*last_cl = save_cln;
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_free_fat_clusters_chain --
|
||||||
|
* Free chain of clusters in Files Allocation Table.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* chain - number of the first cluster in the chain
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_free_fat_clusters_chain(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 chain
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK, rc1 = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = chain;
|
||||||
|
unsigned32 next_cln = 0;
|
||||||
|
unsigned32 freed_cls_cnt = 0;
|
||||||
|
|
||||||
|
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
||||||
|
{
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &next_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
if ((fs_info->vol.type & FAT_FAT32) &&
|
||||||
|
(fs_info->vol.free_cls != FAT_UNDEFINED_VALUE))
|
||||||
|
fs_info->vol.free_cls += freed_cls_cnt;
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, cur_cln, FAT_GENFAT_FREE);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
rc1 = rc;
|
||||||
|
|
||||||
|
freed_cls_cnt++;
|
||||||
|
cur_cln = next_cln;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs_info->vol.type & FAT_FAT32)
|
||||||
|
{
|
||||||
|
fs_info->vol.next_cl = chain;
|
||||||
|
if (fs_info->vol.free_cls != FAT_UNDEFINED_VALUE)
|
||||||
|
fs_info->vol.free_cls += freed_cls_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
if (rc1 != RC_OK)
|
||||||
|
return rc1;
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_get_fat_cluster --
|
||||||
|
* Fetches the contents of the cluster (link to next cluster in the chain)
|
||||||
|
* from Files Allocation Table.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - number of cluster to fetch the contents from
|
||||||
|
* ret_val - contents of the cluster 'cln' (link to next cluster in
|
||||||
|
* the chain)
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_get_fat_cluster(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 *ret_val
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
bdbuf_buffer *block0 = NULL;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 ofs = 0;
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
|
||||||
|
fs_info->vol.afat_loc;
|
||||||
|
ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
switch ( fs_info->vol.type )
|
||||||
|
{
|
||||||
|
case FAT_FAT12:
|
||||||
|
/*
|
||||||
|
* we are enforced in complex computations for FAT12 to escape CPU
|
||||||
|
* align problems for some architectures
|
||||||
|
*/
|
||||||
|
*ret_val = (*((unsigned8 *)(block0->buffer + ofs)));
|
||||||
|
if ( ofs == (fs_info->vol.bps - 1) )
|
||||||
|
{
|
||||||
|
rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
|
||||||
|
&block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*ret_val |= (*((unsigned8 *)(block0->buffer)))<<8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ret_val |= (*((unsigned8 *)(block0->buffer + ofs + 1)))<<8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( FAT_CLUSTER_IS_ODD(cln) )
|
||||||
|
*ret_val = (*ret_val) >> FAT12_SHIFT;
|
||||||
|
else
|
||||||
|
*ret_val = (*ret_val) & FAT_FAT12_MASK;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT_FAT16:
|
||||||
|
*ret_val = *((unsigned16 *)(block0->buffer + ofs));
|
||||||
|
*ret_val = CF_LE_W(*ret_val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT_FAT32:
|
||||||
|
*ret_val = *((unsigned32 *)(block0->buffer + ofs));
|
||||||
|
*ret_val = CF_LE_L(*ret_val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_set_fat_cluster --
|
||||||
|
* Set the contents of the cluster (link to next cluster in the chain)
|
||||||
|
* from Files Allocation Table.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - number of cluster to set contents to
|
||||||
|
* in_val - value to set
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_set_fat_cluster(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 in_val
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 ofs = 0;
|
||||||
|
unsigned16 fat16_clv = 0;
|
||||||
|
unsigned32 fat32_clv = 0;
|
||||||
|
bdbuf_buffer *block0 = NULL;
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
|
||||||
|
fs_info->vol.afat_loc;
|
||||||
|
ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
switch ( fs_info->vol.type )
|
||||||
|
{
|
||||||
|
case FAT_FAT12:
|
||||||
|
if ( FAT_CLUSTER_IS_ODD(cln) )
|
||||||
|
{
|
||||||
|
fat16_clv = CT_LE_W((((unsigned16)in_val) << FAT_FAT12_SHIFT));
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs))) & 0x0F;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs))) |
|
||||||
|
(unsigned8)(fat16_clv & 0x00FF);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
|
||||||
|
if ( ofs == (fs_info->vol.bps - 1) )
|
||||||
|
{
|
||||||
|
rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
|
||||||
|
&block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer)) &= 0x00;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer))) |
|
||||||
|
(unsigned8)((fat16_clv & 0xFF00)>>8);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs + 1)) &= 0x00;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs + 1)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs + 1))) |
|
||||||
|
(unsigned8)((fat16_clv & 0xFF00)>>8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fat16_clv = CT_LE_W((((unsigned16)in_val) & FAT_FAT12_MASK));
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs)) &= 0x00;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs))) |
|
||||||
|
(unsigned8)(fat16_clv & 0x00FF);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
|
||||||
|
if ( ofs == (fs_info->vol.bps - 1) )
|
||||||
|
{
|
||||||
|
rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
|
||||||
|
&block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer))) & 0xF0;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer))) |
|
||||||
|
(unsigned8)((fat16_clv & 0xFF00)>>8);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs + 1)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs + 1))) & 0xF0;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs+1)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs+1))) |
|
||||||
|
(unsigned8)((fat16_clv & 0xFF00)>>8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT_FAT16:
|
||||||
|
*((unsigned16 *)(block0->buffer + ofs)) =
|
||||||
|
(unsigned16)(CT_LE_W(in_val));
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT_FAT32:
|
||||||
|
fat32_clv = CT_LE_L((in_val & FAT_FAT32_MASK));
|
||||||
|
|
||||||
|
*((unsigned32 *)(block0->buffer + ofs)) =
|
||||||
|
(*((unsigned32 *)(block0->buffer + ofs))) & (CT_LE_L(0xF0000000));
|
||||||
|
|
||||||
|
*((unsigned32 *)(block0->buffer + ofs)) =
|
||||||
|
fat32_clv | (*((unsigned32 *)(block0->buffer + ofs)));
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
58
c/src/libfs/src/dosfs/fat_fat_operations.h
Normal file
58
c/src/libfs/src/dosfs/fat_fat_operations.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* fat_fat_operations.h
|
||||||
|
*
|
||||||
|
* Constants/data structures/prototypes for operations on Files Allocation
|
||||||
|
* Table
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#ifndef __DOSFS_FAT_FAT_OPERATIONS_H__
|
||||||
|
#define __DOSFS_FAT_FAT_OPERATIONS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include <rtems/bdbuf.h>
|
||||||
|
#include "fat.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_get_fat_cluster(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 *ret_val);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_set_fat_cluster(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 in_val);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_scan_fat_for_free_clusters(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 *chain,
|
||||||
|
unsigned32 count,
|
||||||
|
unsigned32 *cls_added,
|
||||||
|
unsigned32 *last_cl
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_free_fat_clusters_chain(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 chain
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_FAT_FAT_OPERATIONS_H__ */
|
||||||
979
c/src/libfs/src/dosfs/fat_file.c
Normal file
979
c/src/libfs/src/dosfs/fat_file.c
Normal file
@@ -0,0 +1,979 @@
|
|||||||
|
/*
|
||||||
|
* fat_file.c
|
||||||
|
*
|
||||||
|
* General operations on "fat-file"
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <bsp.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_hash_insert(Chain_Control *hash, unsigned32 key1, unsigned32 key2,
|
||||||
|
fat_file_fd_t *el);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_hash_delete(Chain_Control *hash, unsigned32 key1, unsigned32 key2,
|
||||||
|
fat_file_fd_t *el);
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
_hash_search(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
Chain_Control *hash,
|
||||||
|
unsigned32 key1,
|
||||||
|
unsigned32 key2,
|
||||||
|
void **ret
|
||||||
|
);
|
||||||
|
|
||||||
|
static int
|
||||||
|
fat_file_lseek(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 file_cln,
|
||||||
|
unsigned32 *disk_cln
|
||||||
|
);
|
||||||
|
|
||||||
|
/* fat_file_open --
|
||||||
|
* Open fat-file. Two hash tables are accessed by key
|
||||||
|
* constructed from cluster num and offset of the node (i.e.
|
||||||
|
* files/directories are distinguished by location on the disk).
|
||||||
|
* First, hash table("vhash") consists of fat-file descriptors corresponded
|
||||||
|
* to "valid" files is accessed. Search is made by 2 fields equal to key
|
||||||
|
* constructed. If descriptor is found in the "vhash" - return it.
|
||||||
|
* Otherwise search is made in hash table("rhash") consits of fat-file
|
||||||
|
* descriptors corresponded to "removed-but-still-open" files with the
|
||||||
|
* same keys.
|
||||||
|
* If search failed, new fat-file descriptor is added to "vhash"
|
||||||
|
* with both key fields equal to constructed key. Otherwise new fat-file
|
||||||
|
* descriptor is added to "vhash" with first key field equal to key
|
||||||
|
* constructed and the second equal to an unique (unique among all values
|
||||||
|
* of second key fields) value.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - cluster num of the node
|
||||||
|
* ofs - offset of the node
|
||||||
|
* fat_fd - placeholder for returned fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and pointer to opened descriptor on success, or -1 if error
|
||||||
|
* occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_open(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 ofs,
|
||||||
|
fat_file_fd_t **fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *lfat_fd = NULL;
|
||||||
|
unsigned32 key = 0;
|
||||||
|
|
||||||
|
/* construct key */
|
||||||
|
key = fat_construct_key(mt_entry, cln, ofs);
|
||||||
|
|
||||||
|
/* access "valid" hash table */
|
||||||
|
rc = _hash_search(mt_entry, fs_info->vhash, key, 0, (void **)&lfat_fd);
|
||||||
|
if ( rc == RC_OK )
|
||||||
|
{
|
||||||
|
/* return pointer to fat_file_descriptor allocated before */
|
||||||
|
(*fat_fd) = lfat_fd;
|
||||||
|
lfat_fd->links_num++;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* access "removed-but-still-open" hash table */
|
||||||
|
rc = _hash_search(mt_entry, fs_info->rhash, key, key, (void **)&lfat_fd);
|
||||||
|
|
||||||
|
lfat_fd = (*fat_fd) = (fat_file_fd_t*)malloc(sizeof(fat_file_fd_t));
|
||||||
|
if ( lfat_fd == NULL )
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
|
||||||
|
lfat_fd->links_num = 1;
|
||||||
|
lfat_fd->flags &= ~FAT_FILE_REMOVED;
|
||||||
|
lfat_fd->map.last_cln = FAT_UNDEFINED_VALUE;
|
||||||
|
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
lfat_fd->ino = key;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lfat_fd->ino = fat_get_unique_ino(mt_entry);
|
||||||
|
|
||||||
|
if ( lfat_fd->ino == 0 )
|
||||||
|
{
|
||||||
|
free((*fat_fd));
|
||||||
|
/*
|
||||||
|
* XXX: kernel resource is unsufficient, but not the memory,
|
||||||
|
* but there is no suitable errno :(
|
||||||
|
*/
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_hash_insert(fs_info->vhash, key, lfat_fd->ino, lfat_fd);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* other fields of fat-file descriptor will be initialized on upper
|
||||||
|
* level
|
||||||
|
*/
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* fat_file_reopen --
|
||||||
|
* Increment by 1 number of links
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_reopen(fat_file_fd_t *fat_fd)
|
||||||
|
{
|
||||||
|
fat_fd->links_num++;
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_close --
|
||||||
|
* Close fat-file. If count of links to fat-file
|
||||||
|
* descriptor is greater than 1 (i.e. somebody esle holds pointer
|
||||||
|
* to this descriptor) just decrement it. Otherwise
|
||||||
|
* do the following. If this descriptor corresponded to removed fat-file
|
||||||
|
* then free clusters contained fat-file data, delete descriptor from
|
||||||
|
* "rhash" table and free memory allocated by descriptor. If descriptor
|
||||||
|
* correspondes to non-removed fat-file and 'ino' field has value from
|
||||||
|
* unique inode numbers pool then set count of links to descriptor to zero
|
||||||
|
* and leave it in hash, otherwise delete descriptor from "vhash" and free
|
||||||
|
* memory allocated by the descriptor
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_close(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 key = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if links_num field of fat-file descriptor is greater than 1
|
||||||
|
* decrement the count of links and return
|
||||||
|
*/
|
||||||
|
if (fat_fd->links_num > 1)
|
||||||
|
{
|
||||||
|
fat_fd->links_num--;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
|
||||||
|
|
||||||
|
if (fat_fd->flags & FAT_FILE_REMOVED)
|
||||||
|
{
|
||||||
|
rc = fat_file_truncate(mt_entry, fat_fd, 0);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
_hash_delete(fs_info->rhash, key, fat_fd->ino, fat_fd);
|
||||||
|
|
||||||
|
if ( fat_ino_is_unique(mt_entry, fat_fd->ino) )
|
||||||
|
fat_free_unique_ino(mt_entry, fat_fd->ino);
|
||||||
|
|
||||||
|
free(fat_fd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fat_ino_is_unique(mt_entry, fat_fd->ino))
|
||||||
|
{
|
||||||
|
fat_fd->links_num = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
|
||||||
|
free(fat_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_read --
|
||||||
|
* Read 'count' bytes from 'start' position from fat-file. This
|
||||||
|
* interface hides the architecture of fat-file, represents it as
|
||||||
|
* linear file
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* start - offset in fat-file (in bytes) to read from
|
||||||
|
* count - count of bytes to read
|
||||||
|
* buf - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* the number of bytes read on success, or -1 if error occured (errno
|
||||||
|
* set appropriately)
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
fat_file_read(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 count,
|
||||||
|
char *buf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
ssize_t ret = 0;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cmpltd = 0;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
unsigned32 cl_start = 0;
|
||||||
|
unsigned32 save_cln = 0;
|
||||||
|
unsigned32 ofs = 0;
|
||||||
|
unsigned32 save_ofs;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 byte = 0;
|
||||||
|
unsigned32 c = 0;
|
||||||
|
|
||||||
|
/* it couldn't be removed - otherwise cache update will be broken */
|
||||||
|
if (count == 0)
|
||||||
|
return cmpltd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* >= because start is offset and computed from 0 and file_size
|
||||||
|
* computed from 1
|
||||||
|
*/
|
||||||
|
if ( start >= fat_fd->fat_file_size )
|
||||||
|
return FAT_EOF;
|
||||||
|
|
||||||
|
if ((count > fat_fd->fat_file_size) ||
|
||||||
|
(start > fat_fd->fat_file_size - count))
|
||||||
|
count = fat_fd->fat_file_size - start;
|
||||||
|
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
{
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->cln);
|
||||||
|
sec += (start >> fs_info->vol.sec_log2);
|
||||||
|
byte = start & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
ret = _fat_block_read(mt_entry, sec, byte, count, buf);
|
||||||
|
if ( ret < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl_start = start >> fs_info->vol.bpc_log2;
|
||||||
|
save_ofs = ofs = start & (fs_info->vol.bpc - 1);
|
||||||
|
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
c = MIN(count, (fs_info->vol.bpc - ofs));
|
||||||
|
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
|
||||||
|
sec += (ofs >> fs_info->vol.sec_log2);
|
||||||
|
byte = ofs & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
ret = _fat_block_read(mt_entry, sec, byte, c, buf + cmpltd);
|
||||||
|
if ( ret < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
count -= c;
|
||||||
|
cmpltd += c;
|
||||||
|
save_cln = cur_cln;
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
ofs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update cache */
|
||||||
|
/* XXX: check this - I'm not sure :( */
|
||||||
|
fat_fd->map.file_cln = cl_start +
|
||||||
|
((save_ofs + cmpltd - 1) >> fs_info->vol.bpc_log2);
|
||||||
|
fat_fd->map.disk_cln = save_cln;
|
||||||
|
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_write --
|
||||||
|
* Write 'count' bytes of data from user supplied buffer to fat-file
|
||||||
|
* starting at offset 'start'. This interface hides the architecture
|
||||||
|
* of fat-file, represents it as linear file
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* start - offset(in bytes) to write from
|
||||||
|
* count - count
|
||||||
|
* buf - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* number of bytes actually written to the file on success, or -1 if
|
||||||
|
* error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
fat_file_write(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 count,
|
||||||
|
char *buf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
ssize_t ret = 0;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cmpltd = 0;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
unsigned32 save_cln;
|
||||||
|
unsigned32 cl_start = 0;
|
||||||
|
unsigned32 ofs = 0;
|
||||||
|
unsigned32 save_ofs;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 byte = 0;
|
||||||
|
unsigned32 c = 0;
|
||||||
|
|
||||||
|
if ( count == 0 )
|
||||||
|
return cmpltd;
|
||||||
|
|
||||||
|
if ( start > fat_fd->fat_file_size )
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
if ((count > fat_fd->size_limit) ||
|
||||||
|
(start > fat_fd->size_limit - count))
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
rc = fat_file_extend(mt_entry, fat_fd, start + count, &c);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check whether there was enough room on device to locate
|
||||||
|
* file of 'start + count' bytes
|
||||||
|
*/
|
||||||
|
if (c != (start + count))
|
||||||
|
count = c - start;
|
||||||
|
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
{
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->cln);
|
||||||
|
sec += (start >> fs_info->vol.sec_log2);
|
||||||
|
byte = start & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
ret = _fat_block_write(mt_entry, sec, byte, count, buf);
|
||||||
|
if ( ret < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl_start = start >> fs_info->vol.bpc_log2;
|
||||||
|
save_ofs = ofs = start & (fs_info->vol.bpc - 1);
|
||||||
|
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
c = MIN(count, (fs_info->vol.bpc - ofs));
|
||||||
|
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
|
||||||
|
sec += (ofs >> fs_info->vol.sec_log2);
|
||||||
|
byte = ofs & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
ret = _fat_block_write(mt_entry, sec, byte, c, buf + cmpltd);
|
||||||
|
if ( ret < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
count -= c;
|
||||||
|
cmpltd += c;
|
||||||
|
save_cln = cur_cln;
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
ofs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update cache */
|
||||||
|
/* XXX: check this - I'm not sure :( */
|
||||||
|
fat_fd->map.file_cln = cl_start +
|
||||||
|
((save_ofs + cmpltd - 1) >> fs_info->vol.bpc_log2);
|
||||||
|
fat_fd->map.disk_cln = save_cln;
|
||||||
|
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_extend --
|
||||||
|
* Extend fat-file. If new length less than current fat-file size -
|
||||||
|
* do nothing. Otherwise calculate necessary count of clusters to add,
|
||||||
|
* allocate it and add new clusters chain to the end of
|
||||||
|
* existing clusters chain.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* new_length - new length
|
||||||
|
* a_length - placeholder for result - actual new length of file
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and new length of file on success, or -1 if error occured (errno
|
||||||
|
* set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_extend(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 new_length,
|
||||||
|
unsigned32 *a_length
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 chain = 0;
|
||||||
|
unsigned32 bytes2add = 0;
|
||||||
|
unsigned32 cls2add = 0;
|
||||||
|
unsigned32 old_last_cl;
|
||||||
|
unsigned32 last_cl = 0;
|
||||||
|
unsigned32 bytes_remain = 0;
|
||||||
|
unsigned32 cls_added;
|
||||||
|
|
||||||
|
*a_length = new_length;
|
||||||
|
|
||||||
|
if (new_length <= fat_fd->fat_file_size)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
set_errno_and_return_minus_one( ENOSPC );
|
||||||
|
|
||||||
|
bytes_remain = (fs_info->vol.bpc -
|
||||||
|
(fat_fd->fat_file_size & (fs_info->vol.bpc - 1))) &
|
||||||
|
(fs_info->vol.bpc - 1);
|
||||||
|
|
||||||
|
bytes2add = new_length - fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
if (bytes2add > bytes_remain)
|
||||||
|
bytes2add -= bytes_remain;
|
||||||
|
else
|
||||||
|
bytes2add = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if in last cluster allocated for the file there is enough room to
|
||||||
|
* handle extention (hence we don't need to add even one cluster to the
|
||||||
|
* file ) - return
|
||||||
|
*/
|
||||||
|
if (bytes2add == 0)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
cls2add = ((bytes2add - 1) >> fs_info->vol.bpc_log2) + 1;
|
||||||
|
|
||||||
|
rc = fat_scan_fat_for_free_clusters(mt_entry, &chain, cls2add,
|
||||||
|
&cls_added, &last_cl);
|
||||||
|
|
||||||
|
/* this means that low level I/O error occured */
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* this means that no space left on device */
|
||||||
|
if ((cls_added == 0) && (bytes_remain == 0))
|
||||||
|
set_errno_and_return_minus_one(ENOSPC);
|
||||||
|
|
||||||
|
/* check wether we satisfied request for 'cls2add' clusters */
|
||||||
|
if (cls2add != cls_added)
|
||||||
|
*a_length = new_length -
|
||||||
|
((cls2add - cls_added - 1) << fs_info->vol.bpc_log2) -
|
||||||
|
(bytes2add & (fs_info->vol.bpc - 1));
|
||||||
|
|
||||||
|
/* add new chain to the end of existed */
|
||||||
|
if ( fat_fd->fat_file_size == 0 )
|
||||||
|
{
|
||||||
|
fat_fd->map.disk_cln = fat_fd->cln = chain;
|
||||||
|
fat_fd->map.file_cln = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fat_fd->map.last_cln != FAT_UNDEFINED_VALUE)
|
||||||
|
{
|
||||||
|
old_last_cl = fat_fd->map.last_cln;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
|
||||||
|
(fat_fd->fat_file_size - 1), &old_last_cl);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, chain);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, old_last_cl, chain);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, chain);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update number of the last cluster of the file if it changed */
|
||||||
|
if (cls_added != 0)
|
||||||
|
{
|
||||||
|
fat_fd->map.last_cln = last_cl;
|
||||||
|
if (fat_fd->fat_file_type == FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
rc = fat_init_clusters_chain(mt_entry, chain);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, chain);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_truncate --
|
||||||
|
* Truncate fat-file. If new length greater than current fat-file size -
|
||||||
|
* do nothing. Otherwise find first cluster to free and free all clusters
|
||||||
|
* in the chain starting from this cluster.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* new_length - new length
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_truncate(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 new_length
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
unsigned32 cl_start = 0;
|
||||||
|
unsigned32 new_last_cln = FAT_UNDEFINED_VALUE;
|
||||||
|
|
||||||
|
|
||||||
|
if ( new_length >= fat_fd->fat_file_size )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
assert(fat_fd->fat_file_size);
|
||||||
|
|
||||||
|
cl_start = (new_length + fs_info->vol.bpc - 1) >> fs_info->vol.bpc_log2;
|
||||||
|
|
||||||
|
if ((cl_start << fs_info->vol.bpc_log2) >= fat_fd->fat_file_size)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
if (cl_start != 0)
|
||||||
|
{
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start - 1, &new_last_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = fat_free_fat_clusters_chain(mt_entry, cur_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (cl_start != 0)
|
||||||
|
{
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, new_last_cln, FAT_GENFAT_EOC);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
fat_fd->map.file_cln = cl_start - 1;
|
||||||
|
fat_fd->map.disk_cln = new_last_cln;
|
||||||
|
fat_fd->map.last_cln = new_last_cln;
|
||||||
|
}
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_ioctl --
|
||||||
|
* F_CLU_NUM:
|
||||||
|
* make mapping between serial number of the cluster in fat-file and
|
||||||
|
* its real number on the volume
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cmd - command
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_ioctl(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
int cmd,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
unsigned32 cl_start = 0;
|
||||||
|
unsigned32 pos = 0;
|
||||||
|
unsigned32 *ret;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, cmd);
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case F_CLU_NUM:
|
||||||
|
pos = va_arg(ap, int);
|
||||||
|
ret = va_arg(ap, int *);
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
if ( pos >= fat_fd->fat_file_size )
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
{
|
||||||
|
/* cluster 0 (zero) reserved for root dir */
|
||||||
|
*ret = 0;
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl_start = pos >> fs_info->vol.bpc_log2;
|
||||||
|
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*ret = cur_cln;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
rc = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_mark_removed --
|
||||||
|
* Remove the fat-file descriptor from "valid" hash table, insert it
|
||||||
|
* into "removed-but-still-open" hash table and set up "removed" bit.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fat_file_mark_removed(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 key = 0;
|
||||||
|
|
||||||
|
key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
|
||||||
|
|
||||||
|
_hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
|
||||||
|
|
||||||
|
_hash_insert(fs_info->rhash, key, fat_fd->ino, fat_fd);
|
||||||
|
|
||||||
|
fat_fd->flags |= FAT_FILE_REMOVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_datasync --
|
||||||
|
* Synchronize fat-file - flush all buffered data to the media.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_datasync(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = fat_fd->cln;
|
||||||
|
bdbuf_buffer *block = NULL;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 i = 0;
|
||||||
|
|
||||||
|
if (fat_fd->fat_file_size == 0)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we can use only one bdbuf :( and we also know that cache is useless
|
||||||
|
* for sync operation, so don't use it
|
||||||
|
*/
|
||||||
|
rc = fat_buf_release(fs_info);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* for each cluster of the file ... */
|
||||||
|
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
||||||
|
{
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
|
||||||
|
/* for each sector in cluster ... */
|
||||||
|
for ( i = 0; i < fs_info->vol.spc; i++ )
|
||||||
|
{
|
||||||
|
/* ... sync it */
|
||||||
|
sc = rtems_bdbuf_read(fs_info->vol.dev, (sec + i), &block);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
sc = rtems_bdbuf_sync(block);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL )
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_size --
|
||||||
|
* Calculate fat-file size - fat-file is nothing that clusters chain, so
|
||||||
|
* go through all clusters in the chain and count it. Only
|
||||||
|
* special case is root directory for FAT12/16 volumes.
|
||||||
|
* This function is used only for directories which are fat-files with
|
||||||
|
* non-zero length, hence 'fat_fd->cln' always contains valid data.
|
||||||
|
* Calculated size is stored in 'fat_file_size' field of fat-file
|
||||||
|
* descriptor.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_size(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = fat_fd->cln;
|
||||||
|
unsigned32 save_cln = 0;
|
||||||
|
|
||||||
|
/* Have we requested root dir size for FAT12/16? */
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
{
|
||||||
|
fat_fd->fat_file_size = fs_info->vol.rdir_size;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_fd->fat_file_size = 0;
|
||||||
|
|
||||||
|
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
||||||
|
{
|
||||||
|
save_cln = cur_cln;
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
fat_fd->fat_file_size += fs_info->vol.bpc;
|
||||||
|
}
|
||||||
|
fat_fd->map.last_cln = save_cln;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hash support routines */
|
||||||
|
|
||||||
|
/* _hash_insert --
|
||||||
|
* Insert elemnt into hash based on key 'key1'
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* hash - hash element will be inserted into
|
||||||
|
* key1 - key on which insertion is based on
|
||||||
|
* key2 - not used during insertion
|
||||||
|
* el - element to insert
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
_hash_insert(Chain_Control *hash, unsigned32 key1, unsigned32 key2,
|
||||||
|
fat_file_fd_t *el)
|
||||||
|
{
|
||||||
|
_Chain_Append((hash) + ((key1) % FAT_HASH_MODULE), &(el)->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* _hash_delete --
|
||||||
|
* Remove element from hash
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* hash - hash element will be removed from
|
||||||
|
* key1 - not used
|
||||||
|
* key2 - not used
|
||||||
|
* el - element to delete
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
_hash_delete(Chain_Control *hash, unsigned32 key1, unsigned32 key2,
|
||||||
|
fat_file_fd_t *el)
|
||||||
|
{
|
||||||
|
_Chain_Extract(&(el)->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _hash_search --
|
||||||
|
* Search element in hash. If both keys match pointer to found element
|
||||||
|
* is returned
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* hash - hash element will be removed from
|
||||||
|
* key1 - search key
|
||||||
|
* key2 - search key
|
||||||
|
* ret - placeholder for result
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* 0 and pointer to found element on success, -1 otherwise
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
_hash_search(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
Chain_Control *hash,
|
||||||
|
unsigned32 key1,
|
||||||
|
unsigned32 key2,
|
||||||
|
void **ret
|
||||||
|
)
|
||||||
|
{
|
||||||
|
unsigned32 mod = (key1) % FAT_HASH_MODULE;
|
||||||
|
Chain_Node *the_node = ((Chain_Control *)((hash) + mod))->first;
|
||||||
|
|
||||||
|
for ( ; !_Chain_Is_tail((hash) + mod, the_node) ; )
|
||||||
|
{
|
||||||
|
fat_file_fd_t *ffd = (fat_file_fd_t *)the_node;
|
||||||
|
unsigned32 ck =
|
||||||
|
fat_construct_key(mt_entry, ffd->info_cln, ffd->info_ofs);
|
||||||
|
|
||||||
|
if ( (key1) == ck)
|
||||||
|
{
|
||||||
|
if ( ((key2) == 0) || ((key2) == ffd->ino) )
|
||||||
|
{
|
||||||
|
*ret = (void *)the_node;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
the_node = the_node->next;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
fat_file_lseek(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 file_cln,
|
||||||
|
unsigned32 *disk_cln
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
/*
|
||||||
|
assert(fat_fd->fat_file_size);
|
||||||
|
*/
|
||||||
|
if (file_cln == fat_fd->map.file_cln)
|
||||||
|
*disk_cln = fat_fd->map.disk_cln;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned32 cur_cln;
|
||||||
|
unsigned32 count;
|
||||||
|
unsigned32 i;
|
||||||
|
|
||||||
|
if (file_cln > fat_fd->map.file_cln)
|
||||||
|
{
|
||||||
|
cur_cln = fat_fd->map.disk_cln;
|
||||||
|
count = file_cln - fat_fd->map.file_cln;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur_cln = fat_fd->cln;
|
||||||
|
count = file_cln;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip over the clusters */
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update cache */
|
||||||
|
fat_fd->map.file_cln = file_cln;
|
||||||
|
fat_fd->map.disk_cln = cur_cln;
|
||||||
|
|
||||||
|
*disk_cln = cur_cln;
|
||||||
|
}
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
195
c/src/libfs/src/dosfs/fat_file.h
Normal file
195
c/src/libfs/src/dosfs/fat_file.h
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* fat_file.h
|
||||||
|
*
|
||||||
|
* Constants/data structures/prototypes for operations on "fat-file"
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#ifndef __DOSFS_FAT_FILE_H__
|
||||||
|
#define __DOSFS_FAT_FILE_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/* "fat-file" representation
|
||||||
|
*
|
||||||
|
* the idea is: fat-file is nothing but a cluster chain, any open fat-file is
|
||||||
|
* represented in system by fat-file descriptor and has well-known
|
||||||
|
* file interface:
|
||||||
|
*
|
||||||
|
* fat_file_open()
|
||||||
|
* fat_file_close()
|
||||||
|
* fat_file_read()
|
||||||
|
* fat_file_write()
|
||||||
|
*
|
||||||
|
* Such interface hides the architecture of fat-file and represents it like
|
||||||
|
* linear file
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef rtems_filesystem_node_types_t fat_file_type_t;
|
||||||
|
|
||||||
|
#define FAT_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
|
||||||
|
#define FAT_FILE RTEMS_FILESYSTEM_MEMORY_FILE
|
||||||
|
|
||||||
|
typedef struct fat_file_map_s
|
||||||
|
{
|
||||||
|
unsigned32 file_cln;
|
||||||
|
unsigned32 disk_cln;
|
||||||
|
unsigned32 last_cln;
|
||||||
|
} fat_file_map_t;
|
||||||
|
/*
|
||||||
|
* descriptor of a fat-file
|
||||||
|
*
|
||||||
|
* To each particular clusters chain
|
||||||
|
*/
|
||||||
|
typedef struct fat_file_fd_s
|
||||||
|
{
|
||||||
|
Chain_Node link; /*
|
||||||
|
* fat-file descriptors organized into hash;
|
||||||
|
* collision lists are handled via link
|
||||||
|
* field
|
||||||
|
*/
|
||||||
|
unsigned32 links_num; /*
|
||||||
|
* the number of fat_file_open call on
|
||||||
|
* this fat-file
|
||||||
|
*/
|
||||||
|
unsigned32 ino; /* inode, file serial number :)))) */
|
||||||
|
fat_file_type_t fat_file_type;
|
||||||
|
unsigned32 size_limit;
|
||||||
|
unsigned32 fat_file_size; /* length */
|
||||||
|
unsigned32 info_cln;
|
||||||
|
unsigned32 cln;
|
||||||
|
unsigned16 info_ofs;
|
||||||
|
unsigned char first_char;
|
||||||
|
unsigned8 flags;
|
||||||
|
fat_file_map_t map;
|
||||||
|
time_t mtime;
|
||||||
|
|
||||||
|
} fat_file_fd_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define FAT_FILE_REMOVED 0x01
|
||||||
|
|
||||||
|
#define FAT_FILE_IS_REMOVED(p)\
|
||||||
|
(((p)->flags & FAT_FILE_REMOVED) ? 1 : 0)
|
||||||
|
|
||||||
|
/* ioctl macros */
|
||||||
|
#define F_CLU_NUM 0x01
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each file and directory on a MSDOS volume is unique identified by it
|
||||||
|
* location, i.e. location of it 32 Bytes Directory Entry Structure. We can
|
||||||
|
* distinguish them by cluster number it locates on and offset inside this
|
||||||
|
* cluster. But root directory on any volumes (FAT12/16/32) has no 32 Bytes
|
||||||
|
* Directory Entry Structure corresponded to it. So we assume 32 Bytes
|
||||||
|
* Directory Entry Structure of root directory locates at cluster 1 (invalid
|
||||||
|
* cluaster number) and offset 0
|
||||||
|
*/
|
||||||
|
#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))
|
||||||
|
|
||||||
|
#define FAT_EOF 0x00
|
||||||
|
|
||||||
|
/* fat_construct_key --
|
||||||
|
* Construct key for hash access: convert (cluster num, offset) to
|
||||||
|
* (sector512 num, new offset) and than construct key as
|
||||||
|
* key = (sector512 num) << 4 | (new offset)
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* cl - cluster number
|
||||||
|
* ofs - offset inside cluster 'cl'
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* constructed key
|
||||||
|
*/
|
||||||
|
static inline unsigned32
|
||||||
|
fat_construct_key(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cl,
|
||||||
|
unsigned32 ofs)
|
||||||
|
{
|
||||||
|
return ( ((fat_cluster_num_to_sector512_num(mt_entry, cl) +
|
||||||
|
(ofs >> FAT_SECTOR512_BITS)) << 4) +
|
||||||
|
((ofs >> 5) & (FAT_DIRENTRIES_PER_SEC512 - 1)) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prototypes for "fat-file" operations */
|
||||||
|
int
|
||||||
|
fat_file_open(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 ofs,
|
||||||
|
fat_file_fd_t **fat_fd);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_reopen(fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_close(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
fat_file_read(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 count,
|
||||||
|
char *buf);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
fat_file_write(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 count,
|
||||||
|
char *buf);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_extend(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 new_length,
|
||||||
|
unsigned32 *a_length);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_truncate(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 new_length);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_datasync(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_ioctl(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
int cmd,
|
||||||
|
...);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_size(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
void
|
||||||
|
fat_file_mark_removed(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_FAT_FILE_H__ */
|
||||||
408
c/src/libfs/src/dosfs/msdos.h
Normal file
408
c/src/libfs/src/dosfs/msdos.h
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
/*
|
||||||
|
* msdos.h
|
||||||
|
*
|
||||||
|
* The MSDOS filesystem constants/data structures/prototypes
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#ifndef __DOSFS_MSDOS_H__
|
||||||
|
#define __DOSFS_MSDOS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#ifndef RC_OK
|
||||||
|
#define RC_OK 0x00000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MSDOS_NAME_NOT_FOUND_ERR 0xDD000001
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This structure identifies the instance of the filesystem on the MSDOS
|
||||||
|
* level.
|
||||||
|
*/
|
||||||
|
typedef struct msdos_fs_info_s
|
||||||
|
{
|
||||||
|
fat_fs_info_t fat; /*
|
||||||
|
* volume
|
||||||
|
* description
|
||||||
|
*/
|
||||||
|
rtems_filesystem_file_handlers_r *directory_handlers; /*
|
||||||
|
* a set of routines
|
||||||
|
* that handles the
|
||||||
|
* nodes of directory
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
rtems_filesystem_file_handlers_r *file_handlers; /*
|
||||||
|
* a set of routines
|
||||||
|
* that handles the
|
||||||
|
* nodes of file
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
rtems_id vol_sema; /*
|
||||||
|
* semaphore
|
||||||
|
* associated with
|
||||||
|
* the volume
|
||||||
|
*/
|
||||||
|
unsigned8 *cl_buf; /*
|
||||||
|
* just placeholder
|
||||||
|
* for anything
|
||||||
|
*/
|
||||||
|
} msdos_fs_info_t;
|
||||||
|
|
||||||
|
/* a set of routines that handle the nodes which are directories */
|
||||||
|
extern rtems_filesystem_file_handlers_r msdos_dir_handlers;
|
||||||
|
|
||||||
|
/* a set of routines that handle the nodes which are files */
|
||||||
|
extern rtems_filesystem_file_handlers_r msdos_file_handlers;
|
||||||
|
|
||||||
|
/* Volume semaphore timeout value */
|
||||||
|
#define MSDOS_VOLUME_SEMAPHORE_TIMEOUT 100
|
||||||
|
|
||||||
|
/* Node types */
|
||||||
|
#define MSDOS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
|
||||||
|
#define MSDOS_REGULAR_FILE RTEMS_FILESYSTEM_MEMORY_FILE
|
||||||
|
|
||||||
|
typedef rtems_filesystem_node_types_t msdos_node_type_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros for fetching fields from 32 bytes long FAT Directory Entry
|
||||||
|
* Structure (see M$ White Paper)
|
||||||
|
*/
|
||||||
|
#define MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE 32 /* 32 bytes */
|
||||||
|
|
||||||
|
#define MSDOS_DIR_NAME(x) (unsigned8 *)((x) + 0)
|
||||||
|
#define MSDOS_DIR_ATTR(x) (unsigned8 *)((x) + 11)
|
||||||
|
#define MSDOS_DIR_NT_RES(x) (unsigned8 *)((x) + 12)
|
||||||
|
#define MSDOS_DIR_CRT_TIME_TENTH(x) (unsigned8 *)((x) + 13)
|
||||||
|
#define MSDOS_DIR_CRT_TIME(x) (unsigned16 *)((x) + 14)
|
||||||
|
#define MSDOS_DIR_CRT_DATE(x) (unsigned16 *)((x) + 16)
|
||||||
|
#define MSDOS_DIR_LAST_ACCESS_DATE(x) (unsigned16 *)((x) + 18)
|
||||||
|
#define MSDOS_DIR_FIRST_CLUSTER_HI(x) (unsigned16 *)((x) + 20)
|
||||||
|
#define MSDOS_DIR_WRITE_TIME(x) (unsigned16 *)((x) + 22)
|
||||||
|
#define MSDOS_DIR_WRITE_DATE(x) (unsigned16 *)((x) + 24)
|
||||||
|
#define MSDOS_DIR_FIRST_CLUSTER_LOW(x) (unsigned16 *)((x) + 26)
|
||||||
|
#define MSDOS_DIR_FILE_SIZE(x) (unsigned32 *)((x) + 28)
|
||||||
|
|
||||||
|
#define MSDOS_EXTRACT_CLUSTER_NUM(p) \
|
||||||
|
(unsigned32)( (CF_LE_W(*MSDOS_DIR_FIRST_CLUSTER_LOW(p))) | \
|
||||||
|
((CF_LE_W((*MSDOS_DIR_FIRST_CLUSTER_HI(p))))<<16) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fields offset in 32 bytes long FAT Directory Entry
|
||||||
|
* Structure (see M$ White Paper)
|
||||||
|
*/
|
||||||
|
#define MSDOS_FILE_SIZE_OFFSET 28
|
||||||
|
#define MSDOS_FILE_NAME_OFFSET 0
|
||||||
|
#define MSDOS_FIRST_CLUSTER_HI_OFFSET 20
|
||||||
|
#define MSDOS_FIRST_CLUSTER_LOW_OFFSET 26
|
||||||
|
#define MSDOS_FILE_WDATE_OFFSET 24
|
||||||
|
#define MSDOS_FILE_WTIME_OFFSET 22
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possible values of DIR_Attr field of 32 bytes long FAT Directory Entry
|
||||||
|
* Structure (see M$ White Paper)
|
||||||
|
*/
|
||||||
|
#define MSDOS_ATTR_READ_ONLY 0x01
|
||||||
|
#define MSDOS_ATTR_HIDDEN 0x02
|
||||||
|
#define MSDOS_ATTR_SYSTEM 0x04
|
||||||
|
#define MSDOS_ATTR_VOLUME_ID 0x08
|
||||||
|
#define MSDOS_ATTR_DIRECTORY 0x10
|
||||||
|
#define MSDOS_ATTR_ARCHIVE 0x20
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possible values of DIR_Name[0] field of 32 bytes long FAT Directory Entry
|
||||||
|
* Structure (see M$ White Paper)
|
||||||
|
*/
|
||||||
|
#define MSDOS_THIS_DIR_ENTRY_EMPTY 0xE5
|
||||||
|
#define MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY 0x00
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_NAME_LEN 11 /* 11 characters */
|
||||||
|
#define MSDOS_NAME_MAX MSDOS_SHORT_NAME_LEN
|
||||||
|
#define MSDOS_NAME_MAX_WITH_DOT (MSDOS_NAME_MAX + 1)
|
||||||
|
|
||||||
|
#define MSDOS_DOT_NAME ". " /* ".", padded to MSDOS_NAME chars */
|
||||||
|
#define MSDOS_DOTDOT_NAME ".. " /* "..", padded to MSDOS_NAME chars */
|
||||||
|
|
||||||
|
typedef enum msdos_token_types_e
|
||||||
|
{
|
||||||
|
MSDOS_NO_MORE_PATH,
|
||||||
|
MSDOS_CURRENT_DIR,
|
||||||
|
MSDOS_UP_DIR,
|
||||||
|
MSDOS_NAME,
|
||||||
|
MSDOS_INVALID_TOKEN
|
||||||
|
} msdos_token_types_t;
|
||||||
|
|
||||||
|
/* Others macros */
|
||||||
|
#define MSDOS_RES_NT_VALUE 0x00
|
||||||
|
#define MSDOS_INIT_DIR_SIZE 0x00
|
||||||
|
|
||||||
|
/* "dot" entry offset in a directory */
|
||||||
|
#define MSDOS_DOT_DIR_ENTRY_OFFSET 0x00 /* first entry in directory */
|
||||||
|
|
||||||
|
/* "dotdot" entry offset in a directory */
|
||||||
|
#define MSDOS_DOTDOT_DIR_ENTRY_OFFSET 0x20 /* second entry in directory */
|
||||||
|
|
||||||
|
/* 'p' should be char* */
|
||||||
|
#define DOT_NODE_P(p) ((char *)(p))
|
||||||
|
#define DOTDOT_NODE_P(p) ((char *)((p) + MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE))
|
||||||
|
|
||||||
|
/* Size limits for files and directories (see M$ White Paper) */
|
||||||
|
#define MSDOS_MAX_DIR_LENGHT 0x200000 /* 2,097,152 bytes */
|
||||||
|
#define MSDOS_MAX_FILE_SIZE 0xFFFFFFFF /* 4 Gb */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of 32 bytes long FAT Directory Entry
|
||||||
|
* Structures per 512 bytes sector
|
||||||
|
*/
|
||||||
|
#define MSDOS_DPS512_NUM 16
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
int
|
||||||
|
msdos_initialize(rtems_filesystem_mount_table_entry_t *temp_mt_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_eval_path(const char *pathname, /* IN */
|
||||||
|
int flags, /* IN */
|
||||||
|
rtems_filesystem_location_info_t *pathloc /* IN/OUT */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_eval4make(const char *path, /* IN */
|
||||||
|
rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
|
||||||
|
const char **name /* OUT */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_unlink(rtems_filesystem_location_info_t *pathloc /* IN */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_free_node_info(rtems_filesystem_location_info_t *pathloc /* IN */);
|
||||||
|
|
||||||
|
rtems_filesystem_node_types_t
|
||||||
|
msdos_node_type(rtems_filesystem_location_info_t *pathloc);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_mknod(const char *path, /* IN */
|
||||||
|
mode_t mode, /* IN */
|
||||||
|
dev_t dev, /* IN */
|
||||||
|
rtems_filesystem_location_info_t *pathloc /* IN/OUT */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_utime(rtems_filesystem_location_info_t *pathloc, /* IN */
|
||||||
|
time_t actime, /* IN */
|
||||||
|
time_t modtime /* IN */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_initialize_support(
|
||||||
|
rtems_filesystem_mount_table_entry_t *temp_mt_entry,
|
||||||
|
rtems_filesystem_operations_table *op_table,
|
||||||
|
rtems_filesystem_file_handlers_r *file_handlers,
|
||||||
|
rtems_filesystem_file_handlers_r *directory_handlers
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_open(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
const char *pathname, /* IN */
|
||||||
|
unsigned32 flag, /* IN */
|
||||||
|
unsigned32 mode /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_close(rtems_libio_t *iop /* IN */);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
msdos_file_read(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
void *buffer, /* IN */
|
||||||
|
unsigned32 count /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
msdos_file_write(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
const void *buffer, /* IN */
|
||||||
|
unsigned32 count /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_lseek(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
off_t offset, /* IN */
|
||||||
|
int whence /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_stat(rtems_filesystem_location_info_t *loc, /* IN */
|
||||||
|
struct stat *buf /* OUT */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_ftruncate(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
off_t length /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_sync(rtems_libio_t *iop);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_datasync(rtems_libio_t *iop);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_ioctl(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
unsigned32 command, /* IN */
|
||||||
|
void *buffer /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc /* IN */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_open(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
const char *pathname, /* IN */
|
||||||
|
unsigned32 flag, /* IN */
|
||||||
|
unsigned32 mode /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_close(rtems_libio_t *iop /* IN */);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
msdos_dir_read(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
void *buffer, /* IN */
|
||||||
|
unsigned32 count /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_lseek(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
off_t offset, /* IN */
|
||||||
|
int whence /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc /* IN */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_sync(rtems_libio_t *iop);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_stat(
|
||||||
|
rtems_filesystem_location_info_t *loc, /* IN */
|
||||||
|
struct stat *buf /* OUT */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_creat_node(rtems_filesystem_location_info_t *parent_loc,
|
||||||
|
msdos_node_type_t type,
|
||||||
|
char *name,
|
||||||
|
mode_t mode);
|
||||||
|
|
||||||
|
/* Misc prototypes */
|
||||||
|
msdos_token_types_t msdos_get_token(const char *path,
|
||||||
|
char *token,
|
||||||
|
int *token_len);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_find_name(rtems_filesystem_location_info_t *parent_loc,
|
||||||
|
char *name);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_get_name_node(rtems_filesystem_location_info_t *parent_loc,
|
||||||
|
char *name,
|
||||||
|
fat_auxiliary_t *paux,
|
||||||
|
char *name_dir_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_info_remove(rtems_filesystem_location_info_t *pathloc);
|
||||||
|
|
||||||
|
void
|
||||||
|
msdos_date_unix2dos(int unix_date,
|
||||||
|
unsigned short *time_val,
|
||||||
|
unsigned short *date);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
msdos_date_dos2unix(unsigned short time_val, unsigned short date);
|
||||||
|
|
||||||
|
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,
|
||||||
|
unsigned32 cl,
|
||||||
|
unsigned32 ofs,
|
||||||
|
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,
|
||||||
|
rtems_boolean *ret_val);
|
||||||
|
|
||||||
|
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,
|
||||||
|
char *name_dir_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_find_node_by_cluster_num_in_fat_file(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 cl4find,
|
||||||
|
fat_auxiliary_t *paux,
|
||||||
|
char *dir_entry
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_get_dotdot_dir_info_cluster_num_and_offset(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
fat_auxiliary_t *paux,
|
||||||
|
char *dir_entry
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_MSDOS_H__ */
|
||||||
208
c/src/libfs/src/dosfs/msdos_create.c
Normal file
208
c/src/libfs/src/dosfs/msdos_create.c
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* Routine to create a new MSDOS filesystem node
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_creat_node --
|
||||||
|
* Create a new node. If a new node is file, FAT 32 Bytes Directory
|
||||||
|
* Entry Structure (see M$ White Paper) 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 new directory and dot and dotdot nodes are created
|
||||||
|
* in alloceted cluster.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* parent_loc - parent (directory we are going to create node in)
|
||||||
|
* type - new node type (file or directory)
|
||||||
|
* name - new node name
|
||||||
|
* mode - mode
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_creat_node(
|
||||||
|
rtems_filesystem_location_info_t *parent_loc,
|
||||||
|
msdos_node_type_t type,
|
||||||
|
char *name,
|
||||||
|
mode_t mode
|
||||||
|
)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
unsigned16 time_val = 0;
|
||||||
|
unsigned16 date = 0;
|
||||||
|
fat_auxiliary_t aux;
|
||||||
|
unsigned char new_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
|
||||||
|
unsigned char dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
|
||||||
|
|
||||||
|
memset(new_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);
|
||||||
|
|
||||||
|
/* fill reserved field */
|
||||||
|
*MSDOS_DIR_NT_RES(new_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);
|
||||||
|
|
||||||
|
/* initialize directory/file size */
|
||||||
|
*MSDOS_DIR_FILE_SIZE(new_node) = MSDOS_INIT_DIR_SIZE;
|
||||||
|
|
||||||
|
if (type == MSDOS_DIRECTORY)
|
||||||
|
*MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_DIRECTORY;
|
||||||
|
else
|
||||||
|
*MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find free space in the parent directory and write new initialized
|
||||||
|
* FAT 32 Bytes Directory Entry Structure (see M$ White Paper)
|
||||||
|
* to the disk
|
||||||
|
*/
|
||||||
|
rc = msdos_get_name_node(parent_loc, NULL, &aux, new_node);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if we create a new file we are done, if directory there are more steps
|
||||||
|
* to do
|
||||||
|
*/
|
||||||
|
if (type == MSDOS_DIRECTORY)
|
||||||
|
{
|
||||||
|
/* open new directory as fat-file */
|
||||||
|
rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dot and dotdot entries are identical to new node except the
|
||||||
|
* names
|
||||||
|
*/
|
||||||
|
memcpy(DOT_NODE_P(dot_dotdot), new_node,
|
||||||
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
|
||||||
|
memcpy(DOTDOT_NODE_P(dot_dotdot), new_node,
|
||||||
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
|
||||||
|
memcpy(MSDOS_DIR_NAME(DOT_NODE_P(dot_dotdot)), MSDOS_DOT_NAME,
|
||||||
|
MSDOS_NAME_MAX);
|
||||||
|
memcpy(MSDOS_DIR_NAME(DOTDOT_NODE_P(dot_dotdot)), MSDOS_DOTDOT_NAME,
|
||||||
|
MSDOS_NAME_MAX);
|
||||||
|
|
||||||
|
/* set up cluster num for dotdot entry */
|
||||||
|
/*
|
||||||
|
* here we can ommit FAT32 condition because for all FAT types dirs
|
||||||
|
* right under root dir should contain 0 in dotdot entry but for
|
||||||
|
* FAT12/16 parent_fat_fd->cluster_num always contains such value
|
||||||
|
*/
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(parent_fat_fd)) &&
|
||||||
|
(fs_info->fat.vol.type & FAT_FAT32))
|
||||||
|
{
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_LOW(DOTDOT_NODE_P(dot_dotdot)) = 0x0000;
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_HI(DOTDOT_NODE_P(dot_dotdot)) = 0x0000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_LOW(DOTDOT_NODE_P(dot_dotdot)) =
|
||||||
|
CT_LE_W((unsigned16)((parent_fat_fd->cln) & 0x0000FFFF));
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_HI(DOTDOT_NODE_P(dot_dotdot)) =
|
||||||
|
CT_LE_W((unsigned16)(((parent_fat_fd->cln) & 0xFFFF0000)>>16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* write dot and dotdot entries to new fat-file: currently fat-file
|
||||||
|
* correspondes to a new node is zero length, so it will be extended
|
||||||
|
* by one cluster and entries will be written
|
||||||
|
*/
|
||||||
|
ret = fat_file_write(parent_loc->mt_entry, fat_fd, 0,
|
||||||
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2,
|
||||||
|
dot_dotdot);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* increment fat-file size by cluster size */
|
||||||
|
fat_fd->fat_file_size += fs_info->fat.vol.bpc;
|
||||||
|
|
||||||
|
/* set up cluster num for dot entry */
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_LOW(DOT_NODE_P(dot_dotdot)) =
|
||||||
|
CT_LE_W((unsigned16)((fat_fd->cln) & 0x0000FFFF));
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_HI(DOT_NODE_P(dot_dotdot)) =
|
||||||
|
CT_LE_W((unsigned16)(((fat_fd->cln) & 0xFFFF0000) >> 16));
|
||||||
|
|
||||||
|
/* rewrite dot entry */
|
||||||
|
ret = fat_file_write(parent_loc->mt_entry, fat_fd, 0,
|
||||||
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
|
||||||
|
DOT_NODE_P(dot_dotdot));
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write first cluster num of a new directory to disk */
|
||||||
|
rc = msdos_set_first_cluster_num(parent_loc->mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
fat_file_close(parent_loc->mt_entry, fat_fd);
|
||||||
|
}
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
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);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
483
c/src/libfs/src/dosfs/msdos_dir.c
Normal file
483
c/src/libfs/src/dosfs/msdos_dir.c
Normal file
@@ -0,0 +1,483 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS directory handlers implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_dir_open --
|
||||||
|
* Open fat-file which correspondes to the directory being opened and
|
||||||
|
* set offset field of file control block to zero.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* pathname - name
|
||||||
|
* flag - flags
|
||||||
|
* mode - mode
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, if directory opened successfully, or -1 if error occured (errno
|
||||||
|
* set apropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_open(rtems_libio_t *iop, const char *pathname, unsigned32 flag,
|
||||||
|
unsigned32 mode)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
rc = fat_file_reopen(fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
iop->offset = 0;
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_close --
|
||||||
|
* Close fat-file which correspondes to the directory being closed
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, if directory closed successfully, or -1 if error occured (errno
|
||||||
|
* set apropriately.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_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;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_read --
|
||||||
|
* This routine will read the next directory entry based on the directory
|
||||||
|
* offset. The offset should be equal to -n- time the size of an
|
||||||
|
* individual dirent structure. If n is not an integer multiple of the
|
||||||
|
* sizeof a dirent structure, an integer division will be performed to
|
||||||
|
* determine directory entry that will be returned in the buffer. Count
|
||||||
|
* should reflect -m- times the sizeof dirent bytes to be placed in the
|
||||||
|
* buffer.
|
||||||
|
* If there are not -m- dirent elements from the current directory
|
||||||
|
* position to the end of the exisiting file, the remaining entries will
|
||||||
|
* be placed in the buffer and the returned value will be equal to
|
||||||
|
* -m actual- times the size of a directory entry.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* buffer - buffer provided by user
|
||||||
|
* count - count of bytes to read
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* the number of bytes read on success, or -1 if error occured (errno
|
||||||
|
* set apropriately).
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
msdos_dir_read(rtems_libio_t *iop, void *buffer, unsigned32 count)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
fat_file_fd_t *tmp_fat_fd = NULL;
|
||||||
|
struct dirent tmp_dirent;
|
||||||
|
unsigned32 start = 0;
|
||||||
|
ssize_t ret = 0;
|
||||||
|
unsigned32 cmpltd = 0;
|
||||||
|
unsigned32 j = 0, i = 0;
|
||||||
|
unsigned32 bts2rd = 0;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cast start and count - protect against using sizes that are not exact
|
||||||
|
* multiples of the -dirent- size. These could result in unexpected
|
||||||
|
* results
|
||||||
|
*/
|
||||||
|
start = iop->offset / sizeof(struct dirent);
|
||||||
|
count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* optimization: we know that root directory for FAT12/16 volumes is
|
||||||
|
* sequential set of sectors and any cluster is sequential set of sectors
|
||||||
|
* too, so read such set of sectors is quick operation for low-level IO
|
||||||
|
* layer.
|
||||||
|
*/
|
||||||
|
bts2rd = (FAT_FD_OF_ROOT_DIR(fat_fd) &&
|
||||||
|
(fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) ?
|
||||||
|
fat_fd->fat_file_size :
|
||||||
|
fs_info->fat.vol.bpc;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* fat-file is already opened by open call, so read it
|
||||||
|
* Always read directory fat-file from the beggining because of MSDOS
|
||||||
|
* directories feature :( - we should count elements currently
|
||||||
|
* present in the directory because there may be holes :)
|
||||||
|
*/
|
||||||
|
ret = fat_file_read(iop->pathinfo.mt_entry, fat_fd, (j * bts2rd),
|
||||||
|
bts2rd, fs_info->cl_buf);
|
||||||
|
if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ret; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
|
||||||
|
{
|
||||||
|
if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
|
||||||
|
MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
|
||||||
|
MSDOS_THIS_DIR_ENTRY_EMPTY)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* skip active entries until get the entry to start from
|
||||||
|
*/
|
||||||
|
if (start)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_file_open(iop->pathinfo.mt_entry, cur_cln, i,
|
||||||
|
&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;
|
||||||
|
tmp_dirent.d_namlen = MSDOS_SHORT_NAME_LEN;
|
||||||
|
memcpy(tmp_dirent.d_name, MSDOS_DIR_NAME((fs_info->cl_buf + i)),
|
||||||
|
MSDOS_SHORT_NAME_LEN);
|
||||||
|
|
||||||
|
/* d_name is null-terminated */
|
||||||
|
tmp_dirent.d_name[MSDOS_SHORT_NAME_LEN] = 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_write --
|
||||||
|
* no write for directory
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* msdos_dir_lseek --
|
||||||
|
*
|
||||||
|
* This routine will behave in one of three ways based on the state of
|
||||||
|
* argument whence. Based on the state of its value the offset argument will
|
||||||
|
* be interpreted using one of the following methods:
|
||||||
|
*
|
||||||
|
* SEEK_SET - offset is the absolute byte offset from the start of the
|
||||||
|
* logical start of the dirent sequence that represents the
|
||||||
|
* directory
|
||||||
|
* SEEK_CUR - offset is used as the relative byte offset from the current
|
||||||
|
* directory position index held in the iop structure
|
||||||
|
* SEEK_END - N/A --> This will cause an assert.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* offset - offset
|
||||||
|
* whence - predefine directive
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno
|
||||||
|
* set apropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_lseek(rtems_libio_t *iop, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
switch (whence)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
case SEEK_CUR:
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
* Movement past the end of the directory via lseek is not a
|
||||||
|
* permitted operation
|
||||||
|
*/
|
||||||
|
case SEEK_END:
|
||||||
|
default:
|
||||||
|
set_errno_and_return_minus_one( EINVAL );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_stat --
|
||||||
|
*
|
||||||
|
* This routine will obtain the following information concerning the current
|
||||||
|
* directory:
|
||||||
|
* st_dev device id
|
||||||
|
* st_ino node serial number :)
|
||||||
|
* st_mode mode extracted from the node
|
||||||
|
* st_size total size in bytes
|
||||||
|
* st_blksize blocksize for filesystem I/O
|
||||||
|
* st_blocks number of blocks allocated
|
||||||
|
* stat_mtime time of last modification
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* loc - this directory
|
||||||
|
* buf - stat buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and filled stat buffer on success, or -1 if error occured (errno
|
||||||
|
* set apropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_stat(
|
||||||
|
rtems_filesystem_location_info_t *loc,
|
||||||
|
struct stat *buf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = loc->node_access;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
buf->st_dev = fs_info->fat.vol.dev;
|
||||||
|
buf->st_ino = fat_fd->ino;
|
||||||
|
buf->st_mode = S_IFDIR;
|
||||||
|
buf->st_rdev = 0ll;
|
||||||
|
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_mtime = fat_fd->mtime;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_truncate --
|
||||||
|
* No truncate for directory.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* msdos_dir_sync --
|
||||||
|
* The following routine does a syncronization on a MSDOS directory node.
|
||||||
|
* DIR_WrtTime, DIR_WrtDate and DIR_fileSize fields of 32 Bytes Directory
|
||||||
|
* Entry Structure(see M$ White Paper) should not be updated for
|
||||||
|
* directories, so only call to corresponding fat-file routine.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set apropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_sync(rtems_libio_t *iop)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
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)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_rmnod --
|
||||||
|
* Remove directory node.
|
||||||
|
*
|
||||||
|
* Check that this directory node is not opened as fat-file, is empty and
|
||||||
|
* not filesystem root node. If all this conditions met then delete.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathloc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set apropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = pathloc->node_access;
|
||||||
|
rtems_boolean is_empty = FALSE;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We deny attemp to delete open directory (if directory is current
|
||||||
|
* directory we assume it is open one)
|
||||||
|
*/
|
||||||
|
if (fat_fd->links_num > 1)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
set_errno_and_return_minus_one(EBUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You cannot remove a node that still has children
|
||||||
|
*/
|
||||||
|
rc = msdos_dir_is_empty(pathloc->mt_entry, fat_fd, &is_empty);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_empty)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
set_errno_and_return_minus_one(ENOTEMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You cannot remove the file system root node.
|
||||||
|
*/
|
||||||
|
if (pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
set_errno_and_return_minus_one(EBUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You cannot remove a mountpoint.
|
||||||
|
* not used - mount() not implemenetd yet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* mark file removed */
|
||||||
|
rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
|
||||||
|
fat_fd->info_ofs,
|
||||||
|
MSDOS_THIS_DIR_ENTRY_EMPTY);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_file_mark_removed(pathloc->mt_entry, fat_fd);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
435
c/src/libfs/src/dosfs/msdos_eval.c
Normal file
435
c/src/libfs/src/dosfs/msdos_eval.c
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS evaluation routines
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_set_handlers --
|
||||||
|
* Set handlers for the node with specified type(i.e. handlers for file
|
||||||
|
* or directory).
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* loc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
msdos_set_handlers(rtems_filesystem_location_info_t *loc)
|
||||||
|
{
|
||||||
|
msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = loc->node_access;
|
||||||
|
|
||||||
|
if (fat_fd->fat_file_type == FAT_DIRECTORY)
|
||||||
|
loc->handlers = fs_info->directory_handlers;
|
||||||
|
else
|
||||||
|
loc->handlers = fs_info->file_handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_eval_path --
|
||||||
|
*
|
||||||
|
* The following routine evaluate path for a node that wishes to be
|
||||||
|
* accessed. Structure 'pathloc' is returned with a pointer to the
|
||||||
|
* node to be accessed.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathname - path for evaluation
|
||||||
|
* flags - flags
|
||||||
|
* pathloc - node description (IN/OUT)
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and filled pathloc on success, or -1 if error occured
|
||||||
|
* (errno set appropriately)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_eval_path(
|
||||||
|
const char *pathname,
|
||||||
|
int flags,
|
||||||
|
rtems_filesystem_location_info_t *pathloc
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = NULL;
|
||||||
|
rtems_filesystem_location_info_t newloc;
|
||||||
|
int i = 0;
|
||||||
|
int len = 0;
|
||||||
|
msdos_token_types_t type = MSDOS_CURRENT_DIR;
|
||||||
|
char token[MSDOS_NAME_MAX + 1];
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
if (!pathloc->node_access)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
rc = fat_file_reopen(fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
while ((type != MSDOS_NO_MORE_PATH) && (type != MSDOS_INVALID_TOKEN))
|
||||||
|
{
|
||||||
|
type = msdos_get_token(&pathname[i], token, &len);
|
||||||
|
i += len;
|
||||||
|
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case MSDOS_UP_DIR:
|
||||||
|
/*
|
||||||
|
* Only a directory can be decended into.
|
||||||
|
*/
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Am I at the root of this mounted filesystem?
|
||||||
|
*/
|
||||||
|
if (pathloc->node_access ==
|
||||||
|
pathloc->mt_entry->mt_fs_root.node_access)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Am I at the root of all filesystems?
|
||||||
|
* XXX: MSDOS is not supposed to be base fs.
|
||||||
|
*/
|
||||||
|
if (pathloc->node_access ==
|
||||||
|
rtems_filesystem_root.node_access)
|
||||||
|
{
|
||||||
|
break; /* Throw out the .. in this case */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newloc = pathloc->mt_entry->mt_point_node;
|
||||||
|
*pathloc = newloc;
|
||||||
|
|
||||||
|
rc = fat_file_close(pathloc->mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return (*pathloc->ops->evalpath_h)(&(pathname[i-len]),
|
||||||
|
flags, pathloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = msdos_find_name(pathloc, token);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
if (rc == MSDOS_NAME_NOT_FOUND_ERR)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_NAME:
|
||||||
|
/*
|
||||||
|
* Only a directory can be decended into.
|
||||||
|
*/
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
if (rc == MSDOS_NAME_NOT_FOUND_ERR)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_NO_MORE_PATH:
|
||||||
|
case MSDOS_CURRENT_DIR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_INVALID_TOKEN:
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Always return the root node.
|
||||||
|
*
|
||||||
|
* If we are at a node that is a mount point. Set loc to the
|
||||||
|
* new fs root node and let let the mounted filesystem set the handlers.
|
||||||
|
*
|
||||||
|
* NOTE: The behavior of stat() on a mount point appears to be
|
||||||
|
* questionable.
|
||||||
|
* NOTE: MSDOS filesystem currently doesn't support mount functionality ->
|
||||||
|
* action not implemented
|
||||||
|
*/
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
msdos_set_handlers(pathloc);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
fat_file_close(pathloc->mt_entry, fat_fd);
|
||||||
|
|
||||||
|
err:
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_eval4make --
|
||||||
|
* The following routine evaluate path for a new node to be created.
|
||||||
|
* 'pathloc' is returned with a pointer to the parent of the new node.
|
||||||
|
* 'name' is returned with a pointer to the first character in the
|
||||||
|
* new node name. The parent node is verified to be a directory.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* path - path for evaluation
|
||||||
|
* pathloc - IN/OUT (start point for evaluation/parent directory for
|
||||||
|
* creation)
|
||||||
|
* name - new node name
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, filled pathloc for parent directory and name of new node on
|
||||||
|
* success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_eval4make(
|
||||||
|
const char *path,
|
||||||
|
rtems_filesystem_location_info_t *pathloc,
|
||||||
|
const char **name
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = NULL;
|
||||||
|
rtems_filesystem_location_info_t newloc;
|
||||||
|
msdos_token_types_t type;
|
||||||
|
int i = 0;
|
||||||
|
int len;
|
||||||
|
char token[ MSDOS_NAME_MAX + 1 ];
|
||||||
|
rtems_boolean done = 0;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
if (!pathloc->node_access)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
rc = fat_file_reopen(fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
type = msdos_get_token(&path[i], token, &len);
|
||||||
|
i += len;
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case MSDOS_UP_DIR:
|
||||||
|
/*
|
||||||
|
* Only a directory can be decended into.
|
||||||
|
*/
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Am I at the root of this mounted filesystem?
|
||||||
|
*/
|
||||||
|
if (pathloc->node_access ==
|
||||||
|
pathloc->mt_entry->mt_fs_root.node_access)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Am I at the root of all filesystems?
|
||||||
|
* XXX: MSDOS is not supposed to be base fs.
|
||||||
|
*/
|
||||||
|
if (pathloc->node_access ==
|
||||||
|
rtems_filesystem_root.node_access)
|
||||||
|
{
|
||||||
|
break; /* Throw out the .. in this case */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newloc = pathloc->mt_entry->mt_point_node;
|
||||||
|
*pathloc = newloc;
|
||||||
|
|
||||||
|
rc = fat_file_close(pathloc->mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return (*pathloc->ops->evalformake_h)(&path[i-len],
|
||||||
|
pathloc, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = msdos_find_name(pathloc, token);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
if (rc == MSDOS_NAME_NOT_FOUND_ERR)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_NAME:
|
||||||
|
/*
|
||||||
|
* Only a directory can be decended into.
|
||||||
|
*/
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
if (rc != MSDOS_NAME_NOT_FOUND_ERR)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
done = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_NO_MORE_PATH:
|
||||||
|
errno = EEXIST;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_CURRENT_DIR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_INVALID_TOKEN:
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*name = &path[i - len];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have evaluated the path as far as we can.
|
||||||
|
* Verify there is not any invalid stuff at the end of the name.
|
||||||
|
*/
|
||||||
|
for( ; path[i] != '\0'; i++)
|
||||||
|
{
|
||||||
|
if (!msdos_is_separator(path[i]))
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
msdos_set_handlers(pathloc);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
fat_file_close(pathloc->mt_entry, fat_fd);
|
||||||
|
|
||||||
|
err:
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
485
c/src/libfs/src/dosfs/msdos_file.c
Normal file
485
c/src/libfs/src/dosfs/msdos_file.c
Normal file
@@ -0,0 +1,485 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS file handlers implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_file_open --
|
||||||
|
* Open fat-file which correspondes to the file
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* pathname - name
|
||||||
|
* flag - flags
|
||||||
|
* mode - mode
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, if file opened successfully, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_open(rtems_libio_t *iop, const char *pathname, unsigned32 flag,
|
||||||
|
unsigned32 mode)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_reopen(fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iop->flags & LIBIO_FLAGS_APPEND)
|
||||||
|
iop->offset = fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
iop->size = fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* buffer - buffer provided by user
|
||||||
|
* count - the number of bytes to read
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* the number of bytes read on success, or -1 if error occured (errno set
|
||||||
|
* appropriately)
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
msdos_file_read(rtems_libio_t *iop, void *buffer, unsigned32 count)
|
||||||
|
{
|
||||||
|
ssize_t ret = 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->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
ret = fat_file_read(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
|
||||||
|
buffer);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_write --
|
||||||
|
* This routine writes the specified data buffer into the file pointed to
|
||||||
|
* by file control block.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* buffer - data to write
|
||||||
|
* count - count of bytes to write
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* the number of bytes written on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
msdos_file_write(rtems_libio_t *iop,const void *buffer, unsigned32 count)
|
||||||
|
{
|
||||||
|
ssize_t ret = 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->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
ret = fat_file_write(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
|
||||||
|
buffer);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* update file size in both fat-file descriptor and file control block if
|
||||||
|
* file was extended
|
||||||
|
*/
|
||||||
|
if (iop->offset + ret > fat_fd->fat_file_size)
|
||||||
|
fat_fd->fat_file_size = iop->offset + ret;
|
||||||
|
|
||||||
|
iop->size = fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_lseek --
|
||||||
|
* Process lseek call to the file: extend file if lseek is up to the end
|
||||||
|
* of the file.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* offset - new offset
|
||||||
|
* whence - predefine directive
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* new offset on success, or -1 if error occured (errno set
|
||||||
|
* appropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_lseek(rtems_libio_t *iop, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
unsigned32 real_size = 0;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_extend(iop->pathinfo.mt_entry, fat_fd, iop->offset,
|
||||||
|
&real_size);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (real_size > fat_fd->fat_file_size)
|
||||||
|
fat_fd->fat_file_size = iop->offset = real_size;
|
||||||
|
|
||||||
|
iop->size = fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return iop->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_stat --
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* loc - node description
|
||||||
|
* buf - stat buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_stat(
|
||||||
|
rtems_filesystem_location_info_t *loc,
|
||||||
|
struct stat *buf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = loc->node_access;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
buf->st_dev = fs_info->fat.vol.dev;
|
||||||
|
buf->st_ino = fat_fd->ino;
|
||||||
|
buf->st_mode = S_IFREG;
|
||||||
|
buf->st_rdev = 0ll;
|
||||||
|
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_mtime = fat_fd->mtime;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_ftruncate --
|
||||||
|
* Truncate the file (if new length is greater then current do nothing).
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* length - new length
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
|
||||||
|
if (length >= fat_fd->fat_file_size)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_truncate(iop->pathinfo.mt_entry, fat_fd, length);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fat_file_truncate do nothing if new length >= fat-file size, so update
|
||||||
|
* file size only if length < fat-file size
|
||||||
|
*/
|
||||||
|
if (length < fat_fd->fat_file_size)
|
||||||
|
iop->size = fat_fd->fat_file_size = length;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_sync --
|
||||||
|
* Synchronize file - synchronize file data and if file is not removed
|
||||||
|
* synchronize file metadata.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_sync(rtems_libio_t *iop)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
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)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/* synchronize file data */
|
||||||
|
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if fat-file descriptor is not marked "removed" - synchronize file
|
||||||
|
* metadata
|
||||||
|
*/
|
||||||
|
if (!FAT_FILE_IS_REMOVED(fat_fd))
|
||||||
|
{
|
||||||
|
rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_datasync --
|
||||||
|
* Synchronize file - synchronize only file data (metadata is letf intact).
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_datasync(rtems_libio_t *iop)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
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)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/* synchronize file data */
|
||||||
|
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* msdos_file_ioctl --
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_ioctl(rtems_libio_t *iop,unsigned32 command, void *buffer)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* correspondes to the file as "removed"
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathloc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
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,
|
||||||
|
MSDOS_THIS_DIR_ENTRY_EMPTY);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_file_mark_removed(pathloc->mt_entry, fat_fd);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
56
c/src/libfs/src/dosfs/msdos_free.c
Normal file
56
c/src/libfs/src/dosfs/msdos_free.c
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Free node handler implementation for the filesystem
|
||||||
|
* operations table.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_free_node_info --
|
||||||
|
* Call fat-file close routine.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathloc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 code if error occured
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_free_node_info(rtems_filesystem_location_info_t *pathloc)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_close(pathloc->mt_entry, pathloc->node_access);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
71
c/src/libfs/src/dosfs/msdos_fsunmount.c
Normal file
71
c/src/libfs/src/dosfs/msdos_fsunmount.c
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS shut down handler implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_shut_down --
|
||||||
|
* Shut down MSDOS filesystem - free all allocated resources (don't
|
||||||
|
* return if deallocation of some resource failed - free as much as
|
||||||
|
* possible).
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* temp_mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set apropriately).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
msdos_fs_info_t *fs_info = temp_mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = temp_mt_entry->mt_fs_root.node_access;
|
||||||
|
|
||||||
|
/* close fat-file which correspondes to root directory */
|
||||||
|
if (fat_file_close(temp_mt_entry, fat_fd) != RC_OK)
|
||||||
|
{
|
||||||
|
/* no return - try to free as much as possible */
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fat_shutdown_drive(temp_mt_entry) != RC_OK)
|
||||||
|
{
|
||||||
|
/* no return - try to free as much as possible */
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_semaphore_delete(fs_info->vol_sema);
|
||||||
|
free(fs_info->cl_buf);
|
||||||
|
free(temp_mt_entry->fs_info);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
36
c/src/libfs/src/dosfs/msdos_handlers_dir.c
Normal file
36
c/src/libfs/src/dosfs/msdos_handlers_dir.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Directory Handlers Table for MSDOS filesystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
rtems_filesystem_file_handlers_r msdos_dir_handlers = {
|
||||||
|
msdos_dir_open,
|
||||||
|
msdos_dir_close,
|
||||||
|
msdos_dir_read,
|
||||||
|
NULL, /* msdos_dir_write */
|
||||||
|
NULL, /* msdos_dir_ioctl */
|
||||||
|
msdos_dir_lseek,
|
||||||
|
msdos_dir_stat,
|
||||||
|
NULL,
|
||||||
|
NULL, /* msdos_dir_ftruncate */
|
||||||
|
NULL,
|
||||||
|
msdos_dir_sync,
|
||||||
|
msdos_dir_sync,
|
||||||
|
NULL, /* msdos_dir_fcntl */
|
||||||
|
msdos_dir_rmnod
|
||||||
|
};
|
||||||
36
c/src/libfs/src/dosfs/msdos_handlers_file.c
Normal file
36
c/src/libfs/src/dosfs/msdos_handlers_file.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* File Operations Table for MSDOS filesystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
rtems_filesystem_file_handlers_r msdos_file_handlers = {
|
||||||
|
msdos_file_open,
|
||||||
|
msdos_file_close,
|
||||||
|
msdos_file_read,
|
||||||
|
msdos_file_write,
|
||||||
|
msdos_file_ioctl,
|
||||||
|
msdos_file_lseek,
|
||||||
|
msdos_file_stat,
|
||||||
|
NULL,
|
||||||
|
msdos_file_ftruncate,
|
||||||
|
NULL,
|
||||||
|
msdos_file_sync,
|
||||||
|
msdos_file_datasync,
|
||||||
|
NULL, /* msdos_file_fcntl */
|
||||||
|
msdos_file_rmnod
|
||||||
|
};
|
||||||
60
c/src/libfs/src/dosfs/msdos_init.c
Normal file
60
c/src/libfs/src/dosfs/msdos_init.c
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Init routine for MSDOS
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
rtems_filesystem_operations_table msdos_ops = {
|
||||||
|
msdos_eval_path,
|
||||||
|
msdos_eval4make,
|
||||||
|
NULL, /* msdos_link */
|
||||||
|
msdos_file_rmnod,
|
||||||
|
msdos_node_type,
|
||||||
|
msdos_mknod,
|
||||||
|
NULL, /* msdos_chown */
|
||||||
|
msdos_free_node_info,
|
||||||
|
NULL,
|
||||||
|
msdos_initialize,
|
||||||
|
NULL,
|
||||||
|
msdos_shut_down, /* msdos_shut_down */
|
||||||
|
NULL, /* msdos_utime */
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* msdos_initialize --
|
||||||
|
* MSDOS filesystem initialization
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* temp_mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set apropriately).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_initialize(rtems_filesystem_mount_table_entry_t *temp_mt_entry)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
|
||||||
|
rc = msdos_initialize_support(temp_mt_entry,
|
||||||
|
&msdos_ops,
|
||||||
|
&msdos_file_handlers,
|
||||||
|
&msdos_dir_handlers);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
149
c/src/libfs/src/dosfs/msdos_initsupp.c
Normal file
149
c/src/libfs/src/dosfs/msdos_initsupp.c
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS Initialization support routine implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_initialize_support --
|
||||||
|
* MSDOS filesystem initialization
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* temp_mt_entry - mount table entry
|
||||||
|
* op_table - filesystem operations table
|
||||||
|
* file_handlers - file operations table
|
||||||
|
* directory_handlers - directory operations table
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and filled temp_mt_entry on success, or -1 if error occured
|
||||||
|
* (errno set apropriately)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_initialize_support(
|
||||||
|
rtems_filesystem_mount_table_entry_t *temp_mt_entry,
|
||||||
|
rtems_filesystem_operations_table *op_table,
|
||||||
|
rtems_filesystem_file_handlers_r *file_handlers,
|
||||||
|
rtems_filesystem_file_handlers_r *directory_handlers
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = NULL;
|
||||||
|
fat_file_fd_t *fat_fd = NULL;
|
||||||
|
unsigned32 cl_buf_size;
|
||||||
|
|
||||||
|
fs_info = (msdos_fs_info_t *)calloc(1, sizeof(msdos_fs_info_t));
|
||||||
|
if (!fs_info)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
|
||||||
|
temp_mt_entry->fs_info = fs_info;
|
||||||
|
|
||||||
|
rc = fat_init_volume_info(temp_mt_entry);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
free(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs_info->file_handlers = file_handlers;
|
||||||
|
fs_info->directory_handlers = directory_handlers;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
fat_shutdown_drive(temp_mt_entry);
|
||||||
|
free(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
fat_fd->map.disk_cln = fat_fd->cln;
|
||||||
|
|
||||||
|
/* if we have FAT12/16 */
|
||||||
|
if ( fat_fd->cln == 0 )
|
||||||
|
{
|
||||||
|
fat_fd->fat_file_size = fs_info->fat.vol.rdir_size;
|
||||||
|
cl_buf_size = (fs_info->fat.vol.bpc > fs_info->fat.vol.rdir_size) ?
|
||||||
|
fs_info->fat.vol.bpc :
|
||||||
|
fs_info->fat.vol.rdir_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = fat_file_size(temp_mt_entry, fat_fd);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
fat_file_close(temp_mt_entry, fat_fd);
|
||||||
|
fat_shutdown_drive(temp_mt_entry);
|
||||||
|
free(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
cl_buf_size = fs_info->fat.vol.bpc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs_info->cl_buf = (char *)calloc(cl_buf_size, sizeof(char));
|
||||||
|
if (fs_info->cl_buf == NULL)
|
||||||
|
{
|
||||||
|
fat_file_close(temp_mt_entry, fat_fd);
|
||||||
|
fat_shutdown_drive(temp_mt_entry);
|
||||||
|
free(fs_info);
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
sc = rtems_semaphore_create(3,
|
||||||
|
1,
|
||||||
|
RTEMS_BINARY_SEMAPHORE | RTEMS_FIFO,
|
||||||
|
RTEMS_INHERIT_PRIORITY,
|
||||||
|
&fs_info->vol_sema);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
{
|
||||||
|
fat_file_close(temp_mt_entry, fat_fd);
|
||||||
|
fat_shutdown_drive(temp_mt_entry);
|
||||||
|
free(fs_info->cl_buf);
|
||||||
|
free(fs_info);
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
}
|
||||||
|
|
||||||
|
temp_mt_entry->mt_fs_root.node_access = fat_fd;
|
||||||
|
temp_mt_entry->mt_fs_root.handlers = directory_handlers;
|
||||||
|
temp_mt_entry->mt_fs_root.ops = op_table;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
1087
c/src/libfs/src/dosfs/msdos_misc.c
Normal file
1087
c/src/libfs/src/dosfs/msdos_misc.c
Normal file
File diff suppressed because it is too large
Load Diff
90
c/src/libfs/src/dosfs/msdos_mknod.c
Normal file
90
c/src/libfs/src/dosfs/msdos_mknod.c
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Routine for node creation in MSDOS filesystem.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_mknod --
|
||||||
|
* The following function checks spelling and formats name for a new node,
|
||||||
|
* determines type of the node to be created and creates it.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* token - non-formatted name of a new node
|
||||||
|
* mode - node type
|
||||||
|
* dev - dev
|
||||||
|
* pathloc - parent directory description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on succes, or -1 if error occured and set errno
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_mknod(
|
||||||
|
const char *token,
|
||||||
|
mode_t mode,
|
||||||
|
dev_t dev,
|
||||||
|
rtems_filesystem_location_info_t *pathloc
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
if (S_ISDIR(mode))
|
||||||
|
{
|
||||||
|
type = MSDOS_DIRECTORY;
|
||||||
|
}
|
||||||
|
else if (S_ISREG(mode))
|
||||||
|
{
|
||||||
|
type = MSDOS_REGULAR_FILE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
set_errno_and_return_minus_one(EINVAL);
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/* Create an MSDOS node */
|
||||||
|
rc = msdos_creat_node(pathloc, type, new_name, mode);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
58
c/src/libfs/src/dosfs/msdos_node_type.c
Normal file
58
c/src/libfs/src/dosfs/msdos_node_type.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* The following returns the type of node that the loc refers to.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_node_type --
|
||||||
|
* Determine type of the node that the pathloc refers to.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathloc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* node type
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
rtems_filesystem_node_types_t
|
||||||
|
msdos_node_type(rtems_filesystem_location_info_t *pathloc)
|
||||||
|
{
|
||||||
|
fat_file_fd_t *fat_fd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we don't need to obtain the volume semaphore here because node_type_h
|
||||||
|
* call always follows evalpath_h call(hence link increment occured) and
|
||||||
|
* hence node_access memory can't be freed during processing node_type_h
|
||||||
|
* call
|
||||||
|
*/
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
return fat_fd->fat_file_type;
|
||||||
|
}
|
||||||
0
c/src/libfs/src/dosfs/stamp-h2.in
Normal file
0
c/src/libfs/src/dosfs/stamp-h2.in
Normal file
@@ -13,7 +13,9 @@ include $(top_srcdir)/../../../automake/lib.am
|
|||||||
|
|
||||||
IMFSLIB = ../src/imfs/$(ARCH)/libimfs.a
|
IMFSLIB = ../src/imfs/$(ARCH)/libimfs.a
|
||||||
|
|
||||||
TMP_LIBS = $(IMFSLIB)
|
DOSFSLIB = ../src/dosfs/$(ARCH)/libdosfs.a
|
||||||
|
|
||||||
|
TMP_LIBS = $(IMFSLIB) $(DOSFSLIB)
|
||||||
|
|
||||||
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB)
|
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB)
|
||||||
$(INSTALL_DATA) $< $@
|
$(INSTALL_DATA) $< $@
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
2002-02-28 Victor V. Vengerov <vvv@oktet.ru>
|
||||||
|
|
||||||
|
* DOS filesystem including FAT12, FAT16, and FAT32 support submitted.
|
||||||
|
* src/dosfs, src/dosfs/Makefile.am, src/dosfs/stamp-h2.in,
|
||||||
|
src/dosfs/config.h.in, src/dosfs/dosfs.h, src/dosfs/fat.c,
|
||||||
|
src/dosfs/fat.h, src/dosfs/fat_fat_operations.c,
|
||||||
|
src/dosfs/fat_fat_operations.h, src/dosfs/fat_file.c,
|
||||||
|
src/dosfs/fat_file.h, src/dosfs/msdos.h, src/dosfs/msdos_create.c,
|
||||||
|
src/dosfs/msdos_dir.c, src/dosfs/msdos_eval.c, src/dosfs/msdos_file.c,
|
||||||
|
src/dosfs/msdos_free.c, src/dosfs/msdos_fsunmount.c,
|
||||||
|
src/dosfs/msdos_handlers_dir.c, src/dosfs/msdos_handlers_file.c,
|
||||||
|
src/dosfs/msdos_init.c, src/dosfs/msdos_initsupp.c,
|
||||||
|
src/dosfs/msdos_misc.c, src/dosfs/msdos_mknod.c,
|
||||||
|
src/dosfs/msdos_node_type.c, src/dosfs/.cvsignore: New files.
|
||||||
|
* configure.ac, src/Makefile.am, wrapup/Makefile.am: Modified to
|
||||||
|
reflect addition.
|
||||||
|
|
||||||
2002-01-07 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
2002-01-07 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
||||||
|
|
||||||
* src/imfs/imfs_load_tar.c: Add include <sys/types.h>.
|
* src/imfs/imfs_load_tar.c: Add include <sys/types.h>.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
AC_PREREQ(2.52)
|
AC_PREREQ(2.52)
|
||||||
AC_INIT
|
AC_INIT
|
||||||
AC_CONFIG_SRCDIR([src/imfs/imfs.h])
|
AC_CONFIG_SRCDIR([src/imfs/imfs.h])
|
||||||
|
AC_CONFIG_SRCDIR([src/dosfs/dosfs.h])
|
||||||
RTEMS_TOP(../../..)
|
RTEMS_TOP(../../..)
|
||||||
AC_CONFIG_AUX_DIR(../../..)
|
AC_CONFIG_AUX_DIR(../../..)
|
||||||
|
|
||||||
@@ -27,11 +28,13 @@ RTEMS_CANONICALIZE_TOOLS
|
|||||||
|
|
||||||
AM_CONDITIONAL(UNIX,test x"$RTEMS_CPU" = x"unix")
|
AM_CONDITIONAL(UNIX,test x"$RTEMS_CPU" = x"unix")
|
||||||
AM_CONFIG_HEADER(src/imfs/config.h)
|
AM_CONFIG_HEADER(src/imfs/config.h)
|
||||||
|
AM_CONFIG_HEADER(src/dosfs/config.h)
|
||||||
|
|
||||||
# Explicitly list all Makefiles here
|
# Explicitly list all Makefiles here
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
src/imfs/Makefile
|
src/imfs/Makefile
|
||||||
|
src/dosfs/Makefile
|
||||||
wrapup/Makefile
|
wrapup/Makefile
|
||||||
])
|
])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
AUTOMAKE_OPTIONS = foreign 1.4
|
AUTOMAKE_OPTIONS = foreign 1.4
|
||||||
|
|
||||||
SUBDIRS = imfs
|
SUBDIRS = imfs dosfs
|
||||||
|
|
||||||
include $(top_srcdir)/../../../automake/subdirs.am
|
include $(top_srcdir)/../../../automake/subdirs.am
|
||||||
include $(top_srcdir)/../../../automake/local.am
|
include $(top_srcdir)/../../../automake/local.am
|
||||||
|
|||||||
6
cpukit/libfs/src/dosfs/.cvsignore
Normal file
6
cpukit/libfs/src/dosfs/.cvsignore
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
config.h
|
||||||
|
config.h.in
|
||||||
|
stamp-h
|
||||||
|
stamp-h.in
|
||||||
80
cpukit/libfs/src/dosfs/Makefile.am
Normal file
80
cpukit/libfs/src/dosfs/Makefile.am
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
##
|
||||||
|
## $Id$
|
||||||
|
##
|
||||||
|
|
||||||
|
AUTOMAKE_OPTIONS = foreign 1.4
|
||||||
|
|
||||||
|
INCLUDES = -I.
|
||||||
|
|
||||||
|
LIBNAME = libdosfs
|
||||||
|
LIB = ${ARCH}/${LIBNAME}.a
|
||||||
|
|
||||||
|
FATFS_C_FILES = fat.c fat_fat_operations.c fat_file.c
|
||||||
|
|
||||||
|
DOSFS_C_FILES = msdos_create.c msdos_dir.c msdos_eval.c msdos_file.c \
|
||||||
|
msdos_free.c msdos_fsunmount.c msdos_handlers_dir.c \
|
||||||
|
msdos_handlers_file.c msdos_init.c msdos_initsupp.c \
|
||||||
|
msdos_misc.c msdos_mknod.c msdos_node_type.c
|
||||||
|
|
||||||
|
|
||||||
|
UNIX_C_FILES = msdos_unixstub.c
|
||||||
|
|
||||||
|
EMBEDDED_C_FILES = $(FATFS_C_FILES) $(DOSFS_C_FILES)
|
||||||
|
|
||||||
|
COMMON_C_FILES =
|
||||||
|
|
||||||
|
if UNIX
|
||||||
|
C_FILES = $(COMMON_C_FILES) $(UNIX_C_FILES)
|
||||||
|
else
|
||||||
|
C_FILES = $(COMMON_C_FILES) $(EMBEDDED_C_FILES)
|
||||||
|
endif
|
||||||
|
C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o)
|
||||||
|
|
||||||
|
include_HEADERS = fat.h fat_fat_operations.h \
|
||||||
|
fat_file.h msdos.h dosfs.h
|
||||||
|
SYS_H_FILES =
|
||||||
|
RTEMS_H_FILES =
|
||||||
|
noinst_HEADERS =
|
||||||
|
|
||||||
|
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||||
|
include $(top_srcdir)/../../../automake/compile.am
|
||||||
|
include $(top_srcdir)/../../../automake/lib.am
|
||||||
|
|
||||||
|
PREINSTALL_FILES = $(PROJECT_INCLUDE) $(PROJECT_INCLUDE)/rtems \
|
||||||
|
$(PROJECT_INCLUDE)/sys $(include_HEADERS:%=$(PROJECT_INCLUDE)/%) \
|
||||||
|
$(RTEMS_H_FILES:%=$(PROJECT_INCLUDE)/rtems/%) \
|
||||||
|
$(SYS_H_FILES:%=$(PROJECT_INCLUDE)/sys/%)
|
||||||
|
|
||||||
|
$(PROJECT_INCLUDE):
|
||||||
|
@$(mkinstalldirs) $@
|
||||||
|
$(PROJECT_INCLUDE)/rtems:
|
||||||
|
@$(mkinstalldirs) $@
|
||||||
|
$(PROJECT_INCLUDE)/sys:
|
||||||
|
@$(mkinstalldirs) $@
|
||||||
|
|
||||||
|
$(PROJECT_INCLUDE)/%.h: %.h
|
||||||
|
$(INSTALL_DATA) $< $@
|
||||||
|
$(PROJECT_INCLUDE)/rtems/%.h: %.h
|
||||||
|
$(INSTALL_DATA) $< $@
|
||||||
|
$(PROJECT_INCLUDE)/sys/%.h: %.h
|
||||||
|
$(INSTALL_DATA) $< $@
|
||||||
|
|
||||||
|
OBJS = $(C_O_FILES)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add local stuff here using +=
|
||||||
|
#
|
||||||
|
|
||||||
|
AM_CFLAGS += $(LIBC_DEFINES)
|
||||||
|
|
||||||
|
all-local: ${ARCH} $(LIB)
|
||||||
|
|
||||||
|
$(LIB): ${OBJS}
|
||||||
|
$(make-library)
|
||||||
|
|
||||||
|
DOC_FILES =
|
||||||
|
|
||||||
|
EXTRA_DIST = $(DOC_FILES) $(COMMON_C_FILES) $(EMBEDDED_C_FILES) \
|
||||||
|
$(UNIX_C_FILES) $(RTEMS_H_FILES) $(SYS_H_FILES)
|
||||||
|
|
||||||
|
include $(top_srcdir)/../../../automake/local.am
|
||||||
31
cpukit/libfs/src/dosfs/dosfs.h
Normal file
31
cpukit/libfs/src/dosfs/dosfs.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* dosfs.h
|
||||||
|
*
|
||||||
|
* Application interface to MSDOS filesystem.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#ifndef __DOSFS_DOSFS_H__
|
||||||
|
#define __DOSFS_DOSFS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
|
||||||
|
extern rtems_filesystem_operations_table msdos_ops;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_DOSFS_H__ */
|
||||||
695
cpukit/libfs/src/dosfs/fat.c
Normal file
695
cpukit/libfs/src/dosfs/fat.c
Normal file
@@ -0,0 +1,695 @@
|
|||||||
|
/*
|
||||||
|
* fat.c
|
||||||
|
*
|
||||||
|
* Low-level operations on a volume with FAT filesystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
|
||||||
|
/* _fat_block_read --
|
||||||
|
* This function reads 'count' bytes from device filesystem is mounted on,
|
||||||
|
* starts at 'start+offset' position where 'start' computed in sectors
|
||||||
|
* and 'offset' is offset inside sector (reading may cross sectors
|
||||||
|
* boundary; in this case assumed we want to read sequential sector(s))
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* start - sector num to start read from
|
||||||
|
* offset - offset inside sector 'start'
|
||||||
|
* count - count of bytes to read
|
||||||
|
* buff - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* bytes read on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
_fat_block_read(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 offset,
|
||||||
|
unsigned32 count,
|
||||||
|
void *buff
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
ssize_t cmpltd = 0;
|
||||||
|
unsigned32 blk = start;
|
||||||
|
unsigned32 ofs = offset;
|
||||||
|
bdbuf_buffer *block = NULL;
|
||||||
|
unsigned32 c = 0;
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
c = MIN(count, (fs_info->vol.bps - ofs));
|
||||||
|
memcpy((buff + cmpltd), (block->buffer + ofs), c);
|
||||||
|
|
||||||
|
count -= c;
|
||||||
|
cmpltd += c;
|
||||||
|
blk++;
|
||||||
|
ofs = 0;
|
||||||
|
}
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _fat_block_write --
|
||||||
|
* This function write 'count' bytes to device filesystem is mounted on,
|
||||||
|
* starts at 'start+offset' position where 'start' computed in sectors
|
||||||
|
* and 'offset' is offset inside sector (writing may cross sectors
|
||||||
|
* boundary; in this case assumed we want to write sequential sector(s))
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* start - sector num to start read from
|
||||||
|
* offset - offset inside sector 'start'
|
||||||
|
* count - count of bytes to write
|
||||||
|
* buff - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* bytes written on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
_fat_block_write(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 offset,
|
||||||
|
unsigned32 count,
|
||||||
|
const void *buff)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
ssize_t cmpltd = 0;
|
||||||
|
unsigned32 blk = start;
|
||||||
|
unsigned32 ofs = offset;
|
||||||
|
bdbuf_buffer *block = NULL;
|
||||||
|
unsigned32 c = 0;
|
||||||
|
|
||||||
|
while(count > 0)
|
||||||
|
{
|
||||||
|
c = MIN(count, (fs_info->vol.bps - ofs));
|
||||||
|
|
||||||
|
if (c == fs_info->vol.bps)
|
||||||
|
rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_GET, &block);
|
||||||
|
else
|
||||||
|
rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
memcpy((block->buffer + ofs), (buff + cmpltd), c);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
|
||||||
|
count -= c;
|
||||||
|
cmpltd +=c;
|
||||||
|
blk++;
|
||||||
|
ofs = 0;
|
||||||
|
}
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* fat_cluster_read --
|
||||||
|
* wrapper for reading a whole cluster at once
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - number of cluster to read
|
||||||
|
* buff - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* bytes read on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
fat_cluster_read(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
void *buff
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 fsec = 0;
|
||||||
|
|
||||||
|
fsec = fat_cluster_num_to_sector_num(mt_entry, cln);
|
||||||
|
|
||||||
|
return _fat_block_read(mt_entry, fsec, 0,
|
||||||
|
fs_info->vol.spc << fs_info->vol.sec_log2, buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_cluster_write --
|
||||||
|
* wrapper for writting a whole cluster at once
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - number of cluster to write
|
||||||
|
* buff - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* bytes written on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
fat_cluster_write(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
const void *buff
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 fsec = 0;
|
||||||
|
|
||||||
|
fsec = fat_cluster_num_to_sector_num(mt_entry, cln);
|
||||||
|
|
||||||
|
return _fat_block_write(mt_entry, fsec, 0,
|
||||||
|
fs_info->vol.spc << fs_info->vol.sec_log2, buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_init_volume_info --
|
||||||
|
* Get inforamtion about volume on which filesystem is mounted on
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
register fat_vol_t *vol = &fs_info->vol;
|
||||||
|
unsigned32 data_secs = 0;
|
||||||
|
char boot_rec[FAT_MAX_BPB_SIZE];
|
||||||
|
char fs_info_sector[FAT_USEFUL_INFO_SIZE];
|
||||||
|
ssize_t ret = 0;
|
||||||
|
int fd;
|
||||||
|
struct stat stat_buf;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
rc = stat(mt_entry->dev, &stat_buf);
|
||||||
|
if (rc == -1)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* rtmes feature: no block devices, all are character devices */
|
||||||
|
if (!S_ISCHR(stat_buf.st_mode))
|
||||||
|
set_errno_and_return_minus_one(ENOTBLK);
|
||||||
|
|
||||||
|
/* check that device is registred as block device and lock it */
|
||||||
|
vol->dd = rtems_disk_lookup(stat_buf.st_dev);
|
||||||
|
if (vol->dd == NULL)
|
||||||
|
set_errno_and_return_minus_one(ENOTBLK);
|
||||||
|
|
||||||
|
vol->dev = stat_buf.st_dev;
|
||||||
|
|
||||||
|
fd = open(mt_entry->dev, O_RDONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = read(fd, (void *)boot_rec, FAT_MAX_BPB_SIZE);
|
||||||
|
if ( ret != FAT_MAX_BPB_SIZE )
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
vol->bps = FAT_BR_BYTES_PER_SECTOR(boot_rec);
|
||||||
|
|
||||||
|
if ( (vol->bps != 512) &&
|
||||||
|
(vol->bps != 1024) &&
|
||||||
|
(vol->bps != 2048) &&
|
||||||
|
(vol->bps != 4096))
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( EINVAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0;
|
||||||
|
i >>= 1, vol->sec_mul++);
|
||||||
|
for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0;
|
||||||
|
i >>= 1, vol->sec_log2++);
|
||||||
|
|
||||||
|
vol->spc = FAT_BR_SECTORS_PER_CLUSTER(boot_rec);
|
||||||
|
for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0;
|
||||||
|
i >>= 1, vol->spc_log2++);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* According to M$ White Paper "bytes per cluster" value
|
||||||
|
* greater than 32K is invalid
|
||||||
|
*/
|
||||||
|
if ((vol->bpc = vol->bps << vol->spc_log2) > MS_BYTES_PER_CLUSTER_LIMIT)
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0;
|
||||||
|
i >>= 1, vol->bpc_log2++);
|
||||||
|
|
||||||
|
vol->fats = FAT_BR_FAT_NUM(boot_rec);
|
||||||
|
vol->fat_loc = FAT_BR_RESERVED_SECTORS_NUM(boot_rec);
|
||||||
|
|
||||||
|
vol->rdir_entrs = FAT_BR_FILES_PER_ROOT_DIR(boot_rec);
|
||||||
|
|
||||||
|
/* calculate the count of sectors occupied by the root directory */
|
||||||
|
vol->rdir_secs = ((vol->rdir_entrs * FAT_DIRENTRY_SIZE) + (vol->bps - 1)) /
|
||||||
|
vol->bps;
|
||||||
|
|
||||||
|
vol->rdir_size = vol->rdir_secs << vol->sec_log2;
|
||||||
|
|
||||||
|
if ( (FAT_BR_SECTORS_PER_FAT(boot_rec)) != 0)
|
||||||
|
vol->fat_length = FAT_BR_SECTORS_PER_FAT(boot_rec);
|
||||||
|
else
|
||||||
|
vol->fat_length = FAT_BR_SECTORS_PER_FAT32(boot_rec);
|
||||||
|
|
||||||
|
vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length +
|
||||||
|
vol->rdir_secs;
|
||||||
|
|
||||||
|
/* for FAT12/16 root dir starts at(sector) */
|
||||||
|
vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length;
|
||||||
|
|
||||||
|
if ( (FAT_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0)
|
||||||
|
vol->tot_secs = FAT_BR_TOTAL_SECTORS_NUM16(boot_rec);
|
||||||
|
else
|
||||||
|
vol->tot_secs = FAT_BR_TOTAL_SECTORS_NUM32(boot_rec);
|
||||||
|
|
||||||
|
data_secs = vol->tot_secs - vol->data_fsec;
|
||||||
|
|
||||||
|
vol->data_cls = data_secs / vol->spc;
|
||||||
|
|
||||||
|
/* determine FAT type at least */
|
||||||
|
if ( vol->data_cls < FAT_FAT12_MAX_CLN)
|
||||||
|
{
|
||||||
|
vol->type = FAT_FAT12;
|
||||||
|
vol->mask = FAT_FAT12_MASK;
|
||||||
|
vol->eoc_val = FAT_FAT12_EOC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( vol->data_cls < FAT_FAT16_MAX_CLN)
|
||||||
|
{
|
||||||
|
vol->type = FAT_FAT16;
|
||||||
|
vol->mask = FAT_FAT16_MASK;
|
||||||
|
vol->eoc_val = FAT_FAT16_EOC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vol->type = FAT_FAT32;
|
||||||
|
vol->mask = FAT_FAT32_MASK;
|
||||||
|
vol->eoc_val = FAT_FAT32_EOC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vol->type == FAT_FAT32)
|
||||||
|
{
|
||||||
|
vol->rdir_cl = FAT_BR_FAT32_ROOT_CLUSTER(boot_rec);
|
||||||
|
|
||||||
|
vol->mirror = FAT_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR;
|
||||||
|
if (vol->mirror)
|
||||||
|
vol->afat = FAT_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM;
|
||||||
|
else
|
||||||
|
vol->afat = 0;
|
||||||
|
|
||||||
|
vol->info_sec = FAT_BR_FAT32_FS_INFO_SECTOR(boot_rec);
|
||||||
|
if( vol->info_sec == 0 )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( EINVAL );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = _fat_block_read(mt_entry, vol->info_sec , 0,
|
||||||
|
FAT_FSI_LEADSIG_SIZE, fs_info_sector);
|
||||||
|
if ( ret < 0 )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAT_FSINFO_LEAD_SIGNATURE(fs_info_sector) !=
|
||||||
|
FAT_FSINFO_LEAD_SIGNATURE_VALUE)
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( EINVAL );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = _fat_block_read(mt_entry, vol->info_sec , FAT_FSI_INFO,
|
||||||
|
FAT_USEFUL_INFO_SIZE, fs_info_sector);
|
||||||
|
if ( ret < 0 )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vol->free_cls = FAT_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector);
|
||||||
|
vol->next_cl = FAT_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector);
|
||||||
|
rc = fat_fat32_update_fsinfo_sector(mt_entry, 0xFFFFFFFF,
|
||||||
|
0xFFFFFFFF);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vol->rdir_cl = 0;
|
||||||
|
vol->mirror = 0;
|
||||||
|
vol->afat = 0;
|
||||||
|
vol->free_cls = 0xFFFFFFFF;
|
||||||
|
vol->next_cl = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat;
|
||||||
|
|
||||||
|
/* set up collection of fat-files fd */
|
||||||
|
fs_info->vhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control));
|
||||||
|
if ( fs_info->vhash == NULL )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < FAT_HASH_SIZE; i++)
|
||||||
|
_Chain_Initialize_empty(fs_info->vhash + i);
|
||||||
|
|
||||||
|
fs_info->rhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control));
|
||||||
|
if ( fs_info->rhash == NULL )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
free(fs_info->vhash);
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
for (i = 0; i < FAT_HASH_SIZE; i++)
|
||||||
|
_Chain_Initialize_empty(fs_info->rhash + i);
|
||||||
|
|
||||||
|
fs_info->uino_pool_size = FAT_UINO_POOL_INIT_SIZE;
|
||||||
|
fs_info->uino_base = (vol->tot_secs << vol->sec_mul) << 4;
|
||||||
|
fs_info->index = 0;
|
||||||
|
fs_info->uino = (char *)calloc(fs_info->uino_pool_size, sizeof(char));
|
||||||
|
if ( fs_info->uino == NULL )
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
free(fs_info->vhash);
|
||||||
|
free(fs_info->rhash);
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
fs_info->sec_buf = (char *)calloc(vol->bps, sizeof(char));
|
||||||
|
if (fs_info->sec_buf == NULL)
|
||||||
|
{
|
||||||
|
rtems_disk_release(vol->dd);
|
||||||
|
free(fs_info->vhash);
|
||||||
|
free(fs_info->rhash);
|
||||||
|
free(fs_info->uino);
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_shutdown_drive --
|
||||||
|
* Free all allocated resources and synchronize all necessary data
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_shutdown_drive(rtems_filesystem_mount_table_entry_t *mt_entry)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (fs_info->vol.type & FAT_FAT32)
|
||||||
|
{
|
||||||
|
rc = fat_fat32_update_fsinfo_sector(mt_entry, fs_info->vol.free_cls,
|
||||||
|
fs_info->vol.next_cl);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
|
||||||
|
if (rtems_bdbuf_syncdev(fs_info->vol.dev) != RTEMS_SUCCESSFUL)
|
||||||
|
rc = -1;
|
||||||
|
|
||||||
|
for (i = 0; i < FAT_HASH_SIZE; i++)
|
||||||
|
{
|
||||||
|
Chain_Node *node = NULL;
|
||||||
|
Chain_Control *the_chain = fs_info->vhash + i;
|
||||||
|
|
||||||
|
while ( (node = _Chain_Get(the_chain)) != NULL )
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < FAT_HASH_SIZE; i++)
|
||||||
|
{
|
||||||
|
Chain_Node *node = NULL;
|
||||||
|
Chain_Control *the_chain = fs_info->rhash + i;
|
||||||
|
|
||||||
|
while ( (node = _Chain_Get(the_chain)) != NULL )
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fs_info->vhash);
|
||||||
|
free(fs_info->rhash);
|
||||||
|
|
||||||
|
free(fs_info->uino);
|
||||||
|
free(fs_info->sec_buf);
|
||||||
|
rtems_disk_release(fs_info->vol.dd);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
errno = EIO;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_init_clusters_chain --
|
||||||
|
* Zeroing contents of all clusters in the chain
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* start_cluster_num - num of first cluster in the chain
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_init_clusters_chain(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start_cln
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
ssize_t ret = 0;
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = start_cln;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
buf = calloc(fs_info->vol.bpc, sizeof(char));
|
||||||
|
if ( buf == NULL )
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
||||||
|
{
|
||||||
|
ret = fat_cluster_write(mt_entry, cur_cln, buf);
|
||||||
|
if ( ret == -1 )
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FAT_UNIQ_INO_BASE 0x0FFFFF00
|
||||||
|
|
||||||
|
#define FAT_UNIQ_INO_IS_BUSY(index, arr) \
|
||||||
|
(((arr)[((index)>>3)]>>((index) & (8-1))) & 0x01)
|
||||||
|
|
||||||
|
#define FAT_SET_UNIQ_INO_BUSY(index, arr) \
|
||||||
|
((arr)[((index)>>3)] |= (0x01<<((index) & (8-1))))
|
||||||
|
|
||||||
|
#define FAT_SET_UNIQ_INO_FREE(index, arr) \
|
||||||
|
((arr)[((index)>>3)] &= (~(0x01<<((index) & (8-1)))))
|
||||||
|
|
||||||
|
/* fat_get_unique_ino --
|
||||||
|
* Allocate unique ino from unique ino pool
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* unique inode number on success, or 0 if there is no free unique inode
|
||||||
|
* number in the pool
|
||||||
|
*
|
||||||
|
* ATTENTION:
|
||||||
|
* 0 means FAILED !!!
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
unsigned32
|
||||||
|
fat_get_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry)
|
||||||
|
{
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 j = 0;
|
||||||
|
rtems_boolean resrc_unsuff = FALSE;
|
||||||
|
|
||||||
|
while (!resrc_unsuff)
|
||||||
|
{
|
||||||
|
for (j = 0; j < fs_info->uino_pool_size; j++)
|
||||||
|
{
|
||||||
|
if (!FAT_UNIQ_INO_IS_BUSY(fs_info->index, fs_info->uino))
|
||||||
|
{
|
||||||
|
FAT_SET_UNIQ_INO_BUSY(fs_info->index, fs_info->uino);
|
||||||
|
return (fs_info->uino_base + fs_info->index);
|
||||||
|
}
|
||||||
|
fs_info->index++;
|
||||||
|
if (fs_info->index >= fs_info->uino_pool_size)
|
||||||
|
fs_info->index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fs_info->uino_pool_size << 1) < (0x0FFFFFFF - fs_info->uino_base))
|
||||||
|
{
|
||||||
|
fs_info->uino_pool_size <<= 1;
|
||||||
|
fs_info->uino = realloc(fs_info->uino, fs_info->uino_pool_size);
|
||||||
|
if (fs_info->uino != NULL)
|
||||||
|
fs_info->index = fs_info->uino_pool_size;
|
||||||
|
else
|
||||||
|
resrc_unsuff = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
resrc_unsuff = TRUE;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_free_unique_ino --
|
||||||
|
* Return unique ino to unique ino pool
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* ino - inode number to free
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fat_free_unique_ino(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 ino
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
|
||||||
|
FAT_SET_UNIQ_INO_FREE((ino - fs_info->uino_base), fs_info->uino);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_ino_is_unique --
|
||||||
|
* Test whether ino is from unique ino pool
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* ino - ino to be tested
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* TRUE if ino is allocated from unique ino pool, FALSE otherwise
|
||||||
|
*/
|
||||||
|
inline rtems_boolean
|
||||||
|
fat_ino_is_unique(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 ino
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
|
||||||
|
return (ino >= fs_info->uino_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_fat32_update_fsinfo_sector --
|
||||||
|
* Synchronize fsinfo sector for FAT32 volumes
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* free_count - count of free clusters
|
||||||
|
* next_free - the next free cluster num
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_fat32_update_fsinfo_sector(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 free_count,
|
||||||
|
unsigned32 next_free
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ssize_t ret1 = 0, ret2 = 0;
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 le_free_count = 0;
|
||||||
|
unsigned32 le_next_free = 0;
|
||||||
|
|
||||||
|
le_free_count = CT_LE_L(free_count);
|
||||||
|
le_next_free = CT_LE_L(next_free);
|
||||||
|
|
||||||
|
ret1 = _fat_block_write(mt_entry,
|
||||||
|
fs_info->vol.info_sec,
|
||||||
|
FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET,
|
||||||
|
4,
|
||||||
|
(char *)(&le_free_count));
|
||||||
|
|
||||||
|
ret2 = _fat_block_write(mt_entry,
|
||||||
|
fs_info->vol.info_sec,
|
||||||
|
FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET,
|
||||||
|
4,
|
||||||
|
(char *)(&le_next_free));
|
||||||
|
|
||||||
|
if ( (ret1 < 0) || (ret2 < 0) )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
489
cpukit/libfs/src/dosfs/fat.h
Normal file
489
cpukit/libfs/src/dosfs/fat.h
Normal file
@@ -0,0 +1,489 @@
|
|||||||
|
/*
|
||||||
|
* fat.h
|
||||||
|
*
|
||||||
|
* Constants/data structures/prototypes for low-level operations on a volume
|
||||||
|
* with FAT filesystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DOSFS_FAT_H__
|
||||||
|
#define __DOSFS_FAT_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems/seterr.h>
|
||||||
|
|
||||||
|
/* XXX: temporary hack :(( */
|
||||||
|
#ifndef set_errno_and_return_minus_one
|
||||||
|
#define set_errno_and_return_minus_one rtems_set_errno_and_return_minus_one
|
||||||
|
#endif /* set_errno_and_return_minus_one */
|
||||||
|
|
||||||
|
#include <rtems/score/cpu.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <rtems/bdbuf.h>
|
||||||
|
|
||||||
|
#define DBG1(x) x
|
||||||
|
#define DBG2(x) x
|
||||||
|
|
||||||
|
#ifndef RC_OK
|
||||||
|
#define RC_OK 0x00000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remember that all FAT file system on disk data structure is
|
||||||
|
* "little endian"!
|
||||||
|
* (derived from linux)
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Conversion from and to little-endian byte order. (no-op on i386/i486)
|
||||||
|
*
|
||||||
|
* Naming: Ca_b_c, where a: F = from, T = to, b: LE = little-endian,
|
||||||
|
* BE = big-endian, c: W = word (16 bits), L = longword (32 bits)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (CPU_BIG_ENDIAN == TRUE)
|
||||||
|
# define CF_LE_W(v) CPU_swap_u16(v)
|
||||||
|
# define CF_LE_L(v) CPU_swap_u32(v)
|
||||||
|
# define CT_LE_W(v) CPU_swap_u16(v)
|
||||||
|
# define CT_LE_L(v) CPU_swap_u32(v)
|
||||||
|
#else
|
||||||
|
# define CF_LE_W(v) (v)
|
||||||
|
# define CF_LE_L(v) (v)
|
||||||
|
# define CT_LE_W(v) (v)
|
||||||
|
# define CT_LE_L(v) (v)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
#define FAT_HASH_SIZE 2
|
||||||
|
#define FAT_HASH_MODULE FAT_HASH_SIZE
|
||||||
|
|
||||||
|
|
||||||
|
#define FAT_SECTOR512_SIZE 512 /* sector size (bytes) */
|
||||||
|
#define FAT_SECTOR512_BITS 9 /* log2(SECTOR_SIZE) */
|
||||||
|
|
||||||
|
/* maximum + 1 number of clusters for FAT12 */
|
||||||
|
#define FAT_FAT12_MAX_CLN 4085
|
||||||
|
|
||||||
|
/* maximum + 1 number of clusters for FAT16 */
|
||||||
|
#define FAT_FAT16_MAX_CLN 65525
|
||||||
|
|
||||||
|
#define FAT_FAT12 0x01
|
||||||
|
#define FAT_FAT16 0x02
|
||||||
|
#define FAT_FAT32 0x04
|
||||||
|
|
||||||
|
#define FAT_UNDEFINED_VALUE 0xFFFFFFFF
|
||||||
|
|
||||||
|
#define FAT_FAT12_EOC 0x0FFF
|
||||||
|
#define FAT_FAT16_EOC 0xFFFF
|
||||||
|
#define FAT_FAT32_EOC 0x0FFFFFFF
|
||||||
|
|
||||||
|
#define FAT_FAT12_FREE 0x0000
|
||||||
|
#define FAT_FAT16_FREE 0x0000
|
||||||
|
#define FAT_FAT32_FREE 0x00000000
|
||||||
|
|
||||||
|
#define FAT_GENFAT_EOC 0xFFFFFFFF
|
||||||
|
#define FAT_GENFAT_FREE 0x00000000
|
||||||
|
|
||||||
|
#define FAT_FAT12_SHIFT 0x04
|
||||||
|
|
||||||
|
#define FAT_FAT12_MASK 0x00000FFF
|
||||||
|
#define FAT_FAT16_MASK 0x0000FFFF
|
||||||
|
#define FAT_FAT32_MASK 0x0FFFFFFF
|
||||||
|
|
||||||
|
#define FAT_MAX_BPB_SIZE 90
|
||||||
|
|
||||||
|
/* size of useful information in FSInfo sector */
|
||||||
|
#define FAT_USEFUL_INFO_SIZE 12
|
||||||
|
|
||||||
|
#define FAT_VAL8(x, ofs) (unsigned8)(*((unsigned8 *)(x) + (ofs)))
|
||||||
|
|
||||||
|
#define FAT_VAL16(x, ofs) \
|
||||||
|
(unsigned16)( (*((unsigned8 *)(x) + (ofs))) | \
|
||||||
|
((*((unsigned8 *)(x) + (ofs) + 1)) << 8) )
|
||||||
|
|
||||||
|
#define FAT_VAL32(x, ofs) \
|
||||||
|
(unsigned32)( (*((unsigned8 *)(x) + (ofs))) | \
|
||||||
|
((*((unsigned8 *)(x) + (ofs) + 1)) << 8) | \
|
||||||
|
((*((unsigned8 *)(x) + (ofs) + 2)) << 16) | \
|
||||||
|
((*((unsigned8 *)(x) + (ofs) + 3)) << 24) )
|
||||||
|
|
||||||
|
/* macros to access boot sector fields */
|
||||||
|
#define FAT_BR_BYTES_PER_SECTOR(x) FAT_VAL16(x, 11)
|
||||||
|
#define FAT_BR_SECTORS_PER_CLUSTER(x) FAT_VAL8(x, 13)
|
||||||
|
#define FAT_BR_RESERVED_SECTORS_NUM(x) FAT_VAL16(x, 14)
|
||||||
|
#define FAT_BR_FAT_NUM(x) FAT_VAL8(x, 16)
|
||||||
|
#define FAT_BR_FILES_PER_ROOT_DIR(x) FAT_VAL16(x, 17)
|
||||||
|
#define FAT_BR_TOTAL_SECTORS_NUM16(x) FAT_VAL16(x, 19)
|
||||||
|
#define FAT_BR_MEDIA(x) FAT_VAL8(x, 21)
|
||||||
|
#define FAT_BR_SECTORS_PER_FAT(x) FAT_VAL16(x, 22)
|
||||||
|
#define FAT_BR_TOTAL_SECTORS_NUM32(x) FAT_VAL32(x, 32)
|
||||||
|
#define FAT_BR_SECTORS_PER_FAT32(x) FAT_VAL32(x, 36)
|
||||||
|
#define FAT_BR_EXT_FLAGS(x) FAT_VAL16(x, 40)
|
||||||
|
#define FAT_BR_FAT32_ROOT_CLUSTER(x) FAT_VAL32(x, 44)
|
||||||
|
#define FAT_BR_FAT32_FS_INFO_SECTOR(x) FAT_VAL16(x, 48)
|
||||||
|
#define FAT_FSINFO_LEAD_SIGNATURE(x) FAT_VAL32(x, 0)
|
||||||
|
/*
|
||||||
|
* I read FSInfo sector from offset 484 to access the information, so offsets
|
||||||
|
* of these fields a relative
|
||||||
|
*/
|
||||||
|
#define FAT_FSINFO_FREE_CLUSTER_COUNT(x) FAT_VAL32(x, 4)
|
||||||
|
#define FAT_FSINFO_NEXT_FREE_CLUSTER(x) FAT_VAL32(x, 8)
|
||||||
|
|
||||||
|
#define FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET 488
|
||||||
|
|
||||||
|
#define FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET 492
|
||||||
|
|
||||||
|
#define FAT_RSRVD_CLN 0x02
|
||||||
|
|
||||||
|
#define FAT_FSINFO_LEAD_SIGNATURE_VALUE 0x41615252
|
||||||
|
|
||||||
|
#define FAT_FSI_LEADSIG_SIZE 0x04
|
||||||
|
|
||||||
|
#define FAT_FSI_INFO 484
|
||||||
|
|
||||||
|
#define MS_BYTES_PER_CLUSTER_LIMIT 0x8000 /* 32K */
|
||||||
|
|
||||||
|
#define FAT_BR_EXT_FLAGS_MIRROR 0x0080
|
||||||
|
|
||||||
|
#define FAT_BR_EXT_FLAGS_FAT_NUM 0x000F
|
||||||
|
|
||||||
|
|
||||||
|
#define FAT_DIRENTRY_SIZE 32
|
||||||
|
|
||||||
|
#define FAT_DIRENTRIES_PER_SEC512 16
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Volume descriptor
|
||||||
|
* Description of the volume the FAT filesystem is located on - generally
|
||||||
|
* the fields of the structure corresponde to Boot Sector and BPB Srtucture
|
||||||
|
* (see M$ White Paper) fields
|
||||||
|
*/
|
||||||
|
typedef struct fat_vol_s
|
||||||
|
{
|
||||||
|
unsigned16 bps; /* bytes per sector */
|
||||||
|
unsigned8 sec_log2; /* log2 of bps */
|
||||||
|
unsigned8 sec_mul; /* log2 of 512bts sectors number per sector */
|
||||||
|
unsigned8 spc; /* sectors per cluster */
|
||||||
|
unsigned8 spc_log2; /* log2 of spc */
|
||||||
|
unsigned16 bpc; /* bytes per cluster */
|
||||||
|
unsigned8 bpc_log2; /* log2 of bytes per cluster */
|
||||||
|
unsigned8 fats; /* number of FATs */
|
||||||
|
unsigned8 type; /* FAT type */
|
||||||
|
unsigned32 mask;
|
||||||
|
unsigned32 eoc_val;
|
||||||
|
unsigned16 fat_loc; /* FAT start */
|
||||||
|
unsigned32 fat_length; /* sectors per FAT */
|
||||||
|
unsigned32 rdir_loc; /* root directory start */
|
||||||
|
unsigned16 rdir_entrs; /* files per root directory */
|
||||||
|
unsigned32 rdir_secs; /* sectors per root directory */
|
||||||
|
unsigned32 rdir_size; /* root directory size in bytes */
|
||||||
|
unsigned32 tot_secs; /* total count of sectors */
|
||||||
|
unsigned32 data_fsec; /* first data sector */
|
||||||
|
unsigned32 data_cls; /* count of data clusters */
|
||||||
|
unsigned32 rdir_cl; /* first cluster of the root directory */
|
||||||
|
unsigned16 info_sec; /* FSInfo Sector Structure location */
|
||||||
|
unsigned32 free_cls; /* last known free clusters count */
|
||||||
|
unsigned32 next_cl; /* next free cluster number */
|
||||||
|
unsigned8 mirror; /* mirroring enabla/disable */
|
||||||
|
unsigned32 afat_loc; /* active FAT location */
|
||||||
|
unsigned8 afat; /* the number of active FAT */
|
||||||
|
dev_t dev; /* device ID */
|
||||||
|
disk_device *dd; /* disk device (see libblock) */
|
||||||
|
void *private_data; /* reserved */
|
||||||
|
} fat_vol_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct fat_cache_s
|
||||||
|
{
|
||||||
|
unsigned32 blk_num;
|
||||||
|
rtems_boolean modified;
|
||||||
|
unsigned8 state;
|
||||||
|
bdbuf_buffer *buf;
|
||||||
|
} fat_cache_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This structure identifies the instance of the filesystem on the FAT
|
||||||
|
* ("fat-file") level.
|
||||||
|
*/
|
||||||
|
typedef struct fat_fs_info_s
|
||||||
|
{
|
||||||
|
fat_vol_t vol; /* volume descriptor */
|
||||||
|
Chain_Control *vhash; /* "vhash" of fat-file descriptors */
|
||||||
|
Chain_Control *rhash; /* "rhash" of fat-file descriptors */
|
||||||
|
char *uino; /* array of unique ino numbers */
|
||||||
|
unsigned32 index;
|
||||||
|
unsigned32 uino_pool_size; /* size */
|
||||||
|
unsigned32 uino_base;
|
||||||
|
fat_cache_t c; /* cache */
|
||||||
|
unsigned8 *sec_buf; /* just placeholder for anything */
|
||||||
|
} 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
|
||||||
|
*/
|
||||||
|
typedef struct fat_auxiliary_s
|
||||||
|
{
|
||||||
|
unsigned32 cln;
|
||||||
|
unsigned32 ofs;
|
||||||
|
} fat_auxiliary_t;
|
||||||
|
|
||||||
|
#define FAT_FAT_OFFSET(fat_type, cln) \
|
||||||
|
((fat_type) & FAT_FAT12 ? ((cln) + ((cln) >> 1)) : \
|
||||||
|
(fat_type) & FAT_FAT16 ? ((cln) << 1) : \
|
||||||
|
((cln) << 2))
|
||||||
|
|
||||||
|
#define FAT_CLUSTER_IS_ODD(n) ((n) & 0x0001)
|
||||||
|
|
||||||
|
#define FAT12_SHIFT 0x4 /* half of a byte */
|
||||||
|
|
||||||
|
/* initial size of array of unique ino */
|
||||||
|
#define FAT_UINO_POOL_INIT_SIZE 0x100
|
||||||
|
|
||||||
|
/* cache support */
|
||||||
|
#define FAT_CACHE_EMPTY 0x0
|
||||||
|
#define FAT_CACHE_ACTUAL 0x1
|
||||||
|
|
||||||
|
#define FAT_OP_TYPE_READ 0x1
|
||||||
|
#define FAT_OP_TYPE_GET 0x2
|
||||||
|
|
||||||
|
static inline unsigned32
|
||||||
|
fat_cluster_num_to_sector_num(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln
|
||||||
|
)
|
||||||
|
{
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
|
||||||
|
if ( (cln == 0) && (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)) )
|
||||||
|
return fs_info->vol.rdir_loc;
|
||||||
|
|
||||||
|
return (((cln - FAT_RSRVD_CLN) << fs_info->vol.spc_log2) +
|
||||||
|
fs_info->vol.data_fsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned32
|
||||||
|
fat_cluster_num_to_sector512_num(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
|
||||||
|
if (cln == 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return (fat_cluster_num_to_sector_num(mt_entry, cln) <<
|
||||||
|
fs_info->vol.sec_mul);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
fat_buf_access(fat_fs_info_t *fs_info, unsigned32 blk, int op_type,
|
||||||
|
bdbuf_buffer **buf)
|
||||||
|
{
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
unsigned8 i;
|
||||||
|
rtems_boolean sec_of_fat;
|
||||||
|
|
||||||
|
|
||||||
|
if (fs_info->c.state == FAT_CACHE_EMPTY)
|
||||||
|
{
|
||||||
|
if (op_type == FAT_OP_TYPE_READ)
|
||||||
|
sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
|
||||||
|
else
|
||||||
|
sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
fs_info->c.blk_num = blk;
|
||||||
|
fs_info->c.state = FAT_CACHE_ACTUAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
|
||||||
|
(fs_info->c.blk_num < fs_info->vol.rdir_loc));
|
||||||
|
|
||||||
|
if (fs_info->c.blk_num != blk)
|
||||||
|
{
|
||||||
|
if (fs_info->c.modified)
|
||||||
|
{
|
||||||
|
if (sec_of_fat && !fs_info->vol.mirror)
|
||||||
|
memcpy(fs_info->sec_buf, fs_info->c.buf->buffer,
|
||||||
|
fs_info->vol.bps);
|
||||||
|
|
||||||
|
sc = rtems_bdbuf_release_modified(fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
fs_info->c.modified = 0;
|
||||||
|
|
||||||
|
if (sec_of_fat && !fs_info->vol.mirror)
|
||||||
|
{
|
||||||
|
bdbuf_buffer *b;
|
||||||
|
|
||||||
|
for (i = 1; i < fs_info->vol.fats; i++)
|
||||||
|
{
|
||||||
|
sc = rtems_bdbuf_get(fs_info->vol.dev,
|
||||||
|
fs_info->c.blk_num +
|
||||||
|
fs_info->vol.fat_length * i,
|
||||||
|
&b);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
|
||||||
|
sc = rtems_bdbuf_release_modified(b);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sc = rtems_bdbuf_release(fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (op_type == FAT_OP_TYPE_READ)
|
||||||
|
sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
|
||||||
|
else
|
||||||
|
sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
fs_info->c.blk_num = blk;
|
||||||
|
}
|
||||||
|
*buf = fs_info->c.buf;
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
fat_buf_release(fat_fs_info_t *fs_info)
|
||||||
|
{
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
unsigned8 i;
|
||||||
|
rtems_boolean sec_of_fat;
|
||||||
|
|
||||||
|
if (fs_info->c.state == FAT_CACHE_EMPTY)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
|
||||||
|
(fs_info->c.blk_num < fs_info->vol.rdir_loc));
|
||||||
|
|
||||||
|
if (fs_info->c.modified)
|
||||||
|
{
|
||||||
|
if (sec_of_fat && !fs_info->vol.mirror)
|
||||||
|
memcpy(fs_info->sec_buf, fs_info->c.buf->buffer, fs_info->vol.bps);
|
||||||
|
|
||||||
|
sc = rtems_bdbuf_release_modified(fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
fs_info->c.modified = 0;
|
||||||
|
|
||||||
|
if (sec_of_fat && !fs_info->vol.mirror)
|
||||||
|
{
|
||||||
|
bdbuf_buffer *b;
|
||||||
|
|
||||||
|
for (i = 1; i < fs_info->vol.fats; i++)
|
||||||
|
{
|
||||||
|
sc = rtems_bdbuf_get(fs_info->vol.dev,
|
||||||
|
fs_info->c.blk_num +
|
||||||
|
fs_info->vol.fat_length * i,
|
||||||
|
&b);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
|
||||||
|
sc = rtems_bdbuf_release_modified(b);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sc = rtems_bdbuf_release(fs_info->c.buf);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
}
|
||||||
|
fs_info->c.state = FAT_CACHE_EMPTY;
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
fat_buf_mark_modified(fat_fs_info_t *fs_info)
|
||||||
|
{
|
||||||
|
fs_info->c.modified = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
_fat_block_read(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 offset,
|
||||||
|
unsigned32 count,
|
||||||
|
void *buff);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
_fat_block_write(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 offset,
|
||||||
|
unsigned32 count,
|
||||||
|
const void *buff);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
fat_cluster_read(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
void *buff);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
fat_cluster_write(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
const void *buff);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_init_clusters_chain(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 start_cln);
|
||||||
|
|
||||||
|
unsigned32
|
||||||
|
fat_cluster_num_to_sector_num(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_shutdown_drive(rtems_filesystem_mount_table_entry_t *mt_entry);
|
||||||
|
|
||||||
|
|
||||||
|
unsigned32
|
||||||
|
fat_get_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry);
|
||||||
|
|
||||||
|
rtems_boolean
|
||||||
|
fat_ino_is_unique(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 ino);
|
||||||
|
|
||||||
|
void
|
||||||
|
fat_free_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 ino);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_fat32_update_fsinfo_sector(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 free_count,
|
||||||
|
unsigned32 next_free
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_FAT_H__ */
|
||||||
445
cpukit/libfs/src/dosfs/fat_fat_operations.c
Normal file
445
cpukit/libfs/src/dosfs/fat_fat_operations.c
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
/*
|
||||||
|
* fat_fat_operations.c
|
||||||
|
*
|
||||||
|
* General operations on File Allocation Table
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
|
||||||
|
/* fat_scan_fat_for_free_clusters --
|
||||||
|
* Allocate chain of free clusters from Files Allocation Table
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* chain - the number of the first allocated cluster (first cluster
|
||||||
|
* in the chain)
|
||||||
|
* count - count of clusters to allocate (chain length)
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or error code if error occured (errno set
|
||||||
|
* appropriately)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_scan_fat_for_free_clusters(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 *chain,
|
||||||
|
unsigned32 count,
|
||||||
|
unsigned32 *cls_added,
|
||||||
|
unsigned32 *last_cl
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cl4find = 2;
|
||||||
|
unsigned32 next_cln = 0;
|
||||||
|
unsigned32 save_cln = 0;
|
||||||
|
unsigned32 data_cls_val = fs_info->vol.data_cls + 2;
|
||||||
|
unsigned32 i = 2;
|
||||||
|
|
||||||
|
*cls_added = 0;
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if ((fs_info->vol.type & FAT_FAT32) &&
|
||||||
|
(fs_info->vol.next_cl != FAT_UNDEFINED_VALUE))
|
||||||
|
cl4find = fs_info->vol.next_cl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fs_info->vol.data_cls is exactly the count of data clusters
|
||||||
|
* starting at cluster 2, so the maximum valid cluster number is
|
||||||
|
* (fs_info->vol.data_cls + 1)
|
||||||
|
*/
|
||||||
|
while (i < data_cls_val)
|
||||||
|
{
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cl4find, &next_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
if (*cls_added != 0)
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, (*chain));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((next_cln & fs_info->vol.mask) == FAT_GENFAT_FREE)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We are enforced to process allocation of the first free cluster
|
||||||
|
* by separate 'if' statement because otherwise undo function
|
||||||
|
* wouldn't work properly
|
||||||
|
*/
|
||||||
|
if (*cls_added == 0)
|
||||||
|
{
|
||||||
|
*chain = cl4find;
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_EOC);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* this is the first cluster we tried to allocate so no
|
||||||
|
* cleanup activity needed
|
||||||
|
*/
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* set EOC value to new allocated cluster */
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_EOC);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
/* cleanup activity */
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, (*chain));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, save_cln, cl4find);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
/* cleanup activity */
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, (*chain));
|
||||||
|
/* trying to save last allocated cluster for future use */
|
||||||
|
fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_FREE);
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
save_cln = cl4find;
|
||||||
|
(*cls_added)++;
|
||||||
|
|
||||||
|
/* have we satisfied request ? */
|
||||||
|
if (*cls_added == count)
|
||||||
|
{
|
||||||
|
if (fs_info->vol.type & FAT_FAT32)
|
||||||
|
{
|
||||||
|
fs_info->vol.next_cl = save_cln;
|
||||||
|
if (fs_info->vol.free_cls != 0xFFFFFFFF)
|
||||||
|
fs_info->vol.free_cls -= (*cls_added);
|
||||||
|
}
|
||||||
|
*last_cl = save_cln;
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
cl4find++;
|
||||||
|
if (cl4find >= data_cls_val)
|
||||||
|
cl4find = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs_info->vol.type & FAT_FAT32)
|
||||||
|
{
|
||||||
|
fs_info->vol.next_cl = save_cln;
|
||||||
|
if (fs_info->vol.free_cls != 0xFFFFFFFF)
|
||||||
|
fs_info->vol.free_cls -= (*cls_added);
|
||||||
|
}
|
||||||
|
*last_cl = save_cln;
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_free_fat_clusters_chain --
|
||||||
|
* Free chain of clusters in Files Allocation Table.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* chain - number of the first cluster in the chain
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_free_fat_clusters_chain(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 chain
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK, rc1 = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = chain;
|
||||||
|
unsigned32 next_cln = 0;
|
||||||
|
unsigned32 freed_cls_cnt = 0;
|
||||||
|
|
||||||
|
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
||||||
|
{
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &next_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
if ((fs_info->vol.type & FAT_FAT32) &&
|
||||||
|
(fs_info->vol.free_cls != FAT_UNDEFINED_VALUE))
|
||||||
|
fs_info->vol.free_cls += freed_cls_cnt;
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, cur_cln, FAT_GENFAT_FREE);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
rc1 = rc;
|
||||||
|
|
||||||
|
freed_cls_cnt++;
|
||||||
|
cur_cln = next_cln;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs_info->vol.type & FAT_FAT32)
|
||||||
|
{
|
||||||
|
fs_info->vol.next_cl = chain;
|
||||||
|
if (fs_info->vol.free_cls != FAT_UNDEFINED_VALUE)
|
||||||
|
fs_info->vol.free_cls += freed_cls_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
if (rc1 != RC_OK)
|
||||||
|
return rc1;
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_get_fat_cluster --
|
||||||
|
* Fetches the contents of the cluster (link to next cluster in the chain)
|
||||||
|
* from Files Allocation Table.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - number of cluster to fetch the contents from
|
||||||
|
* ret_val - contents of the cluster 'cln' (link to next cluster in
|
||||||
|
* the chain)
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_get_fat_cluster(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 *ret_val
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
register fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
bdbuf_buffer *block0 = NULL;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 ofs = 0;
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
|
||||||
|
fs_info->vol.afat_loc;
|
||||||
|
ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
switch ( fs_info->vol.type )
|
||||||
|
{
|
||||||
|
case FAT_FAT12:
|
||||||
|
/*
|
||||||
|
* we are enforced in complex computations for FAT12 to escape CPU
|
||||||
|
* align problems for some architectures
|
||||||
|
*/
|
||||||
|
*ret_val = (*((unsigned8 *)(block0->buffer + ofs)));
|
||||||
|
if ( ofs == (fs_info->vol.bps - 1) )
|
||||||
|
{
|
||||||
|
rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
|
||||||
|
&block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*ret_val |= (*((unsigned8 *)(block0->buffer)))<<8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ret_val |= (*((unsigned8 *)(block0->buffer + ofs + 1)))<<8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( FAT_CLUSTER_IS_ODD(cln) )
|
||||||
|
*ret_val = (*ret_val) >> FAT12_SHIFT;
|
||||||
|
else
|
||||||
|
*ret_val = (*ret_val) & FAT_FAT12_MASK;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT_FAT16:
|
||||||
|
*ret_val = *((unsigned16 *)(block0->buffer + ofs));
|
||||||
|
*ret_val = CF_LE_W(*ret_val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT_FAT32:
|
||||||
|
*ret_val = *((unsigned32 *)(block0->buffer + ofs));
|
||||||
|
*ret_val = CF_LE_L(*ret_val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_set_fat_cluster --
|
||||||
|
* Set the contents of the cluster (link to next cluster in the chain)
|
||||||
|
* from Files Allocation Table.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - number of cluster to set contents to
|
||||||
|
* in_val - value to set
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_set_fat_cluster(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 in_val
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 ofs = 0;
|
||||||
|
unsigned16 fat16_clv = 0;
|
||||||
|
unsigned32 fat32_clv = 0;
|
||||||
|
bdbuf_buffer *block0 = NULL;
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
|
||||||
|
fs_info->vol.afat_loc;
|
||||||
|
ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
switch ( fs_info->vol.type )
|
||||||
|
{
|
||||||
|
case FAT_FAT12:
|
||||||
|
if ( FAT_CLUSTER_IS_ODD(cln) )
|
||||||
|
{
|
||||||
|
fat16_clv = CT_LE_W((((unsigned16)in_val) << FAT_FAT12_SHIFT));
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs))) & 0x0F;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs))) |
|
||||||
|
(unsigned8)(fat16_clv & 0x00FF);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
|
||||||
|
if ( ofs == (fs_info->vol.bps - 1) )
|
||||||
|
{
|
||||||
|
rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
|
||||||
|
&block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer)) &= 0x00;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer))) |
|
||||||
|
(unsigned8)((fat16_clv & 0xFF00)>>8);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs + 1)) &= 0x00;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs + 1)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs + 1))) |
|
||||||
|
(unsigned8)((fat16_clv & 0xFF00)>>8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fat16_clv = CT_LE_W((((unsigned16)in_val) & FAT_FAT12_MASK));
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs)) &= 0x00;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs))) |
|
||||||
|
(unsigned8)(fat16_clv & 0x00FF);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
|
||||||
|
if ( ofs == (fs_info->vol.bps - 1) )
|
||||||
|
{
|
||||||
|
rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
|
||||||
|
&block0);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer))) & 0xF0;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer))) |
|
||||||
|
(unsigned8)((fat16_clv & 0xFF00)>>8);
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs + 1)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs + 1))) & 0xF0;
|
||||||
|
|
||||||
|
*((unsigned8 *)(block0->buffer + ofs+1)) =
|
||||||
|
(*((unsigned8 *)(block0->buffer + ofs+1))) |
|
||||||
|
(unsigned8)((fat16_clv & 0xFF00)>>8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT_FAT16:
|
||||||
|
*((unsigned16 *)(block0->buffer + ofs)) =
|
||||||
|
(unsigned16)(CT_LE_W(in_val));
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT_FAT32:
|
||||||
|
fat32_clv = CT_LE_L((in_val & FAT_FAT32_MASK));
|
||||||
|
|
||||||
|
*((unsigned32 *)(block0->buffer + ofs)) =
|
||||||
|
(*((unsigned32 *)(block0->buffer + ofs))) & (CT_LE_L(0xF0000000));
|
||||||
|
|
||||||
|
*((unsigned32 *)(block0->buffer + ofs)) =
|
||||||
|
fat32_clv | (*((unsigned32 *)(block0->buffer + ofs)));
|
||||||
|
|
||||||
|
fat_buf_mark_modified(fs_info);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
58
cpukit/libfs/src/dosfs/fat_fat_operations.h
Normal file
58
cpukit/libfs/src/dosfs/fat_fat_operations.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* fat_fat_operations.h
|
||||||
|
*
|
||||||
|
* Constants/data structures/prototypes for operations on Files Allocation
|
||||||
|
* Table
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#ifndef __DOSFS_FAT_FAT_OPERATIONS_H__
|
||||||
|
#define __DOSFS_FAT_FAT_OPERATIONS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include <rtems/bdbuf.h>
|
||||||
|
#include "fat.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_get_fat_cluster(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 *ret_val);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_set_fat_cluster(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 in_val);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_scan_fat_for_free_clusters(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 *chain,
|
||||||
|
unsigned32 count,
|
||||||
|
unsigned32 *cls_added,
|
||||||
|
unsigned32 *last_cl
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_free_fat_clusters_chain(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 chain
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_FAT_FAT_OPERATIONS_H__ */
|
||||||
979
cpukit/libfs/src/dosfs/fat_file.c
Normal file
979
cpukit/libfs/src/dosfs/fat_file.c
Normal file
@@ -0,0 +1,979 @@
|
|||||||
|
/*
|
||||||
|
* fat_file.c
|
||||||
|
*
|
||||||
|
* General operations on "fat-file"
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <bsp.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_hash_insert(Chain_Control *hash, unsigned32 key1, unsigned32 key2,
|
||||||
|
fat_file_fd_t *el);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_hash_delete(Chain_Control *hash, unsigned32 key1, unsigned32 key2,
|
||||||
|
fat_file_fd_t *el);
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
_hash_search(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
Chain_Control *hash,
|
||||||
|
unsigned32 key1,
|
||||||
|
unsigned32 key2,
|
||||||
|
void **ret
|
||||||
|
);
|
||||||
|
|
||||||
|
static int
|
||||||
|
fat_file_lseek(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 file_cln,
|
||||||
|
unsigned32 *disk_cln
|
||||||
|
);
|
||||||
|
|
||||||
|
/* fat_file_open --
|
||||||
|
* Open fat-file. Two hash tables are accessed by key
|
||||||
|
* constructed from cluster num and offset of the node (i.e.
|
||||||
|
* files/directories are distinguished by location on the disk).
|
||||||
|
* First, hash table("vhash") consists of fat-file descriptors corresponded
|
||||||
|
* to "valid" files is accessed. Search is made by 2 fields equal to key
|
||||||
|
* constructed. If descriptor is found in the "vhash" - return it.
|
||||||
|
* Otherwise search is made in hash table("rhash") consits of fat-file
|
||||||
|
* descriptors corresponded to "removed-but-still-open" files with the
|
||||||
|
* same keys.
|
||||||
|
* If search failed, new fat-file descriptor is added to "vhash"
|
||||||
|
* with both key fields equal to constructed key. Otherwise new fat-file
|
||||||
|
* descriptor is added to "vhash" with first key field equal to key
|
||||||
|
* constructed and the second equal to an unique (unique among all values
|
||||||
|
* of second key fields) value.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cln - cluster num of the node
|
||||||
|
* ofs - offset of the node
|
||||||
|
* fat_fd - placeholder for returned fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and pointer to opened descriptor on success, or -1 if error
|
||||||
|
* occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_open(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 ofs,
|
||||||
|
fat_file_fd_t **fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *lfat_fd = NULL;
|
||||||
|
unsigned32 key = 0;
|
||||||
|
|
||||||
|
/* construct key */
|
||||||
|
key = fat_construct_key(mt_entry, cln, ofs);
|
||||||
|
|
||||||
|
/* access "valid" hash table */
|
||||||
|
rc = _hash_search(mt_entry, fs_info->vhash, key, 0, (void **)&lfat_fd);
|
||||||
|
if ( rc == RC_OK )
|
||||||
|
{
|
||||||
|
/* return pointer to fat_file_descriptor allocated before */
|
||||||
|
(*fat_fd) = lfat_fd;
|
||||||
|
lfat_fd->links_num++;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* access "removed-but-still-open" hash table */
|
||||||
|
rc = _hash_search(mt_entry, fs_info->rhash, key, key, (void **)&lfat_fd);
|
||||||
|
|
||||||
|
lfat_fd = (*fat_fd) = (fat_file_fd_t*)malloc(sizeof(fat_file_fd_t));
|
||||||
|
if ( lfat_fd == NULL )
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
|
||||||
|
lfat_fd->links_num = 1;
|
||||||
|
lfat_fd->flags &= ~FAT_FILE_REMOVED;
|
||||||
|
lfat_fd->map.last_cln = FAT_UNDEFINED_VALUE;
|
||||||
|
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
lfat_fd->ino = key;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lfat_fd->ino = fat_get_unique_ino(mt_entry);
|
||||||
|
|
||||||
|
if ( lfat_fd->ino == 0 )
|
||||||
|
{
|
||||||
|
free((*fat_fd));
|
||||||
|
/*
|
||||||
|
* XXX: kernel resource is unsufficient, but not the memory,
|
||||||
|
* but there is no suitable errno :(
|
||||||
|
*/
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_hash_insert(fs_info->vhash, key, lfat_fd->ino, lfat_fd);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* other fields of fat-file descriptor will be initialized on upper
|
||||||
|
* level
|
||||||
|
*/
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* fat_file_reopen --
|
||||||
|
* Increment by 1 number of links
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_reopen(fat_file_fd_t *fat_fd)
|
||||||
|
{
|
||||||
|
fat_fd->links_num++;
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_close --
|
||||||
|
* Close fat-file. If count of links to fat-file
|
||||||
|
* descriptor is greater than 1 (i.e. somebody esle holds pointer
|
||||||
|
* to this descriptor) just decrement it. Otherwise
|
||||||
|
* do the following. If this descriptor corresponded to removed fat-file
|
||||||
|
* then free clusters contained fat-file data, delete descriptor from
|
||||||
|
* "rhash" table and free memory allocated by descriptor. If descriptor
|
||||||
|
* correspondes to non-removed fat-file and 'ino' field has value from
|
||||||
|
* unique inode numbers pool then set count of links to descriptor to zero
|
||||||
|
* and leave it in hash, otherwise delete descriptor from "vhash" and free
|
||||||
|
* memory allocated by the descriptor
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_close(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 key = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if links_num field of fat-file descriptor is greater than 1
|
||||||
|
* decrement the count of links and return
|
||||||
|
*/
|
||||||
|
if (fat_fd->links_num > 1)
|
||||||
|
{
|
||||||
|
fat_fd->links_num--;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
|
||||||
|
|
||||||
|
if (fat_fd->flags & FAT_FILE_REMOVED)
|
||||||
|
{
|
||||||
|
rc = fat_file_truncate(mt_entry, fat_fd, 0);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
_hash_delete(fs_info->rhash, key, fat_fd->ino, fat_fd);
|
||||||
|
|
||||||
|
if ( fat_ino_is_unique(mt_entry, fat_fd->ino) )
|
||||||
|
fat_free_unique_ino(mt_entry, fat_fd->ino);
|
||||||
|
|
||||||
|
free(fat_fd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fat_ino_is_unique(mt_entry, fat_fd->ino))
|
||||||
|
{
|
||||||
|
fat_fd->links_num = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
|
||||||
|
free(fat_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_read --
|
||||||
|
* Read 'count' bytes from 'start' position from fat-file. This
|
||||||
|
* interface hides the architecture of fat-file, represents it as
|
||||||
|
* linear file
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* start - offset in fat-file (in bytes) to read from
|
||||||
|
* count - count of bytes to read
|
||||||
|
* buf - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* the number of bytes read on success, or -1 if error occured (errno
|
||||||
|
* set appropriately)
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
fat_file_read(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 count,
|
||||||
|
char *buf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
ssize_t ret = 0;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cmpltd = 0;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
unsigned32 cl_start = 0;
|
||||||
|
unsigned32 save_cln = 0;
|
||||||
|
unsigned32 ofs = 0;
|
||||||
|
unsigned32 save_ofs;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 byte = 0;
|
||||||
|
unsigned32 c = 0;
|
||||||
|
|
||||||
|
/* it couldn't be removed - otherwise cache update will be broken */
|
||||||
|
if (count == 0)
|
||||||
|
return cmpltd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* >= because start is offset and computed from 0 and file_size
|
||||||
|
* computed from 1
|
||||||
|
*/
|
||||||
|
if ( start >= fat_fd->fat_file_size )
|
||||||
|
return FAT_EOF;
|
||||||
|
|
||||||
|
if ((count > fat_fd->fat_file_size) ||
|
||||||
|
(start > fat_fd->fat_file_size - count))
|
||||||
|
count = fat_fd->fat_file_size - start;
|
||||||
|
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
{
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->cln);
|
||||||
|
sec += (start >> fs_info->vol.sec_log2);
|
||||||
|
byte = start & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
ret = _fat_block_read(mt_entry, sec, byte, count, buf);
|
||||||
|
if ( ret < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl_start = start >> fs_info->vol.bpc_log2;
|
||||||
|
save_ofs = ofs = start & (fs_info->vol.bpc - 1);
|
||||||
|
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
c = MIN(count, (fs_info->vol.bpc - ofs));
|
||||||
|
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
|
||||||
|
sec += (ofs >> fs_info->vol.sec_log2);
|
||||||
|
byte = ofs & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
ret = _fat_block_read(mt_entry, sec, byte, c, buf + cmpltd);
|
||||||
|
if ( ret < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
count -= c;
|
||||||
|
cmpltd += c;
|
||||||
|
save_cln = cur_cln;
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
ofs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update cache */
|
||||||
|
/* XXX: check this - I'm not sure :( */
|
||||||
|
fat_fd->map.file_cln = cl_start +
|
||||||
|
((save_ofs + cmpltd - 1) >> fs_info->vol.bpc_log2);
|
||||||
|
fat_fd->map.disk_cln = save_cln;
|
||||||
|
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_write --
|
||||||
|
* Write 'count' bytes of data from user supplied buffer to fat-file
|
||||||
|
* starting at offset 'start'. This interface hides the architecture
|
||||||
|
* of fat-file, represents it as linear file
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* start - offset(in bytes) to write from
|
||||||
|
* count - count
|
||||||
|
* buf - buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* number of bytes actually written to the file on success, or -1 if
|
||||||
|
* error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
fat_file_write(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 count,
|
||||||
|
char *buf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
ssize_t ret = 0;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cmpltd = 0;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
unsigned32 save_cln;
|
||||||
|
unsigned32 cl_start = 0;
|
||||||
|
unsigned32 ofs = 0;
|
||||||
|
unsigned32 save_ofs;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 byte = 0;
|
||||||
|
unsigned32 c = 0;
|
||||||
|
|
||||||
|
if ( count == 0 )
|
||||||
|
return cmpltd;
|
||||||
|
|
||||||
|
if ( start > fat_fd->fat_file_size )
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
if ((count > fat_fd->size_limit) ||
|
||||||
|
(start > fat_fd->size_limit - count))
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
rc = fat_file_extend(mt_entry, fat_fd, start + count, &c);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check whether there was enough room on device to locate
|
||||||
|
* file of 'start + count' bytes
|
||||||
|
*/
|
||||||
|
if (c != (start + count))
|
||||||
|
count = c - start;
|
||||||
|
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
{
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->cln);
|
||||||
|
sec += (start >> fs_info->vol.sec_log2);
|
||||||
|
byte = start & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
ret = _fat_block_write(mt_entry, sec, byte, count, buf);
|
||||||
|
if ( ret < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl_start = start >> fs_info->vol.bpc_log2;
|
||||||
|
save_ofs = ofs = start & (fs_info->vol.bpc - 1);
|
||||||
|
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
c = MIN(count, (fs_info->vol.bpc - ofs));
|
||||||
|
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
|
||||||
|
sec += (ofs >> fs_info->vol.sec_log2);
|
||||||
|
byte = ofs & (fs_info->vol.bps - 1);
|
||||||
|
|
||||||
|
ret = _fat_block_write(mt_entry, sec, byte, c, buf + cmpltd);
|
||||||
|
if ( ret < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
count -= c;
|
||||||
|
cmpltd += c;
|
||||||
|
save_cln = cur_cln;
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
ofs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update cache */
|
||||||
|
/* XXX: check this - I'm not sure :( */
|
||||||
|
fat_fd->map.file_cln = cl_start +
|
||||||
|
((save_ofs + cmpltd - 1) >> fs_info->vol.bpc_log2);
|
||||||
|
fat_fd->map.disk_cln = save_cln;
|
||||||
|
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_extend --
|
||||||
|
* Extend fat-file. If new length less than current fat-file size -
|
||||||
|
* do nothing. Otherwise calculate necessary count of clusters to add,
|
||||||
|
* allocate it and add new clusters chain to the end of
|
||||||
|
* existing clusters chain.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* new_length - new length
|
||||||
|
* a_length - placeholder for result - actual new length of file
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and new length of file on success, or -1 if error occured (errno
|
||||||
|
* set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_extend(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 new_length,
|
||||||
|
unsigned32 *a_length
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 chain = 0;
|
||||||
|
unsigned32 bytes2add = 0;
|
||||||
|
unsigned32 cls2add = 0;
|
||||||
|
unsigned32 old_last_cl;
|
||||||
|
unsigned32 last_cl = 0;
|
||||||
|
unsigned32 bytes_remain = 0;
|
||||||
|
unsigned32 cls_added;
|
||||||
|
|
||||||
|
*a_length = new_length;
|
||||||
|
|
||||||
|
if (new_length <= fat_fd->fat_file_size)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
set_errno_and_return_minus_one( ENOSPC );
|
||||||
|
|
||||||
|
bytes_remain = (fs_info->vol.bpc -
|
||||||
|
(fat_fd->fat_file_size & (fs_info->vol.bpc - 1))) &
|
||||||
|
(fs_info->vol.bpc - 1);
|
||||||
|
|
||||||
|
bytes2add = new_length - fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
if (bytes2add > bytes_remain)
|
||||||
|
bytes2add -= bytes_remain;
|
||||||
|
else
|
||||||
|
bytes2add = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if in last cluster allocated for the file there is enough room to
|
||||||
|
* handle extention (hence we don't need to add even one cluster to the
|
||||||
|
* file ) - return
|
||||||
|
*/
|
||||||
|
if (bytes2add == 0)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
cls2add = ((bytes2add - 1) >> fs_info->vol.bpc_log2) + 1;
|
||||||
|
|
||||||
|
rc = fat_scan_fat_for_free_clusters(mt_entry, &chain, cls2add,
|
||||||
|
&cls_added, &last_cl);
|
||||||
|
|
||||||
|
/* this means that low level I/O error occured */
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* this means that no space left on device */
|
||||||
|
if ((cls_added == 0) && (bytes_remain == 0))
|
||||||
|
set_errno_and_return_minus_one(ENOSPC);
|
||||||
|
|
||||||
|
/* check wether we satisfied request for 'cls2add' clusters */
|
||||||
|
if (cls2add != cls_added)
|
||||||
|
*a_length = new_length -
|
||||||
|
((cls2add - cls_added - 1) << fs_info->vol.bpc_log2) -
|
||||||
|
(bytes2add & (fs_info->vol.bpc - 1));
|
||||||
|
|
||||||
|
/* add new chain to the end of existed */
|
||||||
|
if ( fat_fd->fat_file_size == 0 )
|
||||||
|
{
|
||||||
|
fat_fd->map.disk_cln = fat_fd->cln = chain;
|
||||||
|
fat_fd->map.file_cln = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fat_fd->map.last_cln != FAT_UNDEFINED_VALUE)
|
||||||
|
{
|
||||||
|
old_last_cl = fat_fd->map.last_cln;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
|
||||||
|
(fat_fd->fat_file_size - 1), &old_last_cl);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, chain);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, old_last_cl, chain);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, chain);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
fat_buf_release(fs_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update number of the last cluster of the file if it changed */
|
||||||
|
if (cls_added != 0)
|
||||||
|
{
|
||||||
|
fat_fd->map.last_cln = last_cl;
|
||||||
|
if (fat_fd->fat_file_type == FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
rc = fat_init_clusters_chain(mt_entry, chain);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
fat_free_fat_clusters_chain(mt_entry, chain);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_truncate --
|
||||||
|
* Truncate fat-file. If new length greater than current fat-file size -
|
||||||
|
* do nothing. Otherwise find first cluster to free and free all clusters
|
||||||
|
* in the chain starting from this cluster.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* new_length - new length
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_truncate(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 new_length
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
unsigned32 cl_start = 0;
|
||||||
|
unsigned32 new_last_cln = FAT_UNDEFINED_VALUE;
|
||||||
|
|
||||||
|
|
||||||
|
if ( new_length >= fat_fd->fat_file_size )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
assert(fat_fd->fat_file_size);
|
||||||
|
|
||||||
|
cl_start = (new_length + fs_info->vol.bpc - 1) >> fs_info->vol.bpc_log2;
|
||||||
|
|
||||||
|
if ((cl_start << fs_info->vol.bpc_log2) >= fat_fd->fat_file_size)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
if (cl_start != 0)
|
||||||
|
{
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start - 1, &new_last_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = fat_free_fat_clusters_chain(mt_entry, cur_cln);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (cl_start != 0)
|
||||||
|
{
|
||||||
|
rc = fat_set_fat_cluster(mt_entry, new_last_cln, FAT_GENFAT_EOC);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
fat_fd->map.file_cln = cl_start - 1;
|
||||||
|
fat_fd->map.disk_cln = new_last_cln;
|
||||||
|
fat_fd->map.last_cln = new_last_cln;
|
||||||
|
}
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_ioctl --
|
||||||
|
* F_CLU_NUM:
|
||||||
|
* make mapping between serial number of the cluster in fat-file and
|
||||||
|
* its real number on the volume
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* cmd - command
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_ioctl(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
int cmd,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
unsigned32 cl_start = 0;
|
||||||
|
unsigned32 pos = 0;
|
||||||
|
unsigned32 *ret;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, cmd);
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case F_CLU_NUM:
|
||||||
|
pos = va_arg(ap, int);
|
||||||
|
ret = va_arg(ap, int *);
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
if ( pos >= fat_fd->fat_file_size )
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
{
|
||||||
|
/* cluster 0 (zero) reserved for root dir */
|
||||||
|
*ret = 0;
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl_start = pos >> fs_info->vol.bpc_log2;
|
||||||
|
|
||||||
|
rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*ret = cur_cln;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
rc = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_mark_removed --
|
||||||
|
* Remove the fat-file descriptor from "valid" hash table, insert it
|
||||||
|
* into "removed-but-still-open" hash table and set up "removed" bit.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fat_file_mark_removed(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 key = 0;
|
||||||
|
|
||||||
|
key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
|
||||||
|
|
||||||
|
_hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
|
||||||
|
|
||||||
|
_hash_insert(fs_info->rhash, key, fat_fd->ino, fat_fd);
|
||||||
|
|
||||||
|
fat_fd->flags |= FAT_FILE_REMOVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_datasync --
|
||||||
|
* Synchronize fat-file - flush all buffered data to the media.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_datasync(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = fat_fd->cln;
|
||||||
|
bdbuf_buffer *block = NULL;
|
||||||
|
unsigned32 sec = 0;
|
||||||
|
unsigned32 i = 0;
|
||||||
|
|
||||||
|
if (fat_fd->fat_file_size == 0)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we can use only one bdbuf :( and we also know that cache is useless
|
||||||
|
* for sync operation, so don't use it
|
||||||
|
*/
|
||||||
|
rc = fat_buf_release(fs_info);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* for each cluster of the file ... */
|
||||||
|
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
||||||
|
{
|
||||||
|
sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
|
||||||
|
/* for each sector in cluster ... */
|
||||||
|
for ( i = 0; i < fs_info->vol.spc; i++ )
|
||||||
|
{
|
||||||
|
/* ... sync it */
|
||||||
|
sc = rtems_bdbuf_read(fs_info->vol.dev, (sec + i), &block);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
sc = rtems_bdbuf_sync(block);
|
||||||
|
if ( sc != RTEMS_SUCCESSFUL )
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fat_file_size --
|
||||||
|
* Calculate fat-file size - fat-file is nothing that clusters chain, so
|
||||||
|
* go through all clusters in the chain and count it. Only
|
||||||
|
* special case is root directory for FAT12/16 volumes.
|
||||||
|
* This function is used only for directories which are fat-files with
|
||||||
|
* non-zero length, hence 'fat_fd->cln' always contains valid data.
|
||||||
|
* Calculated size is stored in 'fat_file_size' field of fat-file
|
||||||
|
* descriptor.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* fat_fd - fat-file descriptor
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fat_file_size(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||||
|
unsigned32 cur_cln = fat_fd->cln;
|
||||||
|
unsigned32 save_cln = 0;
|
||||||
|
|
||||||
|
/* Have we requested root dir size for FAT12/16? */
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
|
||||||
|
(fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
|
||||||
|
{
|
||||||
|
fat_fd->fat_file_size = fs_info->vol.rdir_size;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_fd->fat_file_size = 0;
|
||||||
|
|
||||||
|
while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
|
||||||
|
{
|
||||||
|
save_cln = cur_cln;
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
fat_fd->fat_file_size += fs_info->vol.bpc;
|
||||||
|
}
|
||||||
|
fat_fd->map.last_cln = save_cln;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hash support routines */
|
||||||
|
|
||||||
|
/* _hash_insert --
|
||||||
|
* Insert elemnt into hash based on key 'key1'
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* hash - hash element will be inserted into
|
||||||
|
* key1 - key on which insertion is based on
|
||||||
|
* key2 - not used during insertion
|
||||||
|
* el - element to insert
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
_hash_insert(Chain_Control *hash, unsigned32 key1, unsigned32 key2,
|
||||||
|
fat_file_fd_t *el)
|
||||||
|
{
|
||||||
|
_Chain_Append((hash) + ((key1) % FAT_HASH_MODULE), &(el)->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* _hash_delete --
|
||||||
|
* Remove element from hash
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* hash - hash element will be removed from
|
||||||
|
* key1 - not used
|
||||||
|
* key2 - not used
|
||||||
|
* el - element to delete
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
_hash_delete(Chain_Control *hash, unsigned32 key1, unsigned32 key2,
|
||||||
|
fat_file_fd_t *el)
|
||||||
|
{
|
||||||
|
_Chain_Extract(&(el)->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _hash_search --
|
||||||
|
* Search element in hash. If both keys match pointer to found element
|
||||||
|
* is returned
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
* hash - hash element will be removed from
|
||||||
|
* key1 - search key
|
||||||
|
* key2 - search key
|
||||||
|
* ret - placeholder for result
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* 0 and pointer to found element on success, -1 otherwise
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
_hash_search(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
Chain_Control *hash,
|
||||||
|
unsigned32 key1,
|
||||||
|
unsigned32 key2,
|
||||||
|
void **ret
|
||||||
|
)
|
||||||
|
{
|
||||||
|
unsigned32 mod = (key1) % FAT_HASH_MODULE;
|
||||||
|
Chain_Node *the_node = ((Chain_Control *)((hash) + mod))->first;
|
||||||
|
|
||||||
|
for ( ; !_Chain_Is_tail((hash) + mod, the_node) ; )
|
||||||
|
{
|
||||||
|
fat_file_fd_t *ffd = (fat_file_fd_t *)the_node;
|
||||||
|
unsigned32 ck =
|
||||||
|
fat_construct_key(mt_entry, ffd->info_cln, ffd->info_ofs);
|
||||||
|
|
||||||
|
if ( (key1) == ck)
|
||||||
|
{
|
||||||
|
if ( ((key2) == 0) || ((key2) == ffd->ino) )
|
||||||
|
{
|
||||||
|
*ret = (void *)the_node;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
the_node = the_node->next;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
fat_file_lseek(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 file_cln,
|
||||||
|
unsigned32 *disk_cln
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
/*
|
||||||
|
assert(fat_fd->fat_file_size);
|
||||||
|
*/
|
||||||
|
if (file_cln == fat_fd->map.file_cln)
|
||||||
|
*disk_cln = fat_fd->map.disk_cln;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned32 cur_cln;
|
||||||
|
unsigned32 count;
|
||||||
|
unsigned32 i;
|
||||||
|
|
||||||
|
if (file_cln > fat_fd->map.file_cln)
|
||||||
|
{
|
||||||
|
cur_cln = fat_fd->map.disk_cln;
|
||||||
|
count = file_cln - fat_fd->map.file_cln;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur_cln = fat_fd->cln;
|
||||||
|
count = file_cln;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip over the clusters */
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update cache */
|
||||||
|
fat_fd->map.file_cln = file_cln;
|
||||||
|
fat_fd->map.disk_cln = cur_cln;
|
||||||
|
|
||||||
|
*disk_cln = cur_cln;
|
||||||
|
}
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
195
cpukit/libfs/src/dosfs/fat_file.h
Normal file
195
cpukit/libfs/src/dosfs/fat_file.h
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* fat_file.h
|
||||||
|
*
|
||||||
|
* Constants/data structures/prototypes for operations on "fat-file"
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#ifndef __DOSFS_FAT_FILE_H__
|
||||||
|
#define __DOSFS_FAT_FILE_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/* "fat-file" representation
|
||||||
|
*
|
||||||
|
* the idea is: fat-file is nothing but a cluster chain, any open fat-file is
|
||||||
|
* represented in system by fat-file descriptor and has well-known
|
||||||
|
* file interface:
|
||||||
|
*
|
||||||
|
* fat_file_open()
|
||||||
|
* fat_file_close()
|
||||||
|
* fat_file_read()
|
||||||
|
* fat_file_write()
|
||||||
|
*
|
||||||
|
* Such interface hides the architecture of fat-file and represents it like
|
||||||
|
* linear file
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef rtems_filesystem_node_types_t fat_file_type_t;
|
||||||
|
|
||||||
|
#define FAT_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
|
||||||
|
#define FAT_FILE RTEMS_FILESYSTEM_MEMORY_FILE
|
||||||
|
|
||||||
|
typedef struct fat_file_map_s
|
||||||
|
{
|
||||||
|
unsigned32 file_cln;
|
||||||
|
unsigned32 disk_cln;
|
||||||
|
unsigned32 last_cln;
|
||||||
|
} fat_file_map_t;
|
||||||
|
/*
|
||||||
|
* descriptor of a fat-file
|
||||||
|
*
|
||||||
|
* To each particular clusters chain
|
||||||
|
*/
|
||||||
|
typedef struct fat_file_fd_s
|
||||||
|
{
|
||||||
|
Chain_Node link; /*
|
||||||
|
* fat-file descriptors organized into hash;
|
||||||
|
* collision lists are handled via link
|
||||||
|
* field
|
||||||
|
*/
|
||||||
|
unsigned32 links_num; /*
|
||||||
|
* the number of fat_file_open call on
|
||||||
|
* this fat-file
|
||||||
|
*/
|
||||||
|
unsigned32 ino; /* inode, file serial number :)))) */
|
||||||
|
fat_file_type_t fat_file_type;
|
||||||
|
unsigned32 size_limit;
|
||||||
|
unsigned32 fat_file_size; /* length */
|
||||||
|
unsigned32 info_cln;
|
||||||
|
unsigned32 cln;
|
||||||
|
unsigned16 info_ofs;
|
||||||
|
unsigned char first_char;
|
||||||
|
unsigned8 flags;
|
||||||
|
fat_file_map_t map;
|
||||||
|
time_t mtime;
|
||||||
|
|
||||||
|
} fat_file_fd_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define FAT_FILE_REMOVED 0x01
|
||||||
|
|
||||||
|
#define FAT_FILE_IS_REMOVED(p)\
|
||||||
|
(((p)->flags & FAT_FILE_REMOVED) ? 1 : 0)
|
||||||
|
|
||||||
|
/* ioctl macros */
|
||||||
|
#define F_CLU_NUM 0x01
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each file and directory on a MSDOS volume is unique identified by it
|
||||||
|
* location, i.e. location of it 32 Bytes Directory Entry Structure. We can
|
||||||
|
* distinguish them by cluster number it locates on and offset inside this
|
||||||
|
* cluster. But root directory on any volumes (FAT12/16/32) has no 32 Bytes
|
||||||
|
* Directory Entry Structure corresponded to it. So we assume 32 Bytes
|
||||||
|
* Directory Entry Structure of root directory locates at cluster 1 (invalid
|
||||||
|
* cluaster number) and offset 0
|
||||||
|
*/
|
||||||
|
#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))
|
||||||
|
|
||||||
|
#define FAT_EOF 0x00
|
||||||
|
|
||||||
|
/* fat_construct_key --
|
||||||
|
* Construct key for hash access: convert (cluster num, offset) to
|
||||||
|
* (sector512 num, new offset) and than construct key as
|
||||||
|
* key = (sector512 num) << 4 | (new offset)
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* cl - cluster number
|
||||||
|
* ofs - offset inside cluster 'cl'
|
||||||
|
* mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* constructed key
|
||||||
|
*/
|
||||||
|
static inline unsigned32
|
||||||
|
fat_construct_key(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cl,
|
||||||
|
unsigned32 ofs)
|
||||||
|
{
|
||||||
|
return ( ((fat_cluster_num_to_sector512_num(mt_entry, cl) +
|
||||||
|
(ofs >> FAT_SECTOR512_BITS)) << 4) +
|
||||||
|
((ofs >> 5) & (FAT_DIRENTRIES_PER_SEC512 - 1)) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prototypes for "fat-file" operations */
|
||||||
|
int
|
||||||
|
fat_file_open(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
unsigned32 ofs,
|
||||||
|
fat_file_fd_t **fat_fd);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_reopen(fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_close(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
fat_file_read(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 count,
|
||||||
|
char *buf);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
fat_file_write(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 start,
|
||||||
|
unsigned32 count,
|
||||||
|
char *buf);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_extend(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 new_length,
|
||||||
|
unsigned32 *a_length);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_truncate(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 new_length);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_datasync(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_ioctl(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
int cmd,
|
||||||
|
...);
|
||||||
|
|
||||||
|
int
|
||||||
|
fat_file_size(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
void
|
||||||
|
fat_file_mark_removed(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_FAT_FILE_H__ */
|
||||||
408
cpukit/libfs/src/dosfs/msdos.h
Normal file
408
cpukit/libfs/src/dosfs/msdos.h
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
/*
|
||||||
|
* msdos.h
|
||||||
|
*
|
||||||
|
* The MSDOS filesystem constants/data structures/prototypes
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#ifndef __DOSFS_MSDOS_H__
|
||||||
|
#define __DOSFS_MSDOS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#ifndef RC_OK
|
||||||
|
#define RC_OK 0x00000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MSDOS_NAME_NOT_FOUND_ERR 0xDD000001
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This structure identifies the instance of the filesystem on the MSDOS
|
||||||
|
* level.
|
||||||
|
*/
|
||||||
|
typedef struct msdos_fs_info_s
|
||||||
|
{
|
||||||
|
fat_fs_info_t fat; /*
|
||||||
|
* volume
|
||||||
|
* description
|
||||||
|
*/
|
||||||
|
rtems_filesystem_file_handlers_r *directory_handlers; /*
|
||||||
|
* a set of routines
|
||||||
|
* that handles the
|
||||||
|
* nodes of directory
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
rtems_filesystem_file_handlers_r *file_handlers; /*
|
||||||
|
* a set of routines
|
||||||
|
* that handles the
|
||||||
|
* nodes of file
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
rtems_id vol_sema; /*
|
||||||
|
* semaphore
|
||||||
|
* associated with
|
||||||
|
* the volume
|
||||||
|
*/
|
||||||
|
unsigned8 *cl_buf; /*
|
||||||
|
* just placeholder
|
||||||
|
* for anything
|
||||||
|
*/
|
||||||
|
} msdos_fs_info_t;
|
||||||
|
|
||||||
|
/* a set of routines that handle the nodes which are directories */
|
||||||
|
extern rtems_filesystem_file_handlers_r msdos_dir_handlers;
|
||||||
|
|
||||||
|
/* a set of routines that handle the nodes which are files */
|
||||||
|
extern rtems_filesystem_file_handlers_r msdos_file_handlers;
|
||||||
|
|
||||||
|
/* Volume semaphore timeout value */
|
||||||
|
#define MSDOS_VOLUME_SEMAPHORE_TIMEOUT 100
|
||||||
|
|
||||||
|
/* Node types */
|
||||||
|
#define MSDOS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
|
||||||
|
#define MSDOS_REGULAR_FILE RTEMS_FILESYSTEM_MEMORY_FILE
|
||||||
|
|
||||||
|
typedef rtems_filesystem_node_types_t msdos_node_type_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros for fetching fields from 32 bytes long FAT Directory Entry
|
||||||
|
* Structure (see M$ White Paper)
|
||||||
|
*/
|
||||||
|
#define MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE 32 /* 32 bytes */
|
||||||
|
|
||||||
|
#define MSDOS_DIR_NAME(x) (unsigned8 *)((x) + 0)
|
||||||
|
#define MSDOS_DIR_ATTR(x) (unsigned8 *)((x) + 11)
|
||||||
|
#define MSDOS_DIR_NT_RES(x) (unsigned8 *)((x) + 12)
|
||||||
|
#define MSDOS_DIR_CRT_TIME_TENTH(x) (unsigned8 *)((x) + 13)
|
||||||
|
#define MSDOS_DIR_CRT_TIME(x) (unsigned16 *)((x) + 14)
|
||||||
|
#define MSDOS_DIR_CRT_DATE(x) (unsigned16 *)((x) + 16)
|
||||||
|
#define MSDOS_DIR_LAST_ACCESS_DATE(x) (unsigned16 *)((x) + 18)
|
||||||
|
#define MSDOS_DIR_FIRST_CLUSTER_HI(x) (unsigned16 *)((x) + 20)
|
||||||
|
#define MSDOS_DIR_WRITE_TIME(x) (unsigned16 *)((x) + 22)
|
||||||
|
#define MSDOS_DIR_WRITE_DATE(x) (unsigned16 *)((x) + 24)
|
||||||
|
#define MSDOS_DIR_FIRST_CLUSTER_LOW(x) (unsigned16 *)((x) + 26)
|
||||||
|
#define MSDOS_DIR_FILE_SIZE(x) (unsigned32 *)((x) + 28)
|
||||||
|
|
||||||
|
#define MSDOS_EXTRACT_CLUSTER_NUM(p) \
|
||||||
|
(unsigned32)( (CF_LE_W(*MSDOS_DIR_FIRST_CLUSTER_LOW(p))) | \
|
||||||
|
((CF_LE_W((*MSDOS_DIR_FIRST_CLUSTER_HI(p))))<<16) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fields offset in 32 bytes long FAT Directory Entry
|
||||||
|
* Structure (see M$ White Paper)
|
||||||
|
*/
|
||||||
|
#define MSDOS_FILE_SIZE_OFFSET 28
|
||||||
|
#define MSDOS_FILE_NAME_OFFSET 0
|
||||||
|
#define MSDOS_FIRST_CLUSTER_HI_OFFSET 20
|
||||||
|
#define MSDOS_FIRST_CLUSTER_LOW_OFFSET 26
|
||||||
|
#define MSDOS_FILE_WDATE_OFFSET 24
|
||||||
|
#define MSDOS_FILE_WTIME_OFFSET 22
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possible values of DIR_Attr field of 32 bytes long FAT Directory Entry
|
||||||
|
* Structure (see M$ White Paper)
|
||||||
|
*/
|
||||||
|
#define MSDOS_ATTR_READ_ONLY 0x01
|
||||||
|
#define MSDOS_ATTR_HIDDEN 0x02
|
||||||
|
#define MSDOS_ATTR_SYSTEM 0x04
|
||||||
|
#define MSDOS_ATTR_VOLUME_ID 0x08
|
||||||
|
#define MSDOS_ATTR_DIRECTORY 0x10
|
||||||
|
#define MSDOS_ATTR_ARCHIVE 0x20
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possible values of DIR_Name[0] field of 32 bytes long FAT Directory Entry
|
||||||
|
* Structure (see M$ White Paper)
|
||||||
|
*/
|
||||||
|
#define MSDOS_THIS_DIR_ENTRY_EMPTY 0xE5
|
||||||
|
#define MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY 0x00
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_NAME_LEN 11 /* 11 characters */
|
||||||
|
#define MSDOS_NAME_MAX MSDOS_SHORT_NAME_LEN
|
||||||
|
#define MSDOS_NAME_MAX_WITH_DOT (MSDOS_NAME_MAX + 1)
|
||||||
|
|
||||||
|
#define MSDOS_DOT_NAME ". " /* ".", padded to MSDOS_NAME chars */
|
||||||
|
#define MSDOS_DOTDOT_NAME ".. " /* "..", padded to MSDOS_NAME chars */
|
||||||
|
|
||||||
|
typedef enum msdos_token_types_e
|
||||||
|
{
|
||||||
|
MSDOS_NO_MORE_PATH,
|
||||||
|
MSDOS_CURRENT_DIR,
|
||||||
|
MSDOS_UP_DIR,
|
||||||
|
MSDOS_NAME,
|
||||||
|
MSDOS_INVALID_TOKEN
|
||||||
|
} msdos_token_types_t;
|
||||||
|
|
||||||
|
/* Others macros */
|
||||||
|
#define MSDOS_RES_NT_VALUE 0x00
|
||||||
|
#define MSDOS_INIT_DIR_SIZE 0x00
|
||||||
|
|
||||||
|
/* "dot" entry offset in a directory */
|
||||||
|
#define MSDOS_DOT_DIR_ENTRY_OFFSET 0x00 /* first entry in directory */
|
||||||
|
|
||||||
|
/* "dotdot" entry offset in a directory */
|
||||||
|
#define MSDOS_DOTDOT_DIR_ENTRY_OFFSET 0x20 /* second entry in directory */
|
||||||
|
|
||||||
|
/* 'p' should be char* */
|
||||||
|
#define DOT_NODE_P(p) ((char *)(p))
|
||||||
|
#define DOTDOT_NODE_P(p) ((char *)((p) + MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE))
|
||||||
|
|
||||||
|
/* Size limits for files and directories (see M$ White Paper) */
|
||||||
|
#define MSDOS_MAX_DIR_LENGHT 0x200000 /* 2,097,152 bytes */
|
||||||
|
#define MSDOS_MAX_FILE_SIZE 0xFFFFFFFF /* 4 Gb */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of 32 bytes long FAT Directory Entry
|
||||||
|
* Structures per 512 bytes sector
|
||||||
|
*/
|
||||||
|
#define MSDOS_DPS512_NUM 16
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
int
|
||||||
|
msdos_initialize(rtems_filesystem_mount_table_entry_t *temp_mt_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_eval_path(const char *pathname, /* IN */
|
||||||
|
int flags, /* IN */
|
||||||
|
rtems_filesystem_location_info_t *pathloc /* IN/OUT */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_eval4make(const char *path, /* IN */
|
||||||
|
rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
|
||||||
|
const char **name /* OUT */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_unlink(rtems_filesystem_location_info_t *pathloc /* IN */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_free_node_info(rtems_filesystem_location_info_t *pathloc /* IN */);
|
||||||
|
|
||||||
|
rtems_filesystem_node_types_t
|
||||||
|
msdos_node_type(rtems_filesystem_location_info_t *pathloc);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_mknod(const char *path, /* IN */
|
||||||
|
mode_t mode, /* IN */
|
||||||
|
dev_t dev, /* IN */
|
||||||
|
rtems_filesystem_location_info_t *pathloc /* IN/OUT */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_utime(rtems_filesystem_location_info_t *pathloc, /* IN */
|
||||||
|
time_t actime, /* IN */
|
||||||
|
time_t modtime /* IN */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_initialize_support(
|
||||||
|
rtems_filesystem_mount_table_entry_t *temp_mt_entry,
|
||||||
|
rtems_filesystem_operations_table *op_table,
|
||||||
|
rtems_filesystem_file_handlers_r *file_handlers,
|
||||||
|
rtems_filesystem_file_handlers_r *directory_handlers
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_open(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
const char *pathname, /* IN */
|
||||||
|
unsigned32 flag, /* IN */
|
||||||
|
unsigned32 mode /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_close(rtems_libio_t *iop /* IN */);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
msdos_file_read(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
void *buffer, /* IN */
|
||||||
|
unsigned32 count /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
msdos_file_write(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
const void *buffer, /* IN */
|
||||||
|
unsigned32 count /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_lseek(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
off_t offset, /* IN */
|
||||||
|
int whence /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_stat(rtems_filesystem_location_info_t *loc, /* IN */
|
||||||
|
struct stat *buf /* OUT */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_ftruncate(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
off_t length /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_sync(rtems_libio_t *iop);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_datasync(rtems_libio_t *iop);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_ioctl(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
unsigned32 command, /* IN */
|
||||||
|
void *buffer /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc /* IN */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_open(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
const char *pathname, /* IN */
|
||||||
|
unsigned32 flag, /* IN */
|
||||||
|
unsigned32 mode /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_close(rtems_libio_t *iop /* IN */);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
msdos_dir_read(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
void *buffer, /* IN */
|
||||||
|
unsigned32 count /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_lseek(
|
||||||
|
rtems_libio_t *iop, /* IN */
|
||||||
|
off_t offset, /* IN */
|
||||||
|
int whence /* IN */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc /* IN */);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_sync(rtems_libio_t *iop);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_stat(
|
||||||
|
rtems_filesystem_location_info_t *loc, /* IN */
|
||||||
|
struct stat *buf /* OUT */
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_creat_node(rtems_filesystem_location_info_t *parent_loc,
|
||||||
|
msdos_node_type_t type,
|
||||||
|
char *name,
|
||||||
|
mode_t mode);
|
||||||
|
|
||||||
|
/* Misc prototypes */
|
||||||
|
msdos_token_types_t msdos_get_token(const char *path,
|
||||||
|
char *token,
|
||||||
|
int *token_len);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_find_name(rtems_filesystem_location_info_t *parent_loc,
|
||||||
|
char *name);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_get_name_node(rtems_filesystem_location_info_t *parent_loc,
|
||||||
|
char *name,
|
||||||
|
fat_auxiliary_t *paux,
|
||||||
|
char *name_dir_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_dir_info_remove(rtems_filesystem_location_info_t *pathloc);
|
||||||
|
|
||||||
|
void
|
||||||
|
msdos_date_unix2dos(int unix_date,
|
||||||
|
unsigned short *time_val,
|
||||||
|
unsigned short *date);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
msdos_date_dos2unix(unsigned short time_val, unsigned short date);
|
||||||
|
|
||||||
|
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,
|
||||||
|
unsigned32 cl,
|
||||||
|
unsigned32 ofs,
|
||||||
|
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,
|
||||||
|
rtems_boolean *ret_val);
|
||||||
|
|
||||||
|
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,
|
||||||
|
char *name_dir_entry);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_find_node_by_cluster_num_in_fat_file(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
fat_file_fd_t *fat_fd,
|
||||||
|
unsigned32 cl4find,
|
||||||
|
fat_auxiliary_t *paux,
|
||||||
|
char *dir_entry
|
||||||
|
);
|
||||||
|
|
||||||
|
int
|
||||||
|
msdos_get_dotdot_dir_info_cluster_num_and_offset(
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||||
|
unsigned32 cln,
|
||||||
|
fat_auxiliary_t *paux,
|
||||||
|
char *dir_entry
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DOSFS_MSDOS_H__ */
|
||||||
208
cpukit/libfs/src/dosfs/msdos_create.c
Normal file
208
cpukit/libfs/src/dosfs/msdos_create.c
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* Routine to create a new MSDOS filesystem node
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_creat_node --
|
||||||
|
* Create a new node. If a new node is file, FAT 32 Bytes Directory
|
||||||
|
* Entry Structure (see M$ White Paper) 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 new directory and dot and dotdot nodes are created
|
||||||
|
* in alloceted cluster.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* parent_loc - parent (directory we are going to create node in)
|
||||||
|
* type - new node type (file or directory)
|
||||||
|
* name - new node name
|
||||||
|
* mode - mode
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_creat_node(
|
||||||
|
rtems_filesystem_location_info_t *parent_loc,
|
||||||
|
msdos_node_type_t type,
|
||||||
|
char *name,
|
||||||
|
mode_t mode
|
||||||
|
)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
unsigned16 time_val = 0;
|
||||||
|
unsigned16 date = 0;
|
||||||
|
fat_auxiliary_t aux;
|
||||||
|
unsigned char new_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
|
||||||
|
unsigned char dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
|
||||||
|
|
||||||
|
memset(new_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);
|
||||||
|
|
||||||
|
/* fill reserved field */
|
||||||
|
*MSDOS_DIR_NT_RES(new_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);
|
||||||
|
|
||||||
|
/* initialize directory/file size */
|
||||||
|
*MSDOS_DIR_FILE_SIZE(new_node) = MSDOS_INIT_DIR_SIZE;
|
||||||
|
|
||||||
|
if (type == MSDOS_DIRECTORY)
|
||||||
|
*MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_DIRECTORY;
|
||||||
|
else
|
||||||
|
*MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find free space in the parent directory and write new initialized
|
||||||
|
* FAT 32 Bytes Directory Entry Structure (see M$ White Paper)
|
||||||
|
* to the disk
|
||||||
|
*/
|
||||||
|
rc = msdos_get_name_node(parent_loc, NULL, &aux, new_node);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if we create a new file we are done, if directory there are more steps
|
||||||
|
* to do
|
||||||
|
*/
|
||||||
|
if (type == MSDOS_DIRECTORY)
|
||||||
|
{
|
||||||
|
/* open new directory as fat-file */
|
||||||
|
rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dot and dotdot entries are identical to new node except the
|
||||||
|
* names
|
||||||
|
*/
|
||||||
|
memcpy(DOT_NODE_P(dot_dotdot), new_node,
|
||||||
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
|
||||||
|
memcpy(DOTDOT_NODE_P(dot_dotdot), new_node,
|
||||||
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
|
||||||
|
memcpy(MSDOS_DIR_NAME(DOT_NODE_P(dot_dotdot)), MSDOS_DOT_NAME,
|
||||||
|
MSDOS_NAME_MAX);
|
||||||
|
memcpy(MSDOS_DIR_NAME(DOTDOT_NODE_P(dot_dotdot)), MSDOS_DOTDOT_NAME,
|
||||||
|
MSDOS_NAME_MAX);
|
||||||
|
|
||||||
|
/* set up cluster num for dotdot entry */
|
||||||
|
/*
|
||||||
|
* here we can ommit FAT32 condition because for all FAT types dirs
|
||||||
|
* right under root dir should contain 0 in dotdot entry but for
|
||||||
|
* FAT12/16 parent_fat_fd->cluster_num always contains such value
|
||||||
|
*/
|
||||||
|
if ((FAT_FD_OF_ROOT_DIR(parent_fat_fd)) &&
|
||||||
|
(fs_info->fat.vol.type & FAT_FAT32))
|
||||||
|
{
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_LOW(DOTDOT_NODE_P(dot_dotdot)) = 0x0000;
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_HI(DOTDOT_NODE_P(dot_dotdot)) = 0x0000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_LOW(DOTDOT_NODE_P(dot_dotdot)) =
|
||||||
|
CT_LE_W((unsigned16)((parent_fat_fd->cln) & 0x0000FFFF));
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_HI(DOTDOT_NODE_P(dot_dotdot)) =
|
||||||
|
CT_LE_W((unsigned16)(((parent_fat_fd->cln) & 0xFFFF0000)>>16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* write dot and dotdot entries to new fat-file: currently fat-file
|
||||||
|
* correspondes to a new node is zero length, so it will be extended
|
||||||
|
* by one cluster and entries will be written
|
||||||
|
*/
|
||||||
|
ret = fat_file_write(parent_loc->mt_entry, fat_fd, 0,
|
||||||
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2,
|
||||||
|
dot_dotdot);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* increment fat-file size by cluster size */
|
||||||
|
fat_fd->fat_file_size += fs_info->fat.vol.bpc;
|
||||||
|
|
||||||
|
/* set up cluster num for dot entry */
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_LOW(DOT_NODE_P(dot_dotdot)) =
|
||||||
|
CT_LE_W((unsigned16)((fat_fd->cln) & 0x0000FFFF));
|
||||||
|
*MSDOS_DIR_FIRST_CLUSTER_HI(DOT_NODE_P(dot_dotdot)) =
|
||||||
|
CT_LE_W((unsigned16)(((fat_fd->cln) & 0xFFFF0000) >> 16));
|
||||||
|
|
||||||
|
/* rewrite dot entry */
|
||||||
|
ret = fat_file_write(parent_loc->mt_entry, fat_fd, 0,
|
||||||
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
|
||||||
|
DOT_NODE_P(dot_dotdot));
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write first cluster num of a new directory to disk */
|
||||||
|
rc = msdos_set_first_cluster_num(parent_loc->mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
fat_file_close(parent_loc->mt_entry, fat_fd);
|
||||||
|
}
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
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);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
483
cpukit/libfs/src/dosfs/msdos_dir.c
Normal file
483
cpukit/libfs/src/dosfs/msdos_dir.c
Normal file
@@ -0,0 +1,483 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS directory handlers implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_dir_open --
|
||||||
|
* Open fat-file which correspondes to the directory being opened and
|
||||||
|
* set offset field of file control block to zero.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* pathname - name
|
||||||
|
* flag - flags
|
||||||
|
* mode - mode
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, if directory opened successfully, or -1 if error occured (errno
|
||||||
|
* set apropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_open(rtems_libio_t *iop, const char *pathname, unsigned32 flag,
|
||||||
|
unsigned32 mode)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
rc = fat_file_reopen(fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
iop->offset = 0;
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_close --
|
||||||
|
* Close fat-file which correspondes to the directory being closed
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, if directory closed successfully, or -1 if error occured (errno
|
||||||
|
* set apropriately.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_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;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
|
||||||
|
rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_read --
|
||||||
|
* This routine will read the next directory entry based on the directory
|
||||||
|
* offset. The offset should be equal to -n- time the size of an
|
||||||
|
* individual dirent structure. If n is not an integer multiple of the
|
||||||
|
* sizeof a dirent structure, an integer division will be performed to
|
||||||
|
* determine directory entry that will be returned in the buffer. Count
|
||||||
|
* should reflect -m- times the sizeof dirent bytes to be placed in the
|
||||||
|
* buffer.
|
||||||
|
* If there are not -m- dirent elements from the current directory
|
||||||
|
* position to the end of the exisiting file, the remaining entries will
|
||||||
|
* be placed in the buffer and the returned value will be equal to
|
||||||
|
* -m actual- times the size of a directory entry.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* buffer - buffer provided by user
|
||||||
|
* count - count of bytes to read
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* the number of bytes read on success, or -1 if error occured (errno
|
||||||
|
* set apropriately).
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
msdos_dir_read(rtems_libio_t *iop, void *buffer, unsigned32 count)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
fat_file_fd_t *tmp_fat_fd = NULL;
|
||||||
|
struct dirent tmp_dirent;
|
||||||
|
unsigned32 start = 0;
|
||||||
|
ssize_t ret = 0;
|
||||||
|
unsigned32 cmpltd = 0;
|
||||||
|
unsigned32 j = 0, i = 0;
|
||||||
|
unsigned32 bts2rd = 0;
|
||||||
|
unsigned32 cur_cln = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cast start and count - protect against using sizes that are not exact
|
||||||
|
* multiples of the -dirent- size. These could result in unexpected
|
||||||
|
* results
|
||||||
|
*/
|
||||||
|
start = iop->offset / sizeof(struct dirent);
|
||||||
|
count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* optimization: we know that root directory for FAT12/16 volumes is
|
||||||
|
* sequential set of sectors and any cluster is sequential set of sectors
|
||||||
|
* too, so read such set of sectors is quick operation for low-level IO
|
||||||
|
* layer.
|
||||||
|
*/
|
||||||
|
bts2rd = (FAT_FD_OF_ROOT_DIR(fat_fd) &&
|
||||||
|
(fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) ?
|
||||||
|
fat_fd->fat_file_size :
|
||||||
|
fs_info->fat.vol.bpc;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* fat-file is already opened by open call, so read it
|
||||||
|
* Always read directory fat-file from the beggining because of MSDOS
|
||||||
|
* directories feature :( - we should count elements currently
|
||||||
|
* present in the directory because there may be holes :)
|
||||||
|
*/
|
||||||
|
ret = fat_file_read(iop->pathinfo.mt_entry, fat_fd, (j * bts2rd),
|
||||||
|
bts2rd, fs_info->cl_buf);
|
||||||
|
if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ret; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
|
||||||
|
{
|
||||||
|
if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
|
||||||
|
MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
|
||||||
|
MSDOS_THIS_DIR_ENTRY_EMPTY)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* skip active entries until get the entry to start from
|
||||||
|
*/
|
||||||
|
if (start)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_file_open(iop->pathinfo.mt_entry, cur_cln, i,
|
||||||
|
&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;
|
||||||
|
tmp_dirent.d_namlen = MSDOS_SHORT_NAME_LEN;
|
||||||
|
memcpy(tmp_dirent.d_name, MSDOS_DIR_NAME((fs_info->cl_buf + i)),
|
||||||
|
MSDOS_SHORT_NAME_LEN);
|
||||||
|
|
||||||
|
/* d_name is null-terminated */
|
||||||
|
tmp_dirent.d_name[MSDOS_SHORT_NAME_LEN] = 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return cmpltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_write --
|
||||||
|
* no write for directory
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* msdos_dir_lseek --
|
||||||
|
*
|
||||||
|
* This routine will behave in one of three ways based on the state of
|
||||||
|
* argument whence. Based on the state of its value the offset argument will
|
||||||
|
* be interpreted using one of the following methods:
|
||||||
|
*
|
||||||
|
* SEEK_SET - offset is the absolute byte offset from the start of the
|
||||||
|
* logical start of the dirent sequence that represents the
|
||||||
|
* directory
|
||||||
|
* SEEK_CUR - offset is used as the relative byte offset from the current
|
||||||
|
* directory position index held in the iop structure
|
||||||
|
* SEEK_END - N/A --> This will cause an assert.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* offset - offset
|
||||||
|
* whence - predefine directive
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno
|
||||||
|
* set apropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_lseek(rtems_libio_t *iop, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
switch (whence)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
case SEEK_CUR:
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
* Movement past the end of the directory via lseek is not a
|
||||||
|
* permitted operation
|
||||||
|
*/
|
||||||
|
case SEEK_END:
|
||||||
|
default:
|
||||||
|
set_errno_and_return_minus_one( EINVAL );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_stat --
|
||||||
|
*
|
||||||
|
* This routine will obtain the following information concerning the current
|
||||||
|
* directory:
|
||||||
|
* st_dev device id
|
||||||
|
* st_ino node serial number :)
|
||||||
|
* st_mode mode extracted from the node
|
||||||
|
* st_size total size in bytes
|
||||||
|
* st_blksize blocksize for filesystem I/O
|
||||||
|
* st_blocks number of blocks allocated
|
||||||
|
* stat_mtime time of last modification
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* loc - this directory
|
||||||
|
* buf - stat buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and filled stat buffer on success, or -1 if error occured (errno
|
||||||
|
* set apropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_stat(
|
||||||
|
rtems_filesystem_location_info_t *loc,
|
||||||
|
struct stat *buf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = loc->node_access;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
buf->st_dev = fs_info->fat.vol.dev;
|
||||||
|
buf->st_ino = fat_fd->ino;
|
||||||
|
buf->st_mode = S_IFDIR;
|
||||||
|
buf->st_rdev = 0ll;
|
||||||
|
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_mtime = fat_fd->mtime;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_truncate --
|
||||||
|
* No truncate for directory.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* msdos_dir_sync --
|
||||||
|
* The following routine does a syncronization on a MSDOS directory node.
|
||||||
|
* DIR_WrtTime, DIR_WrtDate and DIR_fileSize fields of 32 Bytes Directory
|
||||||
|
* Entry Structure(see M$ White Paper) should not be updated for
|
||||||
|
* directories, so only call to corresponding fat-file routine.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set apropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_sync(rtems_libio_t *iop)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
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)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_dir_rmnod --
|
||||||
|
* Remove directory node.
|
||||||
|
*
|
||||||
|
* Check that this directory node is not opened as fat-file, is empty and
|
||||||
|
* not filesystem root node. If all this conditions met then delete.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathloc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set apropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = pathloc->node_access;
|
||||||
|
rtems_boolean is_empty = FALSE;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We deny attemp to delete open directory (if directory is current
|
||||||
|
* directory we assume it is open one)
|
||||||
|
*/
|
||||||
|
if (fat_fd->links_num > 1)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
set_errno_and_return_minus_one(EBUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You cannot remove a node that still has children
|
||||||
|
*/
|
||||||
|
rc = msdos_dir_is_empty(pathloc->mt_entry, fat_fd, &is_empty);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_empty)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
set_errno_and_return_minus_one(ENOTEMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You cannot remove the file system root node.
|
||||||
|
*/
|
||||||
|
if (pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
set_errno_and_return_minus_one(EBUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You cannot remove a mountpoint.
|
||||||
|
* not used - mount() not implemenetd yet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* mark file removed */
|
||||||
|
rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
|
||||||
|
fat_fd->info_ofs,
|
||||||
|
MSDOS_THIS_DIR_ENTRY_EMPTY);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_file_mark_removed(pathloc->mt_entry, fat_fd);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
435
cpukit/libfs/src/dosfs/msdos_eval.c
Normal file
435
cpukit/libfs/src/dosfs/msdos_eval.c
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS evaluation routines
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_set_handlers --
|
||||||
|
* Set handlers for the node with specified type(i.e. handlers for file
|
||||||
|
* or directory).
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* loc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
msdos_set_handlers(rtems_filesystem_location_info_t *loc)
|
||||||
|
{
|
||||||
|
msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = loc->node_access;
|
||||||
|
|
||||||
|
if (fat_fd->fat_file_type == FAT_DIRECTORY)
|
||||||
|
loc->handlers = fs_info->directory_handlers;
|
||||||
|
else
|
||||||
|
loc->handlers = fs_info->file_handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_eval_path --
|
||||||
|
*
|
||||||
|
* The following routine evaluate path for a node that wishes to be
|
||||||
|
* accessed. Structure 'pathloc' is returned with a pointer to the
|
||||||
|
* node to be accessed.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathname - path for evaluation
|
||||||
|
* flags - flags
|
||||||
|
* pathloc - node description (IN/OUT)
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and filled pathloc on success, or -1 if error occured
|
||||||
|
* (errno set appropriately)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_eval_path(
|
||||||
|
const char *pathname,
|
||||||
|
int flags,
|
||||||
|
rtems_filesystem_location_info_t *pathloc
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = NULL;
|
||||||
|
rtems_filesystem_location_info_t newloc;
|
||||||
|
int i = 0;
|
||||||
|
int len = 0;
|
||||||
|
msdos_token_types_t type = MSDOS_CURRENT_DIR;
|
||||||
|
char token[MSDOS_NAME_MAX + 1];
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
if (!pathloc->node_access)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
rc = fat_file_reopen(fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
while ((type != MSDOS_NO_MORE_PATH) && (type != MSDOS_INVALID_TOKEN))
|
||||||
|
{
|
||||||
|
type = msdos_get_token(&pathname[i], token, &len);
|
||||||
|
i += len;
|
||||||
|
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case MSDOS_UP_DIR:
|
||||||
|
/*
|
||||||
|
* Only a directory can be decended into.
|
||||||
|
*/
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Am I at the root of this mounted filesystem?
|
||||||
|
*/
|
||||||
|
if (pathloc->node_access ==
|
||||||
|
pathloc->mt_entry->mt_fs_root.node_access)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Am I at the root of all filesystems?
|
||||||
|
* XXX: MSDOS is not supposed to be base fs.
|
||||||
|
*/
|
||||||
|
if (pathloc->node_access ==
|
||||||
|
rtems_filesystem_root.node_access)
|
||||||
|
{
|
||||||
|
break; /* Throw out the .. in this case */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newloc = pathloc->mt_entry->mt_point_node;
|
||||||
|
*pathloc = newloc;
|
||||||
|
|
||||||
|
rc = fat_file_close(pathloc->mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return (*pathloc->ops->evalpath_h)(&(pathname[i-len]),
|
||||||
|
flags, pathloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = msdos_find_name(pathloc, token);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
if (rc == MSDOS_NAME_NOT_FOUND_ERR)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_NAME:
|
||||||
|
/*
|
||||||
|
* Only a directory can be decended into.
|
||||||
|
*/
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
if (rc == MSDOS_NAME_NOT_FOUND_ERR)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_NO_MORE_PATH:
|
||||||
|
case MSDOS_CURRENT_DIR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_INVALID_TOKEN:
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Always return the root node.
|
||||||
|
*
|
||||||
|
* If we are at a node that is a mount point. Set loc to the
|
||||||
|
* new fs root node and let let the mounted filesystem set the handlers.
|
||||||
|
*
|
||||||
|
* NOTE: The behavior of stat() on a mount point appears to be
|
||||||
|
* questionable.
|
||||||
|
* NOTE: MSDOS filesystem currently doesn't support mount functionality ->
|
||||||
|
* action not implemented
|
||||||
|
*/
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
msdos_set_handlers(pathloc);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
fat_file_close(pathloc->mt_entry, fat_fd);
|
||||||
|
|
||||||
|
err:
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_eval4make --
|
||||||
|
* The following routine evaluate path for a new node to be created.
|
||||||
|
* 'pathloc' is returned with a pointer to the parent of the new node.
|
||||||
|
* 'name' is returned with a pointer to the first character in the
|
||||||
|
* new node name. The parent node is verified to be a directory.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* path - path for evaluation
|
||||||
|
* pathloc - IN/OUT (start point for evaluation/parent directory for
|
||||||
|
* creation)
|
||||||
|
* name - new node name
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, filled pathloc for parent directory and name of new node on
|
||||||
|
* success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_eval4make(
|
||||||
|
const char *path,
|
||||||
|
rtems_filesystem_location_info_t *pathloc,
|
||||||
|
const char **name
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = NULL;
|
||||||
|
rtems_filesystem_location_info_t newloc;
|
||||||
|
msdos_token_types_t type;
|
||||||
|
int i = 0;
|
||||||
|
int len;
|
||||||
|
char token[ MSDOS_NAME_MAX + 1 ];
|
||||||
|
rtems_boolean done = 0;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
if (!pathloc->node_access)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
rc = fat_file_reopen(fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
type = msdos_get_token(&path[i], token, &len);
|
||||||
|
i += len;
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case MSDOS_UP_DIR:
|
||||||
|
/*
|
||||||
|
* Only a directory can be decended into.
|
||||||
|
*/
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Am I at the root of this mounted filesystem?
|
||||||
|
*/
|
||||||
|
if (pathloc->node_access ==
|
||||||
|
pathloc->mt_entry->mt_fs_root.node_access)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Am I at the root of all filesystems?
|
||||||
|
* XXX: MSDOS is not supposed to be base fs.
|
||||||
|
*/
|
||||||
|
if (pathloc->node_access ==
|
||||||
|
rtems_filesystem_root.node_access)
|
||||||
|
{
|
||||||
|
break; /* Throw out the .. in this case */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newloc = pathloc->mt_entry->mt_point_node;
|
||||||
|
*pathloc = newloc;
|
||||||
|
|
||||||
|
rc = fat_file_close(pathloc->mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return (*pathloc->ops->evalformake_h)(&path[i-len],
|
||||||
|
pathloc, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = msdos_find_name(pathloc, token);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
if (rc == MSDOS_NAME_NOT_FOUND_ERR)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_NAME:
|
||||||
|
/*
|
||||||
|
* Only a directory can be decended into.
|
||||||
|
*/
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
if (rc != MSDOS_NAME_NOT_FOUND_ERR)
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
done = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_NO_MORE_PATH:
|
||||||
|
errno = EEXIST;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_CURRENT_DIR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSDOS_INVALID_TOKEN:
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*name = &path[i - len];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have evaluated the path as far as we can.
|
||||||
|
* Verify there is not any invalid stuff at the end of the name.
|
||||||
|
*/
|
||||||
|
for( ; path[i] != '\0'; i++)
|
||||||
|
{
|
||||||
|
if (!msdos_is_separator(path[i]))
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
if (fat_fd->fat_file_type != FAT_DIRECTORY)
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
rc = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
msdos_set_handlers(pathloc);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
fat_file_close(pathloc->mt_entry, fat_fd);
|
||||||
|
|
||||||
|
err:
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
485
cpukit/libfs/src/dosfs/msdos_file.c
Normal file
485
cpukit/libfs/src/dosfs/msdos_file.c
Normal file
@@ -0,0 +1,485 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS file handlers implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_file_open --
|
||||||
|
* Open fat-file which correspondes to the file
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* pathname - name
|
||||||
|
* flag - flags
|
||||||
|
* mode - mode
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK, if file opened successfully, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_open(rtems_libio_t *iop, const char *pathname, unsigned32 flag,
|
||||||
|
unsigned32 mode)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_reopen(fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iop->flags & LIBIO_FLAGS_APPEND)
|
||||||
|
iop->offset = fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
iop->size = fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* buffer - buffer provided by user
|
||||||
|
* count - the number of bytes to read
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* the number of bytes read on success, or -1 if error occured (errno set
|
||||||
|
* appropriately)
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
msdos_file_read(rtems_libio_t *iop, void *buffer, unsigned32 count)
|
||||||
|
{
|
||||||
|
ssize_t ret = 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->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
ret = fat_file_read(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
|
||||||
|
buffer);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_write --
|
||||||
|
* This routine writes the specified data buffer into the file pointed to
|
||||||
|
* by file control block.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* buffer - data to write
|
||||||
|
* count - count of bytes to write
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* the number of bytes written on success, or -1 if error occured
|
||||||
|
* and errno set appropriately
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
msdos_file_write(rtems_libio_t *iop,const void *buffer, unsigned32 count)
|
||||||
|
{
|
||||||
|
ssize_t ret = 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->file_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
ret = fat_file_write(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
|
||||||
|
buffer);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* update file size in both fat-file descriptor and file control block if
|
||||||
|
* file was extended
|
||||||
|
*/
|
||||||
|
if (iop->offset + ret > fat_fd->fat_file_size)
|
||||||
|
fat_fd->fat_file_size = iop->offset + ret;
|
||||||
|
|
||||||
|
iop->size = fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_lseek --
|
||||||
|
* Process lseek call to the file: extend file if lseek is up to the end
|
||||||
|
* of the file.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* offset - new offset
|
||||||
|
* whence - predefine directive
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* new offset on success, or -1 if error occured (errno set
|
||||||
|
* appropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_lseek(rtems_libio_t *iop, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
unsigned32 real_size = 0;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_extend(iop->pathinfo.mt_entry, fat_fd, iop->offset,
|
||||||
|
&real_size);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (real_size > fat_fd->fat_file_size)
|
||||||
|
fat_fd->fat_file_size = iop->offset = real_size;
|
||||||
|
|
||||||
|
iop->size = fat_fd->fat_file_size;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return iop->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_stat --
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* loc - node description
|
||||||
|
* buf - stat buffer provided by user
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_stat(
|
||||||
|
rtems_filesystem_location_info_t *loc,
|
||||||
|
struct stat *buf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = loc->node_access;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
buf->st_dev = fs_info->fat.vol.dev;
|
||||||
|
buf->st_ino = fat_fd->ino;
|
||||||
|
buf->st_mode = S_IFREG;
|
||||||
|
buf->st_rdev = 0ll;
|
||||||
|
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_mtime = fat_fd->mtime;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_ftruncate --
|
||||||
|
* Truncate the file (if new length is greater then current do nothing).
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* length - new length
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
|
||||||
|
{
|
||||||
|
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->file_info;
|
||||||
|
|
||||||
|
if (length >= fat_fd->fat_file_size)
|
||||||
|
return RC_OK;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_truncate(iop->pathinfo.mt_entry, fat_fd, length);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fat_file_truncate do nothing if new length >= fat-file size, so update
|
||||||
|
* file size only if length < fat-file size
|
||||||
|
*/
|
||||||
|
if (length < fat_fd->fat_file_size)
|
||||||
|
iop->size = fat_fd->fat_file_size = length;
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_sync --
|
||||||
|
* Synchronize file - synchronize file data and if file is not removed
|
||||||
|
* synchronize file metadata.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_sync(rtems_libio_t *iop)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
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)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/* synchronize file data */
|
||||||
|
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if fat-file descriptor is not marked "removed" - synchronize file
|
||||||
|
* metadata
|
||||||
|
*/
|
||||||
|
if (!FAT_FILE_IS_REMOVED(fat_fd))
|
||||||
|
{
|
||||||
|
rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* msdos_file_datasync --
|
||||||
|
* Synchronize file - synchronize only file data (metadata is letf intact).
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_datasync(rtems_libio_t *iop)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
fat_file_fd_t *fat_fd = iop->file_info;
|
||||||
|
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)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/* synchronize file data */
|
||||||
|
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* msdos_file_ioctl --
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* iop - file control block
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_ioctl(rtems_libio_t *iop,unsigned32 command, void *buffer)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* correspondes to the file as "removed"
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathloc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
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,
|
||||||
|
MSDOS_THIS_DIR_ENTRY_EMPTY);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_file_mark_removed(pathloc->mt_entry, fat_fd);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return RC_OK;
|
||||||
|
}
|
||||||
56
cpukit/libfs/src/dosfs/msdos_free.c
Normal file
56
cpukit/libfs/src/dosfs/msdos_free.c
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Free node handler implementation for the filesystem
|
||||||
|
* operations table.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_free_node_info --
|
||||||
|
* Call fat-file close routine.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathloc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 code if error occured
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_free_node_info(rtems_filesystem_location_info_t *pathloc)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
rc = fat_file_close(pathloc->mt_entry, pathloc->node_access);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
71
cpukit/libfs/src/dosfs/msdos_fsunmount.c
Normal file
71
cpukit/libfs/src/dosfs/msdos_fsunmount.c
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS shut down handler implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_shut_down --
|
||||||
|
* Shut down MSDOS filesystem - free all allocated resources (don't
|
||||||
|
* return if deallocation of some resource failed - free as much as
|
||||||
|
* possible).
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* temp_mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set apropriately).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
msdos_fs_info_t *fs_info = temp_mt_entry->fs_info;
|
||||||
|
fat_file_fd_t *fat_fd = temp_mt_entry->mt_fs_root.node_access;
|
||||||
|
|
||||||
|
/* close fat-file which correspondes to root directory */
|
||||||
|
if (fat_file_close(temp_mt_entry, fat_fd) != RC_OK)
|
||||||
|
{
|
||||||
|
/* no return - try to free as much as possible */
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fat_shutdown_drive(temp_mt_entry) != RC_OK)
|
||||||
|
{
|
||||||
|
/* no return - try to free as much as possible */
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_semaphore_delete(fs_info->vol_sema);
|
||||||
|
free(fs_info->cl_buf);
|
||||||
|
free(temp_mt_entry->fs_info);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
36
cpukit/libfs/src/dosfs/msdos_handlers_dir.c
Normal file
36
cpukit/libfs/src/dosfs/msdos_handlers_dir.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Directory Handlers Table for MSDOS filesystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
rtems_filesystem_file_handlers_r msdos_dir_handlers = {
|
||||||
|
msdos_dir_open,
|
||||||
|
msdos_dir_close,
|
||||||
|
msdos_dir_read,
|
||||||
|
NULL, /* msdos_dir_write */
|
||||||
|
NULL, /* msdos_dir_ioctl */
|
||||||
|
msdos_dir_lseek,
|
||||||
|
msdos_dir_stat,
|
||||||
|
NULL,
|
||||||
|
NULL, /* msdos_dir_ftruncate */
|
||||||
|
NULL,
|
||||||
|
msdos_dir_sync,
|
||||||
|
msdos_dir_sync,
|
||||||
|
NULL, /* msdos_dir_fcntl */
|
||||||
|
msdos_dir_rmnod
|
||||||
|
};
|
||||||
36
cpukit/libfs/src/dosfs/msdos_handlers_file.c
Normal file
36
cpukit/libfs/src/dosfs/msdos_handlers_file.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* File Operations Table for MSDOS filesystem
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
rtems_filesystem_file_handlers_r msdos_file_handlers = {
|
||||||
|
msdos_file_open,
|
||||||
|
msdos_file_close,
|
||||||
|
msdos_file_read,
|
||||||
|
msdos_file_write,
|
||||||
|
msdos_file_ioctl,
|
||||||
|
msdos_file_lseek,
|
||||||
|
msdos_file_stat,
|
||||||
|
NULL,
|
||||||
|
msdos_file_ftruncate,
|
||||||
|
NULL,
|
||||||
|
msdos_file_sync,
|
||||||
|
msdos_file_datasync,
|
||||||
|
NULL, /* msdos_file_fcntl */
|
||||||
|
msdos_file_rmnod
|
||||||
|
};
|
||||||
60
cpukit/libfs/src/dosfs/msdos_init.c
Normal file
60
cpukit/libfs/src/dosfs/msdos_init.c
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Init routine for MSDOS
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
rtems_filesystem_operations_table msdos_ops = {
|
||||||
|
msdos_eval_path,
|
||||||
|
msdos_eval4make,
|
||||||
|
NULL, /* msdos_link */
|
||||||
|
msdos_file_rmnod,
|
||||||
|
msdos_node_type,
|
||||||
|
msdos_mknod,
|
||||||
|
NULL, /* msdos_chown */
|
||||||
|
msdos_free_node_info,
|
||||||
|
NULL,
|
||||||
|
msdos_initialize,
|
||||||
|
NULL,
|
||||||
|
msdos_shut_down, /* msdos_shut_down */
|
||||||
|
NULL, /* msdos_utime */
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* msdos_initialize --
|
||||||
|
* MSDOS filesystem initialization
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* temp_mt_entry - mount table entry
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on success, or -1 if error occured (errno set apropriately).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_initialize(rtems_filesystem_mount_table_entry_t *temp_mt_entry)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
|
||||||
|
rc = msdos_initialize_support(temp_mt_entry,
|
||||||
|
&msdos_ops,
|
||||||
|
&msdos_file_handlers,
|
||||||
|
&msdos_dir_handlers);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
149
cpukit/libfs/src/dosfs/msdos_initsupp.c
Normal file
149
cpukit/libfs/src/dosfs/msdos_initsupp.c
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* MSDOS Initialization support routine implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_initialize_support --
|
||||||
|
* MSDOS filesystem initialization
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* temp_mt_entry - mount table entry
|
||||||
|
* op_table - filesystem operations table
|
||||||
|
* file_handlers - file operations table
|
||||||
|
* directory_handlers - directory operations table
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK and filled temp_mt_entry on success, or -1 if error occured
|
||||||
|
* (errno set apropriately)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_initialize_support(
|
||||||
|
rtems_filesystem_mount_table_entry_t *temp_mt_entry,
|
||||||
|
rtems_filesystem_operations_table *op_table,
|
||||||
|
rtems_filesystem_file_handlers_r *file_handlers,
|
||||||
|
rtems_filesystem_file_handlers_r *directory_handlers
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
msdos_fs_info_t *fs_info = NULL;
|
||||||
|
fat_file_fd_t *fat_fd = NULL;
|
||||||
|
unsigned32 cl_buf_size;
|
||||||
|
|
||||||
|
fs_info = (msdos_fs_info_t *)calloc(1, sizeof(msdos_fs_info_t));
|
||||||
|
if (!fs_info)
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
|
||||||
|
temp_mt_entry->fs_info = fs_info;
|
||||||
|
|
||||||
|
rc = fat_init_volume_info(temp_mt_entry);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
free(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs_info->file_handlers = file_handlers;
|
||||||
|
fs_info->directory_handlers = directory_handlers;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
if (rc != RC_OK)
|
||||||
|
{
|
||||||
|
fat_shutdown_drive(temp_mt_entry);
|
||||||
|
free(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
fat_fd->map.disk_cln = fat_fd->cln;
|
||||||
|
|
||||||
|
/* if we have FAT12/16 */
|
||||||
|
if ( fat_fd->cln == 0 )
|
||||||
|
{
|
||||||
|
fat_fd->fat_file_size = fs_info->fat.vol.rdir_size;
|
||||||
|
cl_buf_size = (fs_info->fat.vol.bpc > fs_info->fat.vol.rdir_size) ?
|
||||||
|
fs_info->fat.vol.bpc :
|
||||||
|
fs_info->fat.vol.rdir_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = fat_file_size(temp_mt_entry, fat_fd);
|
||||||
|
if ( rc != RC_OK )
|
||||||
|
{
|
||||||
|
fat_file_close(temp_mt_entry, fat_fd);
|
||||||
|
fat_shutdown_drive(temp_mt_entry);
|
||||||
|
free(fs_info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
cl_buf_size = fs_info->fat.vol.bpc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs_info->cl_buf = (char *)calloc(cl_buf_size, sizeof(char));
|
||||||
|
if (fs_info->cl_buf == NULL)
|
||||||
|
{
|
||||||
|
fat_file_close(temp_mt_entry, fat_fd);
|
||||||
|
fat_shutdown_drive(temp_mt_entry);
|
||||||
|
free(fs_info);
|
||||||
|
set_errno_and_return_minus_one(ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
sc = rtems_semaphore_create(3,
|
||||||
|
1,
|
||||||
|
RTEMS_BINARY_SEMAPHORE | RTEMS_FIFO,
|
||||||
|
RTEMS_INHERIT_PRIORITY,
|
||||||
|
&fs_info->vol_sema);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
{
|
||||||
|
fat_file_close(temp_mt_entry, fat_fd);
|
||||||
|
fat_shutdown_drive(temp_mt_entry);
|
||||||
|
free(fs_info->cl_buf);
|
||||||
|
free(fs_info);
|
||||||
|
set_errno_and_return_minus_one( EIO );
|
||||||
|
}
|
||||||
|
|
||||||
|
temp_mt_entry->mt_fs_root.node_access = fat_fd;
|
||||||
|
temp_mt_entry->mt_fs_root.handlers = directory_handlers;
|
||||||
|
temp_mt_entry->mt_fs_root.ops = op_table;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
1087
cpukit/libfs/src/dosfs/msdos_misc.c
Normal file
1087
cpukit/libfs/src/dosfs/msdos_misc.c
Normal file
File diff suppressed because it is too large
Load Diff
90
cpukit/libfs/src/dosfs/msdos_mknod.c
Normal file
90
cpukit/libfs/src/dosfs/msdos_mknod.c
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Routine for node creation in MSDOS filesystem.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_mknod --
|
||||||
|
* The following function checks spelling and formats name for a new node,
|
||||||
|
* determines type of the node to be created and creates it.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* token - non-formatted name of a new node
|
||||||
|
* mode - node type
|
||||||
|
* dev - dev
|
||||||
|
* pathloc - parent directory description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* RC_OK on succes, or -1 if error occured and set errno
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
msdos_mknod(
|
||||||
|
const char *token,
|
||||||
|
mode_t mode,
|
||||||
|
dev_t dev,
|
||||||
|
rtems_filesystem_location_info_t *pathloc
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rc = RC_OK;
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
if (S_ISDIR(mode))
|
||||||
|
{
|
||||||
|
type = MSDOS_DIRECTORY;
|
||||||
|
}
|
||||||
|
else if (S_ISREG(mode))
|
||||||
|
{
|
||||||
|
type = MSDOS_REGULAR_FILE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
set_errno_and_return_minus_one(EINVAL);
|
||||||
|
|
||||||
|
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||||
|
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one(EIO);
|
||||||
|
|
||||||
|
/* Create an MSDOS node */
|
||||||
|
rc = msdos_creat_node(pathloc, type, new_name, mode);
|
||||||
|
|
||||||
|
rtems_semaphore_release(fs_info->vol_sema);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
58
cpukit/libfs/src/dosfs/msdos_node_type.c
Normal file
58
cpukit/libfs/src/dosfs/msdos_node_type.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* The following returns the type of node that the loc refers to.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||||
|
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
|
*
|
||||||
|
* @(#) $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
|
||||||
|
#include <rtems/libio_.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
#include "fat_fat_operations.h"
|
||||||
|
#include "fat_file.h"
|
||||||
|
|
||||||
|
#include "msdos.h"
|
||||||
|
|
||||||
|
/* msdos_node_type --
|
||||||
|
* Determine type of the node that the pathloc refers to.
|
||||||
|
*
|
||||||
|
* PARAMETERS:
|
||||||
|
* pathloc - node description
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* node type
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
rtems_filesystem_node_types_t
|
||||||
|
msdos_node_type(rtems_filesystem_location_info_t *pathloc)
|
||||||
|
{
|
||||||
|
fat_file_fd_t *fat_fd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we don't need to obtain the volume semaphore here because node_type_h
|
||||||
|
* call always follows evalpath_h call(hence link increment occured) and
|
||||||
|
* hence node_access memory can't be freed during processing node_type_h
|
||||||
|
* call
|
||||||
|
*/
|
||||||
|
fat_fd = pathloc->node_access;
|
||||||
|
|
||||||
|
return fat_fd->fat_file_type;
|
||||||
|
}
|
||||||
@@ -13,7 +13,9 @@ include $(top_srcdir)/../../../automake/lib.am
|
|||||||
|
|
||||||
IMFSLIB = ../src/imfs/$(ARCH)/libimfs.a
|
IMFSLIB = ../src/imfs/$(ARCH)/libimfs.a
|
||||||
|
|
||||||
TMP_LIBS = $(IMFSLIB)
|
DOSFSLIB = ../src/dosfs/$(ARCH)/libdosfs.a
|
||||||
|
|
||||||
|
TMP_LIBS = $(IMFSLIB) $(DOSFSLIB)
|
||||||
|
|
||||||
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB)
|
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB)
|
||||||
$(INSTALL_DATA) $< $@
|
$(INSTALL_DATA) $< $@
|
||||||
|
|||||||
Reference in New Issue
Block a user