static void sibling_extent(ffs_sort_t *entry, uint32_t size_sib_entry, block_info_t *block_info){ f3s_extptr_t next, dir_next; f3s_head_t dir_extent; uint32_t pos, nbytes; uint16_t extent_flags; // // Setup 'next' pointer to new extent // dir_next.logi_unit = swap16(target_endian,block_info->block_index + 1); dir_next.index = swap16(target_endian,block_info->extent_index); // // now write the entry to the correct place // 'next' entry is // pos = entry->extent_pos; lseek(flashimage, pos, SEEK_SET); if (read(flashimage,&dir_extent,sizeof(dir_extent)) != sizeof(dir_extent)) mk_flash_exit("read failed: %s\n",strerror(errno)); dir_extent.status &= swap16(target_endian,~F3S_EXT_NO_NEXT); dir_extent.next = dir_next; lseek(flashimage, pos, SEEK_SET); memcpy(blk_buffer_ptr,&dir_extent, sizeof(dir_extent)); if ((nbytes = write(flashimage,blk_buffer_ptr,sizeof(dir_extent))) !=sizeof(dir_extent)) mk_flash_exit("write failed: %s\n",strerror(errno)); entry->status |=FFS_SORT_ENTRY_SET; // // write extent for the new entry // extent_flags = ~F3S_EXT_TYPE & 0xff00; extent_flags |= (F3S_EXT_DIR | F3S_EXT_NO_NEXT | F3S_EXT_NO_SUPER | F3S_EXT_ALLOC | F3S_EXT_LAST | F3S_EXT_NO_SPLIT); next.logi_unit = FNULL; next.index = FNULL; write_extent(block_info, next, extent_flags, size_sib_entry); }
/* * update_ext() * * Given a (struct hfs_fork) write an extent record back to disk. */ static void update_ext(struct hfs_fork *fork, struct hfs_extent *ext) { struct hfs_ext_key target; struct hfs_brec brec; if (ext->start) { build_key(&target, fork, ext->start); if (!hfs_bfind(&brec, fork->entry->mdb->ext_tree, HFS_BKEY(&target), HFS_BFIND_WRITE)) { write_extent(brec.data, ext); hfs_brec_relse(&brec, NULL); } } }
/* * new_extent() * * Description: * Adds a new extent record to a fork, extending its physical length. * Input Variable(s): * struct hfs_fork *fork: the fork to extend * struct hfs_extent *ext: the current last extent for 'fork' * hfs_u16 ablock: the number of allocation blocks in 'fork'. * hfs_u16 start: first allocation block to add to 'fork'. * hfs_u16 len: the number of allocation blocks to add to 'fork'. * hfs_u32 ablksz: number of sectors in an allocation block. * Output Variable(s): * NONE * Returns: * (struct hfs_extent *) the new extent or NULL * Preconditions: * 'fork' points to a valid (struct hfs_fork) * 'ext' point to a valid (struct hfs_extent) which is the last in 'fork' * 'ablock', 'start', 'len' and 'ablksz' are what they claim to be. * Postconditions: * If NULL is returned then no changes have been made to 'fork'. * If the return value is non-NULL that it is the extent that has been * added to 'fork' both in memory and on disk. The 'psize' field of * 'fork' has been updated to reflect the new physical size. */ static struct hfs_extent *new_extent(struct hfs_fork *fork, struct hfs_extent *ext, hfs_u16 ablock, hfs_u16 start, hfs_u16 len, hfs_u16 ablksz) { struct hfs_raw_extent raw; struct hfs_ext_key key; int error; if (fork->entry->cnid == htonl(HFS_EXT_CNID)) { /* Limit extents tree to the record in the MDB */ return NULL; } if (!HFS_NEW(ext->next)) { return NULL; } ext->next->prev = ext; ext->next->next = NULL; ext = ext->next; relse_ext(ext->prev); ext->start = ablock; ext->block[0] = start; ext->length[0] = len; ext->block[1] = 0; ext->length[1] = 0; ext->block[2] = 0; ext->length[2] = 0; ext->end = ablock + len - 1; ext->count = 1; write_extent(&raw, ext); build_key(&key, fork, ablock); error = hfs_binsert(fork->entry->mdb->ext_tree, HFS_BKEY(&key), &raw, sizeof(raw)); if (error) { ext->prev->next = NULL; HFS_DELETE(ext); return NULL; } set_cache(fork, ext); return ext; }
static void child_extent(ffs_sort_t *entry, uint32_t size_child_entry, block_info_t *block_info){ f3s_extptr_t first, next; uint32_t pos, nbytes; uint16_t extent_flags; // // Setup 'first' pointer to new extent // first.logi_unit = swap16(target_endian,block_info->block_index + 1); first.index = swap16(target_endian,block_info->extent_index); // // now write the entry to the correct place // 'first' entry is 4 bytes offset into the f3s_dirent_t structure // pos = entry->entry_pos + sizeof(int); memcpy(blk_buffer_ptr,&first, sizeof(first)); lseek(flashimage,pos,SEEK_SET); if ((nbytes = write(flashimage,blk_buffer_ptr,sizeof(first))) !=sizeof(first)) mk_flash_exit("write failed: %s\n",strerror(errno)); entry->status |=FFS_SORT_ENTRY_SET; // // write extent for the new entry // extent_flags = ~F3S_EXT_TYPE & 0xff00; extent_flags |= (F3S_EXT_DIR | F3S_EXT_NO_NEXT | F3S_EXT_NO_SUPER | F3S_EXT_ALLOC | F3S_EXT_LAST | F3S_EXT_NO_SPLIT); next.logi_unit = FNULL; next.index = FNULL; write_extent(block_info, next, extent_flags, size_child_entry); }
static void first_file_extent(uint32_t position, uint32_t size_file_entry, block_info_t *block_info){ f3s_extptr_t next, first; uint32_t nbytes; uint16_t extent_flags; // // Setup extent pointer to new extent // first.logi_unit = swap16(target_endian,block_info->block_index + 1); first.index = swap16(target_endian,block_info->extent_index); // // write the update to the correct place // lseek(flashimage, position, SEEK_SET); memcpy(blk_buffer_ptr, &first, sizeof(first)); if ((nbytes = write(flashimage,blk_buffer_ptr,sizeof(first))) !=sizeof(first)) mk_flash_exit("write failed: %s\n",strerror(errno)); // // write extent for the new entry // extent_flags = ~F3S_EXT_TYPE & 0xff00; extent_flags |= (F3S_EXT_FILE | F3S_EXT_NO_NEXT | F3S_EXT_NO_SUPER | F3S_EXT_ALLOC | F3S_EXT_LAST | F3S_EXT_NO_SPLIT); next.logi_unit = FNULL; next.index = FNULL; write_extent(block_info, next, extent_flags, size_file_entry); }
static block_info_t *init_block(int block_size, uint16_t unit_flags){ f3s_extptr_t extptr, next; f3s_unit_t unit; block_info_t ** binfo; uint32_t position; uint16_t extent_flags; uint8_t *init_blk_ptr; // // setup the block allocation structure // binfo = realloc (block_info, (block_index + 1) * sizeof(block_info_t *)); if (binfo == NULL) return (NULL); block_info = binfo; block_info[block_index] = (block_info_t *)malloc(sizeof(block_info_t)); if (block_info[block_index] == NULL) mk_flash_exit("malloc failed: %s\n", strerror(errno)); block_info[block_index]->block_index = block_index; block_info[block_index]->available_space = block_size; block_info[block_index]->offset_top = 0; block_info[block_index]->block_size = block_size; block_info[block_index]->offset_bottom = block_size; block_info[block_index]->extent_index = 0; block_info[block_index]->next = NULL; // // every block will contain a unit header information // structure // unit.status = swap16(target_endian,unit_flags); unit.struct_size = swap16(target_endian,sizeof(unit)); unit.endian = target_endian ? 'B' : 'L'; unit.age = 0; // hard coded, does not apply here if (unit_flags&F3S_UNIT_NO_LOGI) unit.logi = ~0; else unit.logi = swap16(target_endian,block_index+1); unit.unit_pow2 = swap16(target_endian,calc_log2(block_size)); unit.reserve = 0xffff; unit.erase_count = 0; // hard coded, does not apply here // // setup the f3s_extptr_t to boot structure // these values are hard coded since they should not change // extptr.logi_unit = swap16(target_endian,F3S_FIRST_LOGI); extptr.index = swap16(target_endian,F3S_BOOT_INDEX); unit.boot = extptr; // // create a memory region to build our block // if ((init_blk_ptr = (char *) malloc(block_size)) == NULL) mk_flash_exit("memory allocation failed: %s\n",strerror(errno)); // // initialize block // memset(init_blk_ptr,0xff,block_size); // // the unit header info is written at the start of each block // memcpy(init_blk_ptr,&unit,sizeof(unit)); position = (block_info[block_index]->block_index) * block_info[block_index]->block_size; lseek(flashimage, position,SEEK_SET); if (write(flashimage,init_blk_ptr,block_size) != block_size) mk_flash_exit("write failed: %s\n",strerror(errno)); // // write extent information // next.logi_unit = FNULL; next.index = FNULL; extent_flags = ~F3S_EXT_TYPE & 0xff00; extent_flags |= (F3S_EXT_SYS | F3S_EXT_NO_NEXT | F3S_EXT_NO_SUPER | F3S_EXT_NO_SPLIT | F3S_EXT_ALLOC |F3S_EXT_LAST); write_extent(block_info[block_index], next, extent_flags, sizeof(unit)); // // update block information structure // block_info[block_index]->available_space -= sizeof(unit); block_info[block_index]->offset_top = sizeof(unit); // // free our malloc'd memory // block_index++; free(init_blk_ptr); return block_info[block_index-1]; }
static void write_boot_record(block_info_t *block_info, uint16_t spare, ffs_sort_t *sort) { f3s_boot_t boot_record; f3s_extptr_t root, next; uint32_t nbytes, namelen, size, position; uint16_t boot_flags, extent_flags; // // setup the boot record structure // boot_flags = ~F3S_BOOT_NO_INDEX; boot_record.status = swap16(target_endian,boot_flags); boot_record.struct_size = swap16(target_endian,sizeof(boot_record)); memcpy(&boot_record.sig, F3S_SIG_STRING, F3S_SIG_SIZE); boot_record.rev_major = F3S_REV_MAJOR; boot_record.rev_minor = F3S_REV_MINOR; // // offset information needed by the filesystem manager // boot_record.unit_index = 0; // // to be determined once the filesystem is completed // boot_record.unit_total = 0; boot_record.unit_spare = swap16(target_endian,spare); // // these two entries are hard coded for now // boot_record.align_pow2 = swap16(target_endian,2); boot_record.xip_pow2 = swap16(target_endian,12); // // setup root extent pointer // root.logi_unit = swap16(target_endian,F3S_FIRST_LOGI); root.index = swap16(target_endian,F3S_ROOT_INDEX); boot_record.root = root; memcpy(blk_buffer_ptr,&boot_record,sizeof(boot_record)); position = block_info->offset_top; lseek(flashimage,position,SEEK_SET); if((nbytes=write(flashimage,blk_buffer_ptr,sizeof(boot_record))) != sizeof(boot_record)) mk_flash_exit("write failed: %s\n",strerror(errno)); // // call extent header routine for boot structure // next.logi_unit = FNULL; next.index = FNULL; extent_flags = ~F3S_EXT_TYPE & 0xff00; extent_flags |= (F3S_EXT_SYS | F3S_EXT_NO_NEXT | F3S_EXT_NO_SUPER | F3S_EXT_NO_SPLIT | F3S_EXT_ALLOC | F3S_EXT_LAST); write_extent(block_info, next, extent_flags, sizeof(boot_record)); // // update block_info structures // block_info->available_space -= sizeof(boot_record); block_info->offset_top += sizeof(boot_record); // // call extent header routine for root structure (dirent) // extent_flags = (extent_flags & ~F3S_EXT_SYS) | F3S_EXT_DIR; // // calculate the size of the root name (can't assume /) // namelen = strlen(sort->name) + 1; size = sizeof(f3s_dirent_t) + F3S_NAME_ALIGN(namelen) + sizeof(f3s_stat_t); write_extent(block_info, next, extent_flags, size); }