Пример #1
0
void e2fsck_set_bitmap_type(ext2_filsys fs, unsigned int default_type,
			    const char *profile_name, unsigned int *old_type)
{
	unsigned type;

	if (old_type)
		*old_type = fs->default_bitmap_type;
	profile_get_uint(e2fsck_global_ctx->profile, "bitmaps",
			 profile_name, 0, default_type, &type);
	profile_get_uint(e2fsck_global_ctx->profile, "bitmaps",
			 "all", 0, type, &type);
	fs->default_bitmap_type = type ? type : default_type;
}
static void setup_tdb(e2fsck_t ctx, ext2_ino_t num_dirs)
{
    struct dir_info_db	*db = ctx->dir_info;
    unsigned int		threshold;
    errcode_t		retval;
    char			*tdb_dir, uuid[40];
    int			fd, enable;

    profile_get_string(ctx->profile, "scratch_files", "directory", 0, 0,
                       &tdb_dir);
    profile_get_uint(ctx->profile, "scratch_files",
                     "numdirs_threshold", 0, 0, &threshold);
    profile_get_boolean(ctx->profile, "scratch_files",
                        "dirinfo", 0, 1, &enable);

    if (!enable || !tdb_dir || access(tdb_dir, W_OK) ||
            (threshold && num_dirs <= threshold))
        return;

    retval = ext2fs_get_mem(strlen(tdb_dir) + 64, &db->tdb_fn);
    if (retval)
        return;

    uuid_unparse(ctx->fs->super->s_uuid, uuid);
    sprintf(db->tdb_fn, "%s/%s-dirinfo-XXXXXX", tdb_dir, uuid);
    fd = mkstemp(db->tdb_fn);
    db->tdb = tdb_open(db->tdb_fn, 0, TDB_CLEAR_IF_FIRST,
                       O_RDWR | O_CREAT | O_TRUNC, 0600);
    close(fd);
}
Пример #3
0
static void setup_tdb(e2fsck_t ctx, ext2_ino_t num_dirs)
{
    struct dir_info_db	*db = ctx->dir_info;
    unsigned int		threshold;
    errcode_t		retval;
    mode_t			save_umask;
    char			*tdb_dir, uuid[40];
    int			fd, enable;

    profile_get_string(ctx->profile, "scratch_files", "directory", 0, 0,
                       &tdb_dir);
    profile_get_uint(ctx->profile, "scratch_files",
                     "numdirs_threshold", 0, 0, &threshold);
    profile_get_boolean(ctx->profile, "scratch_files",
                        "dirinfo", 0, 1, &enable);

    if (!enable || !tdb_dir || access(tdb_dir, W_OK) ||
            (threshold && num_dirs <= threshold))
        return;

    retval = ext2fs_get_mem(strlen(tdb_dir) + 64, &db->tdb_fn);
    if (retval)
        return;

    uuid_unparse(ctx->fs->super->s_uuid, uuid);
    sprintf(db->tdb_fn, "%s/%s-dirinfo-XXXXXX", tdb_dir, uuid);
    save_umask = umask(077);
    fd = mkstemp(db->tdb_fn);
    umask(save_umask);
    if (fd < 0) {
        db->tdb = NULL;
        return;
    }

    if (num_dirs < 99991)
        num_dirs = 99991; /* largest 5 digit prime */

    db->tdb = tdb_open(db->tdb_fn, num_dirs, TDB_NOLOCK | TDB_NOSYNC,
                       O_RDWR | O_CREAT | O_TRUNC, 0600);
    close(fd);
}
Пример #4
0
static errcode_t copy_dir_entries(e2fsck_t ctx,
				  struct fill_dir_struct *fd,
				  struct out_dir *outdir)
{
	ext2_filsys 		fs = ctx->fs;
	errcode_t		retval;
	char			*block_start;
	struct hash_entry 	*ent;
	struct ext2_dir_entry	*dirent;
	unsigned int		rec_len, prev_rec_len, left, slack, offset;
	int			i;
	ext2_dirhash_t		prev_hash;
	int			csum_size = 0;
	struct			ext2_dir_entry_tail *t;

	if (ctx->htree_slack_percentage == 255) {
		profile_get_uint(ctx->profile, "options",
				 "indexed_dir_slack_percentage",
				 0, 20,
				 &ctx->htree_slack_percentage);
		if (ctx->htree_slack_percentage > 100)
			ctx->htree_slack_percentage = 20;
	}

	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
		csum_size = sizeof(struct ext2_dir_entry_tail);

