/** * This rountine will verify that the node being opened as a directory is in * fact a directory node. If it is then the offset into the directory will be * set to 0 to position to the first directory entry. */ static int rtems_rfs_rtems_dir_open (rtems_libio_t* iop, const char* pathname, int oflag, mode_t mode) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo); rtems_rfs_ino ino = rtems_rfs_rtems_get_iop_ino (iop); 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 ("dir_open: opening inode", 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 ("dir_open: not dir", ENOTDIR); } iop->offset = 0; rtems_rfs_inode_close (fs, &inode); rtems_rfs_rtems_unlock (fs); return 0; }
static rtems_filesystem_node_types_t rtems_rfs_rtems_node_type_by_inode (rtems_rfs_inode_handle* inode) { /* * 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. */ 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; }
bool rtems_rfs_rtems_set_handlers (rtems_filesystem_location_info_t* loc, rtems_rfs_inode_handle* inode) { uint16_t mode = rtems_rfs_inode_get_mode (inode); loc->handlers = NULL; if (RTEMS_RFS_S_ISDIR (mode)) loc->handlers = rtems_rfs_rtems_handlers (dir); else if (RTEMS_RFS_S_ISCHR (mode) || RTEMS_RFS_S_ISBLK(mode)) loc->handlers = rtems_rfs_rtems_handlers (device); else if (RTEMS_RFS_S_ISLNK (mode)) loc->handlers = rtems_rfs_rtems_handlers (link); else if (RTEMS_RFS_S_ISREG (mode)) loc->handlers = rtems_rfs_rtems_handlers (file); else { printf ("rtems-rfs: mode type unknown: %04x\n", mode); return false; } return true; }
int rtems_rfs_fs_open (const char* name, void* user, uint32_t flags, uint32_t max_held_buffers, rtems_rfs_file_system** fs) { #if UNUSED rtems_rfs_group* group; size_t group_base; #endif rtems_rfs_inode_handle inode; uint16_t mode; int rc; if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: open: %s\n", name); *fs = malloc (sizeof (rtems_rfs_file_system)); if (!*fs) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: open: no memory for file system data\n"); errno = ENOMEM; return -1; } memset (*fs, 0, sizeof (rtems_rfs_file_system)); (*fs)->user = user; rtems_chain_initialize_empty (&(*fs)->buffers); rtems_chain_initialize_empty (&(*fs)->release); rtems_chain_initialize_empty (&(*fs)->release_modified); rtems_chain_initialize_empty (&(*fs)->file_shares); (*fs)->max_held_buffers = max_held_buffers; (*fs)->buffers_count = 0; (*fs)->release_count = 0; (*fs)->release_modified_count = 0; (*fs)->flags = flags; #if UNUSED group = &(*fs)->groups[0]; group_base = 0; #endif /* * Open the buffer interface. */ rc = rtems_rfs_buffer_open (name, *fs); if (rc > 0) { free (*fs); if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: open: buffer open failed: %d: %s\n", rc, strerror (rc)); errno = rc; return -1; } rc = rtems_rfs_fs_read_superblock (*fs); if (rc > 0) { rtems_rfs_buffer_close (*fs); free (*fs); if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: open: reading superblock: %d: %s\n", rc, strerror (rc)); errno = rc; return -1; } rc = rtems_rfs_inode_open (*fs, RTEMS_RFS_ROOT_INO, &inode, true); if (rc > 0) { rtems_rfs_buffer_close (*fs); free (*fs); if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: open: reading root inode: %d: %s\n", rc, strerror (rc)); errno = rc; return -1; } if (((*fs)->flags & RTEMS_RFS_FS_FORCE_OPEN) == 0) { mode = rtems_rfs_inode_get_mode (&inode); if ((mode == 0xffff) || !RTEMS_RFS_S_ISDIR (mode)) { rtems_rfs_inode_close (*fs, &inode); rtems_rfs_buffer_close (*fs); free (*fs); if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: open: invalid root inode mode\n"); errno = EIO; return -1; } } rc = rtems_rfs_inode_close (*fs, &inode); if (rc > 0) { rtems_rfs_buffer_close (*fs); free (*fs); if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: open: closing root inode: %d: %s\n", rc, strerror (rc)); errno = rc; return -1; } errno = 0; return 0; }
int rtems_rfs_inode_create (rtems_rfs_file_system* fs, rtems_rfs_ino parent, const char* name, size_t length, uint16_t mode, uint16_t links, uid_t uid, gid_t gid, rtems_rfs_ino* ino) { rtems_rfs_inode_handle parent_inode; rtems_rfs_inode_handle inode; int rc; if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_CREATE)) { const char* type = "unknown"; int c; if (RTEMS_RFS_S_ISDIR (mode)) type = "dir"; else if (RTEMS_RFS_S_ISCHR (mode)) type = "char"; else if (RTEMS_RFS_S_ISBLK (mode)) type = "block"; else if (RTEMS_RFS_S_ISREG (mode)) type = "file"; else if (RTEMS_RFS_S_ISLNK (mode)) type = "link"; printf("rtems-rfs: inode-create: parent:%" PRIu32 " name:", parent); for (c = 0; c < length; c++) printf ("%c", name[c]); printf (" type:%s mode:%04x (%03o)\n", type, mode, mode & ((1 << 10) - 1)); } /* * The file type is field within the mode. Check we have a sane mode set. */ switch (mode & RTEMS_RFS_S_IFMT) { case RTEMS_RFS_S_IFDIR: case RTEMS_RFS_S_IFCHR: case RTEMS_RFS_S_IFBLK: case RTEMS_RFS_S_IFREG: case RTEMS_RFS_S_IFLNK: break; default: return EINVAL; } rc = rtems_rfs_inode_alloc (fs, parent, ino); if (rc > 0) return rc; rc = rtems_rfs_inode_open (fs, *ino, &inode, true); if (rc > 0) { rtems_rfs_inode_free (fs, *ino); return rc; } rc = rtems_rfs_inode_initialise (&inode, links, mode, uid, gid); if (rc > 0) { rtems_rfs_inode_close (fs, &inode); rtems_rfs_inode_free (fs, *ino); return rc; } /* * Only handle the specifics of a directory. Let caller handle the others. * * The inode delete will free the inode. */ if (RTEMS_RFS_S_ISDIR (mode)) { rc = rtems_rfs_dir_add_entry (fs, &inode, ".", 1, *ino); if (rc == 0) rc = rtems_rfs_dir_add_entry (fs, &inode, "..", 2, parent); if (rc > 0) { rtems_rfs_inode_delete (fs, &inode); rtems_rfs_inode_close (fs, &inode); return rc; } } rc = rtems_rfs_inode_open (fs, parent, &parent_inode, true); if (rc > 0) { rtems_rfs_inode_delete (fs, &inode); rtems_rfs_inode_close (fs, &inode); return rc; } rc = rtems_rfs_dir_add_entry (fs, &parent_inode, name, length, *ino); if (rc > 0) { rtems_rfs_inode_delete (fs, &inode); rtems_rfs_inode_close (fs, &inode); rtems_rfs_inode_close (fs, &parent_inode); return rc; } /* * If the node is a directory update the parent link count as the * new directory has the '..' link that points to the parent. */ if (RTEMS_RFS_S_ISDIR (mode)) rtems_rfs_inode_set_links (&parent_inode, rtems_rfs_inode_get_links (&parent_inode) + 1); rc = rtems_rfs_inode_close (fs, &parent_inode); if (rc > 0) { rtems_rfs_inode_delete (fs, &inode); rtems_rfs_inode_close (fs, &inode); return rc; } rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { rtems_rfs_inode_free (fs, *ino); return rc; } return 0; }
int rtems_rfs_unlink (rtems_rfs_file_system* fs, rtems_rfs_ino parent, rtems_rfs_ino target, uint32_t doff, rtems_rfs_unlink_dir dir_mode) { rtems_rfs_inode_handle parent_inode; rtems_rfs_inode_handle target_inode; uint16_t links; bool dir; int rc; if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK)) printf ("rtems-rfs: unlink: parent(%" PRIu32 ") -X-> (%" PRIu32 ")\n", parent, target); rc = rtems_rfs_inode_open (fs, target, &target_inode, true); if (rc) return rc; /* * If a directory process the unlink mode. */ dir = RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&target_inode)); if (dir) { switch (dir_mode) { case rtems_rfs_unlink_dir_denied: if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK)) printf ("rtems-rfs: link is a directory\n"); rtems_rfs_inode_close (fs, &target_inode); return EISDIR; case rtems_rfs_unlink_dir_if_empty: rc = rtems_rfs_dir_empty (fs, &target_inode); if (rc > 0) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK)) printf ("rtems-rfs: dir-empty: %d: %s\n", rc, strerror (rc)); rtems_rfs_inode_close (fs, &target_inode); return rc; } break; default: break; } } rc = rtems_rfs_inode_open (fs, parent, &parent_inode, true); if (rc) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK)) printf ("rtems-rfs: link: inode-open failed: %d: %s\n", rc, strerror (rc)); rtems_rfs_inode_close (fs, &target_inode); return rc; } rc = rtems_rfs_dir_del_entry (fs, &parent_inode, target, doff); if (rc > 0) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK)) printf ("rtems-rfs: unlink: dir-del failed: %d: %s\n", rc, strerror (rc)); rtems_rfs_inode_close (fs, &parent_inode); rtems_rfs_inode_close (fs, &target_inode); return rc; } links = rtems_rfs_inode_get_links (&target_inode); if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK)) printf ("rtems-rfs: unlink: target:%" PRIu32 " links:%u\n", target, links); if (links > 1) { links--; rtems_rfs_inode_set_links (&target_inode, links); } else { /* * Erasing the inode releases all blocks attached to it. */ rc = rtems_rfs_inode_delete (fs, &target_inode); if (rc > 0) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK)) printf ("rtems-rfs: unlink: inode-del failed: %d: %s\n", rc, strerror (rc)); rtems_rfs_inode_close (fs, &parent_inode); rtems_rfs_inode_close (fs, &target_inode); return rc; } if (dir) { links = rtems_rfs_inode_get_links (&parent_inode); if (links > 1) links--; rtems_rfs_inode_set_links (&parent_inode, links); } } rc = rtems_rfs_inode_time_stamp_now (&parent_inode, true, true); if (rc > 0) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK)) printf ("rtems-rfs: link: inode-time-stamp failed: %d: %s\n", rc, strerror (rc)); rtems_rfs_inode_close (fs, &parent_inode); rtems_rfs_inode_close (fs, &target_inode); return rc; } rc = rtems_rfs_inode_close (fs, &parent_inode); if (rc > 0) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK)) printf ("rtems-rfs: link: parent inode-close failed: %d: %s\n", rc, strerror (rc)); rtems_rfs_inode_close (fs, &target_inode); return rc; } rc = rtems_rfs_inode_close (fs, &target_inode); if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK)) printf ("rtems-rfs: link: target inode-close failed: %d: %s\n", rc, strerror (rc)); return rc; }
static int rtems_rfs_shell_inode (rtems_rfs_file_system* fs, int argc, char *argv[]) { rtems_rfs_ino start; rtems_rfs_ino end; rtems_rfs_ino total; rtems_rfs_ino ino; bool show_all; bool error_check_only; bool forced; bool have_start; bool have_end; int arg; int b; int rc; total = fs->group_inodes * fs->group_count; start = RTEMS_RFS_ROOT_INO; end = total - 1; show_all = false; error_check_only = false; forced = false; have_start = have_end = false; for (arg = 1; arg < argc; arg++) { if (argv[arg][0] == '-') { switch (argv[arg][1]) { case 'a': show_all = true; break; case 'e': error_check_only = true; break; case 'f': forced = true; break; default: printf ("warning: option ignored: %s\n", argv[arg]); break; } } else { if (have_end && have_start) printf ("warning: option ignored: %s\n", argv[arg]); else if (!have_start) { start = end = strtoul (argv[arg], 0, 0); have_start = true; } else { end = strtoul (argv[arg], 0, 0); have_end = true; } } } if ((start >= total) || (end >= total)) { printf ("error: inode out of range (0->%" PRId32 ").\n", total - 1); return 1; } rtems_rfs_shell_lock_rfs (fs); for (ino = start; ino <= end; ino++) { rtems_rfs_inode_handle inode; bool allocated; rc = rtems_rfs_group_bitmap_test (fs, true, ino, &allocated); if (rc > 0) { rtems_rfs_shell_unlock_rfs (fs); printf ("error: testing inode state: ino=%" PRIu32 ": (%d) %s\n", ino, rc, strerror (rc)); return 1; } if (show_all || allocated) { uint16_t mode; bool error; rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc > 0) { rtems_rfs_shell_unlock_rfs (fs); printf ("error: opening inode handle: ino=%" PRIu32 ": (%d) %s\n", ino, rc, strerror (rc)); return 1; } error = false; mode = rtems_rfs_inode_get_mode (&inode); if (error_check_only) { if (!RTEMS_RFS_S_ISDIR (mode) && !RTEMS_RFS_S_ISCHR (mode) && !RTEMS_RFS_S_ISBLK (mode) && !RTEMS_RFS_S_ISREG (mode) && !RTEMS_RFS_S_ISLNK (mode)) error = true; else { #if NEED_TO_HANDLE_DIFFERENT_TYPES int b; for (b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++) { uint32_t block; block = rtems_rfs_inode_get_block (&inode, b); if ((block <= RTEMS_RFS_SUPERBLOCK_SIZE) || (block >= rtems_rfs_fs_blocks (fs))) error = true; } #endif } } if (!error_check_only || error) { printf (" %5" PRIu32 ": pos=%06" PRIu32 ":%04zx %c ", ino, rtems_rfs_buffer_bnum (&inode.buffer), inode.offset * RTEMS_RFS_INODE_SIZE, allocated ? 'A' : 'F'); if (!allocated && !forced) printf (" --\n"); else { const char* type; type = "UKN"; if (RTEMS_RFS_S_ISDIR (mode)) type = "DIR"; else if (RTEMS_RFS_S_ISCHR (mode)) type = "CHR"; else if (RTEMS_RFS_S_ISBLK (mode)) type = "BLK"; else if (RTEMS_RFS_S_ISREG (mode)) type = "REG"; else if (RTEMS_RFS_S_ISLNK (mode)) type = "LNK"; printf ("links=%03i mode=%04x (%s/%03o) bo=%04u bc=%04" PRIu32 " b=[", rtems_rfs_inode_get_links (&inode), mode, type, mode & ((1 << 10) - 1), rtems_rfs_inode_get_block_offset (&inode), rtems_rfs_inode_get_block_count (&inode)); for (b = 0; b < (RTEMS_RFS_INODE_BLOCKS - 1); b++) printf ("%" PRIu32 " ", rtems_rfs_inode_get_block (&inode, b)); printf ("%" PRIu32 "]\n", rtems_rfs_inode_get_block (&inode, b)); } } rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { rtems_rfs_shell_unlock_rfs (fs); printf ("error: closing inode handle: ino=%" PRIu32 ": (%d) %s\n", ino, rc, strerror (rc)); return 1; } } } rtems_rfs_shell_unlock_rfs (fs); return 0; }