errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, void *buf, size_t size) { struct ext2_inode inode_buf; struct ext2_inline_data data; errcode_t retval; size_t free_ea_size, existing_size, free_inode_size; if (!inode) { retval = ext2fs_read_inode(fs, ino, &inode_buf); if (retval) return retval; inode = &inode_buf; } if (size <= EXT4_MIN_INLINE_DATA_SIZE) { retval = ext2fs_inline_data_ea_remove(fs, ino); if (retval) return retval; memcpy((void *)inode->i_block, buf, size); return ext2fs_write_inode(fs, ino, inode); } retval = ext2fs_xattr_inode_max_size(fs, ino, &free_ea_size); if (retval) return retval; retval = ext2fs_inline_data_size(fs, ino, &existing_size); if (retval) return retval; if (existing_size < EXT4_MIN_INLINE_DATA_SIZE) free_inode_size = EXT4_MIN_INLINE_DATA_SIZE - existing_size; else free_inode_size = 0; if (size != existing_size && size > existing_size + free_ea_size + free_inode_size) return EXT2_ET_INLINE_DATA_NO_SPACE; memcpy((void *)inode->i_block, buf, EXT4_MIN_INLINE_DATA_SIZE); retval = ext2fs_write_inode(fs, ino, inode); if (retval) return retval; data.fs = fs; data.ino = ino; data.ea_size = size - EXT4_MIN_INLINE_DATA_SIZE; data.ea_data = buf + EXT4_MIN_INLINE_DATA_SIZE; return ext2fs_inline_data_ea_set(&data); }
static void move_quota_inode(ext2_filsys fs, ext2_ino_t from_ino, ext2_ino_t to_ino, int qtype) { struct ext2_inode inode; char qf_name[QUOTA_NAME_LEN]; /* We need the inode bitmap to be loaded */ if (ext2fs_read_bitmaps(fs)) return; if (ext2fs_read_inode(fs, from_ino, &inode)) return; inode.i_links_count = 1; inode.i_mode = LINUX_S_IFREG | 0600; inode.i_flags = EXT2_IMMUTABLE_FL; if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) inode.i_flags |= EXT4_EXTENTS_FL; ext2fs_write_new_inode(fs, to_ino, &inode); /* unlink the old inode */ quota_get_qf_name(qtype, QFMT_VFS_V1, qf_name); ext2fs_unlink(fs, EXT2_ROOT_INO, qf_name, from_ino, 0); ext2fs_inode_alloc_stats(fs, from_ino, -1); /* Clear out the original inode in the inode-table block. */ memset(&inode, 0, sizeof(struct ext2_inode)); ext2fs_write_inode(fs, from_ino, &inode); }
static int fix_directory(ext2_filsys fs, struct ext2_db_entry2 *db, void *priv_data) { errcode_t retval; empty_dir_info edi = (empty_dir_info) priv_data; edi->logblk = 0; edi->freed_blocks = 0; edi->ino = db->ino; retval = ext2fs_read_inode(fs, db->ino, &edi->inode); if (retval) return 0; retval = ext2fs_block_iterate3(fs, db->ino, 0, edi->block_buf, empty_pass1, edi); if (retval) return 0; if (edi->freed_blocks) { edi->inode.i_size -= edi->freed_blocks * fs->blocksize; ext2fs_iblk_add_blocks(fs, &edi->inode, edi->freed_blocks); retval = ext2fs_write_inode(fs, db->ino, &edi->inode); if (retval) return 0; } return 0; }
static errcode_t update_path(ext2_extent_handle_t handle) { blk64_t blk; errcode_t retval; struct ext3_extent_idx *ix; struct ext3_extent_header *eh; if (handle->level == 0) { retval = ext2fs_write_inode(handle->fs, handle->ino, handle->inode); } else { ix = handle->path[handle->level - 1].curr; blk = ext2fs_le32_to_cpu(ix->ei_leaf) + ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32); /* then update the checksum */ eh = (struct ext3_extent_header *) handle->path[handle->level].buf; retval = ext2fs_extent_block_csum_set(handle->fs, handle->ino, eh); if (retval) return retval; retval = io_channel_write_blk64(handle->fs->io, blk, 1, handle->path[handle->level].buf); } return retval; }
int modinode(e2i_ctx_t *e2c, const char *fname, ext2_ino_t e2ino) { struct ext2_inode inode; int uid, gid, ret; /* read the inode, alter uid, gid and write it back */ ret = ext2fs_read_inode(e2c->fs, e2ino, &inode); E2_ERR(ret, "Ext2 read Inode Error", ""); /* do the root squash */ if (! e2c->preserve_uidgid) { inode.i_uid = e2c->default_uid; inode.i_gid = e2c->default_gid; } /* if the filename is mentioned in .UIDGID we must change the owner */ if (uiddb_search(e2c->uid_db, fname, &uid, &gid)){ if (e2c->verbose) printf("Changing UID and GID for %s (%d:%d)\n", fname, uid, gid); inode.i_uid = uid; inode.i_gid = gid; } ret = ext2fs_write_inode(e2c->fs, e2ino, &inode); E2_ERR(ret, "Ext2 write Inode Error", ""); return 0; }
/* Link an inode number to a directory */ static errcode_t add_link(ext2_filsys fs, ext2_ino_t parent_ino, ext2_ino_t ino, const char *name) { struct ext2_inode inode; errcode_t retval; retval = ext2fs_read_inode(fs, ino, &inode); if (retval) { com_err(__func__, retval, "while reading inode %u", ino); return retval; } retval = ext2fs_link(fs, parent_ino, name, ino, inode.i_flags); if (retval == EXT2_ET_DIR_NO_SPACE) { retval = ext2fs_expand_dir(fs, parent_ino); if (retval) { com_err(__func__, retval, "while expanding directory"); return retval; } retval = ext2fs_link(fs, parent_ino, name, ino, inode.i_flags); } if (retval) { com_err(__func__, retval, "while linking %s", name); return retval; } inode.i_links_count++; retval = ext2fs_write_inode(fs, ino, &inode); if (retval) com_err(__func__, retval, "while writing inode %u", ino); 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; 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 ext3u_write_inode(ext2_filsys fs, ext2_ino_t undel_ino, int flags) { char *buf; errcode_t retval; struct ext2_inode inode; struct mk_ext3u_struct es; __u32 num_blocks = ext3u_fifo_reserved + ext3u_skip_reserved + ext3u_index_reserved + 1; if ((retval = ext3u_create_superblock(fs, flags, &buf))) return retval; if ((retval = ext2fs_read_bitmaps(fs))) return retval; if ((retval = ext2fs_read_inode(fs, undel_ino, &inode))) return retval; if (inode.i_blocks > 0) return EEXIST; es.goal = 0; es.num_blocks = num_blocks; es.newblocks = 0; es.buf = buf; es.err = 0; es.zero_count = 0; retval = ext2fs_block_iterate2(fs, undel_ino, BLOCK_FLAG_APPEND, 0, mk_ext3u_proc, &es); if (es.err) { retval = es.err; goto errout; } if (es.zero_count) { retval = ext2fs_zero_blocks(fs, es.blk_to_zero, es.zero_count, 0, 0); if (retval) goto errout; } if ((retval = ext2fs_read_inode(fs, undel_ino, &inode))) goto errout; inode.i_size += 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; if ((retval = ext2fs_write_inode(fs, undel_ino, &inode))) goto errout; retval = 0; errout: ext2fs_free_mem(&buf); return retval; }
long write_inode(ext2_filsys fs, ext2_ino_t file, struct ext2_inode *inode) { long retval; if ((retval = ext2fs_write_inode(fs, file, inode))) fprintf(stderr, "%s\n", error_message(retval)); 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 size, int flags) { char *buf; errcode_t retval; struct ext2_inode inode; struct mkjournal_struct es; if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf))) return retval; if ((retval = ext2fs_read_bitmaps(fs))) return retval; if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) return retval; if (inode.i_blocks > 0) return EEXIST; es.num_blocks = size; es.newblocks = 0; es.buf = buf; es.err = 0; retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND, 0, mkjournal_proc, &es); if (es.err) { retval = es.err; goto errout; } if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) goto errout; inode.i_size += fs->blocksize * size; inode.i_blocks += (fs->blocksize / 512) * es.newblocks; inode.i_mtime = inode.i_ctime = time(0); inode.i_links_count = 1; inode.i_mode = LINUX_S_IFREG | 0600; if ((retval = ext2fs_write_inode(fs, journal_ino, &inode))) goto errout; retval = 0; memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); fs->super->s_jnl_blocks[16] = inode.i_size; fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; ext2fs_mark_super_dirty(fs); errout: ext2fs_free_mem(&buf); return retval; }
void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino, struct ext2_inode * inode, const char *proc) { errcode_t retval; retval = ext2fs_write_inode(ctx->fs, ino, inode); if (retval) { com_err("ext2fs_write_inode", retval, _("while writing inode %lu in %s"), ino, proc); fatal_error(ctx, 0); } }
int debugfs_write_inode(ext2_ino_t ino, struct ext2_inode * inode, const char *cmd) { int retval; retval = ext2fs_write_inode(current_fs, ino, inode); if (retval) { com_err(cmd, retval, "while writing inode %u", ino); return 1; } return 0; }
static errcode_t create_directory(ext2_filsys fs, char *dir, ext2_ino_t *ret_ino) { struct ext2_inode inode; ext2_ino_t ino = EXT2_ROOT_INO; ext2_ino_t newdir; errcode_t retval = 0; char *fn, *cp, *next; fn = malloc(strlen(dir) + 1); if (fn == NULL) return ENOMEM; strcpy(fn, dir); cp = fn; while(1) { next = strchr(cp, '/'); if (next) *next++ = 0; if (*cp) { retval = ext2fs_new_inode(fs, ino, LINUX_S_IFDIR, NULL, &newdir); if (retval) goto errout; retval = ext2fs_mkdir(fs, ino, newdir, cp); if (retval) goto errout; ino = newdir; retval = ext2fs_read_inode(fs, ino, &inode); if (retval) goto errout; 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_inode(fs, ino, &inode); if (retval) goto errout; } if (next == NULL || *next == '\0') break; cp = next; } errout: free(fn); if (retval == 0) *ret_ino = ino; return retval; }
static errcode_t ext2fs_inline_data_dir_expand(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, char *buf, size_t size) { errcode_t retval; blk64_t blk; char *blk_buf; retval = ext2fs_get_memzero(fs->blocksize, &blk_buf); if (retval) return retval; #ifdef WORDS_BIGENDIAN retval = ext2fs_dirent_swab_in2(fs, buf + EXT4_INLINE_DATA_DOTDOT_SIZE, size, 0); if (retval) goto errout; #endif /* Adjust the rec_len */ retval = ext2fs_inline_data_convert_dir(fs, ino, blk_buf, buf, size); if (retval) goto errout; /* Allocate a new block */ retval = ext2fs_new_block2(fs, 0, 0, &blk); if (retval) goto errout; retval = ext2fs_write_dir_block4(fs, blk, blk_buf, 0, ino); if (retval) goto errout; /* Update inode */ if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT3_FEATURE_INCOMPAT_EXTENTS)) inode->i_flags |= EXT4_EXTENTS_FL; inode->i_flags &= ~EXT4_INLINE_DATA_FL; retval = ext2fs_iblk_add_blocks(fs, inode, 1); if (retval) goto errout; inode->i_size = fs->blocksize; retval = ext2fs_bmap2(fs, ino, inode, 0, BMAP_SET, 0, 0, &blk); if (retval) goto errout; retval = ext2fs_write_inode(fs, ino, inode); if (retval) goto errout; ext2fs_block_alloc_stats(fs, blk, +1); errout: ext2fs_free_mem(&blk_buf); return retval; }
errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir) { errcode_t retval; struct expand_dir_struct es; struct ext2_inode inode; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); if (!(fs->flags & EXT2_FLAG_RW)) return EXT2_ET_RO_FILSYS; if (!fs->block_map) return EXT2_ET_NO_BLOCK_BITMAP; retval = ext2fs_check_directory(fs, dir); if (retval) return retval; es.done = 0; es.err = 0; es.goal = 0; es.newblocks = 0; es.dir = dir; retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_APPEND, 0, expand_dir_proc, &es); if (es.err) return es.err; if (!es.done) return EXT2_ET_EXPAND_DIR_ERR; /* * Update the size and block count fields in the inode. */ retval = ext2fs_read_inode(fs, dir, &inode); if (retval) return retval; inode.i_size += fs->blocksize; ext2fs_iblk_add_blocks(fs, &inode, es.newblocks); retval = ext2fs_write_inode(fs, dir, &inode); if (retval) return retval; return 0; }
errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, ext2_ino_t ino, int flags) { errcode_t retval; struct link_struct ls; struct ext2_inode inode; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); if (!(fs->flags & EXT2_FLAG_RW)) return EXT2_ET_RO_FILSYS; ls.fs = fs; ls.name = name; ls.namelen = name ? strlen(name) : 0; ls.inode = ino; ls.flags = flags; ls.done = 0; ls.sb = fs->super; ls.blocksize = fs->blocksize; ls.err = 0; retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, 0, link_proc, &ls); if (retval) return retval; if (ls.err) return ls.err; if (!ls.done) return EXT2_ET_DIR_NO_SPACE; if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0) return retval; /* * If this function changes to preserve the htree, remove the * two hunks in link_proc that shove checksum tails into the * former dx_root/dx_node blocks. */ if (inode.i_flags & EXT2_INDEX_FL) { inode.i_flags &= ~EXT2_INDEX_FL; if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0) return retval; } return 0; }
int do_writeinode (ext2_filsys e2fs, ext2_ino_t ino, struct ext2_inode *inode) { int rt; errcode_t rc; if (inode->i_links_count < 1) { rt = do_killfilebyinode(e2fs, ino, inode); if (rt) { debugf("do_killfilebyinode(e2fs, ino, inode); failed"); return rt; } } else { rc = ext2fs_write_inode(e2fs, ino, inode); if (rc) { debugf("ext2fs_read_inode(e2fs, *ino, inode); failed"); return -EIO; } } return 0; }
/* Set the uid, gid, mode and time for the inode */ static errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t cwd, ext2_ino_t ino, struct stat *st) { errcode_t retval; struct ext2_inode inode; retval = ext2fs_read_inode(fs, ino, &inode); if (retval) { com_err(__func__, retval, "while reading inode %u", ino); return retval; } fill_inode(&inode, st); retval = ext2fs_write_inode(fs, ino, &inode); if (retval) com_err(__func__, retval, "while writing inode %u", ino); return retval; }
static errcode_t update_path(ext2_extent_handle_t handle) { blk64_t blk; errcode_t retval; struct ext3_extent_idx *ix; if (handle->level == 0) { retval = ext2fs_write_inode(handle->fs, handle->ino, handle->inode); } else { ix = handle->path[handle->level - 1].curr; blk = ext2fs_le32_to_cpu(ix->ei_leaf) + ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32); retval = io_channel_write_blk(handle->fs->io, blk, 1, handle->path[handle->level].buf); } return retval; }
errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, ext2_ino_t ino, int flags) { errcode_t retval; struct link_struct ls; struct ext2_inode inode; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); if (!(fs->flags & EXT2_FLAG_RW)) return EXT2_ET_RO_FILSYS; ls.fs = fs; ls.name = name; ls.namelen = name ? strlen(name) : 0; ls.inode = ino; ls.flags = flags; ls.done = 0; ls.sb = fs->super; ls.blocksize = fs->blocksize; ls.err = 0; retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, 0, link_proc, &ls); if (retval) return retval; if (ls.err) return ls.err; if (!ls.done) return EXT2_ET_DIR_NO_SPACE; if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0) return retval; if (inode.i_flags & EXT2_INDEX_FL) { inode.i_flags &= ~EXT2_INDEX_FL; if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0) return retval; } return 0; }
errcode_t quota_remove_inode(ext2_filsys fs, enum quota_type qtype) { ext2_ino_t qf_ino; errcode_t retval; retval = ext2fs_read_bitmaps(fs); if (retval) { log_debug("Couldn't read bitmaps: %s", error_message(retval)); return retval; } qf_ino = *quota_sb_inump(fs->super, qtype); if (qf_ino == 0) return 0; retval = quota_inode_truncate(fs, qf_ino); if (retval) return retval; if (qf_ino >= EXT2_FIRST_INODE(fs->super)) { struct ext2_inode inode; retval = ext2fs_read_inode(fs, qf_ino, &inode); if (!retval) { memset(&inode, 0, sizeof(struct ext2_inode)); ext2fs_write_inode(fs, qf_ino, &inode); } ext2fs_inode_alloc_stats2(fs, qf_ino, -1, 0); ext2fs_mark_ib_dirty(fs); } quota_set_sb_inum(fs, 0, qtype); ext2fs_mark_super_dirty(fs); fs->flags &= ~EXT2_FLAG_SUPER_ONLY; retval = ext2fs_write_bitmaps(fs); if (retval) { log_debug("Couldn't write bitmaps: %s", error_message(retval)); return retval; } return 0; }
static void move_quota_inode(ext2_filsys fs, ext2_ino_t from_ino, ext2_ino_t to_ino, enum quota_type qtype) { struct ext2_inode inode; errcode_t retval; char qf_name[QUOTA_NAME_LEN]; /* We need the inode bitmap to be loaded */ if (ext2fs_read_bitmaps(fs)) return; retval = ext2fs_read_inode(fs, from_ino, &inode); if (retval) { com_err("ext2fs_read_inode", retval, "%s", _("in move_quota_inode")); return; } inode.i_links_count = 1; inode.i_mode = LINUX_S_IFREG | 0600; inode.i_flags = EXT2_IMMUTABLE_FL; if (ext2fs_has_feature_extents(fs->super)) inode.i_flags |= EXT4_EXTENTS_FL; retval = ext2fs_write_new_inode(fs, to_ino, &inode); if (retval) { com_err("ext2fs_write_new_inode", retval, "%s", _("in move_quota_inode")); return; } /* unlink the old inode */ quota_get_qf_name(qtype, QFMT_VFS_V1, qf_name); ext2fs_unlink(fs, EXT2_ROOT_INO, qf_name, from_ino, 0); ext2fs_inode_alloc_stats(fs, from_ino, -1); /* Clear out the original inode in the inode-table block. */ memset(&inode, 0, sizeof(struct ext2_inode)); ext2fs_write_inode(fs, from_ino, &inode); }
/* * Utility routine to adjust the inode counts on an inode. */ errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj) { ext2_filsys fs = ctx->fs; errcode_t retval; struct ext2_inode inode; if (!ino) return 0; retval = ext2fs_read_inode(fs, ino, &inode); if (retval) return retval; #if 0 printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj, inode.i_links_count); #endif if (adj == 1) { ext2fs_icount_increment(ctx->inode_count, ino, 0); if (inode.i_links_count == (__u16) ~0) return 0; ext2fs_icount_increment(ctx->inode_link_info, ino, 0); inode.i_links_count++; } else if (adj == -1) { ext2fs_icount_decrement(ctx->inode_count, ino, 0); if (inode.i_links_count == 0) return 0; ext2fs_icount_decrement(ctx->inode_link_info, ino, 0); inode.i_links_count--; } retval = ext2fs_write_inode(fs, ino, &inode); if (retval) return retval; return 0; }
/* Set the uid, gid, mode and time for the inode */ static errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t ino, struct stat *st) { errcode_t retval; struct ext2_inode inode; retval = ext2fs_read_inode(fs, ino, &inode); if (retval) { com_err(__func__, retval, _("while reading inode %u"), ino); return retval; } inode.i_uid = st->st_uid; inode.i_gid = st->st_gid; inode.i_mode |= st->st_mode; inode.i_atime = st->st_atime; inode.i_mtime = st->st_mtime; inode.i_ctime = st->st_ctime; retval = ext2fs_write_inode(fs, ino, &inode); if (retval) com_err(__func__, retval, _("while writing inode %u"), ino); return retval; }
void ext2CloseEntry(ext2_vd *vd, ext2_inode_t * ni) { // Sanity check if (!vd || !ni) { errno = ENODEV; return; } // Lock ext2Lock(vd); // Sync the entry (if it is dirty) if(ni && ni->dirty) ext2fs_write_inode(vd->fs, ni->ino, &ni->ni); // Close the entry if(ni) mem_free(ni); // Unlock ext2Unlock(vd); return; }
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; }
void e2fsck_move_ext3_journal(e2fsck_t ctx) { struct ext2_super_block *sb = ctx->fs->super; struct problem_context pctx; struct ext2_inode inode; ext2_filsys fs = ctx->fs; ext2_ino_t ino; errcode_t retval; const char * const * cpp; int group, mount_flags; clear_problem_context(&pctx); /* * If the filesystem is opened read-only, or there is no * journal, then do nothing. */ if ((ctx->options & E2F_OPT_READONLY) || (sb->s_journal_inum == 0) || !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) return; /* * Read in the journal inode */ if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0) return; /* * If it's necessary to backup the journal inode, do so. */ if ((sb->s_jnl_backup_type == 0) || ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) && memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) { if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) { memcpy(sb->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); sb->s_jnl_blocks[16] = inode.i_size; sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; ext2fs_mark_super_dirty(fs); fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; } } /* * If the journal is already the hidden inode, then do nothing */ if (sb->s_journal_inum == EXT2_JOURNAL_INO) return; /* * The journal inode had better have only one link and not be readable. */ if (inode.i_links_count != 1) return; /* * If the filesystem is mounted, or we can't tell whether * or not it's mounted, do nothing. */ retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags); if (retval || (mount_flags & EXT2_MF_MOUNTED)) return; /* * If we can't find the name of the journal inode, then do * nothing. */ for (cpp = journal_names; *cpp; cpp++) { retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp, strlen(*cpp), 0, &ino); if ((retval == 0) && (ino == sb->s_journal_inum)) break; } if (*cpp == 0) return; /* We need the inode bitmap to be loaded */ retval = ext2fs_read_bitmaps(fs); if (retval) return; pctx.str = *cpp; if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx)) return; /* * OK, we've done all the checks, let's actually move the * journal inode. Errors at this point mean we need to force * an ext2 filesystem check. */ if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0) goto err_out; if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0) goto err_out; sb->s_journal_inum = EXT2_JOURNAL_INO; ext2fs_mark_super_dirty(fs); fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; inode.i_links_count = 0; inode.i_dtime = ctx->now; if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0) goto err_out; group = ext2fs_group_of_ino(fs, ino); ext2fs_unmark_inode_bitmap(fs->inode_map, ino); ext2fs_mark_ib_dirty(fs); fs->group_desc[group].bg_free_inodes_count++; fs->super->s_free_inodes_count++; return; err_out: pctx.errcode = retval; fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx); fs->super->s_state &= ~EXT2_VALID_FS; ext2fs_mark_super_dirty(fs); return; }
/* * Given a bad blocks bitmap, update the bad blocks inode to reflect * the map. */ errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list) { errcode_t retval; struct set_badblock_record rec; struct ext2_inode inode; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); if (!fs->block_map) return EXT2_ET_NO_BLOCK_BITMAP; rec.bad_block_count = 0; rec.ind_blocks_size = rec.ind_blocks_ptr = 0; rec.max_ind_blocks = 10; retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t), &rec.ind_blocks); if (retval) return retval; memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t)); retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf); if (retval) goto cleanup; memset(rec.block_buf, 0, fs->blocksize); rec.err = 0; /* * First clear the old bad blocks (while saving the indirect blocks) */ retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, BLOCK_FLAG_DEPTH_TRAVERSE, 0, clear_bad_block_proc, &rec); if (retval) goto cleanup; if (rec.err) { retval = rec.err; goto cleanup; } /* * Now set the bad blocks! * * First, mark the bad blocks as used. This prevents a bad * block from being used as an indirecto block for the bad * block inode (!). */ if (bb_list) { retval = ext2fs_badblocks_list_iterate_begin(bb_list, &rec.bb_iter); if (retval) goto cleanup; retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, BLOCK_FLAG_APPEND, 0, set_bad_block_proc, &rec); ext2fs_badblocks_list_iterate_end(rec.bb_iter); if (retval) goto cleanup; if (rec.err) { retval = rec.err; goto cleanup; } } /* * Update the bad block inode's mod time and block count * field. */ retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode); if (retval) goto cleanup; inode.i_atime = inode.i_mtime = time(NULL); if (!inode.i_ctime) inode.i_ctime = time(NULL); inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512); inode.i_size = rec.bad_block_count * fs->blocksize; retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode); if (retval) goto cleanup; cleanup: ext2fs_free_mem(&rec.ind_blocks); ext2fs_free_mem(&rec.block_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; int rsv_add; unsigned long long apb, inode_size; blk_t dindir_blk, rsv_off, gdt_off, gdt_blk; int dindir_dirty = 0, inode_dirty = 0; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); sb = fs->super; retval = ext2fs_get_mem(2 * fs->blocksize, (void **)&dindir_buf); if (retval) goto out_free; gdt_buf = (__u32 *)((char *)dindir_buf + fs->blocksize); retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode); if (retval) goto out_free; /* Maximum possible file size (we donly use the dindirect blocks) */ apb = EXT2_ADDR_PER_BLOCK(sb); rsv_add = fs->blocksize / 512; 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 = 3 + sb->s_reserved_gdt_blocks + fs->desc_blocks + 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; inode.i_blocks = rsv_add; 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; inode.i_size = inode_size & 0xFFFFFFFF; inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF; if(inode.i_size_high) { sb->s_feature_ro_compat |= EXT2_FEATURE_RO_COMPAT_LARGE_FILE; } inode.i_ctime = time(0); } for (rsv_off = 0, gdt_off = fs->desc_blocks, gdt_blk = sb->s_first_data_block + 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; inode.i_blocks += rsv_add; #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; inode.i_blocks += rsv_add; 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 = time(0); retval2 = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode); if (!retval) retval = retval2; } out_free: ext2fs_free_mem((void **)&dindir_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, int flags) { char *buf; dgrp_t group, start, end, i, log_flex; 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; 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; } /* * Set the initial goal block to be roughly at the middle of * the filesystem. Pick a group that has the largest number * of free blocks. */ group = ext2fs_group_of_blk2(fs, (ext2fs_blocks_count(fs->super) - fs->super->s_first_data_block) / 2); log_flex = 1 << fs->super->s_log_groups_per_flex; if (fs->super->s_log_groups_per_flex && (group > log_flex)) { group = group & ~(log_flex - 1); while ((group < fs->group_desc_count) && ext2fs_bg_free_blocks_count(fs, group) == 0) group++; if (group == fs->group_desc_count) group = 0; start = group; } else start = (group > 0) ? group-1 : group; end = ((group+1) < fs->group_desc_count) ? group+1 : group; group = start; for (i=start+1; i <= end; i++) if (ext2fs_bg_free_blocks_count(fs, i) > ext2fs_bg_free_blocks_count(fs, group)) group = i; es.goal = ext2fs_group_first_block2(fs, group); retval = ext2fs_block_iterate3(fs, journal_ino, BLOCK_FLAG_APPEND, 0, mkjournal_proc, &es); if (es.err) { retval = es.err; goto errout; } if (es.zero_count) { retval = ext2fs_zero_blocks2(fs, es.blk_to_zero, es.zero_count, 0, 0); if (retval) goto errout; } if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) goto errout; inode_size = (unsigned long long)fs->blocksize * num_blocks; inode.i_size = inode_size & 0xFFFFFFFF; inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF; if (ext2fs_needs_large_file_feature(inode_size)) fs->super->s_feature_ro_compat |= EXT2_FEATURE_RO_COMPAT_LARGE_FILE; 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; if ((retval = ext2fs_write_new_inode(fs, journal_ino, &inode))) goto errout; 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); errout: ext2fs_zero_blocks2(0, 0, 0, 0, 0); out2: ext2fs_free_mem(&buf); return retval; }