summaryrefslogtreecommitdiffstats
path: root/cpukit/libfs
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2010-03-04 06:36:51 +0000
committerChris Johns <chrisj@rtems.org>2010-03-04 06:36:51 +0000
commit8ec7abb551a23bdf47509189145885a364810006 (patch)
tree7b5fa486b93583479b97f05a51c7370dd0c2d69f /cpukit/libfs
parentThis commit was generated by cvs2svn to compensate for changes in r22694, (diff)
downloadrtems-8ec7abb551a23bdf47509189145885a364810006.tar.bz2
010-03-04 Chris Johns <chrisj@rtems.org>
* libcsupport/include/rtems/libio.h, libcsupport/src/_rename_r.c: Add a rename file op and have rename use it. * libfs/Makefile.am, libfs/src/dosfs/msdos_rename.c, libfs/src/imfs/imfs_rename.c: New files to support the rename file op. * libfs/src/imfs/imfs.h: Add rename interface. * libfs/src/imfs/imfs_init.c: Add rename handler. * libfs/src/imfs/miniimfs_init.c: Fix up ops struct. * libfs/src/dosfs/msdos.h: Add msdos_rename and remove msdos_file_link. * libfs/src/dosfs/msdos_create.c: Remove the link call. * libfs/src/dosfs/msdos_eval.c: Fix a path parsing bug. * libfs/src/dosfs/msdos_init.c: Add rename handler and clean up the struct naming. * libfs/src/rfs/rtems-rfs-link.c, libfs/src/rfs/rtems-rfs-link.h: Change the link call to allow linking of directories if told to and change the unlink to handle unlink directories that are not empty so rename can be supported. * libfs/src/rfs/rtems-rfs-rtems-dir.c: Fix the link/unlink calls. * libfs/src/rfs/rtems-rfs-rtems.c: Add a rename handler. Fix the link/unlink calls. * libfs/src/dosfs/msdos_dir.c, libfs/src/dosfs/msdos_format.c, libfs/src/dosfs/msdos_misc.c, httpd/asp.c, libfs/src/nfsclient/src/nfs.c: Work around a newlib warning when using the is*() family of calls.
Diffstat (limited to 'cpukit/libfs')
-rw-r--r--cpukit/libfs/Makefile.am4
-rw-r--r--cpukit/libfs/src/dosfs/msdos.h11
-rw-r--r--cpukit/libfs/src/dosfs/msdos_create.c85
-rw-r--r--cpukit/libfs/src/dosfs/msdos_dir.c4
-rw-r--r--cpukit/libfs/src/dosfs/msdos_eval.c4
-rw-r--r--cpukit/libfs/src/dosfs/msdos_format.c4
-rw-r--r--cpukit/libfs/src/dosfs/msdos_init.c39
-rw-r--r--cpukit/libfs/src/dosfs/msdos_misc.c2
-rw-r--r--cpukit/libfs/src/dosfs/msdos_rename.c93
-rw-r--r--cpukit/libfs/src/imfs/imfs.h7
-rw-r--r--cpukit/libfs/src/imfs/imfs_init.c1
-rw-r--r--cpukit/libfs/src/imfs/imfs_rename.c54
-rw-r--r--cpukit/libfs/src/imfs/miniimfs_init.c4
-rw-r--r--cpukit/libfs/src/nfsclient/src/nfs.c2
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-link.c59
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-link.h21
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c2
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-rtems.c73
18 files changed, 314 insertions, 155 deletions
diff --git a/cpukit/libfs/Makefile.am b/cpukit/libfs/Makefile.am
index 56cdaa0052..02443de495 100644
--- a/cpukit/libfs/Makefile.am
+++ b/cpukit/libfs/Makefile.am
@@ -31,7 +31,7 @@ libimfs_a_SOURCES += src/imfs/imfs_chown.c src/imfs/imfs_config.c \
src/imfs/imfs_debug.c src/imfs/imfs_rmnod.c src/imfs/imfs_symlink.c \
src/imfs/imfs_readlink.c src/imfs/imfs_fdatasync.c src/imfs/imfs_fcntl.c \
src/imfs/ioman.c src/imfs/miniimfs_init.c src/imfs/imfs_load_tar.c \
- src/imfs/imfs.h \
+ src/imfs/imfs_rename.c src/imfs/imfs.h \
src/imfs/deviceerrno.c \
src/devfs/devfs_init.c src/devfs/devfs_eval.c src/devfs/devfs_mknod.c \
src/devfs/devfs_show.c src/devfs/devfs_node_type.c \
@@ -59,7 +59,7 @@ libdosfs_a_SOURCES += src/dosfs/msdos_create.c src/dosfs/msdos_dir.c \
src/dosfs/msdos_initsupp.c src/dosfs/msdos_misc.c \
src/dosfs/msdos_mknod.c src/dosfs/msdos_node_type.c \
src/dosfs/msdos_conv.c src/dosfs/msdos.h src/dosfs/msdos_format.c \
- src/dosfs/dosfs.h
+ src/dosfs/dosfs.h src/dosfs/msdos_rename.c
endif
# RFS
diff --git a/cpukit/libfs/src/dosfs/msdos.h b/cpukit/libfs/src/dosfs/msdos.h
index 260c4d7919..acbea3161e 100644
--- a/cpukit/libfs/src/dosfs/msdos.h
+++ b/cpukit/libfs/src/dosfs/msdos.h
@@ -259,6 +259,11 @@ int msdos_utime(
time_t modtime /* IN */
);
+int msdos_rename(rtems_filesystem_location_info_t *old_parent_loc,
+ rtems_filesystem_location_info_t *old_loc,
+ rtems_filesystem_location_info_t *new_parent_loc,
+ const char *new_name);
+
int msdos_initialize_support(
rtems_filesystem_mount_table_entry_t *temp_mt_entry,
const rtems_filesystem_operations_table *op_table,
@@ -323,12 +328,6 @@ msdos_dir_chmod(
int msdos_file_rmnod(rtems_filesystem_location_info_t *parent_pathloc, /* IN */
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 */
diff --git a/cpukit/libfs/src/dosfs/msdos_create.c b/cpukit/libfs/src/dosfs/msdos_create.c
index a9d8dbaac3..bab4a63fa8 100644
--- a/cpukit/libfs/src/dosfs/msdos_create.c
+++ b/cpukit/libfs/src/dosfs/msdos_create.c
@@ -267,88 +267,3 @@ err:
msdos_set_first_char4file_name(parent_loc->mt_entry, &dir_pos, 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 *name
-)
-{
- int rc = RC_OK;
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- msdos_fs_info_t *fs_info = to_loc->mt_entry->fs_info;
- fat_file_fd_t *to_fat_fd = to_loc->node_access;
- const char *token;
- int len;
-
- /*
- * check spelling and format new node name
- */
- if (MSDOS_NAME != msdos_get_token(name, strlen(name), &token, &len)) {
- rtems_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) {
- rtems_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)
- rtems_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,name,len,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_dir.c b/cpukit/libfs/src/dosfs/msdos_dir.c
index 6fa3ddecf1..1bb5c73024 100644
--- a/cpukit/libfs/src/dosfs/msdos_dir.c
+++ b/cpukit/libfs/src/dosfs/msdos_dir.c
@@ -146,7 +146,7 @@ msdos_format_dirent_with_dot(char *dst,const char *src)
src_tmp = src;
len = i;
while (i-- > 0) {
- *dst++ = tolower(*src_tmp++);
+ *dst++ = tolower((int)(*src_tmp++));
}
/*
* find last non-blank character of extension
@@ -165,7 +165,7 @@ msdos_format_dirent_with_dot(char *dst,const char *src)
len += i + 1; /* extension + dot */
src_tmp = src + MSDOS_SHORT_BASE_LEN;
while (i-- > 0) {
- *dst++ = tolower(*src_tmp++);
+ *dst++ = tolower((int)(*src_tmp++));
len++;
}
}
diff --git a/cpukit/libfs/src/dosfs/msdos_eval.c b/cpukit/libfs/src/dosfs/msdos_eval.c
index a97c245ed0..b216af4d18 100644
--- a/cpukit/libfs/src/dosfs/msdos_eval.c
+++ b/cpukit/libfs/src/dosfs/msdos_eval.c
@@ -108,7 +108,7 @@ msdos_eval_path(
while ((type != MSDOS_NO_MORE_PATH) && (type != MSDOS_INVALID_TOKEN))
{
type = msdos_get_token(&pathname[i], pathnamelen, &token, &token_len);
- pathnamelen += token_len;
+ pathnamelen -= token_len;
i += token_len;
fat_fd = pathloc->node_access;
@@ -152,7 +152,7 @@ msdos_eval_path(
rtems_semaphore_release(fs_info->vol_sema);
return (*pathloc->ops->evalpath_h)(&(pathname[i-token_len]),
- pathnamelen - token_len,
+ pathnamelen + token_len,
flags, pathloc);
}
}
diff --git a/cpukit/libfs/src/dosfs/msdos_format.c b/cpukit/libfs/src/dosfs/msdos_format.c
index d424c54aa6..d2ec19b267 100644
--- a/cpukit/libfs/src/dosfs/msdos_format.c
+++ b/cpukit/libfs/src/dosfs/msdos_format.c
@@ -648,7 +648,7 @@ static int msdos_format_determine_fmt_params
for (cnt = 0;
cnt < (sizeof(fmt_params->OEMName)-1);
cnt++) {
- if (isprint(*from)) {
+ if (isprint((int)*from)) {
*to++ = *from++;
}
else {
@@ -679,7 +679,7 @@ static int msdos_format_determine_fmt_params
for (cnt = 0;
cnt < (sizeof(fmt_params->VolLabel)-1);
cnt++) {
- if (isprint(*from)) {
+ if (isprint((int)*from)) {
*to++ = *from++;
}
else {
diff --git a/cpukit/libfs/src/dosfs/msdos_init.c b/cpukit/libfs/src/dosfs/msdos_init.c
index 89a3dac274..1e17bf9545 100644
--- a/cpukit/libfs/src/dosfs/msdos_init.c
+++ b/cpukit/libfs/src/dosfs/msdos_init.c
@@ -19,27 +19,24 @@
#include "msdos.h"
const rtems_filesystem_operations_table msdos_ops = {
- msdos_eval_path,
- msdos_eval4make,
-#if 0
- NULL, /* msdos_link */
-#else
- msdos_file_link, /* msdos_link (pseudo-functionality) */
-#endif
- 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,
- NULL
+ .evalpath_h = msdos_eval_path,
+ .evalformake_h = msdos_eval4make,
+ .link_h = NULL,
+ .unlink_h = msdos_file_rmnod,
+ .node_type_h = msdos_node_type,
+ .mknod_h = msdos_mknod,
+ .chown_h = NULL,
+ .freenod_h = msdos_free_node_info,
+ .mount_h = NULL,
+ .fsmount_me_h = msdos_initialize,
+ .unmount_h = NULL,
+ .fsunmount_me_h = msdos_shut_down,
+ .utime_h = NULL,
+ .eval_link_h = NULL,
+ .symlink_h = NULL,
+ .readlink_h = NULL,
+ .rename_h = msdos_rename,
+ .statvfs_h = NULL
};
/* msdos_initialize --
diff --git a/cpukit/libfs/src/dosfs/msdos_misc.c b/cpukit/libfs/src/dosfs/msdos_misc.c
index 003d2f57f4..4ab8e22b32 100644
--- a/cpukit/libfs/src/dosfs/msdos_misc.c
+++ b/cpukit/libfs/src/dosfs/msdos_misc.c
@@ -65,7 +65,7 @@ msdos_is_valid_name_char(const char ch)
if (strchr(" +,;=[]", ch) != NULL)
return MSDOS_NAME_LONG;
- if ((ch == '.') || isalnum(ch) ||
+ if ((ch == '.') || isalnum((int)ch) ||
(strchr("$%'-_@~`!(){}^#&", ch) != NULL))
return MSDOS_NAME_SHORT;
diff --git a/cpukit/libfs/src/dosfs/msdos_rename.c b/cpukit/libfs/src/dosfs/msdos_rename.c
new file mode 100644
index 0000000000..1ad625a251
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_rename.c
@@ -0,0 +1,93 @@
+/*
+ * Routine to rename a MSDOS filesystem node
+ *
+ * Copyright (C) 2010 Chris Johns <chrisj@rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ *
+ */
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <assert.h>
+#include <stdio.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_rename --
+ * Rename the node by removing the exitsing directory entry and creating a
+ * new one.
+ *
+ * PARAMETERS:
+ * old_parent_loc - node description for the "old parent" node
+ * old_loc - node description for the "old" node
+ * new_parent_loc - node description for the "parent" node
+ * name - name of new node
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set appropriately)
+ */
+int
+msdos_rename(rtems_filesystem_location_info_t *old_parent_loc,
+ rtems_filesystem_location_info_t *old_loc,
+ rtems_filesystem_location_info_t *new_parent_loc,
+ const char *new_name)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = new_parent_loc->mt_entry->fs_info;
+ fat_file_fd_t *old_fat_fd = old_loc->node_access;
+ const char *token;
+ int len;
+
+ /*
+ * check spelling and format new node name
+ */
+ if (MSDOS_NAME != msdos_get_token(new_name, strlen(new_name), &token, &len)) {
+ rtems_set_errno_and_return_minus_one(ENAMETOOLONG);
+ }
+ /*
+ * lock volume
+ */
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_set_errno_and_return_minus_one(EIO);
+
+ /*
+ * create new directory entry as "hard link", copying relevant info from
+ * existing file
+ */
+ rc = msdos_creat_node(new_parent_loc,
+ MSDOS_HARD_LINK,new_name,len,S_IFREG,
+ old_fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ /*
+ * mark file removed
+ */
+ rc = msdos_set_first_char4file_name(old_loc->mt_entry,
+ &old_fat_fd->dir_pos,
+ MSDOS_THIS_DIR_ENTRY_EMPTY);
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+}
diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h
index d198c5d884..ae682c06fd 100644
--- a/cpukit/libfs/src/imfs/imfs.h
+++ b/cpukit/libfs/src/imfs/imfs.h
@@ -529,6 +529,13 @@ extern int IMFS_readlink(
size_t bufsize
);
+extern int IMFS_rename(
+ rtems_filesystem_location_info_t *old_loc, /* IN */
+ rtems_filesystem_location_info_t *old_parent_loc, /* IN */
+ rtems_filesystem_location_info_t *new_parent_loc, /* IN */
+ const char *new_name /* IN */
+);
+
extern int IMFS_fdatasync(
rtems_libio_t *iop
);
diff --git a/cpukit/libfs/src/imfs/imfs_init.c b/cpukit/libfs/src/imfs/imfs_init.c
index d1b2d44fcf..9dae7cc690 100644
--- a/cpukit/libfs/src/imfs/imfs_init.c
+++ b/cpukit/libfs/src/imfs/imfs_init.c
@@ -50,6 +50,7 @@ const rtems_filesystem_operations_table IMFS_ops = {
IMFS_evaluate_link,
IMFS_symlink,
IMFS_readlink,
+ IMFS_rename,
NULL
};
diff --git a/cpukit/libfs/src/imfs/imfs_rename.c b/cpukit/libfs/src/imfs/imfs_rename.c
new file mode 100644
index 0000000000..f45aa5b694
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_rename.c
@@ -0,0 +1,54 @@
+/*
+ * IMFS_rename
+ *
+ * The following rouine creates a new link node under parent with the
+ * name given in name and removes the old.
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int IMFS_rename(
+ rtems_filesystem_location_info_t *old_parent_loc, /* IN */
+ rtems_filesystem_location_info_t *old_loc, /* IN */
+ rtems_filesystem_location_info_t *new_parent_loc, /* IN */
+ const char *new_name /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+ IMFS_jnode_t *new_parent;
+
+ the_jnode = old_loc->node_access;
+
+ strncpy( the_jnode->name, new_name, IMFS_NAME_MAX );
+
+ if ( the_jnode->Parent != NULL )
+ rtems_chain_extract( (rtems_chain_node *) the_jnode );
+
+ new_parent = new_parent_loc->node_access;
+ the_jnode->Parent = new_parent;
+
+ rtems_chain_append( &new_parent->info.directory.Entries, &the_jnode->Node );
+
+ /*
+ * Update the time.
+ */
+ IMFS_update_ctime( the_jnode );
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/miniimfs_init.c b/cpukit/libfs/src/imfs/miniimfs_init.c
index 15ca663429..2244dfde7d 100644
--- a/cpukit/libfs/src/imfs/miniimfs_init.c
+++ b/cpukit/libfs/src/imfs/miniimfs_init.c
@@ -49,7 +49,9 @@ const rtems_filesystem_operations_table miniIMFS_ops = {
NULL, /* XXX IMFS_utime, */
NULL, /* XXX IMFS_evaluate_link, */
NULL, /* XXX IMFS_symlink, */
- NULL /* XXX IMFS_readlink */
+ NULL, /* XXX IMFS_readlink */
+ NULL, /* XXX IMFS_rename */
+ NULL /* XXX IMFS_statvfs */
};
/*
diff --git a/cpukit/libfs/src/nfsclient/src/nfs.c b/cpukit/libfs/src/nfsclient/src/nfs.c
index 7014055448..53bfa770fb 100644
--- a/cpukit/libfs/src/nfsclient/src/nfs.c
+++ b/cpukit/libfs/src/nfsclient/src/nfs.c
@@ -3262,7 +3262,7 @@ char *dev = 0;
host++;
}
- if (isdigit(*host)) {
+ if (isdigit((int)*host)) {
/* avoid using gethostbyname */
sprintf(dev,"%s:%s",uidhost,path);
} else {
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-link.c b/cpukit/libfs/src/rfs/rtems-rfs-link.c
index bfbcae66e7..5346eabae3 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-link.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-link.c
@@ -24,13 +24,15 @@
#include <rtems/rfs/rtems-rfs-trace.h>
#include <rtems/rfs/rtems-rfs-dir.h>
#include <rtems/rfs/rtems-rfs-dir-hash.h>
+#include <rtems/rfs/rtems-rfs-link.h>
int
rtems_rfs_link (rtems_rfs_file_system* fs,
const char* name,
int length,
rtems_rfs_ino parent,
- rtems_rfs_ino target)
+ rtems_rfs_ino target,
+ bool link_dir)
{
rtems_rfs_inode_handle parent_inode;
rtems_rfs_inode_handle target_inode;
@@ -50,7 +52,11 @@ rtems_rfs_link (rtems_rfs_file_system* fs,
if (rc)
return rc;
- if (S_ISDIR (rtems_rfs_inode_get_mode (&target_inode)))
+ /*
+ * If the target inode is a directory and we cannot link directories
+ * return a not supported error code.
+ */
+ if (!link_dir && S_ISDIR (rtems_rfs_inode_get_mode (&target_inode)))
{
rtems_rfs_inode_close (fs, &target_inode);
return ENOTSUP;
@@ -99,11 +105,12 @@ rtems_rfs_unlink (rtems_rfs_file_system* fs,
rtems_rfs_ino parent,
rtems_rfs_ino target,
uint32_t doff,
- bool dir)
+ rtems_rfs_unlink_dir dir_mode)
{
rtems_rfs_inode_handle parent_inode;
rtems_rfs_inode_handle target_inode;
uint16_t links;
+ bool dir;
int rc;
if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
@@ -112,29 +119,35 @@ rtems_rfs_unlink (rtems_rfs_file_system* fs,
rc = rtems_rfs_inode_open (fs, target, &target_inode, true);
if (rc)
return rc;
-
+
+ /*
+ * If a directory process the unlink mode.
+ */
+
+ dir = RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&target_inode));
if (dir)
{
- rc = rtems_rfs_dir_empty (fs, &target_inode);
- if (rc > 0)
- {
- if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
- printf ("rtems-rfs: dir-empty: %d: %s\n", rc, strerror (rc));
- rtems_rfs_inode_close (fs, &target_inode);
- return rc;
- }
- }
- else
- {
- /*
- * Directories not allowed and the target is a directory.
- */
- if (RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&target_inode)))
+ switch (dir_mode)
{
- if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
- printf ("rtems-rfs: link is a directory\n");
- rtems_rfs_inode_close (fs, &target_inode);
- return EISDIR;
+ case rtems_rfs_unlink_dir_denied:
+ if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
+ printf ("rtems-rfs: link is a directory\n");
+ rtems_rfs_inode_close (fs, &target_inode);
+ return EISDIR;
+
+ case rtems_rfs_unlink_dir_if_empty:
+ rc = rtems_rfs_dir_empty (fs, &target_inode);
+ if (rc > 0)
+ {
+ if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
+ printf ("rtems-rfs: dir-empty: %d: %s\n", rc, strerror (rc));
+ rtems_rfs_inode_close (fs, &target_inode);
+ return rc;
+ }
+ break;
+
+ default:
+ break;
}
}
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-link.h b/cpukit/libfs/src/rfs/rtems-rfs-link.h
index d80db0195c..359360f0fd 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-link.h
+++ b/cpukit/libfs/src/rfs/rtems-rfs-link.h
@@ -26,20 +26,33 @@
#include <rtems/rfs/rtems-rfs-inode.h>
/**
- * Create a link.
+ * Directory unlink modes.
+ */
+typedef enum rtems_rfs_unlink_dir_e
+{
+ rtems_rfs_unlink_dir_denied, /**< Not allowed to unlink a directory. */
+ rtems_rfs_unlink_dir_if_empty, /**< Unlink if the directory is empty. */
+ rtems_rfs_unlink_dir_allowed /**< Unlinking of directories is allowed. */
+} rtems_rfs_unlink_dir;
+
+/**
+ * Create a link. Do not link directories unless renaming or you will create
+ * loops in the file system.
*
* @param fs The file system.
* @param name The name of the link.
* @param length The length of the name.
* @param parent The inode number of the parent directory.
* @param target The inode of the target.
+ * @param link_dir If true directories can be linked. Useful when renaming.
* @return int The error number (errno). No error if 0.
*/
int rtems_rfs_link (rtems_rfs_file_system* fs,
const char* name,
int length,
rtems_rfs_ino parent,
- rtems_rfs_ino target);
+ rtems_rfs_ino target,
+ bool link_dir);
/**
* Unlink the node from the parent directory. A directory offset for the target
@@ -50,14 +63,14 @@ int rtems_rfs_link (rtems_rfs_file_system* fs,
* @param parent The inode number of the parent directory.
* @param target The inode of the target.
* @param doff Parent directory entry offset for the target entry.
- * @param dir If true unlinking of directory nodes is allowed.
+ * @param dir_mode Directory unlink mode.
* @return int The error number (errno). No error if 0.
*/
int rtems_rfs_unlink (rtems_rfs_file_system* fs,
rtems_rfs_ino parent,
rtems_rfs_ino target,
uint32_t doff,
- bool dir);
+ rtems_rfs_unlink_dir dir_mode);
/**
* Symbolic link is an inode that has a path attached.
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c
index f22e3d6913..1de55a0e5b 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c
@@ -205,7 +205,7 @@ rtems_rfs_rtems_dir_rmnod (rtems_filesystem_location_info_t* parent_pathloc,
rtems_rfs_rtems_lock (fs);
- rc = rtems_rfs_unlink (fs, parent, ino, doff, true);
+ rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_if_empty);
if (rc)
{
rtems_rfs_rtems_unlock (fs);
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems.c
index 97e803a615..081f97646d 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-rtems.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems.c
@@ -478,7 +478,7 @@ rtems_rfs_rtems_link (rtems_filesystem_location_info_t* to_loc,
rtems_rfs_rtems_lock (fs);
- rc = rtems_rfs_link (fs, name, strlen (name), parent, target);
+ rc = rtems_rfs_link (fs, name, strlen (name), parent, target, false);
if (rc)
{
rtems_rfs_rtems_unlock (fs);
@@ -514,7 +514,7 @@ rtems_rfs_rtems_unlink (rtems_filesystem_location_info_t* parent_loc,
printf("rtems-rfs-rtems: unlink: parent:%ld doff:%lu ino:%ld\n",
parent, doff, ino);
- rc = rtems_rfs_unlink (fs, parent, ino, doff, false);
+ rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_denied);
if (rc)
{
rtems_rfs_rtems_unlock (fs);
@@ -1043,6 +1043,7 @@ rtems_rfs_rtems_mknod (const char *name,
*
* @param parent_pathloc
* @param pathloc
+ * @return int
*/
int
rtems_rfs_rtems_rmnod (rtems_filesystem_location_info_t* parent_pathloc,
@@ -1060,7 +1061,7 @@ rtems_rfs_rtems_rmnod (rtems_filesystem_location_info_t* parent_pathloc,
rtems_rfs_rtems_lock (fs);
- rc = rtems_rfs_unlink (fs, parent, ino, doff, false);
+ rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_denied);
if (rc)
{
rtems_rfs_rtems_unlock (fs);
@@ -1076,6 +1077,7 @@ rtems_rfs_rtems_rmnod (rtems_filesystem_location_info_t* parent_pathloc,
* everything related to this device.
*
* @param iop
+ * @return int
*/
int
rtems_rfs_rtems_fdatasync (rtems_libio_t* iop)
@@ -1090,6 +1092,68 @@ rtems_rfs_rtems_fdatasync (rtems_libio_t* iop)
}
/**
+ * Rename the node.
+ *
+ * @param old_parent_loc The old name's parent location.
+ * @param old_loc The old name's location.
+ * @param new_parent_loc The new name's parent location.
+ * @param new_name The new name.
+ * @return int
+ */
+int
+rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_loc,
+ rtems_filesystem_location_info_t* old_loc,
+ rtems_filesystem_location_info_t* new_parent_loc,
+ const char* new_name)
+{
+ rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (old_loc);
+ rtems_rfs_ino old_parent;
+ rtems_rfs_ino new_parent;
+ rtems_rfs_ino ino;
+ uint32_t doff;
+ int rc;
+
+ old_parent = rtems_rfs_rtems_get_pathloc_ino (old_parent_loc);
+ new_parent = rtems_rfs_rtems_get_pathloc_ino (new_parent_loc);
+
+ ino = rtems_rfs_rtems_get_pathloc_ino (old_loc);
+ doff = rtems_rfs_rtems_get_pathloc_doff (old_loc);
+
+ if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RENAME))
+ printf ("rtems-rfs: rename: ino:%ld doff:%lu, new parent:%ld new name:%s\n",
+ ino, doff, new_parent, new_name);
+
+ rtems_rfs_rtems_lock (fs);
+
+ /*
+ * Link to the inode before unlinking so the inode is not erased when
+ * unlinked.
+ */
+ rc = rtems_rfs_link (fs, new_name, strlen (new_name), new_parent, ino, true);
+ if (rc)
+ {
+ rtems_rfs_rtems_unlock (fs);
+ return rtems_rfs_rtems_error ("rename: linking", rc);
+ }
+
+ /*
+ * Unlink all inodes even directories with the dir option as false because a
+ * directory may not be empty.
+ */
+ rc = rtems_rfs_unlink (fs, old_parent, ino, doff,
+ rtems_rfs_unlink_dir_allowed);
+ if (rc)
+ {
+ rtems_rfs_rtems_unlock (fs);
+ return rtems_rfs_rtems_error ("rename: unlinking", rc);
+ }
+
+ rtems_rfs_rtems_unlock (fs);
+
+ return 0;
+}
+
+/**
* Return the file system stat data.
*
* @param pathloc
@@ -1150,7 +1214,7 @@ int rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t *mt_entry);
int rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t *mt_entry);
/**
- * RFS file system operations table
+ * RFS file system operations table.
*/
const rtems_filesystem_operations_table rtems_rfs_ops =
{
@@ -1170,6 +1234,7 @@ const rtems_filesystem_operations_table rtems_rfs_ops =
.eval_link_h = NULL, /* never called cause we lie in the node type */
.symlink_h = rtems_rfs_rtems_symlink,
.readlink_h = rtems_rfs_rtems_readlink,
+ .rename_h = rtems_rfs_rtems_rename,
.statvfs_h = rtems_rfs_rtems_statvfs
};