summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJennifer Averett <Jennifer.Averett@OARcorp.com>2003-08-05 14:05:56 +0000
committerJennifer Averett <Jennifer.Averett@OARcorp.com>2003-08-05 14:05:56 +0000
commit2e7b6dbbb5dfba02c3c45a7976250f6786b11857 (patch)
tree14634231719c9e82eafeb8d4794e20116ebf9504
parentda499ad0e85b665df084fb1bad9fa467609cddee (diff)
downloadrtems-2e7b6dbbb5dfba02c3c45a7976250f6786b11857.tar.bz2
2003-08-04 Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
PR 441/filesystem *src/dosfs/msdos.h: add rename support to DOSFS *src/dosfs/msdos_create.c: add rename support to DOSFS *src/dosfs/msdos_file.c: add rename support to DOSFS *src/dosfs/msdos_init.c: add rename support to DOSFS *src/dosfs/msdos_mknod.c: add rename support to DOSFS
-rw-r--r--cpukit/libfs/src/dosfs/msdos.h9
-rw-r--r--cpukit/libfs/src/dosfs/msdos_create.c149
-rw-r--r--cpukit/libfs/src/dosfs/msdos_init.c6
-rw-r--r--cpukit/libfs/src/dosfs/msdos_mknod.c2
4 files changed, 159 insertions, 7 deletions
diff --git a/cpukit/libfs/src/dosfs/msdos.h b/cpukit/libfs/src/dosfs/msdos.h
index 5e5bea090e..fc7b3fd91b 100644
--- a/cpukit/libfs/src/dosfs/msdos.h
+++ b/cpukit/libfs/src/dosfs/msdos.h
@@ -77,6 +77,7 @@ extern rtems_filesystem_file_handlers_r msdos_file_handlers;
/* Node types */
#define MSDOS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
#define MSDOS_REGULAR_FILE RTEMS_FILESYSTEM_MEMORY_FILE
+#define MSDOS_HARD_LINK RTEMS_FILESYSTEM_HARD_LINK /* pseudo type */
typedef rtems_filesystem_node_types_t msdos_node_type_t;
@@ -301,6 +302,11 @@ int
msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc /* IN */);
int
+msdos_file_link(rtems_filesystem_location_info_t *to_loc,
+ rtems_filesystem_location_info_t *pa_loc,
+ const char *token);
+
+int
msdos_dir_open(
rtems_libio_t *iop, /* IN */
const char *pathname, /* IN */
@@ -341,7 +347,8 @@ int
msdos_creat_node(rtems_filesystem_location_info_t *parent_loc,
msdos_node_type_t type,
char *name,
- mode_t mode);
+ mode_t mode,
+ const fat_file_fd_t *link_fd);
/* Misc prototypes */
msdos_token_types_t msdos_get_token(const char *path,
diff --git a/cpukit/libfs/src/dosfs/msdos_create.c b/cpukit/libfs/src/dosfs/msdos_create.c
index c50935021b..4606598a8e 100644
--- a/cpukit/libfs/src/dosfs/msdos_create.c
+++ b/cpukit/libfs/src/dosfs/msdos_create.c
@@ -40,6 +40,8 @@
* type - new node type (file or directory)
* name - new node name
* mode - mode
+ * link_info - fs_info of existing node for a pseudo "hard-link"
+ * (see msdos_file.c, msdos_link for documentation)
*
* RETURNS:
* RC_OK on success, or -1 if error occured (errno set appropriately).
@@ -50,7 +52,8 @@ msdos_creat_node(
rtems_filesystem_location_info_t *parent_loc,
msdos_node_type_t type,
char *name,
- mode_t mode
+ mode_t mode,
+ const fat_file_fd_t *link_fd
)
{
int rc = RC_OK;
@@ -62,8 +65,11 @@ msdos_creat_node(
unsigned16 time_val = 0;
unsigned16 date = 0;
fat_auxiliary_t aux;
- unsigned char new_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+ unsigned char new_node [MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
unsigned char dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
+ unsigned char link_node [MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+ unsigned32 sec = 0;
+ unsigned32 byte = 0;
memset(new_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
memset(dot_dotdot, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2);
@@ -86,10 +92,58 @@ msdos_creat_node(
/* initialize directory/file size */
*MSDOS_DIR_FILE_SIZE(new_node) = MSDOS_INIT_DIR_SIZE;
- if (type == MSDOS_DIRECTORY)
+ if (type == MSDOS_DIRECTORY){
*MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_DIRECTORY;
- else
+ }
+ else if (type == MSDOS_HARD_LINK) {
+ /*
+ * when we establish a (temporary) hard link,
+ * we must copy some information from the original
+ * node to the newly created
+ */
+ /*
+ * read the original directory entry
+ */
+ sec = fat_cluster_num_to_sector_num(parent_loc->mt_entry,
+ link_fd->info_cln);
+ sec += (link_fd->info_ofs >> fs_info->fat.vol.sec_log2);
+ byte = (link_fd->info_ofs & (fs_info->fat.vol.bps - 1));
+
+ ret = _fat_block_read(parent_loc->mt_entry,
+ sec, byte, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
+ link_node);
+ if (ret < 0) {
+ return -1;
+ }
+ /*
+ * copy various attributes
+ */
+ *MSDOS_DIR_ATTR(new_node) =*MSDOS_DIR_ATTR(link_node);
+ *MSDOS_DIR_CRT_TIME_TENTH(new_node)=*MSDOS_DIR_CRT_TIME_TENTH(link_node);
+ *MSDOS_DIR_CRT_TIME(new_node) =*MSDOS_DIR_CRT_TIME(link_node);
+ *MSDOS_DIR_CRT_DATE(new_node) =*MSDOS_DIR_CRT_DATE(link_node);
+
+ /*
+ * copy/set "file size", "first cluster"
+ */
+ *MSDOS_DIR_FILE_SIZE(new_node) =*MSDOS_DIR_FILE_SIZE(link_node);
+
+ *MSDOS_DIR_FIRST_CLUSTER_LOW(new_node) =
+ *MSDOS_DIR_FIRST_CLUSTER_LOW(link_node);
+ *MSDOS_DIR_FIRST_CLUSTER_HI(new_node) =
+ *MSDOS_DIR_FIRST_CLUSTER_HI(link_node);
+ /*
+ * set "archive bit" due to changes
+ */
+ *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
+ /*
+ * set "last access" date to today
+ */
+ *MSDOS_DIR_LAST_ACCESS_DATE(new_node) = CT_LE_W(date);
+ }
+ else { /* regular file... */
*MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
+ }
/*
* find free space in the parent directory and write new initialized
@@ -204,3 +258,90 @@ err:
0xE5);
return rc;
}
+
+/* msdos_file_link --
+ * Replacement for a file "link" operation.
+ * MSDOS FAT FS does not support links, but this call is needed to
+ * allow "rename" operations. The current NEWLIB rename performs a link
+ * from the old to the new name and then deletes the old filename.
+ *
+ * This pseudo-"link" operation will create a new directory entry,
+ * copy the file size and cluster information from the "old"
+ * to the "new" directory entry and then clear the file size and cluster
+ * info from the "old" filename, leaving this file as
+ * a valid, but empty entry.
+ *
+ * When this "link" call is part of a "rename" sequence, the "old"
+ * entry will be deleted in a subsequent "rmnod" call
+ *
+ * This function has been implemented by Thomas Doerfler,
+ * <Thomas.Doerfler@imd-systems.de>
+ *
+ * PARAMETERS:
+ * to_loc - node description for "existing" node
+ * par_loc - node description for "new" node
+ * token - name of new node
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set appropriately)
+ */
+int
+msdos_file_link(rtems_filesystem_location_info_t *to_loc,
+ rtems_filesystem_location_info_t *par_loc,
+ const char *token
+)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = to_loc->mt_entry->fs_info;
+ fat_file_fd_t *to_fat_fd = to_loc->node_access;
+ fat_file_fd_t *par_fat_fd = par_loc->node_access;
+ char new_name[ MSDOS_NAME_MAX + 1 ];
+ int len;
+
+ /*
+ * check spelling and format new node name
+ */
+ if (MSDOS_NAME != msdos_get_token(token, new_name, &len)) {
+ set_errno_and_return_minus_one(ENAMETOOLONG);
+ }
+ /*
+ * verify, that the existing node can be linked to
+ * check that nodes are in same FS/volume?
+ */
+ if (to_loc->mt_entry->fs_info != par_loc->mt_entry->fs_info) {
+ set_errno_and_return_minus_one(EXDEV);
+ }
+ /*
+ * lock volume
+ */
+ 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 new directory entry as "hard link",
+ * copying relevant info from existing file
+ */
+ rc = msdos_creat_node(par_loc,MSDOS_HARD_LINK,new_name,S_IFREG,
+ to_loc->node_access);
+ /*
+ * set file size and first cluster number of old entry to 0
+ */
+ if (rc == RC_OK) {
+ to_fat_fd->fat_file_size = 0;
+ to_fat_fd->cln = FAT_EOF;
+ rc = msdos_set_first_cluster_num(to_loc->mt_entry, to_fat_fd);
+ if (rc == RC_OK) {
+ rc = msdos_set_file_size(par_loc->mt_entry, to_fat_fd);
+ }
+ }
+ /*
+ * FIXME: check error/abort handling
+ */
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+}
+
diff --git a/cpukit/libfs/src/dosfs/msdos_init.c b/cpukit/libfs/src/dosfs/msdos_init.c
index 2d5bf6c9e0..93ca508bab 100644
--- a/cpukit/libfs/src/dosfs/msdos_init.c
+++ b/cpukit/libfs/src/dosfs/msdos_init.c
@@ -21,7 +21,11 @@
rtems_filesystem_operations_table msdos_ops = {
msdos_eval_path,
msdos_eval4make,
- NULL, /* msdos_link */
+#if 0
+ NULL, /* msdos_link */
+#else
+ msdos_file_link, /* msdos_link (pseudo-functionality) */
+#endif
msdos_file_rmnod,
msdos_node_type,
msdos_mknod,
diff --git a/cpukit/libfs/src/dosfs/msdos_mknod.c b/cpukit/libfs/src/dosfs/msdos_mknod.c
index 5e32dbf3bf..f56f1d668a 100644
--- a/cpukit/libfs/src/dosfs/msdos_mknod.c
+++ b/cpukit/libfs/src/dosfs/msdos_mknod.c
@@ -83,7 +83,7 @@ msdos_mknod(
set_errno_and_return_minus_one(EIO);
/* Create an MSDOS node */
- rc = msdos_creat_node(pathloc, type, new_name, mode);
+ rc = msdos_creat_node(pathloc, type, new_name, mode, NULL);
rtems_semaphore_release(fs_info->vol_sema);
return rc;