	outdir->max = 0;
	retval = alloc_size_dir(fs, outdir,
				(fd->dir_size / fs->blocksize) + 2);
	if (retval)
		return retval;
	outdir->num = fd->compress ? 0 : 1;
	offset = 0;
	outdir->hashes[0] = 0;
	prev_hash = 1;
	if ((retval = get_next_block(fs, outdir, &block_start)))
		return retval;
	dirent = (struct ext2_dir_entry *) block_start;
	prev_rec_len = 0;
	rec_len = 0;
	left = fs->blocksize - csum_size;
	slack = fd->compress ? 12 :
		((fs->blocksize - csum_size) * ctx->htree_slack_percentage)/100;
	if (slack < 12)
		slack = 12;
	for (i = 0; i < fd->num_array; i++) {
		ent = fd->harray + i;
		if (ent->dir->inode == 0)
			continue;
		rec_len = EXT2_DIR_REC_LEN(ext2fs_dirent_name_len(ent->dir));
		if (rec_len > left) {
			if (left) {
				left += prev_rec_len;
				retval = ext2fs_set_rec_len(fs, left, dirent);
				if (retval)
					return retval;
			}
			if (csum_size) {
				t = EXT2_DIRENT_TAIL(block_start,
						     fs->blocksize);
				ext2fs_initialize_dirent_tail(fs, t);
			}
			if ((retval = get_next_block(fs, outdir,
						      &block_start)))
				return retval;
			offset = 0;
		}
		left = (fs->blocksize - csum_size) - offset;
		dirent = (struct ext2_dir_entry *) (block_start + offset);
		if (offset == 0) {
			if (ent->hash == prev_hash)
				outdir->hashes[outdir->num-1] = ent->hash | 1;
			else
				outdir->hashes[outdir->num-1] = ent->hash;
		}
		dirent->inode = ent->dir->inode;
		ext2fs_dirent_set_name_len(dirent,
					   ext2fs_dirent_name_len(ent->dir));
		ext2fs_dirent_set_file_type(dirent,
					    ext2fs_dirent_file_type(ent->dir));
		retval = ext2fs_set_rec_len(fs, rec_len, dirent);
		if (retval)
			return retval;
		prev_rec_len = rec_len;
		memcpy(dirent->name, ent->dir->name,
		       ext2fs_dirent_name_len(dirent));
		offset += rec_len;
		left -= rec_len;
		if (left < slack) {
			prev_rec_len += left;
			retval = ext2fs_set_rec_len(fs, prev_rec_len, dirent);
			if (retval)
				return retval;
			offset += left;
			left = 0;
		}
		prev_hash = ent->hash;
	}
	if (left)
		retval = ext2fs_set_rec_len(fs, rec_len + left, dirent);
	if (csum_size) {
		t = EXT2_DIRENT_TAIL(block_start, fs->blocksize);
		ext2fs_initialize_dirent_tail(fs, t);
	}

	return retval;
}
Пример #5
0
static errcode_t copy_dir_entries(e2fsck_t ctx,
				  struct fill_dir_struct *fd,
				  struct out_dir *outdir)
{
	ext2_filsys		fs = ctx->fs;
	errcode_t		retval;
	char			*block_start;
	struct hash_entry	*ent;
	struct ext2_dir_entry	*dirent;
	unsigned int		rec_len, prev_rec_len;
	int			i, left;
	ext2_dirhash_t		prev_hash;
	int			offset, slack;

	if (ctx->htree_slack_percentage == 255) {
		profile_get_uint(ctx->profile, "options",
				 "indexed_dir_slack_percentage",
				 0, 20,
				 &ctx->htree_slack_percentage);
		if (ctx->htree_slack_percentage > 100)
			ctx->htree_slack_percentage = 20;
	}

	outdir->max = 0;
	retval = alloc_size_dir(fs, outdir,
				(fd->dir_size / fs->blocksize) + 2);
	if (retval)
		return retval;
	outdir->num = fd->compress ? 0 : 1;
	offset = 0;
	outdir->hashes[0] = 0;
	prev_hash = 1;
	if ((retval = get_next_block(fs, outdir, &block_start)))
		return retval;
	dirent = (struct ext2_dir_entry *) block_start;
	prev_rec_len = 0;
	left = fs->blocksize;
	slack = fd->compress ? 12 :
		(fs->blocksize * ctx->htree_slack_percentage)/100;
	if (slack < 12)
		slack = 12;
	for (i=0; i < fd->num_array; i++) {
		ent = fd->harray + i;
		if (ent->dir->inode == 0)
			continue;
		rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
		if (rec_len > left) {
			if (left) {
				left += prev_rec_len;
				retval = ext2fs_set_rec_len(fs, left, dirent);
				if (retval)
					return retval;
			}
			if ((retval = get_next_block(fs, outdir,
						      &block_start)))
				return retval;
			offset = 0;
		}
		left = fs->blocksize - offset;
		dirent = (struct ext2_dir_entry *) (block_start + offset);
		if (offset == 0) {
			if (ent->hash == prev_hash)
				outdir->hashes[outdir->num-1] = ent->hash | 1;
			else
				outdir->hashes[outdir->num-1] = ent->hash;
		}
		dirent->inode = ent->dir->inode;
		dirent->name_len = ent->dir->name_len;
		retval = ext2fs_set_rec_len(fs, rec_len, dirent);
		if (retval)
			return retval;
		prev_rec_len = rec_len;
		memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
		offset += rec_len;
		left -= rec_len;
		if (left < slack) {
			prev_rec_len += left;
			retval = ext2fs_set_rec_len(fs, prev_rec_len, dirent);
			if (retval)
				return retval;
			offset += left;
			left = 0;
		}
		prev_hash = ent->hash;
	}
	if (left)
		retval = ext2fs_set_rec_len(fs, rec_len + left, dirent);

	return retval;
}