static void check_access( rtems_filesystem_eval_path_context_t *ctx, int eval_flags ) { const rtems_filesystem_location_info_t *currentloc = &ctx->currentloc; const rtems_filesystem_mount_table_entry_t *mt_entry = currentloc->mt_entry; if ((eval_flags & RTEMS_FS_PERMS_WRITE) == 0 || mt_entry->writeable) { struct stat st; int rv; st.st_mode = 0; st.st_uid = 0; st.st_gid = 0; rv = (*currentloc->handlers->fstat_h)(currentloc, &st); if (rv == 0) { bool access_ok = rtems_filesystem_check_access( eval_flags, st.st_mode, st.st_uid, st.st_gid ); if (!access_ok) { rtems_filesystem_eval_path_error(ctx, EACCES); } } else { rtems_filesystem_eval_path_error(ctx, 0); } } else { rtems_filesystem_eval_path_error(ctx, EROFS); } }
void rtems_filesystem_eval_path_continue( rtems_filesystem_eval_path_context_t *ctx ) { int eval_flags; while (ctx->pathlen > 0) { (*ctx->currentloc.mt_entry->ops->eval_path_h)(ctx); } eval_flags = rtems_filesystem_eval_path_get_flags(ctx); if (rtems_filesystem_eval_path_has_token(ctx)) { bool make = (eval_flags & RTEMS_FS_MAKE) != 0; if (make) { check_access(ctx, RTEMS_FS_PERMS_WRITE); } else { rtems_filesystem_eval_path_error(ctx, ENOENT); } } else { bool exclusive = (eval_flags & RTEMS_FS_EXCLUSIVE) != 0; if (!exclusive) { check_access(ctx, ctx->flags); } else { rtems_filesystem_eval_path_error(ctx, EEXIST); } } }
void rtems_filesystem_eval_path_recursive( rtems_filesystem_eval_path_context_t *ctx, const char *path, size_t pathlen ) { if (pathlen > 0) { if (ctx->recursionlevel < RTEMS_FILESYSTEM_SYMLOOP_MAX) { const char *saved_path = ctx->path; size_t saved_pathlen = ctx->pathlen; if (rtems_filesystem_is_delimiter(path [0])) { rtems_filesystem_eval_path_restart(ctx, &ctx->rootloc); } ctx->path = path; ctx->pathlen = pathlen; ++ctx->recursionlevel; while (ctx->pathlen > 0) { (*ctx->currentloc.mt_entry->ops->eval_path_h)(ctx); } --ctx->recursionlevel; ctx->path = saved_path; ctx->pathlen = saved_pathlen; } else { rtems_filesystem_eval_path_error(ctx, ELOOP); } } else { rtems_filesystem_eval_path_error(ctx, ENOENT); } }
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; 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) ); } }
/** * POSIX 1003.1b - 5.5.1 - Remove an existing link */ int unlink( const char *path ) { int rv = 0; rtems_filesystem_eval_path_context_t ctx; int eval_flags = RTEMS_FS_REJECT_TERMINAL_DOT; rtems_filesystem_location_info_t parentloc; int parent_eval_flags = RTEMS_FS_PERMS_WRITE | RTEMS_FS_PERMS_EXEC | RTEMS_FS_FOLLOW_LINK; const rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_start_with_parent( &ctx, path, eval_flags, &parentloc, parent_eval_flags ); if ( !rtems_filesystem_location_is_instance_root( currentloc ) ) { const rtems_filesystem_operations_table *ops = currentloc->mt_entry->ops; rv = (*ops->rmnod_h)( &parentloc, currentloc ); } else { rtems_filesystem_eval_path_error( &ctx, EBUSY ); rv = -1; } rtems_filesystem_eval_path_cleanup_with_parent( &ctx, &parentloc ); return rv; }
static rtems_filesystem_eval_path_generic_status msdos_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; if (rtems_filesystem_is_current_directory(token, tokenlen)) { rtems_filesystem_eval_path_clear_token(ctx); status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; } else { rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_get_currentloc(ctx); int rc = msdos_find_name(currentloc, token, tokenlen); if (rc == RC_OK) { rtems_filesystem_eval_path_clear_token(ctx); msdos_set_handlers(currentloc); if (rtems_filesystem_eval_path_has_path(ctx)) { status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; } } else if (rc == MSDOS_NAME_NOT_FOUND_ERR) { status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY; } else { rtems_filesystem_eval_path_error(ctx, 0); } } return status; }
static void create_regular_file( rtems_filesystem_eval_path_context_t *ctx, mode_t mode ) { int rv = 0; const rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_get_currentloc( ctx ); const char *token = rtems_filesystem_eval_path_get_token( ctx ); size_t tokenlen = rtems_filesystem_eval_path_get_tokenlen( ctx ); rv = rtems_filesystem_mknod( currentloc, token, tokenlen, S_IFREG | mode, 0 ); if ( rv == 0 ) { /* The mode only applies to future accesses of the newly created file */ rtems_filesystem_eval_path_set_flags( ctx, 0 ); rtems_filesystem_eval_path_set_path( ctx, token, tokenlen ); rtems_filesystem_eval_path_continue( ctx ); } else { rtems_filesystem_eval_path_error( ctx, 0 ); } }
static void rtems_ftpfs_eval_path( rtems_filesystem_eval_path_context_t *self ) { rtems_filesystem_eval_path_eat_delimiter(self); if (rtems_filesystem_eval_path_has_path(self)) { const char *path = rtems_filesystem_eval_path_get_path(self); size_t pathlen = rtems_filesystem_eval_path_get_pathlen(self); char *pathdup = malloc(pathlen + 1); rtems_filesystem_eval_path_clear_path(self); if (pathdup != NULL) { rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_get_currentloc(self); memcpy(pathdup, path, pathlen); pathdup [pathlen] = '\0'; currentloc->node_access = pathdup; currentloc->handlers = &rtems_ftpfs_handlers; } else { rtems_filesystem_eval_path_error(self, ENOMEM); } } }
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); if (link != NULL) { int rc = rtems_rfs_symlink_read (fs, ino, link, len, &len); if (rc == 0) { rtems_filesystem_eval_path_recursive (ctx, link, len); } else { rtems_filesystem_eval_path_error (ctx, 0); } free(link); } else { rtems_filesystem_eval_path_error (ctx, ENOMEM); } }
static void rtems_tfs_eval_path(rtems_filesystem_eval_path_context_t *self) { int eval_flags = rtems_filesystem_eval_path_get_flags(self); if ((eval_flags & RTEMS_FS_MAKE) == 0) { int rw = RTEMS_FS_PERMS_READ | RTEMS_FS_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 { rtems_filesystem_eval_path_error(self, EINVAL); } } else { rtems_filesystem_eval_path_error(self, EIO); } }
bool rtems_filesystem_eval_path_check_access( rtems_filesystem_eval_path_context_t *ctx, int eval_flags, mode_t node_mode, uid_t node_uid, gid_t node_gid ) { bool access_ok = rtems_filesystem_check_access( eval_flags, node_mode, node_uid, node_gid ); if (!access_ok) { rtems_filesystem_eval_path_error(ctx, EACCES); } return access_ok; }
ssize_t readlink( const char *path, char *buf, size_t bufsize ) { ssize_t rv = 0; rtems_filesystem_eval_path_context_t ctx; int eval_flags = RTEMS_FS_FOLLOW_HARD_LINK; const rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); const rtems_filesystem_operations_table *ops = currentloc->mt_entry->ops; rtems_filesystem_node_types_t type = (*ops->node_type_h)( currentloc ); if ( type == RTEMS_FILESYSTEM_SYM_LINK ) { rv = (*ops->readlink_h)( currentloc, buf, bufsize ); } else { rtems_filesystem_eval_path_error( &ctx, EINVAL ); rv = -1; } rtems_filesystem_eval_path_cleanup( &ctx ); return rv; }
static int register_subordinate_file_system( rtems_filesystem_mount_table_entry_t *mt_entry, const char *target ) { int rv = 0; rtems_filesystem_eval_path_context_t ctx; int eval_flags = RTEMS_FS_PERMS_RWX | RTEMS_FS_FOLLOW_LINK; rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_start( &ctx, target, eval_flags ); if ( !rtems_filesystem_location_is_instance_root( currentloc ) ) { rtems_filesystem_location_info_t targetloc; rtems_filesystem_global_location_t *mt_point_node; rtems_filesystem_eval_path_extract_currentloc( &ctx, &targetloc ); mt_point_node = rtems_filesystem_location_transform_to_global( &targetloc ); mt_entry->mt_point_node = mt_point_node; rv = (*mt_point_node->location.mt_entry->ops->mount_h)( mt_entry ); if ( rv == 0 ) { rtems_filesystem_mt_lock(); rtems_chain_append_unprotected( &rtems_filesystem_mount_table, &mt_entry->mt_node ); rtems_filesystem_mt_unlock(); } else { rtems_filesystem_global_location_release( mt_point_node ); } } else { rtems_filesystem_eval_path_error( &ctx, EBUSY ); rv = -1; } rtems_filesystem_eval_path_cleanup( &ctx ); return rv; }
static rtems_filesystem_eval_path_generic_status rtems_jffs2_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_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_get_currentloc(ctx); struct _inode *dir_i = rtems_jffs2_get_inode_by_location(currentloc); bool access_ok = rtems_filesystem_eval_path_check_access( ctx, RTEMS_FS_PERMS_EXEC, dir_i->i_mode, dir_i->i_uid, dir_i->i_gid ); if (access_ok) { struct _inode *entry_i; if (rtems_filesystem_is_current_directory(token, tokenlen)) { entry_i = dir_i; ++entry_i->i_count; } else if (rtems_filesystem_is_parent_directory(token, tokenlen)) { entry_i = dir_i->i_parent; ++entry_i->i_count; } else { entry_i = jffs2_lookup(dir_i, token, (int) tokenlen); } if (IS_ERR(entry_i)) { rtems_filesystem_eval_path_error(ctx, PTR_ERR(entry_i)); } else if (entry_i != NULL) { bool terminal = !rtems_filesystem_eval_path_has_path(ctx); int eval_flags = rtems_filesystem_eval_path_get_flags(ctx); bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0; rtems_filesystem_eval_path_clear_token(ctx); if (S_ISLNK(entry_i->i_mode) && (follow_sym_link || !terminal)) { struct jffs2_inode_info *f = JFFS2_INODE_INFO(entry_i); const char *target = f->target; rtems_filesystem_eval_path_recursive(ctx, target, strlen(target)); jffs2_iput(entry_i); } else { if (S_ISDIR(entry_i->i_mode) && entry_i->i_parent == NULL) { entry_i->i_parent = dir_i; ++dir_i->i_count; } jffs2_iput(dir_i); rtems_jffs2_set_location(currentloc, entry_i); if (rtems_filesystem_eval_path_has_path(ctx)) { status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; } } } else { status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY; } } return status; }
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_FS_PERMS_EXEC, 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; } 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_FS_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) ); } } } } } return status; }
int IMFS_make_generic_node( const char *path, mode_t mode, const IMFS_node_control *node_control, void *context ) { int rv = 0; mode &= ~rtems_filesystem_umask; switch (mode & S_IFMT) { case S_IFBLK: case S_IFCHR: case S_IFIFO: case S_IFREG: break; default: errno = EINVAL; rv = -1; break; } if ( rv == 0 ) { if ( node_control->imfs_type == IMFS_GENERIC ) { rtems_filesystem_eval_path_context_t ctx; int eval_flags = RTEMS_FS_FOLLOW_LINK | RTEMS_FS_MAKE | RTEMS_FS_EXCLUSIVE; const rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); if ( IMFS_is_imfs_instance( currentloc ) ) { IMFS_types_union info; IMFS_jnode_t *new_node; info.generic.context = context; new_node = IMFS_create_node_with_control( currentloc, node_control, rtems_filesystem_eval_path_get_token( &ctx ), rtems_filesystem_eval_path_get_tokenlen( &ctx ), mode, &info ); if ( new_node != NULL ) { IMFS_jnode_t *parent = currentloc->node_access; IMFS_update_ctime( parent ); IMFS_update_mtime( parent ); } else { rv = -1; } } else { rtems_filesystem_eval_path_error( &ctx, ENOTSUP ); rv = -1; } rtems_filesystem_eval_path_cleanup( &ctx ); } else { errno = EINVAL; rv = -1; } } return rv; }
static int do_open( rtems_libio_t *iop, const char *path, int oflag, mode_t mode ) { int rv = 0; int fd = rtems_libio_iop_to_descriptor( iop ); int rwflag = oflag + 1; bool read_access = (rwflag & _FREAD) == _FREAD; bool write_access = (rwflag & _FWRITE) == _FWRITE; bool make = (oflag & O_CREAT) == O_CREAT; bool exclusive = (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL); bool truncate = (oflag & O_TRUNC) == O_TRUNC; int eval_flags = RTEMS_FS_FOLLOW_LINK | (read_access ? RTEMS_FS_PERMS_READ : 0) | (write_access ? RTEMS_FS_PERMS_WRITE : 0) | (make ? RTEMS_FS_MAKE : 0) | (exclusive ? RTEMS_FS_EXCLUSIVE : 0); rtems_filesystem_eval_path_context_t ctx; rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); if ( rtems_filesystem_eval_path_has_token( &ctx ) ) { create_regular_file( &ctx, mode ); } if ( write_access ) { const rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_get_currentloc( &ctx ); mode_t type = rtems_filesystem_location_type( currentloc ); if ( S_ISDIR( type ) ) { rtems_filesystem_eval_path_error( &ctx, EISDIR ); } } iop->flags |= rtems_libio_fcntl_flags( oflag ); rtems_filesystem_eval_path_extract_currentloc( &ctx, &iop->pathinfo ); rtems_filesystem_eval_path_cleanup( &ctx ); rv = (*iop->pathinfo.handlers->open_h)( iop, path, oflag, mode ); if ( rv == 0 ) { if ( truncate ) { rv = ftruncate( fd, 0 ); if ( rv != 0 ) { (*iop->pathinfo.handlers->close_h)( iop ); } } if ( rv == 0 ) { rv = fd; } else { rv = -1; } } if ( rv < 0 ) { rtems_libio_free( iop ); } return rv; }