int rtems_rfs_block_map_open (rtems_rfs_file_system* fs, rtems_rfs_inode_handle* inode, rtems_rfs_block_map* map) { int b; int rc; /* * Set the count to 0 so at least find fails, then open the handle and make * sure the inode has been loaded into memory. If we did not load the inode * do not unload it. The caller may assume it is still loaded when we return. */ map->dirty = false; map->inode = NULL; rtems_rfs_block_set_size_zero (&map->size); rtems_rfs_block_set_bpos_zero (&map->bpos); rc = rtems_rfs_buffer_handle_open (fs, &map->singly_buffer); if (rc > 0) return rc; rc = rtems_rfs_buffer_handle_open (fs, &map->doubly_buffer); if (rc > 0) return rc; rc = rtems_rfs_inode_load (fs, inode); if (rc > 0) { rtems_rfs_buffer_handle_close (fs, &map->singly_buffer); rtems_rfs_buffer_handle_close (fs, &map->doubly_buffer); return rc; } /* * Extract the block and block count data from the inode into the targets * byte order. */ map->inode = inode; for (b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++) map->blocks[b] = rtems_rfs_inode_get_block (inode, b); map->size.count = rtems_rfs_inode_get_block_count (inode); map->size.offset = rtems_rfs_inode_get_block_offset (inode); map->last_map_block = rtems_rfs_inode_get_last_map_block (inode); map->last_data_block = rtems_rfs_inode_get_last_data_block (inode); rc = rtems_rfs_inode_unload (fs, inode, false); return rc; }
int rtems_rfs_dir_add_entry (rtems_rfs_file_system* fs, rtems_rfs_inode_handle* dir, const char* name, size_t length, rtems_rfs_ino ino) { rtems_rfs_block_map map; rtems_rfs_block_pos bpos; rtems_rfs_buffer_handle buffer; int rc; if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY)) { int c; printf ("rtems-rfs: dir-add-entry: dir=%" PRId32 ", name=", rtems_rfs_inode_ino (dir)); for (c = 0; c < length; c++) printf ("%c", name[c]); printf (", len=%zd\n", length); } rc = rtems_rfs_block_map_open (fs, dir, &map); if (rc > 0) return rc; rc = rtems_rfs_buffer_handle_open (fs, &buffer); if (rc > 0) { rtems_rfs_block_map_close (fs, &map); return rc; } /* * Search the map from the beginning to find any empty space. */ rtems_rfs_block_set_bpos_zero (&bpos); while (true) { rtems_rfs_block_no block; uint8_t* entry; int offset; bool read = true; /* * Locate the first block. If an error the block will be 0. If the map is * empty which happens when creating a directory and adding the first entry * the seek will return ENXIO. In this case we need to grow the directory. */ rc = rtems_rfs_block_map_find (fs, &map, &bpos, &block); if (rc > 0) { if (rc != ENXIO) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY)) printf ("rtems-rfs: dir-add-entry: " "block map find failed for ino %" PRIu32 ": %d: %s\n", rtems_rfs_inode_ino (dir), rc, strerror (rc)); break; } /* * We have reached the end of the directory so add a block. */ rc = rtems_rfs_block_map_grow (fs, &map, 1, &block); if (rc > 0) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY)) printf ("rtems-rfs: dir-add-entry: " "block map grow failed for ino %" PRIu32 ": %d: %s\n", rtems_rfs_inode_ino (dir), rc, strerror (rc)); break; } read = false; } bpos.bno++; rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, read); if (rc > 0) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY)) printf ("rtems-rfs: dir-add-entry: " "block buffer req failed for ino %" PRIu32 ": %d: %s\n", rtems_rfs_inode_ino (dir), rc, strerror (rc)); break; } entry = rtems_rfs_buffer_data (&buffer); if (!read) memset (entry, 0xff, rtems_rfs_fs_block_size (fs)); offset = 0; while (offset < (rtems_rfs_fs_block_size (fs) - RTEMS_RFS_DIR_ENTRY_SIZE)) { rtems_rfs_ino eino; int elength; elength = rtems_rfs_dir_entry_length (entry); eino = rtems_rfs_dir_entry_ino (entry); if (elength == RTEMS_RFS_DIR_ENTRY_EMPTY) { if ((length + RTEMS_RFS_DIR_ENTRY_SIZE) < (rtems_rfs_fs_block_size (fs) - offset)) { uint32_t hash; hash = rtems_rfs_dir_hash (name, length); rtems_rfs_dir_set_entry_hash (entry, hash); rtems_rfs_dir_set_entry_ino (entry, ino); rtems_rfs_dir_set_entry_length (entry, RTEMS_RFS_DIR_ENTRY_SIZE + length); memcpy (entry + RTEMS_RFS_DIR_ENTRY_SIZE, name, length); rtems_rfs_buffer_mark_dirty (&buffer); rtems_rfs_buffer_handle_close (fs, &buffer); rtems_rfs_block_map_close (fs, &map); return 0; } break; } if (rtems_rfs_dir_entry_valid (fs, elength, eino)) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY)) printf ("rtems-rfs: dir-add-entry: " "bad length or ino for ino %" PRIu32 ": %u/%" PRId32 " @ %04x\n", rtems_rfs_inode_ino (dir), elength, eino, offset); rtems_rfs_buffer_handle_close (fs, &buffer); rtems_rfs_block_map_close (fs, &map); return EIO; } entry += elength; offset += elength; } } rtems_rfs_buffer_handle_close (fs, &buffer); rtems_rfs_block_map_close (fs, &map); return rc; }