diff options
Diffstat (limited to 'c/src/lib/libbsp/shared')
-rw-r--r-- | c/src/lib/libbsp/shared/umon/tfsDriver.c | 339 |
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 }; |