diff options
Diffstat (limited to 'cpukit/libfs/src/rfs/rtems-rfs-rtems.c')
-rw-r--r-- | cpukit/libfs/src/rfs/rtems-rfs-rtems.c | 884 |
1 files changed, 254 insertions, 630 deletions
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems.c index 7c92a09a3c..e6006a8970 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-rtems.c +++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems.c @@ -1,6 +1,9 @@ /* * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> * + * Modifications to support reference counting in the file system are + * Copyright (c) 2012 embedded brains GmbH. + * * 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. @@ -35,522 +38,245 @@ #include <rtems/rfs/rtems-rfs-link.h> #include "rtems-rfs-rtems.h" -/** - * The libio permissions for read/execute. - */ -#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ) -/** - * The libio permissions for write/execute. - */ -#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE) - -/** - * Evaluate the path to a node that wishes to be accessed. The pathloc is - * returned with the ino to the node to be accessed. - * - * The routine starts from the root stripping away any leading path separators - * breaking the path up into the node names and checking an inode exists for - * that node name. Permissions are checked to insure access to the node is - * allowed. A path to a node must be accessable all the way even if the end - * result is directly accessable. As a user on Linux try "ls /root/../tmp" and - * you will see if fails. - * - * The whole process is complicated by crossmount paths where we head down into - * this file system only to return to the top and out to a another mounted file - * system. For example we are mounted on '/e' and the user enters "ls - * /e/a/b/../../dev". We need to head down then back up. - * - * @param path - * @param pathlen - * @param flags - * @param pathloc - */ -static int -rtems_rfs_rtems_eval_path (const char* path, - size_t pathlen, - int flags, - rtems_filesystem_location_info_t* pathloc) +static bool +rtems_rfs_rtems_eval_perms (rtems_filesystem_eval_path_context_t *ctx, + int eval_flags, + rtems_rfs_inode_handle* inode) { - rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); - rtems_rfs_inode_handle inode; - rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); - uint32_t doff = 0; - const char* node; - size_t node_len; - int stripped; - int rc; - - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH)) - printf ("rtems-rfs-rtems: eval-path: in: path:%s pathlen:%zi ino:%" PRId32 "\n", - path, pathlen, ino); + return rtems_filesystem_eval_path_check_access( + ctx, + eval_flags, + rtems_rfs_inode_get_mode (inode), + rtems_rfs_inode_get_uid (inode), + rtems_rfs_inode_get_gid (inode) + ); +} +static rtems_filesystem_node_types_t +rtems_rfs_rtems_node_type_by_inode (rtems_rfs_inode_handle* inode) +{ /* - * Eat any separators at the start of the path. + * Do not return RTEMS_FILESYSTEM_HARD_LINK because this would result in an + * eval link which does not make sense in the case of the RFS file + * system. All directory entries are links to an inode. A link such as a HARD + * link is actually the normal path to a regular file, directory, device + * etc's inode. Links to inodes can be considered "the real" one, yet they + * are all links. */ - stripped = rtems_filesystem_prefix_separators (path, pathlen); - path += stripped; - pathlen -= stripped; - - rtems_rfs_rtems_lock (fs); - - while (true) - { - /* - * Open and load the inode. - */ - rc = rtems_rfs_inode_open (fs, ino, &inode, true); - if (rc > 0) - { - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_path: opening inode", rc); - } - - /* - * Is this the end of the pathname we were given ? - */ - if ((*path == '\0') || (pathlen == 0)) - break; - - /* - * If a directory the execute bit must be set for us to enter. - */ - if (RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)) && - !rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_SEARCH)) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_path: eval perms", EACCES); - } - - /* - * Extract the node name we will look for this time around. - */ - node = path; - node_len = 0; - while (!rtems_filesystem_is_separator (*path) && - (*path != '\0') && pathlen && - ((node_len + 1) < rtems_rfs_fs_max_name (fs))) - { - path++; - pathlen--; - node_len++; - } - - /* - * Eat any separators at the start of the path. - */ - stripped = rtems_filesystem_prefix_separators (path, pathlen); - path += stripped; - pathlen -= stripped; - node_len += stripped; - - /* - * If the node is the current directory and there is more path to come move - * on to it otherwise we are at the inode we want. - */ - if (rtems_rfs_current_dir (node)) - { - if (*path) - { - rtems_rfs_inode_close (fs, &inode); - continue; - } - break; - } - - /* - * If the node is a parent we must move up one directory. If the location - * is on another file system we have a crossmount so we call that file - * system to handle the remainder of the path. - */ - if (rtems_rfs_parent_dir (node)) - { - /* - * If we are at the root inode of the file system we have a crossmount - * path. - */ - if (ino == RTEMS_RFS_ROOT_INO) - { - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH)) - printf("rtems-rfs-rtems: eval-path: crossmount: path:%s (%zd)\n", - path - node_len, pathlen + node_len); - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - *pathloc = pathloc->mt_entry->mt_point_node; - return (*pathloc->ops->evalpath_h)(path - node_len, pathlen + node_len, - flags, pathloc); - } - - /* - * We need to find the parent of this node. - */ - rc = rtems_rfs_dir_lookup_ino (fs, &inode, - RTEMS_RFS_PARENT_DIR_STR, - RTEMS_RFS_PARENT_DIR_SIZE, &ino, &doff); - if (rc > 0) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_path: read parent inode", rc); - } - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH)) - printf("rtems-rfs-rtems: eval-path: parent: ino:%" PRId32 "\n", ino); - } - else - { - /* - * Look up the node name in this directory. If found drop through, close - * the current inode and let the loop open the inode so the mode can be - * read and handlers set. - */ - rc = rtems_rfs_dir_lookup_ino (fs, &inode, - node, node_len - stripped, &ino, &doff); - if (rc > 0) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return ((errno = rc) == 0) ? 0 : -1; - } - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH)) - printf("rtems-rfs-rtems: eval-path: down: path:%s ino:%" PRId32 "\n", node, ino); - } + uint16_t mode = rtems_rfs_inode_get_mode (inode); + if (RTEMS_RFS_S_ISDIR (mode)) + return RTEMS_FILESYSTEM_DIRECTORY; + else if (RTEMS_RFS_S_ISLNK (mode)) + return RTEMS_FILESYSTEM_SYM_LINK; + else if (RTEMS_RFS_S_ISBLK (mode) || RTEMS_RFS_S_ISCHR (mode)) + return RTEMS_FILESYSTEM_DEVICE; + else + return RTEMS_FILESYSTEM_MEMORY_FILE; +} - rc = rtems_rfs_inode_close (fs, &inode); - if (rc > 0) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_path: closing node", rc); - } - } +static void +rtems_rfs_rtems_lock_by_mt_entry (rtems_filesystem_mount_table_entry_t *mt_entry) +{ + rtems_rfs_file_system* fs = mt_entry->fs_info; - rtems_rfs_rtems_set_pathloc_ino (pathloc, ino); - rtems_rfs_rtems_set_pathloc_doff (pathloc, doff); + rtems_rfs_rtems_lock (fs); +} - rc = rtems_rfs_rtems_set_handlers (pathloc, &inode) ? 0 : EIO; +static void +rtems_rfs_rtems_unlock_by_mt_entry (rtems_filesystem_mount_table_entry_t *mt_entry) +{ + rtems_rfs_file_system* fs = mt_entry->fs_info; - rtems_rfs_inode_close (fs, &inode); rtems_rfs_rtems_unlock (fs); - - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH)) - printf("rtems-rfs-rtems: eval-path: ino:%" PRId32 "\n", ino); - - return rc; } -/** - * The following routine evaluates a path for a new node to be created. The - * pathloc is returned with a pointer to the parent of the new node. The name - * is returned with a pointer to the first character in the new node name. The - * parent node is verified to be a directory. - * - * @param path - * @param pathloc - * @param name - * @return int - */ -static int -rtems_rfs_rtems_eval_for_make (const char* path, - rtems_filesystem_location_info_t* pathloc, - const char** name) +static bool +rtems_rfs_rtems_is_directory( + rtems_filesystem_eval_path_context_t *ctx, + void *arg +) { - rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); - rtems_rfs_inode_handle inode; - rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); - rtems_rfs_ino node_ino; - uint32_t doff = 0; - const char* node; - int node_len; - int stripped; - int rc; + rtems_rfs_inode_handle* inode = arg; - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE)) - printf ("rtems-rfs-rtems: eval-for-make: path:%s ino:%" PRId32 "\n", path, ino); - - *name = path + strlen (path); - - while (*name != path) - { - (*name)--; - if (rtems_filesystem_is_separator (**name)) - { - (*name)++; - break; - } - } - - /* - * Eat any separators at start of the path. - */ - stripped = rtems_filesystem_prefix_separators (path, strlen(path)); - path += stripped; - - rtems_rfs_rtems_lock (fs); - - while (true) - { - /* - * Open and load the inode. - */ - rc = rtems_rfs_inode_open (fs, ino, &inode, true); - if (rc > 0) - { - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: read ino", rc); - } + return rtems_rfs_rtems_node_type_by_inode (inode) + == RTEMS_FILESYSTEM_DIRECTORY; +} - /* - * If a directory the execute bit must be set for us to enter. - */ - if (RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)) && - !rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_SEARCH)) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: eval perms", EACCES); - } +static void rtems_rfs_rtems_follow_link( + rtems_filesystem_eval_path_context_t* ctx, + rtems_rfs_file_system* fs, + rtems_rfs_ino ino +) +{ + size_t len = MAXPATHLEN; + char *link = malloc(len + 1); - /* - * Is this the end of the pathname we were given ? - */ - if (path == *name) - break; - - /* - * Extract the node name we will look for this time around. - */ - node = path; - node_len = 0; - while (!rtems_filesystem_is_separator(*path) && - (*path != '\0') && - (node_len < (rtems_rfs_fs_max_name (fs) - 1))) - { - node_len++; - path++; - } + if (link != NULL) { + int rc = rtems_rfs_symlink_read (fs, ino, link, len, &len); - /* - * Eat any separators at start of the new path. - */ - stripped = rtems_filesystem_prefix_separators (path, strlen (path)); - path += stripped; - node_len += stripped; - - /* - * If the node is the current directory and there is more path to come move - * on to it otherwise we are at the inode we want. - */ - if (rtems_rfs_current_dir (node)) - { - if (*path) - { - rtems_rfs_inode_close (fs, &inode); - continue; - } - break; + if (rc == 0) { + rtems_filesystem_eval_path_recursive (ctx, link, len); + } else { + rtems_filesystem_eval_path_error (ctx, 0); } - /* - * If the node is a parent we must move up one directory. If the location - * is on another file system we have a crossmount so we call that file - * system to handle the remainder of the path. - */ - if (rtems_rfs_parent_dir (path)) - { - /* - * If we are at the root inode of the file system we have a crossmount - * path. - */ - if (ino == RTEMS_RFS_ROOT_INO) - { - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE)) - printf("rtems-rfs-rtems: eval-for-make: crossmount: path:%s\n", - path - node_len); - - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - *pathloc = pathloc->mt_entry->mt_point_node; - return (*pathloc->ops->evalformake_h)(path + 2, pathloc, name); - } + free(link); + } else { + rtems_filesystem_eval_path_error (ctx, ENOMEM); + } +} - /* - * If not a directory give and up return. We cannot change dir from a - * regular file or device node. - */ - if (!RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode))) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: not dir", ENOTSUP); +static rtems_filesystem_eval_path_generic_status +rtems_rfs_rtems_eval_token( + rtems_filesystem_eval_path_context_t *ctx, + void *arg, + const char *token, + size_t tokenlen +) +{ + rtems_filesystem_eval_path_generic_status status = + RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE; + rtems_rfs_inode_handle* inode = arg; + bool access_ok = rtems_rfs_rtems_eval_perms (ctx, RTEMS_LIBIO_PERMS_SEARCH, inode); + + if (access_ok) { + if (rtems_filesystem_is_current_directory (token, tokenlen)) { + rtems_filesystem_eval_path_clear_token (ctx); + } else { + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc( ctx ); + rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (currentloc); + rtems_rfs_ino entry_ino; + uint32_t entry_doff; + int rc = rtems_rfs_dir_lookup_ino ( + fs, + inode, + token, + tokenlen, + &entry_ino, + &entry_doff + ); + + if (rc == 0) { + rc = rtems_rfs_inode_close (fs, inode); + if (rc == 0) { + rc = rtems_rfs_inode_open (fs, entry_ino, inode, true); + } + + if (rc != 0) { + /* + * This prevents the rtems_rfs_inode_close() from doing something in + * rtems_rfs_rtems_eval_path(). + */ + memset (inode, 0, sizeof(*inode)); + } + } else { + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY; + rc = -1; } - /* - * We need to find the parent of this node. - */ - rc = rtems_rfs_dir_lookup_ino (fs, &inode, - RTEMS_RFS_PARENT_DIR_STR, - RTEMS_RFS_PARENT_DIR_SIZE, &ino, &doff); - if (rc > 0) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: read parent inode", rc); - } - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE)) - printf ("rtems-rfs-rtems: eval-for-make: parent: ino:%" PRId32 "\n", ino); - } - else - { - /* - * Read the inode so we know it exists and what type it is. - */ - rc = rtems_rfs_dir_lookup_ino (fs, &inode, - node, node_len - stripped, &ino, &doff); - if (rc > 0) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: reading inode", rc); + if (rc == 0) { + bool is_sym_link = rtems_rfs_rtems_node_type_by_inode (inode) + == RTEMS_FILESYSTEM_SYM_LINK; + int eval_flags = rtems_filesystem_eval_path_get_flags (ctx); + bool follow_sym_link = (eval_flags & RTEMS_LIBIO_FOLLOW_SYM_LINK) != 0; + bool terminal = !rtems_filesystem_eval_path_has_path (ctx); + + rtems_filesystem_eval_path_clear_token (ctx); + + if (is_sym_link && (follow_sym_link || !terminal)) { + rtems_rfs_rtems_follow_link (ctx, fs, entry_ino); + } else { + rc = rtems_rfs_rtems_set_handlers (currentloc, inode) ? 0 : EIO; + if (rc == 0) { + rtems_rfs_rtems_set_pathloc_ino (currentloc, entry_ino); + rtems_rfs_rtems_set_pathloc_doff (currentloc, entry_doff); + + if (!terminal) { + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; + } + } else { + rtems_filesystem_eval_path_error ( + ctx, + rtems_rfs_rtems_error ("eval_path: set handlers", rc) + ); + } + } } - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE)) - printf("rtems-rfs-rtems: eval-for-make: down: path:%s ino:%" PRId32 "\n", - node, ino); - } - - rc = rtems_rfs_inode_close (fs, &inode); - if (rc > 0) - { - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: closing node", rc); } } - if (!RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode))) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: not dir", ENOTDIR); - } + return status; +} - if (!rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_WX)) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: cannot write", EACCES); - } +static const rtems_filesystem_eval_path_generic_config +rtems_rfs_rtems_eval_config = { + .is_directory = rtems_rfs_rtems_is_directory, + .eval_token = rtems_rfs_rtems_eval_token +}; - /* - * Make sure the name does not already exists in the directory. - */ - rc = rtems_rfs_dir_lookup_ino (fs, &inode, *name, strlen (*name), - &node_ino, &doff); - if (rc == 0) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: found name", EEXIST); - } +static void +rtems_rfs_rtems_eval_path (rtems_filesystem_eval_path_context_t *ctx) +{ + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc (ctx); + rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (currentloc); + rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (currentloc); + rtems_rfs_inode_handle inode; + int rc; - if (rc != ENOENT) - { - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("eval_for_make: look up", rc); + rc = rtems_rfs_inode_open (fs, ino, &inode, true); + if (rc == 0) { + rtems_filesystem_eval_path_generic ( + ctx, + &inode, + &rtems_rfs_rtems_eval_config + ); + rc = rtems_rfs_inode_close (fs, &inode); + if (rc != 0) { + rtems_filesystem_eval_path_error ( + ctx, + rtems_rfs_rtems_error ("eval_path: closing inode", rc) + ); + } + } else { + rtems_filesystem_eval_path_error ( + ctx, + rtems_rfs_rtems_error ("eval_path: opening inode", rc) + ); } - - /* - * Set the parent ino in the path location. - */ - - rtems_rfs_rtems_set_pathloc_ino (pathloc, ino); - rtems_rfs_rtems_set_pathloc_doff (pathloc, doff); - - rc = rtems_rfs_rtems_set_handlers (pathloc, &inode) ? 0 : EIO; - - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE)) - printf("rtems-rfs-rtems: eval-for-make: parent ino:%" PRId32 " name:%s\n", - ino, *name); - - rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); - - return rc; } /** * The following rouine creates a new link node under parent with the name - * given in name. The link node is set to point to the node at to_loc. - * - * @param to_loc - * @param parent_loc - * @param name - * @return int + * given in name. The link node is set to point to the node at targetloc. */ static int -rtems_rfs_rtems_link (rtems_filesystem_location_info_t* to_loc, - rtems_filesystem_location_info_t* parent_loc, - const char* name) +rtems_rfs_rtems_link (const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *targetloc, + const char *name, + size_t namelen) { - rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (to_loc); - rtems_rfs_ino target = rtems_rfs_rtems_get_pathloc_ino (to_loc); - rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc); + rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (targetloc); + rtems_rfs_ino target = rtems_rfs_rtems_get_pathloc_ino (targetloc); + rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parentloc); int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_LINK)) printf ("rtems-rfs-rtems: link: in: parent:%" PRId32 " target:%" PRId32 "\n", parent, target); - rtems_rfs_rtems_lock (fs); - - rc = rtems_rfs_link (fs, name, strlen (name), parent, target, false); + rc = rtems_rfs_link (fs, name, namelen, parent, target, false); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("link: linking", rc); } - rtems_rfs_rtems_unlock (fs); return 0; } /** - * Routine to remove a link node from the file system. - * - * @param parent_loc - * @param loc - * @return int - */ - -static int -rtems_rfs_rtems_unlink (rtems_filesystem_location_info_t* parent_loc, - rtems_filesystem_location_info_t* loc) -{ - rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parent_loc); - rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc); - rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (loc); - uint32_t doff = rtems_rfs_rtems_get_pathloc_doff (loc); - int rc; - - rtems_rfs_rtems_lock (fs); - - if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_UNLINK)) - printf("rtems-rfs-rtems: unlink: parent:%" PRId32 " doff:%" PRIu32 " ino:%" PRId32 "\n", - parent, doff, ino); - - rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_denied); - if (rc) - { - rtems_rfs_rtems_unlock (fs); - return rtems_rfs_rtems_error ("unlink: unlink inode", rc); - } - - rtems_rfs_rtems_unlock (fs); - - return 0; -} - -/** * The following verifies that and returns the type of node that the loc refers * to. * @@ -559,51 +285,28 @@ rtems_rfs_rtems_unlink (rtems_filesystem_location_info_t* parent_loc, */ static rtems_filesystem_node_types_t -rtems_rfs_rtems_node_type (rtems_filesystem_location_info_t* pathloc) +rtems_rfs_rtems_node_type (const rtems_filesystem_location_info_t* pathloc) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); rtems_filesystem_node_types_t type; rtems_rfs_inode_handle inode; - uint16_t mode; int rc; - rtems_rfs_rtems_lock (fs); - rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("node_type: opening inode", rc); } - /* - * Do not return RTEMS_FILESYSTEM_HARD_LINK because this would result in an - * eval link which does not make sense in the case of the RFS file - * system. All directory entries are links to an inode. A link such as a HARD - * link is actually the normal path to a regular file, directory, device - * etc's inode. Links to inodes can be considered "the real" one, yet they - * are all links. - */ - mode = rtems_rfs_inode_get_mode (&inode); - if (RTEMS_RFS_S_ISDIR (mode)) - type = RTEMS_FILESYSTEM_DIRECTORY; - else if (RTEMS_RFS_S_ISLNK (mode)) - type = RTEMS_FILESYSTEM_SYM_LINK; - else if (RTEMS_RFS_S_ISBLK (mode) || RTEMS_RFS_S_ISCHR (mode)) - type = RTEMS_FILESYSTEM_DEVICE; - else - type = RTEMS_FILESYSTEM_MEMORY_FILE; + type = rtems_rfs_rtems_node_type_by_inode (&inode); rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("node_type: closing inode", rc); } - rtems_rfs_rtems_unlock (fs); - return type; } @@ -618,9 +321,9 @@ rtems_rfs_rtems_node_type (rtems_filesystem_location_info_t* pathloc) */ static int -rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc, - uid_t owner, - gid_t group) +rtems_rfs_rtems_chown (const rtems_filesystem_location_info_t *pathloc, + uid_t owner, + gid_t group) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); @@ -634,12 +337,9 @@ rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc, printf ("rtems-rfs-rtems: chown: in: ino:%" PRId32 " uid:%d gid:%d\n", ino, owner, group); - rtems_rfs_rtems_lock (fs); - rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("chown: opening inode", rc); } @@ -653,7 +353,6 @@ rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc, if ((uid != rtems_rfs_inode_get_uid (&inode)) && (uid != 0)) { rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("chown: not able", EPERM); } #endif @@ -663,12 +362,9 @@ rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc, rc = rtems_rfs_inode_close (fs, &inode); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("chown: closing inode", rc); } - rtems_rfs_rtems_unlock (fs); - return 0; } @@ -683,21 +379,18 @@ rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc, */ static int -rtems_rfs_rtems_utime(rtems_filesystem_location_info_t* pathloc, - time_t atime, - time_t mtime) +rtems_rfs_rtems_utime(const rtems_filesystem_location_info_t* pathloc, + time_t atime, + time_t mtime) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); rtems_rfs_inode_handle inode; int rc; - rtems_rfs_rtems_lock (fs); - rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("utime: read inode", rc); } @@ -707,73 +400,46 @@ rtems_rfs_rtems_utime(rtems_filesystem_location_info_t* pathloc, rc = rtems_rfs_inode_close (fs, &inode); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("utime: closing inode", rc); } - rtems_rfs_rtems_unlock (fs); - return 0; } /** - * The following rouine creates a new symbolic link node under parent with the - * name given in name. The node is set to point to the node at to_loc. - * - * @param parent_loc - * @param link_name - * @param node_name - * return int + * The following routine creates a new symbolic link node under parent with the + * name given in node_name. */ static int -rtems_rfs_rtems_symlink (rtems_filesystem_location_info_t* parent_loc, - const char* link_name, - const char* node_name) +rtems_rfs_rtems_symlink (const rtems_filesystem_location_info_t* parent_loc, + const char* node_name, + size_t node_name_len, + const char* target) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parent_loc); rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc); - uid_t uid; - gid_t gid; int rc; -#if defined(RTEMS_POSIX_API) - uid = geteuid (); - gid = getegid (); -#else - uid = 0; - gid = 0; -#endif - - rtems_rfs_rtems_lock (fs); - - rc = rtems_rfs_symlink (fs, node_name, strlen (node_name), - link_name, strlen (link_name), - uid, gid, parent); + rc = rtems_rfs_symlink (fs, node_name, node_name_len, + target, strlen (target), + geteuid(), getegid(), parent); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("symlink: linking", rc); } - rtems_rfs_rtems_unlock (fs); - return 0; } /** * The following rouine puts the symblic links destination name into buf. - * - * @param loc - * @param buf - * @param bufsize - * @return int */ static ssize_t -rtems_rfs_rtems_readlink (rtems_filesystem_location_info_t* pathloc, - char* buf, - size_t bufsize) +rtems_rfs_rtems_readlink (const rtems_filesystem_location_info_t* pathloc, + char* buf, + size_t bufsize) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); @@ -783,23 +449,18 @@ rtems_rfs_rtems_readlink (rtems_filesystem_location_info_t* pathloc, if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_READLINK)) printf ("rtems-rfs-rtems: readlink: in: ino:%" PRId32 "\n", ino); - rtems_rfs_rtems_lock (fs); - rc = rtems_rfs_symlink_read (fs, ino, buf, bufsize, &length); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("readlink: reading link", rc); } - rtems_rfs_rtems_unlock (fs); - - return (int) length; + return (ssize_t) length; } -int -rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc, - mode_t mode) +static int +rtems_rfs_rtems_fchmod (const rtems_filesystem_location_info_t* pathloc, + mode_t mode) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); @@ -814,12 +475,9 @@ rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc, printf ("rtems-rfs-rtems: fchmod: in: ino:%" PRId32 " mode:%06" PRIomode_t "\n", ino, mode); - rtems_rfs_rtems_lock (fs); - rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("fchmod: opening inode", rc); } @@ -834,7 +492,6 @@ rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc, if ((uid != rtems_rfs_inode_get_uid (&inode)) && (uid != 0)) { rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("fchmod: checking uid", EPERM); } #endif @@ -847,18 +504,15 @@ rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc, rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("fchmod: closing inode", rc); } - rtems_rfs_rtems_unlock (fs); - return 0; } int -rtems_rfs_rtems_fstat (rtems_filesystem_location_info_t* pathloc, - struct stat* buf) +rtems_rfs_rtems_fstat (const rtems_filesystem_location_info_t* pathloc, + struct stat* buf) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); @@ -870,12 +524,9 @@ rtems_rfs_rtems_fstat (rtems_filesystem_location_info_t* pathloc, if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_STAT)) printf ("rtems-rfs-rtems: stat: in: ino:%" PRId32 "\n", ino); - rtems_rfs_rtems_lock (fs); - rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("stat: opening inode", rc); } @@ -931,32 +582,25 @@ rtems_rfs_rtems_fstat (rtems_filesystem_location_info_t* pathloc, rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("stat: closing inode", rc); } - rtems_rfs_rtems_unlock (fs); return 0; } /** * Routine to create a node in the RFS file system. - * - * @param name - * @param mode - * @param dev - * @param pathloc - * @return int */ static int -rtems_rfs_rtems_mknod (const char *name, - mode_t mode, - dev_t dev, - rtems_filesystem_location_info_t *pathloc) +rtems_rfs_rtems_mknod (const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev) { - rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); - rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (pathloc); + rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parentloc); + rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parentloc); rtems_rfs_ino ino; rtems_rfs_inode_handle inode; uid_t uid; @@ -971,21 +615,17 @@ rtems_rfs_rtems_mknod (const char *name, gid = 0; #endif - rtems_rfs_rtems_lock (fs); - - rc = rtems_rfs_inode_create (fs, parent, name, strlen (name), + rc = rtems_rfs_inode_create (fs, parent, name, namelen, rtems_rfs_rtems_imode (mode), 1, uid, gid, &ino); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("mknod: inode create", rc); } rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("mknod: inode open", rc); } @@ -1003,18 +643,15 @@ rtems_rfs_rtems_mknod (const char *name, else { rtems_rfs_inode_close (fs, &inode); - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("mknod: bad mode", EINVAL); } rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("mknod: closing inode", rc); } - rtems_rfs_rtems_unlock (fs); return 0; } @@ -1026,8 +663,8 @@ rtems_rfs_rtems_mknod (const char *name, * @return int */ int -rtems_rfs_rtems_rmnod (rtems_filesystem_location_info_t* parent_pathloc, - rtems_filesystem_location_info_t* pathloc) +rtems_rfs_rtems_rmnod (const rtems_filesystem_location_info_t* parent_pathloc, + const rtems_filesystem_location_info_t* pathloc) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_pathloc); @@ -1039,16 +676,15 @@ rtems_rfs_rtems_rmnod (rtems_filesystem_location_info_t* parent_pathloc, printf ("rtems-rfs: rmnod: parent:%" PRId32 " doff:%" PRIu32 ", ino:%" PRId32 "\n", parent, doff, ino); - rtems_rfs_rtems_lock (fs); + if (ino == RTEMS_RFS_ROOT_INO) + return rtems_rfs_rtems_error ("rmnod: root inode", EBUSY); - rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_denied); + rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_if_empty); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("rmnod: unlinking", rc); } - rtems_rfs_rtems_unlock (fs); return 0; } @@ -1073,18 +709,13 @@ 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 */ static 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_rtems_rename(const rtems_filesystem_location_info_t* old_parent_loc, + const rtems_filesystem_location_info_t* old_loc, + const rtems_filesystem_location_info_t* new_parent_loc, + const char* new_name, + size_t new_name_len) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (old_loc); rtems_rfs_ino old_parent; @@ -1100,19 +731,16 @@ rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_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:%" PRId32 " doff:%" PRIu32 ", new parent:%" PRId32 " new name:%s\n", - ino, doff, new_parent, new_name); - - rtems_rfs_rtems_lock (fs); + printf ("rtems-rfs: rename: ino:%" PRId32 " doff:%" PRIu32 ", new parent:%" PRId32 "\n", + ino, doff, new_parent); /* * 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); + rc = rtems_rfs_link (fs, new_name, new_name_len, new_parent, ino, true); if (rc) { - rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("rename: linking", rc); } @@ -1124,12 +752,9 @@ rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_loc, 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; } @@ -1141,8 +766,8 @@ rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_loc, * @return int */ static int -rtems_rfs_rtems_statvfs (rtems_filesystem_location_info_t* pathloc, - struct statvfs* sb) +rtems_rfs_rtems_statvfs (const rtems_filesystem_location_info_t* pathloc, + struct statvfs* sb) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); size_t blocks; @@ -1177,12 +802,10 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_link_handlers = .ioctl_h = rtems_filesystem_default_ioctl, .lseek_h = rtems_filesystem_default_lseek, .fstat_h = rtems_rfs_rtems_fstat, - .fchmod_h = rtems_filesystem_default_fchmod, .ftruncate_h = rtems_filesystem_default_ftruncate, .fsync_h = rtems_filesystem_default_fsync, .fdatasync_h = rtems_filesystem_default_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, - .rmnod_h = rtems_rfs_rtems_rmnod + .fcntl_h = rtems_filesystem_default_fcntl }; /** @@ -1191,27 +814,30 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_link_handlers = int rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t *mt_entry, const void *data); -int rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t *mt_entry); +void rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t *mt_entry); /** * RFS file system operations table. */ const rtems_filesystem_operations_table rtems_rfs_ops = { - .evalpath_h = rtems_rfs_rtems_eval_path, - .evalformake_h = rtems_rfs_rtems_eval_for_make, + .lock_h = rtems_rfs_rtems_lock_by_mt_entry, + .unlock_h = rtems_rfs_rtems_unlock_by_mt_entry, + .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal, + .eval_path_h = rtems_rfs_rtems_eval_path, .link_h = rtems_rfs_rtems_link, - .unlink_h = rtems_rfs_rtems_unlink, .node_type_h = rtems_rfs_rtems_node_type, + .fchmod_h = rtems_rfs_rtems_fchmod, .mknod_h = rtems_rfs_rtems_mknod, + .rmnod_h = rtems_rfs_rtems_rmnod, .chown_h = rtems_rfs_rtems_chown, + .clonenod_h = rtems_filesystem_default_clonenode, .freenod_h = rtems_filesystem_default_freenode, .mount_h = rtems_filesystem_default_mount, .fsmount_me_h = rtems_rfs_rtems_initialise, .unmount_h = rtems_filesystem_default_unmount, .fsunmount_me_h = rtems_rfs_rtems_shutdown, .utime_h = rtems_rfs_rtems_utime, - .eval_link_h = rtems_filesystem_default_evaluate_link, /* 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, @@ -1292,9 +918,9 @@ rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t* mt_entry, mt_entry->fs_info = fs; - mt_entry->mt_fs_root.node_access = (void*) RTEMS_RFS_ROOT_INO; - mt_entry->mt_fs_root.handlers = &rtems_rfs_rtems_dir_handlers; - mt_entry->mt_fs_root.ops = &rtems_rfs_ops; + mt_entry->mt_fs_root->location.node_access = (void*) RTEMS_RFS_ROOT_INO; + mt_entry->mt_fs_root->location.handlers = &rtems_rfs_rtems_dir_handlers; + mt_entry->mt_fs_root->location.ops = &rtems_rfs_ops; rtems_rfs_rtems_unlock (fs); @@ -1304,19 +930,17 @@ rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t* mt_entry, /** * Shutdown the file system. */ -int +void rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t* mt_entry) { rtems_rfs_file_system* fs = mt_entry->fs_info; rtems_rfs_rtems_private* rtems; - int rc; rtems = rtems_rfs_fs_user (fs); - rc = rtems_rfs_fs_close(fs); + /* FIXME: Return value? */ + rtems_rfs_fs_close(fs); rtems_rfs_mutex_destroy (&rtems->access); free (rtems); - - return rtems_rfs_rtems_error ("shutdown: close", rc); } |