int IMFS_fchmod( const rtems_filesystem_location_info_t *loc, mode_t mode ) { IMFS_jnode_t *jnode; #if defined(RTEMS_POSIX_API) uid_t st_uid; #endif jnode = loc->node_access; /* * Verify I am the owner of the node or the super user. */ #if defined(RTEMS_POSIX_API) st_uid = geteuid(); if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) ) rtems_set_errno_and_return_minus_one( EPERM ); #endif /* * Change only the RWX permissions on the jnode to mode. */ jnode->st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX); jnode->st_mode |= mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX); IMFS_update_ctime( jnode ); return 0; }
int IMFS_mknod( const rtems_filesystem_location_info_t *parentloc, const char *name, size_t namelen, mode_t mode, dev_t dev ) { int rv = 0; IMFS_jnode_types_t type; IMFS_types_union info; IMFS_jnode_t *new_node; get_type_and_info_by_mode_and_dev( mode, dev, &type, &info ); new_node = IMFS_create_node( parentloc, type, name, namelen, mode, &info ); if ( new_node != NULL ) { IMFS_jnode_t *parent = parentloc->node_access; IMFS_update_ctime( parent ); IMFS_update_mtime( parent ); } else { rv = -1; } return rv; }
static IMFS_jnode_t *IMFS_node_remove_hard_link( IMFS_jnode_t *node ) { IMFS_link_t *hard_link = (IMFS_link_t *) node; IMFS_jnode_t *target = hard_link->link_node; _Assert( target != NULL ); if ( target->st_nlink == 1 ) { target = (*target->control->node_remove)( target ); if ( target == NULL ) { node = NULL; } } else { --target->st_nlink; IMFS_update_ctime( target ); } if ( target != NULL ) { --target->reference_count; if ( target->reference_count == 0 ) { IMFS_node_destroy( target ); } } return node; }
int IMFS_chown( rtems_filesystem_location_info_t *pathloc, /* IN */ uid_t owner, /* IN */ gid_t group /* IN */ ) { IMFS_jnode_t *jnode; #if defined(RTEMS_POSIX_API) uid_t st_uid; #endif jnode = (IMFS_jnode_t *) pathloc->node_access; /* * Verify I am the owner of the node or the super user. */ #if defined(RTEMS_POSIX_API) st_uid = geteuid(); if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) ) rtems_set_errno_and_return_minus_one( EPERM ); #endif jnode->st_uid = owner; jnode->st_gid = group; IMFS_update_ctime( jnode ); return 0; }
int memfile_rmnod( rtems_filesystem_location_info_t *parent_pathloc, /* IN */ rtems_filesystem_location_info_t *pathloc /* IN */ ) { IMFS_jnode_t *the_jnode; the_jnode = (IMFS_jnode_t *) pathloc->node_access; /* * Take the node out of the parent's chain that contains this node */ if ( the_jnode->Parent != NULL ) { rtems_chain_extract( (rtems_chain_node *) the_jnode ); the_jnode->Parent = NULL; } /* * Decrement the link counter and see if we can free the space. */ the_jnode->st_nlink--; IMFS_update_ctime( the_jnode ); return memfile_check_rmnod( the_jnode ); }
int IMFS_unlink( rtems_filesystem_location_info_t *parentloc, /* IN */ rtems_filesystem_location_info_t *loc /* IN */ ) { IMFS_jnode_t *node; rtems_filesystem_location_info_t the_link; int result = 0; node = loc->node_access; /* * Decrement the link counter of node pointed to and free the * space. */ /* * If this is the last last pointer to the node * free the node. */ if ( node->type == IMFS_HARD_LINK ) { if ( !node->info.hard_link.link_node ) rtems_set_errno_and_return_minus_one( EINVAL ); the_link = *loc; the_link.node_access = node->info.hard_link.link_node; IMFS_Set_handlers( &the_link ); /* * If removing the last hard link to a node, then we need * to remove the node that is a link and the node itself. */ if ( node->info.hard_link.link_node->st_nlink == 1) { result = (*the_link.handlers->rmnod_h)( parentloc, &the_link ); if ( result != 0 ) return -1; } else { node->info.hard_link.link_node->st_nlink --; IMFS_update_ctime( node->info.hard_link.link_node ); } } /* * Now actually free the node we were asked to free. */ result = (*loc->handlers->rmnod_h)( parentloc, loc ); return result; }
void IMFS_create_orphan( IMFS_jnode_t *jnode ) { if ( jnode->Parent != NULL ) { rtems_chain_extract( &jnode->Node ); jnode->Parent = NULL; } --jnode->st_nlink; IMFS_update_ctime( jnode ); }
/* * IMFS_memfile_extend * * This routine insures that the in-memory file is of the length * specified. If necessary, it will allocate memory blocks to * extend the file. */ MEMFILE_STATIC int IMFS_memfile_extend( IMFS_jnode_t *the_jnode, off_t new_length ) { unsigned int block; unsigned int new_blocks; unsigned int old_blocks; /* * Perform internal consistency checks */ IMFS_assert( the_jnode ); IMFS_assert( IMFS_type( the_jnode ) == IMFS_MEMORY_FILE ); /* * Verify new file size is supported */ if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE ) rtems_set_errno_and_return_minus_one( EINVAL ); /* * Verify new file size is actually larger than current size */ if ( new_length <= the_jnode->info.file.size ) return 0; /* * Calculate the number of range of blocks to allocate */ new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK; old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK; /* * Now allocate each of those blocks. */ for ( block=old_blocks ; block<=new_blocks ; block++ ) { if ( IMFS_memfile_addblock( the_jnode, block ) ) { for ( ; block>=old_blocks ; block-- ) { IMFS_memfile_remove_block( the_jnode, block ); } rtems_set_errno_and_return_minus_one( ENOSPC ); } } /* * Set the new length of the file. */ the_jnode->info.file.size = new_length; IMFS_update_ctime(the_jnode); IMFS_update_mtime(the_jnode); return 0; }
int IMFS_mknod( const char *token, /* IN */ mode_t mode, /* IN */ dev_t dev, /* IN */ rtems_filesystem_location_info_t *pathloc /* IN/OUT */ ) { IMFS_token_types type = 0; IMFS_jnode_t *new_node; int result; char new_name[ IMFS_NAME_MAX + 1 ]; IMFS_types_union info; IMFS_get_token( token, strlen( token ), new_name, &result ); /* * Figure out what type of IMFS node this is. */ if ( S_ISDIR(mode) ) type = IMFS_DIRECTORY; else if ( S_ISREG(mode) ) type = IMFS_MEMORY_FILE; else if ( S_ISBLK(mode) || S_ISCHR(mode) ) { type = IMFS_DEVICE; rtems_filesystem_split_dev_t( dev, info.device.major, info.device.minor ); } else if (S_ISFIFO(mode)) type = IMFS_FIFO; else IMFS_assert( 0 ); /* * Allocate and fill in an IMFS jnode * * NOTE: Coverity Id 21 reports this as a leak. * While technically not a leak, it indicated that IMFS_create_node * was ONLY passed a NULL when we created the root node. We * added a new IMFS_create_root_node() so this path no longer * existed. The result was simpler code which should not have * this path. */ new_node = IMFS_create_node( pathloc, type, new_name, mode, &info ); if ( !new_node ) rtems_set_errno_and_return_minus_one( ENOMEM ); IMFS_update_ctime(new_node->Parent); IMFS_update_mtime(new_node->Parent); return 0; }
int IMFS_chown( const rtems_filesystem_location_info_t *loc, uid_t owner, gid_t group ) { IMFS_jnode_t *jnode; jnode = (IMFS_jnode_t *) loc->node_access; jnode->st_uid = owner; jnode->st_gid = group; IMFS_update_ctime( jnode ); return 0; }
static IMFS_jnode_t *IMFS_node_remove_hard_link( IMFS_jnode_t *node ) { IMFS_jnode_t *target = node->info.hard_link.link_node; if ( target->st_nlink == 1) { target = (*target->control->node_remove)( target ); if ( target == NULL ) { node = NULL; } } else { --target->st_nlink; IMFS_update_ctime( target ); } return node; }
int IMFS_link( const rtems_filesystem_location_info_t *parentloc, const rtems_filesystem_location_info_t *targetloc, const char *name, size_t namelen ) { IMFS_types_union info; IMFS_jnode_t *new_node; IMFS_jnode_t *target; target = targetloc->node_access; info.hard_link.link_node = target; /* * Verify this node can be linked to. */ if ( target->st_nlink >= LINK_MAX ) rtems_set_errno_and_return_minus_one( EMLINK ); /* * Create a new link node. */ new_node = IMFS_create_node( parentloc, IMFS_HARD_LINK, name, namelen, ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )), &info ); if ( !new_node ) rtems_set_errno_and_return_minus_one( ENOMEM ); /* * Increment the link count of the node being pointed to. */ target->reference_count++; target->st_nlink++; IMFS_update_ctime( target ); return 0; }
int IMFS_rename( const rtems_filesystem_location_info_t *oldparentloc, const rtems_filesystem_location_info_t *oldloc, const rtems_filesystem_location_info_t *newparentloc, const char *name, size_t namelen ) { int rv = 0; IMFS_jnode_t *node = oldloc->node_access; IMFS_jnode_t *new_parent = newparentloc->node_access; /* * FIXME: Due to insufficient checks we can create inaccessible nodes with * this operation. */ if ( node->Parent != NULL ) { if ( namelen < IMFS_NAME_MAX ) { memcpy( node->name, name, namelen ); node->name [namelen] = '\0'; IMFS_remove_from_directory( node ); IMFS_add_to_directory( new_parent, node ); IMFS_update_ctime( node ); } else { errno = ENAMETOOLONG; rv = -1; } } else { errno = EINVAL; rv = -1; } return rv; }
int imfs_dir_rmnod( rtems_filesystem_location_info_t *parent_pathloc, /* IN */ rtems_filesystem_location_info_t *pathloc /* IN */ ) { IMFS_jnode_t *the_jnode; the_jnode = (IMFS_jnode_t *) pathloc->node_access; /* * You cannot remove a node that still has children */ if ( ! rtems_chain_is_empty( &the_jnode->info.directory.Entries ) ) rtems_set_errno_and_return_minus_one( ENOTEMPTY ); /* * You cannot remove the file system root node. */ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access ) rtems_set_errno_and_return_minus_one( EBUSY ); /* * You cannot remove a mountpoint. */ if ( the_jnode->info.directory.mt_fs != NULL ) rtems_set_errno_and_return_minus_one( EBUSY ); /* * Take the node out of the parent's chain that contains this node */ if ( the_jnode->Parent != NULL ) { rtems_chain_extract( (rtems_chain_node *) the_jnode ); the_jnode->Parent = NULL; } /* * Decrement the link counter and see if we can free the space. */ the_jnode->st_nlink--; IMFS_update_ctime( the_jnode ); /* * The file cannot be open and the link must be less than 1 to free. */ if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) { /* * Is the rtems_filesystem_current is this node? */ if ( rtems_filesystem_current.node_access == pathloc->node_access ) rtems_filesystem_current.node_access = NULL; /* * Free memory associated with a memory file. */ free( the_jnode ); } return 0; }
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; }