static errcode_t mk_hugefile(ext2_filsys fs, blk64_t num, ext2_ino_t dir, unsigned long idx, ext2_ino_t *ino) { errcode_t retval; struct ext2_inode inode; retval = ext2fs_new_inode(fs, 0, LINUX_S_IFREG, NULL, ino); if (retval) return retval; memset(&inode, 0, sizeof(struct ext2_inode)); inode.i_mode = LINUX_S_IFREG | (0666 & ~fs->umask); inode.i_links_count = 1; inode.i_uid = uid & 0xFFFF; ext2fs_set_i_uid_high(inode, (uid >> 16) & 0xffff); inode.i_gid = gid & 0xFFFF; ext2fs_set_i_gid_high(inode, (gid >> 16) & 0xffff); retval = ext2fs_write_new_inode(fs, *ino, &inode); if (retval) return retval; ext2fs_inode_alloc_stats2(fs, *ino, +1, 0); if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT3_FEATURE_INCOMPAT_EXTENTS)) inode.i_flags |= EXT4_EXTENTS_FL; retval = ext2fs_fallocate(fs, EXT2_FALLOCATE_FORCE_INIT | EXT2_FALLOCATE_ZERO_BLOCKS, *ino, &inode, goal, 0, num); if (retval) return retval; retval = ext2fs_inode_size_set(fs, &inode, num * fs->blocksize); if (retval) return retval; retval = ext2fs_write_inode(fs, *ino, &inode); if (retval) goto errout; if (idx_digits) sprintf(fn_numbuf, "%0*lu", idx_digits, idx); else if (num_files > 1) sprintf(fn_numbuf, "%lu", idx); retry: retval = ext2fs_link(fs, dir, fn_buf, *ino, EXT2_FT_REG_FILE); if (retval == EXT2_ET_DIR_NO_SPACE) { retval = ext2fs_expand_dir(fs, dir); if (retval) goto errout; goto retry; } errout: return retval; }
static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs, struct out_dir *outdir, ext2_ino_t ino, struct ext2_inode *inode, int compress) { struct write_dir_struct wd; errcode_t retval; retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num); if (retval) return retval; wd.outdir = outdir; wd.err = 0; wd.ino = ino; wd.ctx = ctx; wd.dir = ino; retval = ext2fs_block_iterate3(fs, ino, 0, NULL, write_dir_block, &wd); if (retval) return retval; if (wd.err) return wd.err; e2fsck_read_inode(ctx, ino, inode, "rehash_dir"); if (compress) inode->i_flags &= ~EXT2_INDEX_FL; else inode->i_flags |= EXT2_INDEX_FL; #ifdef REHASH_DEBUG printf("%u: set inode size to %u blocks = %u bytes\n", ino, outdir->num, outdir->num * fs->blocksize); #endif retval = ext2fs_inode_size_set(fs, inode, (ext2_off64_t)outdir->num * fs->blocksize); if (retval) return retval; /* ext2fs_punch() calls ext2fs_write_inode() which writes the size */ return ext2fs_punch(fs, ino, inode, NULL, outdir->num, ~0ULL); }
static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs, struct out_dir *outdir, ext2_ino_t ino, struct ext2_inode *inode, int compress) { struct write_dir_struct wd; errcode_t retval; retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num); if (retval) return retval; wd.outdir = outdir; wd.err = 0; wd.ctx = ctx; wd.cleared = 0; wd.dir = ino; retval = ext2fs_block_iterate3(fs, ino, 0, 0, write_dir_block, &wd); if (retval) return retval; if (wd.err) return wd.err; e2fsck_read_inode(ctx, ino, inode, "rehash_dir"); if (compress) inode->i_flags &= ~EXT2_INDEX_FL; else inode->i_flags |= EXT2_INDEX_FL; retval = ext2fs_inode_size_set(fs, inode, outdir->num * fs->blocksize); if (retval) return retval; ext2fs_iblk_sub_blocks(fs, inode, wd.cleared); e2fsck_write_inode(ctx, ino, inode, "rehash_dir"); return 0; }
/* * This function creates a journal using direct I/O routines. */ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino, blk_t num_blocks, blk64_t goal, int flags) { char *buf; errcode_t retval; struct ext2_inode inode; unsigned long long inode_size; struct mkjournal_struct es; if ((retval = ext2fs_create_journal_superblock(fs, num_blocks, flags, &buf))) return retval; if ((retval = ext2fs_read_bitmaps(fs))) goto out2; if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) goto out2; if (inode.i_blocks > 0) { retval = EEXIST; goto out2; } es.num_blocks = num_blocks; es.newblocks = 0; es.buf = buf; es.err = 0; es.flags = flags; es.zero_count = 0; es.goal = (goal != ~0ULL) ? goal : get_midpoint_journal_block(fs); if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) { inode.i_flags |= EXT4_EXTENTS_FL; if ((retval = ext2fs_write_inode(fs, journal_ino, &inode))) goto out2; } retval = ext2fs_block_iterate3(fs, journal_ino, BLOCK_FLAG_APPEND, 0, mkjournal_proc, &es); if (retval) goto out2; if (es.err) { retval = es.err; goto out2; } if (es.zero_count) { retval = ext2fs_zero_blocks2(fs, es.blk_to_zero, es.zero_count, 0, 0); if (retval) goto out2; } if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) goto out2; inode_size = (unsigned long long)fs->blocksize * num_blocks; ext2fs_iblk_add_blocks(fs, &inode, es.newblocks); inode.i_mtime = inode.i_ctime = fs->now ? fs->now : time(0); inode.i_links_count = 1; inode.i_mode = LINUX_S_IFREG | 0600; retval = ext2fs_inode_size_set(fs, &inode, inode_size); if (retval) goto out2; if ((retval = ext2fs_write_new_inode(fs, journal_ino, &inode))) goto out2; retval = 0; memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); fs->super->s_jnl_blocks[15] = inode.i_size_high; fs->super->s_jnl_blocks[16] = inode.i_size; fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; ext2fs_mark_super_dirty(fs); out2: ext2fs_free_mem(&buf); return retval; }
/* * This code assumes that the reserved blocks have already been marked in-use * during ext2fs_initialize(), so that they are not allocated for other * uses before we can add them to the resize inode (which has to come * after the creation of the inode table). */ errcode_t ext2fs_create_resize_inode(ext2_filsys fs) { errcode_t retval, retval2; struct ext2_super_block *sb; struct ext2_inode inode; __u32 *dindir_buf, *gdt_buf; unsigned long long apb, inode_size; /* FIXME-64 - can't deal with extents */ blk_t dindir_blk, rsv_off, gdt_off, gdt_blk; int dindir_dirty = 0, inode_dirty = 0, sb_blk = 0; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); sb = fs->super; retval = ext2fs_get_array(2, fs->blocksize, &dindir_buf); if (retval) return retval; gdt_buf = (__u32 *)((char *)dindir_buf + fs->blocksize); retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode); if (retval) goto out_free; /* * File systems with a blocksize of 1024 and bigalloc have * sb->s_first_data_block of 0; yet the superblock is still at * block #1. We compensate for it here. */ sb_blk = sb->s_first_data_block; if (fs->blocksize == 1024 && sb_blk == 0) sb_blk = 1; /* Maximum possible file size (we donly use the dindirect blocks) */ apb = EXT2_ADDR_PER_BLOCK(sb); if ((dindir_blk = inode.i_block[EXT2_DIND_BLOCK])) { #ifdef RES_GDT_DEBUG printf("reading GDT dindir %u\n", dindir_blk); #endif retval = ext2fs_read_ind_block(fs, dindir_blk, dindir_buf); if (retval) goto out_inode; } else { blk_t goal = sb_blk + fs->desc_blocks + sb->s_reserved_gdt_blocks + 2 + fs->inode_blocks_per_group; retval = ext2fs_alloc_block(fs, goal, 0, &dindir_blk); if (retval) goto out_free; inode.i_mode = LINUX_S_IFREG | 0600; inode.i_links_count = 1; inode.i_block[EXT2_DIND_BLOCK] = dindir_blk; ext2fs_iblk_set(fs, &inode, 1); memset(dindir_buf, 0, fs->blocksize); #ifdef RES_GDT_DEBUG printf("allocated GDT dindir %u\n", dindir_blk); #endif dindir_dirty = inode_dirty = 1; inode_size = apb*apb + apb + EXT2_NDIR_BLOCKS; inode_size *= fs->blocksize; retval = ext2fs_inode_size_set(fs, &inode, inode_size); if (retval) goto out_free; inode.i_ctime = fs->now ? fs->now : time(0); } for (rsv_off = 0, gdt_off = fs->desc_blocks, gdt_blk = sb_blk + 1 + fs->desc_blocks; rsv_off < sb->s_reserved_gdt_blocks; rsv_off++, gdt_off++, gdt_blk++) { unsigned int three = 1, five = 5, seven = 7; unsigned int grp, last = 0; int gdt_dirty = 0; gdt_off %= apb; if (!dindir_buf[gdt_off]) { /* FIXME XXX XXX blk_t new_blk; retval = ext2fs_new_block(fs, gdt_blk, 0, &new_blk); if (retval) goto out_free; if (new_blk != gdt_blk) { // XXX free block retval = -1; // XXX } */ gdt_dirty = dindir_dirty = inode_dirty = 1; memset(gdt_buf, 0, fs->blocksize); dindir_buf[gdt_off] = gdt_blk; ext2fs_iblk_add_blocks(fs, &inode, 1); #ifdef RES_GDT_DEBUG printf("added primary GDT block %u at %u[%u]\n", gdt_blk, dindir_blk, gdt_off); #endif } else if (dindir_buf[gdt_off] == gdt_blk) { #ifdef RES_GDT_DEBUG printf("reading primary GDT block %u\n", gdt_blk); #endif retval = ext2fs_read_ind_block(fs, gdt_blk, gdt_buf); if (retval) goto out_dindir; } else { #ifdef RES_GDT_DEBUG printf("bad primary GDT %u != %u at %u[%u]\n", dindir_buf[gdt_off], gdt_blk,dindir_blk,gdt_off); #endif retval = EXT2_ET_RESIZE_INODE_CORRUPT; goto out_dindir; } while ((grp = list_backups(fs, &three, &five, &seven)) < fs->group_desc_count) { blk_t expect = gdt_blk + grp * sb->s_blocks_per_group; if (!gdt_buf[last]) { #ifdef RES_GDT_DEBUG printf("added backup GDT %u grp %u@%u[%u]\n", expect, grp, gdt_blk, last); #endif gdt_buf[last] = expect; ext2fs_iblk_add_blocks(fs, &inode, 1); gdt_dirty = inode_dirty = 1; } else if (gdt_buf[last] != expect) { #ifdef RES_GDT_DEBUG printf("bad backup GDT %u != %u at %u[%u]\n", gdt_buf[last], expect, gdt_blk, last); #endif retval = EXT2_ET_RESIZE_INODE_CORRUPT; goto out_dindir; } last++; } if (gdt_dirty) { #ifdef RES_GDT_DEBUG printf("writing primary GDT block %u\n", gdt_blk); #endif retval = ext2fs_write_ind_block(fs, gdt_blk, gdt_buf); if (retval) goto out_dindir; } } out_dindir: if (dindir_dirty) { retval2 = ext2fs_write_ind_block(fs, dindir_blk, dindir_buf); if (!retval) retval = retval2; } out_inode: #ifdef RES_GDT_DEBUG printf("inode.i_blocks = %u, i_size = %u\n", inode.i_blocks, inode.i_size); #endif if (inode_dirty) { inode.i_atime = inode.i_mtime = fs->now ? fs->now : time(0); retval2 = ext2fs_write_new_inode(fs, EXT2_RESIZE_INO, &inode); if (!retval) retval = retval2; } out_free: ext2fs_free_mem(&dindir_buf); return retval; }
static errcode_t mk_hugefile(ext2_filsys fs, blk64_t num, ext2_ino_t dir, unsigned long idx, ext2_ino_t *ino) { errcode_t retval; blk64_t lblk, bend = 0; __u64 size; blk64_t left; blk64_t count = 0; struct ext2_inode inode; ext2_extent_handle_t handle; retval = ext2fs_new_inode(fs, 0, LINUX_S_IFREG, NULL, ino); if (retval) return retval; memset(&inode, 0, sizeof(struct ext2_inode)); inode.i_mode = LINUX_S_IFREG | (0666 & ~fs->umask); inode.i_links_count = 1; inode.i_uid = uid & 0xFFFF; ext2fs_set_i_uid_high(inode, (uid >> 16) & 0xffff); inode.i_gid = gid & 0xFFFF; ext2fs_set_i_gid_high(inode, (gid >> 16) & 0xffff); retval = ext2fs_write_new_inode(fs, *ino, &inode); if (retval) return retval; ext2fs_inode_alloc_stats2(fs, *ino, +1, 0); retval = ext2fs_extent_open2(fs, *ino, &inode, &handle); if (retval) return retval; /* * We don't use ext2fs_fallocate() here because hugefiles are * designed to be physically contiguous (if the block group * descriptors are configured to be in a single block at the * beginning of the file system, by using the * packed_meta_blocks layout), with the extent tree blocks * allocated near the beginning of the file system. */ lblk = 0; left = num ? num : 1; while (left) { blk64_t pblk, end; blk64_t n = left; retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map, goal, ext2fs_blocks_count(fs->super) - 1, &end); if (retval) goto errout; goal = end; retval = ext2fs_find_first_set_block_bitmap2(fs->block_map, goal, ext2fs_blocks_count(fs->super) - 1, &bend); if (retval == ENOENT) { bend = ext2fs_blocks_count(fs->super); if (num == 0) left = 0; } if (!num || bend - goal < left) n = bend - goal; pblk = goal; if (num) left -= n; goal += n; count += n; ext2fs_block_alloc_stats_range(fs, pblk, n, +1); if (zero_hugefile) { blk64_t ret_blk; retval = ext2fs_zero_blocks2(fs, pblk, n, &ret_blk, NULL); if (retval) com_err(program_name, retval, _("while zeroing block %llu " "for hugefile"), ret_blk); } while (n) { blk64_t l = n; struct ext2fs_extent newextent; if (l > EXT_INIT_MAX_LEN) l = EXT_INIT_MAX_LEN; newextent.e_len = l; newextent.e_pblk = pblk; newextent.e_lblk = lblk; newextent.e_flags = 0; retval = ext2fs_extent_insert(handle, EXT2_EXTENT_INSERT_AFTER, &newextent); if (retval) return retval; pblk += l; lblk += l; n -= l; } } retval = ext2fs_read_inode(fs, *ino, &inode); if (retval) goto errout; retval = ext2fs_iblk_add_blocks(fs, &inode, count / EXT2FS_CLUSTER_RATIO(fs)); if (retval) goto errout; size = (__u64) count * fs->blocksize; retval = ext2fs_inode_size_set(fs, &inode, size); if (retval) goto errout; retval = ext2fs_write_new_inode(fs, *ino, &inode); if (retval) goto errout; if (idx_digits) sprintf(fn_numbuf, "%0*lu", idx_digits, idx); else if (num_files > 1) sprintf(fn_numbuf, "%lu", idx); retry: retval = ext2fs_link(fs, dir, fn_buf, *ino, EXT2_FT_REG_FILE); if (retval == EXT2_ET_DIR_NO_SPACE) { retval = ext2fs_expand_dir(fs, dir); if (retval) goto errout; goto retry; } if (retval) goto errout; errout: if (handle) ext2fs_extent_free(handle); return retval; }
errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino, const char *name, char *target) { errcode_t retval; struct ext2_inode inode; ext2_ino_t scratch_ino; blk64_t blk; int fastlink; unsigned int target_len; char *block_buf = 0; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); /* The Linux kernel doesn't allow for links longer than a block */ target_len = strlen(target); if (target_len > fs->blocksize) { retval = EXT2_ET_INVALID_ARGUMENT; goto cleanup; } /* * Allocate a data block for slow links */ fastlink = (target_len < sizeof(inode.i_block)); if (!fastlink) { retval = ext2fs_new_block2(fs, 0, 0, &blk); if (retval) goto cleanup; retval = ext2fs_get_mem(fs->blocksize, &block_buf); if (retval) goto cleanup; } /* * Allocate an inode, if necessary */ if (!ino) { retval = ext2fs_new_inode(fs, parent, LINUX_S_IFLNK | 0755, 0, &ino); if (retval) goto cleanup; } /* * Create the inode structure.... */ memset(&inode, 0, sizeof(struct ext2_inode)); inode.i_mode = LINUX_S_IFLNK | 0777; inode.i_uid = inode.i_gid = 0; ext2fs_iblk_set(fs, &inode, fastlink ? 0 : 1); inode.i_links_count = 1; ext2fs_inode_size_set(fs, &inode, target_len); /* The time fields are set by ext2fs_write_new_inode() */ if (fastlink) { /* Fast symlinks, target stored in inode */ strcpy((char *)&inode.i_block, target); } else { /* Slow symlinks, target stored in the first block */ memset(block_buf, 0, fs->blocksize); strcpy(block_buf, target); if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) { /* * The extent bmap is setup after the inode and block * have been written out below. */ inode.i_flags |= EXT4_EXTENTS_FL; } } /* * Write out the inode and inode data block. The inode generation * number is assigned by write_new_inode, which means that the * operations using ino must come after it. */ retval = ext2fs_write_new_inode(fs, ino, &inode); if (retval) goto cleanup; if (!fastlink) { retval = ext2fs_bmap2(fs, ino, &inode, NULL, BMAP_SET, 0, NULL, &blk); if (retval) goto cleanup; retval = io_channel_write_blk64(fs->io, blk, 1, block_buf); if (retval) goto cleanup; } /* * Link the symlink into the filesystem hierarchy */ if (name) { retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, &scratch_ino); if (!retval) { retval = EXT2_ET_FILE_EXISTS; goto cleanup; } if (retval != EXT2_ET_FILE_NOT_FOUND) goto cleanup; retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_SYMLINK); if (retval) goto cleanup; } /* * Update accounting.... */ if (!fastlink) ext2fs_block_alloc_stats2(fs, blk, +1); ext2fs_inode_alloc_stats2(fs, ino, +1, 0); cleanup: if (block_buf) ext2fs_free_mem(&block_buf); return retval; }
/* * This function creates a journal using direct I/O routines. */ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino, blk_t num_blocks, blk64_t goal, int flags) { char *buf; errcode_t retval; struct ext2_inode inode; unsigned long long inode_size; int falloc_flags = EXT2_FALLOCATE_FORCE_INIT; blk64_t zblk; if ((retval = ext2fs_create_journal_superblock(fs, num_blocks, flags, &buf))) return retval; if ((retval = ext2fs_read_bitmaps(fs))) goto out2; if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) goto out2; if (inode.i_blocks > 0) { retval = EEXIST; goto out2; } if (goal == ~0ULL) goal = get_midpoint_journal_block(fs); if (ext2fs_has_feature_extents(fs->super)) inode.i_flags |= EXT4_EXTENTS_FL; if (!(flags & EXT2_MKJOURNAL_LAZYINIT)) falloc_flags |= EXT2_FALLOCATE_ZERO_BLOCKS; inode_size = (unsigned long long)fs->blocksize * num_blocks; inode.i_mtime = inode.i_ctime = fs->now ? fs->now : time(0); inode.i_links_count = 1; inode.i_mode = LINUX_S_IFREG | 0600; retval = ext2fs_inode_size_set(fs, &inode, inode_size); if (retval) goto out2; retval = ext2fs_fallocate(fs, falloc_flags, journal_ino, &inode, goal, 0, num_blocks); if (retval) goto out2; if ((retval = ext2fs_write_new_inode(fs, journal_ino, &inode))) goto out2; retval = ext2fs_bmap2(fs, journal_ino, &inode, NULL, 0, 0, NULL, &zblk); if (retval) goto out2; retval = io_channel_write_blk64(fs->io, zblk, 1, buf); if (retval) goto out2; memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); fs->super->s_jnl_blocks[15] = inode.i_size_high; fs->super->s_jnl_blocks[16] = inode.i_size; fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; ext2fs_mark_super_dirty(fs); out2: ext2fs_free_mem(&buf); 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; }