int fuse_to_ext4_acl(const acl_ea_header *facl, size_t facl_sz, ext4_acl_header **eacl, size_t *eacl_sz) { int i, facl_count; ext4_acl_header *h; size_t h_sz; ext4_acl_entry *e; acl_ea_entry *a; unsigned char *hptr; int err = 0; facl_count = acl_ea_count(facl_sz); h_sz = ext4_acl_size(facl_count); if (facl_count < 0 || facl->a_version != ACL_EA_VERSION) return -EINVAL; h = malloc(h_sz); if (!h) return -ENOMEM; h->a_version = ext2fs_cpu_to_le32(EXT4_ACL_VERSION); hptr = (unsigned char *) (h + 1); for (i = 0, a = facl->a_entries; i < facl_count; i++, a++) { e = (ext4_acl_entry *) hptr; e->e_tag = ext2fs_cpu_to_le16(a->e_tag); e->e_perm = ext2fs_cpu_to_le16(a->e_perm); switch (a->e_tag) { case ACL_USER: case ACL_GROUP: e->e_id = ext2fs_cpu_to_le32(a->e_id); hptr += sizeof(ext4_acl_entry); break; case ACL_USER_OBJ: case ACL_GROUP_OBJ: case ACL_MASK: case ACL_OTHER: hptr += sizeof(ext4_acl_entry_short); break; default: err = -EINVAL; goto out; } } *eacl = h; *eacl_sz = h_sz; return err; out: free(h); return err; }
errcode_t ext2fs_extent_replace(ext2_extent_handle_t handle, int flags EXT2FS_ATTR((unused)), struct ext2fs_extent *extent) { struct extent_path *path; struct ext3_extent_idx *ix; struct ext3_extent *ex; EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); if (!(handle->fs->flags & EXT2_FLAG_RW)) return EXT2_ET_RO_FILSYS; if (!handle->path) return EXT2_ET_NO_CURRENT_NODE; path = handle->path + handle->level; if (!path->curr) return EXT2_ET_NO_CURRENT_NODE; #ifdef DEBUG printf("extent replace: %u ", handle->ino); dbg_print_extent(0, extent); #endif if (handle->level == handle->max_depth) { ex = path->curr; ex->ee_block = ext2fs_cpu_to_le32(extent->e_lblk); ex->ee_start = ext2fs_cpu_to_le32(extent->e_pblk & 0xFFFFFFFF); ex->ee_start_hi = ext2fs_cpu_to_le16(extent->e_pblk >> 32); if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT) { if (extent->e_len > EXT_UNINIT_MAX_LEN) return EXT2_ET_EXTENT_INVALID_LENGTH; ex->ee_len = ext2fs_cpu_to_le16(extent->e_len + EXT_INIT_MAX_LEN); } else { if (extent->e_len > EXT_INIT_MAX_LEN) return EXT2_ET_EXTENT_INVALID_LENGTH; ex->ee_len = ext2fs_cpu_to_le16(extent->e_len); } } else {
static errcode_t ext2fs_inline_data_file_expand(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, char *buf, size_t size) { ext2_file_t e2_file; errcode_t retval; /* Update inode */ if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT3_FEATURE_INCOMPAT_EXTENTS)) { int i; struct ext3_extent_header *eh; eh = (struct ext3_extent_header *) &inode->i_block[0]; eh->eh_depth = 0; eh->eh_entries = 0; eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC); i = (sizeof(inode->i_block) - sizeof(*eh)) / sizeof(struct ext3_extent); eh->eh_max = ext2fs_cpu_to_le16(i); inode->i_flags |= EXT4_EXTENTS_FL; } inode->i_flags &= ~EXT4_INLINE_DATA_FL; inode->i_size = 0; retval = ext2fs_write_inode(fs, ino, inode); if (retval) return retval; /* Write out the block buffer */ retval = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &e2_file); if (retval) return retval; retval = ext2fs_file_write(e2_file, buf, size, 0); ext2fs_file_close(e2_file); return retval; }
/* * This function takes the leaf nodes which have been written in * outdir, and populates the root node and any necessary interior nodes. */ static errcode_t calculate_tree(ext2_filsys fs, struct out_dir *outdir, ext2_ino_t ino, ext2_ino_t parent) { struct ext2_dx_root_info *root_info; struct ext2_dx_entry *root, *dx_ent = 0; struct ext2_dx_countlimit *root_limit, *limit; errcode_t retval; char * block_start; int i, c1, c2, nblks; int limit_offset, root_offset; root_info = set_root_node(fs, outdir->buf, ino, parent); root_offset = limit_offset = ((char *) root_info - outdir->buf) + root_info->info_length; root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset); c1 = root_limit->limit; nblks = outdir->num; /* Write out the pointer blocks */ if (nblks-1 <= c1) { /* Just write out the root block, and we're done */ root = (struct ext2_dx_entry *) (outdir->buf + root_offset); for (i=1; i < nblks; i++) { root->block = ext2fs_cpu_to_le32(i); if (i != 1) root->hash = ext2fs_cpu_to_le32(outdir->hashes[i]); root++; c1--; } } else { c2 = 0; limit = 0; root_info->indirect_levels = 1; for (i=1; i < nblks; i++) { if (c1 == 0) return ENOSPC; if (c2 == 0) { if (limit) limit->limit = limit->count = ext2fs_cpu_to_le16(limit->limit); root = (struct ext2_dx_entry *) (outdir->buf + root_offset); root->block = ext2fs_cpu_to_le32(outdir->num); if (i != 1) root->hash = ext2fs_cpu_to_le32(outdir->hashes[i]); if ((retval = get_next_block(fs, outdir, &block_start))) return retval; dx_ent = set_int_node(fs, block_start); limit = (struct ext2_dx_countlimit *) dx_ent; c2 = limit->limit; root_offset += sizeof(struct ext2_dx_entry); c1--; } dx_ent->block = ext2fs_cpu_to_le32(i); if (c2 != limit->limit) dx_ent->hash = ext2fs_cpu_to_le32(outdir->hashes[i]); dx_ent++; c2--; } limit->count = ext2fs_cpu_to_le16(limit->limit - c2); limit->limit = ext2fs_cpu_to_le16(limit->limit); } root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset); root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1); root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit); return 0; }
extern errcode_t ext2fs_extent_open(ext2_filsys fs, ext2_ino_t ino, ext2_extent_handle_t *ret_handle) { struct ext2_extent_handle *handle; errcode_t retval; int isize = EXT2_INODE_SIZE(fs->super); int i; struct ext3_extent_header *eh; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); if ((ino == 0) || (ino > fs->super->s_inodes_count)) return EXT2_ET_BAD_INODE_NUM; retval = ext2fs_get_mem(sizeof(struct ext2_extent_handle), &handle); if (retval) return retval; memset(handle, 0, sizeof(struct ext2_extent_handle)); retval = ext2fs_get_mem(isize, &handle->inode); if (retval) goto errout; handle->ino = ino; handle->fs = fs; retval = ext2fs_read_inode_full(fs, ino, handle->inode, isize); if (retval) goto errout; eh = (struct ext3_extent_header *) &handle->inode->i_block[0]; for (i=0; i < EXT2_N_BLOCKS; i++) if (handle->inode->i_block[i]) break; if (i >= EXT2_N_BLOCKS) { eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC); eh->eh_depth = 0; eh->eh_entries = 0; i = (sizeof(handle->inode->i_block) - sizeof(*eh)) / sizeof(struct ext3_extent); eh->eh_max = ext2fs_cpu_to_le16(i); handle->inode->i_flags |= EXT4_EXTENTS_FL; } if (!(handle->inode->i_flags & EXT4_EXTENTS_FL)) { retval = EXT2_ET_INODE_NOT_EXTENT; goto errout; } retval = ext2fs_extent_header_verify(eh, sizeof(handle->inode->i_block)); if (retval) goto errout; handle->max_depth = ext2fs_le16_to_cpu(eh->eh_depth); handle->type = ext2fs_le16_to_cpu(eh->eh_magic); retval = ext2fs_get_mem(((handle->max_depth+1) * sizeof(struct extent_path)), &handle->path); memset(handle->path, 0, (handle->max_depth+1) * sizeof(struct extent_path)); handle->path[0].buf = (char *) handle->inode->i_block; handle->path[0].left = handle->path[0].entries = ext2fs_le16_to_cpu(eh->eh_entries); handle->path[0].max_entries = ext2fs_le16_to_cpu(eh->eh_max); handle->path[0].curr = 0; handle->path[0].end_blk = ((((__u64) handle->inode->i_size_high << 32) + handle->inode->i_size + (fs->blocksize - 1)) >> EXT2_BLOCK_SIZE_BITS(fs->super)); handle->path[0].visit_num = 1; handle->level = 0; handle->magic = EXT2_ET_MAGIC_EXTENT_HANDLE; *ret_handle = handle; return 0; errout: ext2fs_extent_free(handle); return retval; }
/* Copy the native file to the fs */ errcode_t do_write_internal(ext2_filsys fs, ext2_ino_t cwd, const char *src, const char *dest, ext2_ino_t root) { int fd; struct stat statbuf; ext2_ino_t newfile; errcode_t retval; struct ext2_inode inode; int bufsize = IO_BUFSIZE; int make_holes = 0; fd = ext2fs_open_file(src, O_RDONLY, 0); if (fd < 0) { com_err(src, errno, 0); return errno; } if (fstat(fd, &statbuf) < 0) { com_err(src, errno, 0); close(fd); return errno; } retval = ext2fs_namei(fs, root, cwd, dest, &newfile); if (retval == 0) { close(fd); return EXT2_ET_FILE_EXISTS; } retval = ext2fs_new_inode(fs, cwd, 010755, 0, &newfile); if (retval) { com_err(__func__, retval, 0); close(fd); return retval; } #ifdef DEBUGFS printf("Allocated inode: %u\n", newfile); #endif retval = ext2fs_link(fs, cwd, dest, newfile, EXT2_FT_REG_FILE); if (retval == EXT2_ET_DIR_NO_SPACE) { retval = ext2fs_expand_dir(fs, cwd); if (retval) { com_err(__func__, retval, "while expanding directory"); close(fd); return retval; } retval = ext2fs_link(fs, cwd, dest, newfile, EXT2_FT_REG_FILE); } if (retval) { com_err(dest, retval, 0); close(fd); return errno; } if (ext2fs_test_inode_bitmap2(fs->inode_map, newfile)) com_err(__func__, 0, "Warning: inode already set"); ext2fs_inode_alloc_stats2(fs, newfile, +1, 0); memset(&inode, 0, sizeof(inode)); inode.i_mode = (statbuf.st_mode & ~LINUX_S_IFMT) | LINUX_S_IFREG; inode.i_atime = inode.i_ctime = inode.i_mtime = fs->now ? fs->now : time(0); inode.i_links_count = 1; retval = ext2fs_inode_size_set(fs, &inode, statbuf.st_size); if (retval) { com_err(dest, retval, 0); close(fd); return retval; } if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT4_FEATURE_INCOMPAT_INLINE_DATA)) { inode.i_flags |= EXT4_INLINE_DATA_FL; } else if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) { int i; struct ext3_extent_header *eh; eh = (struct ext3_extent_header *) &inode.i_block[0]; eh->eh_depth = 0; eh->eh_entries = 0; eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC); i = (sizeof(inode.i_block) - sizeof(*eh)) / sizeof(struct ext3_extent); eh->eh_max = ext2fs_cpu_to_le16(i); inode.i_flags |= EXT4_EXTENTS_FL; } retval = ext2fs_write_new_inode(fs, newfile, &inode); if (retval) { com_err(__func__, retval, "while creating inode %u", newfile); close(fd); return retval; } if (inode.i_flags & EXT4_INLINE_DATA_FL) { retval = ext2fs_inline_data_init(fs, newfile); if (retval) { com_err("copy_file", retval, 0); close(fd); return retval; } } if (LINUX_S_ISREG(inode.i_mode)) { if (statbuf.st_blocks < statbuf.st_size / S_BLKSIZE) { make_holes = 1; /* * Use I/O blocksize as buffer size when * copying sparse files. */ bufsize = statbuf.st_blksize; } retval = copy_file(fs, fd, newfile, bufsize, make_holes); if (retval) com_err("copy_file", retval, 0); } close(fd); return retval; }