summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/shared/umon/tfsDriver.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/shared/umon/tfsDriver.c')
-rw-r--r--c/src/lib/libbsp/shared/umon/tfsDriver.c339
1 files changed, 141 insertions, 198 deletions
diff --git a/c/src/lib/libbsp/shared/umon/tfsDriver.c b/c/src/lib/libbsp/shared/umon/tfsDriver.c
index bf56e2a8b4..fcff017b94 100644
--- a/c/src/lib/libbsp/shared/umon/tfsDriver.c
+++ b/c/src/lib/libbsp/shared/umon/tfsDriver.c
@@ -3,6 +3,9 @@
*
* Initial release: Oct 1, 2004 by Ed Sutter
*
+ * Modifications to support reference counting in the file system are
+ * Copyright (c) 2012 embedded brains GmbH.
+ *
* This code was derived from the tftpDriver.c code written by
* W. Eric Norum, which was apparently derived from the IMFS driver.
*
@@ -69,79 +72,31 @@ struct tfdinfo {
*/
char TFS_PATHNAME_PREFIX[128];
-/*
- * Root node_access value
- * By using the address of a local static variable
- * we ensure a unique value for this identifier.
- */
-#define ROOT_NODE_ACCESS (&tfs_mutex)
-
-/* Number of streams open at the same time
- */
-static rtems_id tfs_mutex;
-
-extern rtems_filesystem_operations_table rtems_tfs_ops;
-extern rtems_filesystem_file_handlers_r rtems_tfs_handlers;
-
-/* Direct copy from the IMFS. Look at this.
- */
+static const rtems_filesystem_operations_table rtems_tfs_ops;
+static const rtems_filesystem_file_handlers_r rtems_tfs_handlers;
-rtems_filesystem_limits_and_options_t rtems_tfs_limits_and_options = {
- 5, /* link_max */
- 6, /* max_canon */
- 7, /* max_input */
- 255, /* name_max */
- 255, /* path_max */
- 2, /* pipe_buf */
- 1, /* posix_async_io */
- 2, /* posix_chown_restrictions */
- 3, /* posix_no_trunc */
- 4, /* posix_prio_io */
- 5, /* posix_sync_io */
- 6 /* posix_vdisable */
-};
+static bool rtems_tfs_is_directory(
+ const char *path,
+ size_t pathlen
+)
+{
+ return path [pathlen - 1] == '/';
+}
static int rtems_tfs_mount_me(
rtems_filesystem_mount_table_entry_t *mt_entry,
const void *data
)
{
- rtems_status_code sc;
-
- mt_entry->mt_fs_root.handlers = &rtems_tfs_handlers;
- mt_entry->mt_fs_root.ops = &rtems_tfs_ops;
-
- /* We have no TFS specific data to maintain. This filesystem
- * may only be mounted once. And we maintain no real filesystem
- * nodes, so there is no real root.
- */
-
- mt_entry->fs_info = NULL;
- mt_entry->mt_fs_root.node_access = ROOT_NODE_ACCESS;
+ char *root_path = strdup("/");
- /* These need to be looked at for full POSIX semantics.
- */
-
- mt_entry->pathconf_limits_and_options = rtems_tfs_limits_and_options;
-
-
- /* Now allocate a semaphore for mutual exclusion.
- * NOTE: This could be in an fsinfo for this filesystem type.
- */
-
- sc = rtems_semaphore_create (
- rtems_build_name('U', 'M', 'O', 'N'),
- 1,
- RTEMS_FIFO |
- RTEMS_BINARY_SEMAPHORE |
- RTEMS_NO_INHERIT_PRIORITY |
- RTEMS_NO_PRIORITY_CEILING |
- RTEMS_LOCAL,
- 0,
- &tfs_mutex);
+ if (root_path == NULL) {
+ rtems_set_errno_and_return_minus_one(ENOMEM);
+ }
- if (sc != RTEMS_SUCCESSFUL)
- rtems_set_errno_and_return_minus_one( ENOMEM );
+ mt_entry->mt_fs_root->location.handlers = &rtems_tfs_handlers;
+ mt_entry->mt_fs_root->location.ops = &rtems_tfs_ops;
+ mt_entry->mt_fs_root->location.node_access = root_path;
return 0;
}
@@ -180,16 +135,6 @@ int rtems_initialize_tfs_filesystem(
return(status);
}
-static int rtems_tfs_evaluate_for_make(
- const char *path,
- rtems_filesystem_location_info_t *pathloc,
- const char **name
-)
-{
- pathloc->node_access = NULL;
- rtems_set_errno_and_return_minus_one( EIO );
-}
-
/*
* Convert a path to canonical form
*/
@@ -242,53 +187,41 @@ static void fixPath(char *path)
*outp = '\0';
}
-static int rtems_tfs_eval_path(
- const char *pathname,
- size_t pathnamelen,
- int flags,
- rtems_filesystem_location_info_t *pathloc
-)
+static void rtems_tfs_eval_path(rtems_filesystem_eval_path_context_t *self)
{
- pathloc->handlers = &rtems_tfs_handlers;
-
- /*
- * Hack to provide the illusion of directories inside the TFS file system.
- * Paths ending in a / are assumed to be directories.
- */
- if (pathname[strlen(pathname)-1] == '/') {
- int isRelative = (pathloc->node_access != ROOT_NODE_ACCESS);
- char *cp;
-
- /*
- * Reject attempts to open() directories
- */
- if (flags & RTEMS_LIBIO_PERMS_RDWR)
- rtems_set_errno_and_return_minus_one( EISDIR );
- if (isRelative) {
- cp = malloc (strlen(pathloc->node_access)+strlen(pathname)+1);
- if (cp == NULL)
- rtems_set_errno_and_return_minus_one( ENOMEM );
- strcpy (cp, pathloc->node_access);
- strcat (cp, pathname);
+ int eval_flags = rtems_filesystem_eval_path_get_flags(self);
+
+ if ((eval_flags & RTEMS_LIBIO_MAKE) == 0) {
+ int rw = RTEMS_LIBIO_PERMS_READ | RTEMS_LIBIO_PERMS_WRITE;
+
+ if ((eval_flags & rw) != rw) {
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc(self);
+ char *current = currentloc->node_access;
+ size_t currentlen = strlen(current);
+ const char *path = rtems_filesystem_eval_path_get_path(self);
+ size_t pathlen = rtems_filesystem_eval_path_get_pathlen(self);
+ size_t len = currentlen + pathlen;
+
+ rtems_filesystem_eval_path_clear_path(self);
+
+ current = realloc(current, len + 1);
+ if (current != NULL) {
+ memcpy(current + currentlen, path, pathlen);
+ current [len] = '\0';
+ if (!rtems_tfs_is_directory(current, len)) {
+ fixPath (current);
+ }
+ currentloc->node_access = current;
+ } else {
+ rtems_filesystem_eval_path_error(self, ENOMEM);
+ }
} else {
- cp = strdup (pathname);
- if (cp == NULL)
- rtems_set_errno_and_return_minus_one( ENOMEM );
+ rtems_filesystem_eval_path_error(self, EINVAL);
}
- fixPath (cp);
- pathloc->node_access = cp;
- return 0;
+ } else {
+ rtems_filesystem_eval_path_error(self, EIO);
}
- if (pathloc->node_access != ROOT_NODE_ACCESS)
- pathloc->node_access = 0;
-
- /*
- * Reject it if it's not read-only or write-only.
- */
- flags &= RTEMS_LIBIO_PERMS_READ | RTEMS_LIBIO_PERMS_WRITE;
- if ((flags != RTEMS_LIBIO_PERMS_READ) && (flags != RTEMS_LIBIO_PERMS_WRITE) )
- rtems_set_errno_and_return_minus_one( EINVAL );
- return 0;
}
/*
@@ -310,8 +243,8 @@ static int rtems_tfs_eval_path(
static int rtems_tfs_open_worker(
rtems_libio_t *iop,
char *path,
- uint32_t flags,
- uint32_t mode
+ int oflag,
+ mode_t mode
)
{
static int beenhere = 0;
@@ -321,7 +254,7 @@ static int rtems_tfs_open_worker(
char *buf, *fstr, *istr, *bstr, pathcopy[TFSNAMESIZE*3+1];
if (RTEMS_TFS_DEBUG)
- printk("_open_r(%s,0x%" PRIx32 ",0x%" PRIx32 ")\n",path,flags,mode);
+ printk("_open_r(%s,0x%" PRIx32 ",0x%" PRIx32 ")\n",path,oflag,mode);
if (!beenhere) {
newlib_tfdlock();
@@ -371,7 +304,7 @@ static int rtems_tfs_open_worker(
/* If O_EXCL and O_CREAT are set, then fail if the file exists...
*/
- if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
+ if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
if (mon_tfsstat((char *)pathcopy)) {
return(EEXIST);
}
@@ -384,7 +317,7 @@ static int rtems_tfs_open_worker(
* O_WRONLY | O_CREAT Create if it doesn't exist
* O_WRONLY | O_CREAT | O_EXCL Fail if file exists
*/
- switch(flags & O_ACCMODE) {
+ switch(oflag & O_ACCMODE) {
case O_RDONLY:
flagmode = TFS_RDONLY;
break;
@@ -405,7 +338,7 @@ static int rtems_tfs_open_worker(
flagmode = TFS_CREATE|TFS_APPEND;
break;
default:
- printk("_open_r(): flag 0x%" PRIx32 " not supported\n",flags);
+ printk("_open_r(): flag 0x%i not supported\n",oflag);
return(ENOTSUP);
}
@@ -489,41 +422,27 @@ static int rtems_tfs_open_worker(
static int rtems_tfs_open(
rtems_libio_t *iop,
const char *new_name,
- uint32_t flags,
- uint32_t mode
+ int oflag,
+ mode_t mode
)
{
char *full_path_name;
- char *s1;
int err;
+ full_path_name = iop->pathinfo.node_access;
+
if (RTEMS_TFS_DEBUG)
- printk("rtems_tfs_open(%s)\n",new_name);
+ printk("rtems_tfs_open(%s)\n",full_path_name);
- /*
- * Tack the `current directory' on to relative paths.
- * We know that the current directory ends in a / character.
- */
- if (*new_name == '/') {
- /*
- * Skip the TFS filesystem prefix.
- */
- int len = strlen (TFS_PATHNAME_PREFIX);
- if (strncmp (new_name, TFS_PATHNAME_PREFIX, len))
- return ENOENT;
- new_name += len;
- s1 = "";
- } else {
- s1 = rtems_filesystem_current.node_access;
+ if (rtems_tfs_is_directory(full_path_name, strlen(full_path_name))) {
+ rtems_set_errno_and_return_minus_one (ENOTSUP);
}
- full_path_name = malloc (strlen (s1) + strlen (new_name) + 1);
- if (full_path_name == NULL)
- return ENOMEM;
- strcpy (full_path_name, s1);
- strcat (full_path_name, new_name);
- fixPath (full_path_name);
- err = rtems_tfs_open_worker (iop, full_path_name, flags, mode);
- free (full_path_name);
+
+ err = rtems_tfs_open_worker (iop, full_path_name, oflag, mode);
+ if (err != 0) {
+ rtems_set_errno_and_return_minus_one (err);
+ }
+
return err;
}
@@ -671,68 +590,92 @@ static int rtems_tfs_ioctl(
void *buf
)
{
- int fd, ret;
+ int ret;
- fd = (int) iop->data0;
ret = mon_tfsctrl(cmd,(long)buf,0);
- return(-1);
+ if (ret != TFS_OKAY)
+ return(-1);
+
+ return(0);
}
static rtems_filesystem_node_types_t rtems_tfs_node_type(
- rtems_filesystem_location_info_t *pathloc
+ const rtems_filesystem_location_info_t *loc
)
{
- if ((pathloc->node_access == NULL) ||
- (pathloc->node_access == ROOT_NODE_ACCESS))
- return RTEMS_FILESYSTEM_MEMORY_FILE;
- return RTEMS_FILESYSTEM_DIRECTORY;
-}
+ const char *path = loc->node_access;
+ size_t pathlen = strlen(path);
-static int rtems_tfs_free_node_info(
+ return rtems_tfs_is_directory(path, pathlen) ?
+ RTEMS_FILESYSTEM_DIRECTORY
+ : RTEMS_FILESYSTEM_MEMORY_FILE;
+}
-rtems_filesystem_location_info_t *pathloc)
+static int rtems_tfs_clone_node_info(
+ rtems_filesystem_location_info_t *loc
+)
{
- if (pathloc->node_access && (pathloc->node_access != ROOT_NODE_ACCESS)) {
- free (pathloc->node_access);
- pathloc->node_access = NULL;
+ int rv = 0;
+
+ loc->node_access = strdup(loc->node_access);
+
+ if (loc->node_access == NULL) {
+ errno = ENOMEM;
+ rv = -1;
}
- return 0;
+
+ return rv;
}
+static void rtems_tfs_free_node_info(
+ const rtems_filesystem_location_info_t *loc
+)
+{
+ free(loc->node_access);
+}
+
+static bool rtems_tfs_are_nodes_equal(
+ const rtems_filesystem_location_info_t *a,
+ const rtems_filesystem_location_info_t *b
+)
+{
+ return strcmp(a->node_access, b->node_access) == 0;
+}
-rtems_filesystem_operations_table rtems_tfs_ops = {
- rtems_tfs_eval_path, /* eval_path */
- rtems_tfs_evaluate_for_make, /* evaluate_for_make */
- rtems_filesystem_default_link, /* link */
- rtems_filesystem_default_unlink, /* unlink */
- rtems_tfs_node_type, /* node_type */
- rtems_filesystem_default_mknod, /* mknod */
- rtems_filesystem_default_chown, /* chown */
- rtems_tfs_free_node_info, /* freenodinfo */
- rtems_filesystem_default_mount, /* mount */
- rtems_tfs_mount_me, /* initialize */
- rtems_filesystem_default_unmount, /* unmount */
- rtems_filesystem_default_fsunmount, /* fsunmount */
- rtems_filesystem_default_utime, /* utime */
- rtems_filesystem_default_evaluate_link, /* evaluate_link */
- rtems_filesystem_default_symlink, /* symlink */
- rtems_filesystem_default_readlink, /* readlin */
- rtems_filesystem_default_rename, /* rename */
- rtems_filesystem_default_statvfs /* statvfs */
+static const rtems_filesystem_operations_table rtems_tfs_ops = {
+ .lock_h = rtems_filesystem_default_lock,
+ .unlock_h = rtems_filesystem_default_unlock,
+ .eval_path_h = rtems_tfs_eval_path,
+ .link_h = rtems_filesystem_default_link,
+ .are_nodes_equal_h = rtems_tfs_are_nodes_equal,
+ .node_type_h = rtems_tfs_node_type,
+ .mknod_h = rtems_filesystem_default_mknod,
+ .rmnod_h = rtems_filesystem_default_rmnod,
+ .fchmod_h = rtems_filesystem_default_fchmod,
+ .chown_h = rtems_filesystem_default_chown,
+ .clonenod_h = rtems_tfs_clone_node_info,
+ .freenod_h = rtems_tfs_free_node_info,
+ .mount_h = rtems_filesystem_default_mount,
+ .fsmount_me_h = rtems_tfs_mount_me,
+ .unmount_h = rtems_filesystem_default_unmount,
+ .fsunmount_me_h = rtems_filesystem_default_fsunmount,
+ .utime_h = rtems_filesystem_default_utime,
+ .symlink_h = rtems_filesystem_default_symlink,
+ .readlink_h = rtems_filesystem_default_readlink,
+ .rename_h = rtems_filesystem_default_rename,
+ .statvfs_h = rtems_filesystem_default_statvfs
};
-rtems_filesystem_file_handlers_r rtems_tfs_handlers = {
- rtems_tfs_open, /* open */
- rtems_tfs_close, /* close */
- rtems_tfs_read, /* read */
- rtems_tfs_write, /* write */
- rtems_tfs_ioctl, /* ioctl */
- rtems_tfs_lseek, /* lseek */
- rtems_filesystem_default_fstat, /* fstat */
- rtems_filesystem_default_fchmod, /* fchmod */
- rtems_tfs_ftruncate, /* ftruncate */
- rtems_filesystem_default_fsync, /* fsync */
- rtems_filesystem_default_fdatasync, /* fdatasync */
- rtems_filesystem_default_fcntl, /* fcntl */
- rtems_filesystem_default_rmnod /* rmnod */
+static const rtems_filesystem_file_handlers_r rtems_tfs_handlers = {
+ .open_h = rtems_tfs_open,
+ .close_h = rtems_tfs_close,
+ .read_h = rtems_tfs_read,
+ .write_h = rtems_tfs_write,
+ .ioctl_h = rtems_tfs_ioctl,
+ .lseek_h = rtems_tfs_lseek,
+ .fstat_h = rtems_filesystem_default_fstat,
+ .ftruncate_h = rtems_tfs_ftruncate,
+ .fsync_h = rtems_filesystem_default_fsync,
+ .fdatasync_h = rtems_filesystem_default_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl
};