set_fields.c revision 7c1384c3242a7ff4e60d40e674077c0c5b124a4d
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/* 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * set_fields.c --- set a superblock value 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Copyright (C) 2000, 2001, 2002, 2003, 2004 by Theodore Ts'o. 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * %Begin-Header% 7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * This file may be redistributed under the terms of the GNU Public 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * License. 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * %End-Header% 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) */ 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define _XOPEN_SOURCE 600 /* for inclusion of strptime() and strtoull */ 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#ifdef HAVE_STRTOULL 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define STRTOULL strtoull 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define STRTOULL strtoul 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "config.h" 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <stdio.h> 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <unistd.h> 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <stdlib.h> 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <ctype.h> 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <string.h> 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <strings.h> 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <time.h> 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <sys/types.h> 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <sys/stat.h> 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#ifdef HAVE_ERRNO_H 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <errno.h> 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if HAVE_STRINGS_H 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <strings.h> 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <fcntl.h> 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <utime.h> 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "debugfs.h" 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "uuid/uuid.h" 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "e2p/e2p.h" 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static struct ext2_super_block set_sb; 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static struct ext2_inode_large set_inode; 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static struct ext2_group_desc set_gd; 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static struct ext4_group_desc set_gd4; 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static struct mmp_struct set_mmp; 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static dgrp_t set_bg; 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static ext2_ino_t set_ino; 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int array_idx; 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define FLAG_ARRAY 0x0001 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct field_set_info { 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const char *name; 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void *ptr; 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void *ptr2; 58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch unsigned int size; 59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch errcode_t (*func)(struct field_set_info *info, char *field, char *arg); 60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int flags; 61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int max_idx; 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t parse_uint(struct field_set_info *info, char *field, char *arg); 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t parse_int(struct field_set_info *info, char *field, char *arg); 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t parse_string(struct field_set_info *info, char *field, char *arg); 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t parse_uuid(struct field_set_info *info, char *field, char *arg); 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t parse_hashalg(struct field_set_info *info, char *field, char *arg); 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t parse_time(struct field_set_info *info, char *field, char *arg); 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t parse_bmap(struct field_set_info *info, char *field, char *arg); 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t parse_gd_csum(struct field_set_info *info, char *field, char *arg); 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t parse_mmp_clear(struct field_set_info *info, char *field, 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) char *arg); 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static struct field_set_info super_fields[] = { 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "inodes_count", &set_sb.s_inodes_count, NULL, 4, parse_uint }, 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "blocks_count", &set_sb.s_blocks_count, &set_sb.s_blocks_count_hi, 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4, parse_uint }, 79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "r_blocks_count", &set_sb.s_r_blocks_count, 80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &set_sb.s_r_blocks_count_hi, 4, parse_uint }, 81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "free_blocks_count", &set_sb.s_free_blocks_count, 82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &set_sb.s_free_blocks_hi, 4, parse_uint }, 83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "free_inodes_count", &set_sb.s_free_inodes_count, NULL, 4, parse_uint }, 84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "first_data_block", &set_sb.s_first_data_block, NULL, 4, parse_uint }, 85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "log_block_size", &set_sb.s_log_block_size, NULL, 4, parse_uint }, 86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "log_cluster_size", &set_sb.s_log_cluster_size, NULL, 4, parse_int }, 87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "blocks_per_group", &set_sb.s_blocks_per_group, NULL, 4, parse_uint }, 88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "clusters_per_group", &set_sb.s_clusters_per_group, NULL, 4, parse_uint }, 89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "inodes_per_group", &set_sb.s_inodes_per_group, NULL, 4, parse_uint }, 90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "mtime", &set_sb.s_mtime, NULL, 4, parse_time }, 91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "wtime", &set_sb.s_wtime, NULL, 4, parse_time }, 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "mnt_count", &set_sb.s_mnt_count, NULL, 2, parse_uint }, 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "max_mnt_count", &set_sb.s_max_mnt_count, NULL, 2, parse_int }, 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) /* s_magic */ 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "state", &set_sb.s_state, NULL, 2, parse_uint }, 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "errors", &set_sb.s_errors, NULL, 2, parse_uint }, 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "minor_rev_level", &set_sb.s_minor_rev_level, NULL, 2, parse_uint }, 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "lastcheck", &set_sb.s_lastcheck, NULL, 4, parse_time }, 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "checkinterval", &set_sb.s_checkinterval, NULL, 4, parse_uint }, 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "creator_os", &set_sb.s_creator_os, NULL, 4, parse_uint }, 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "rev_level", &set_sb.s_rev_level, NULL, 4, parse_uint }, 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "def_resuid", &set_sb.s_def_resuid, NULL, 2, parse_uint }, 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "def_resgid", &set_sb.s_def_resgid, NULL, 2, parse_uint }, 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "first_ino", &set_sb.s_first_ino, NULL, 4, parse_uint }, 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "inode_size", &set_sb.s_inode_size, NULL, 2, parse_uint }, 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "block_group_nr", &set_sb.s_block_group_nr, NULL, 2, parse_uint }, 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "feature_compat", &set_sb.s_feature_compat, NULL, 4, parse_uint }, 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "feature_incompat", &set_sb.s_feature_incompat, NULL, 4, parse_uint }, 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "feature_ro_compat", &set_sb.s_feature_ro_compat, NULL, 4, parse_uint }, 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "uuid", &set_sb.s_uuid, NULL, 16, parse_uuid }, 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "volume_name", &set_sb.s_volume_name, NULL, 16, parse_string }, 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "last_mounted", &set_sb.s_last_mounted, NULL, 64, parse_string }, 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "lastcheck", &set_sb.s_lastcheck, NULL, 4, parse_uint }, 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "algorithm_usage_bitmap", &set_sb.s_algorithm_usage_bitmap, NULL, 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4, parse_uint }, 11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "prealloc_blocks", &set_sb.s_prealloc_blocks, NULL, 1, parse_uint }, 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "prealloc_dir_blocks", &set_sb.s_prealloc_dir_blocks, NULL, 1, 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) parse_uint }, 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "reserved_gdt_blocks", &set_sb.s_reserved_gdt_blocks, NULL, 2, 120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch parse_uint }, 121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "journal_uuid", &set_sb.s_journal_uuid, NULL, 16, parse_uuid }, 122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "journal_inum", &set_sb.s_journal_inum, NULL, 4, parse_uint }, 123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "journal_dev", &set_sb.s_journal_dev, NULL, 4, parse_uint }, 124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "last_orphan", &set_sb.s_last_orphan, NULL, 4, parse_uint }, 125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "hash_seed", &set_sb.s_hash_seed, NULL, 16, parse_uuid }, 126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "def_hash_version", &set_sb.s_def_hash_version, NULL, 1, parse_hashalg }, 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "jnl_backup_type", &set_sb.s_jnl_backup_type, NULL, 1, parse_uint }, 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "desc_size", &set_sb.s_desc_size, NULL, 2, parse_uint }, 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "default_mount_opts", &set_sb.s_default_mount_opts, NULL, 4, parse_uint }, 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "first_meta_bg", &set_sb.s_first_meta_bg, NULL, 4, parse_uint }, 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "mkfs_time", &set_sb.s_mkfs_time, NULL, 4, parse_time }, 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "jnl_blocks", &set_sb.s_jnl_blocks[0], NULL, 4, parse_uint, FLAG_ARRAY, 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 17 }, 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "min_extra_isize", &set_sb.s_min_extra_isize, NULL, 2, parse_uint }, 13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "want_extra_isize", &set_sb.s_want_extra_isize, NULL, 2, parse_uint }, 13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "flags", &set_sb.s_flags, NULL, 4, parse_uint }, 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "raid_stride", &set_sb.s_raid_stride, NULL, 2, parse_uint }, 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "min_extra_isize", &set_sb.s_min_extra_isize, NULL, 4, parse_uint }, 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "mmp_interval", &set_sb.s_mmp_update_interval, NULL, 2, parse_uint }, 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "mmp_block", &set_sb.s_mmp_block, NULL, 8, parse_uint }, 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "raid_stripe_width", &set_sb.s_raid_stripe_width, NULL, 4, parse_uint }, 142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "log_groups_per_flex", &set_sb.s_log_groups_per_flex, NULL, 1, parse_uint }, 143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "kbytes_written", &set_sb.s_kbytes_written, NULL, 8, parse_uint }, 144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "snapshot_inum", &set_sb.s_snapshot_inum, NULL, 4, parse_uint }, 145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "snapshot_id", &set_sb.s_snapshot_id, NULL, 4, parse_uint }, 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "snapshot_r_blocks_count", &set_sb.s_snapshot_r_blocks_count, 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NULL, 8, parse_uint }, 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "snapshot_list", &set_sb.s_snapshot_list, NULL, 4, parse_uint }, 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "mount_opts", &set_sb.s_mount_opts, NULL, 64, parse_string }, 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "usr_quota_inum", &set_sb.s_usr_quota_inum, NULL, 4, parse_uint }, 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "grp_quota_inum", &set_sb.s_grp_quota_inum, NULL, 4, parse_uint }, 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "overhead_blocks", &set_sb.s_overhead_blocks, NULL, 4, parse_uint }, 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "checksum", &set_sb.s_checksum, NULL, 4, parse_uint }, 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { 0, 0, 0, 0 } 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 157effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic struct field_set_info inode_fields[] = { 158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "inodes_count", &set_sb.s_inodes_count, NULL, 4, parse_uint }, 159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "mode", &set_inode.i_mode, NULL, 2, parse_uint }, 160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "uid", &set_inode.i_uid, &set_inode.osd2.linux2.l_i_uid_high, 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2, parse_uint }, 1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "size", &set_inode.i_size, &set_inode.i_size_high, 4, parse_uint }, 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "atime", &set_inode.i_atime, NULL, 4, parse_time }, 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "ctime", &set_inode.i_ctime, NULL, 4, parse_time }, 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "mtime", &set_inode.i_mtime, NULL, 4, parse_time }, 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "dtime", &set_inode.i_dtime, NULL, 4, parse_time }, 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "gid", &set_inode.i_gid, &set_inode.osd2.linux2.l_i_gid_high, 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2, parse_uint }, 169effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "links_count", &set_inode.i_links_count, NULL, 2, parse_uint }, 170effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch /* Special case: i_blocks is 4 bytes, i_blocks_high is 2 bytes */ 171effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "blocks", &set_inode.i_blocks, &set_inode.osd2.linux2.l_i_blocks_hi, 172effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 6, parse_uint }, 173effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "flags", &set_inode.i_flags, NULL, 4, parse_uint }, 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "version", &set_inode.osd1.linux1.l_i_version, 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &set_inode.i_version_hi, 4, parse_uint }, 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "translator", &set_inode.osd1.hurd1.h_i_translator, NULL, 4, parse_uint }, 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "block", &set_inode.i_block[0], NULL, 4, parse_uint, FLAG_ARRAY, 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXT2_NDIR_BLOCKS }, 179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "block[IND]", &set_inode.i_block[EXT2_IND_BLOCK], NULL, 4, parse_uint }, 180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "block[DIND]", &set_inode.i_block[EXT2_DIND_BLOCK], NULL, 4, parse_uint }, 18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "block[TIND]", &set_inode.i_block[EXT2_TIND_BLOCK], NULL, 4, parse_uint }, 18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "generation", &set_inode.i_generation, NULL, 4, parse_uint }, 18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) /* Special case: i_file_acl_high is 2 bytes */ 18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "file_acl", &set_inode.i_file_acl, 18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &set_inode.osd2.linux2.l_i_file_acl_high, 6, parse_uint }, 18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "dir_acl", &set_inode.i_dir_acl, NULL, 4, parse_uint }, 18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "faddr", &set_inode.i_faddr, NULL, 4, parse_uint }, 18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "frag", &set_inode.osd2.hurd2.h_i_frag, NULL, 1, parse_uint }, 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "fsize", &set_inode.osd2.hurd2.h_i_fsize, NULL, 1, parse_uint }, 19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "checksum", &set_inode.osd2.linux2.l_i_checksum_lo, 19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &set_inode.i_checksum_hi, 2, parse_uint }, 19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "author", &set_inode.osd2.hurd2.h_i_author, NULL, 19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4, parse_uint }, 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "extra_isize", &set_inode.i_extra_isize, NULL, 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2, parse_uint }, 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "ctime_extra", &set_inode.i_ctime_extra, NULL, 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4, parse_uint }, 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "mtime_extra", &set_inode.i_mtime_extra, NULL, 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4, parse_uint }, 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "atime_extra", &set_inode.i_atime_extra, NULL, 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4, parse_uint }, 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "crtime", &set_inode.i_crtime, NULL, 4, parse_uint }, 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "crtime_extra", &set_inode.i_crtime_extra, NULL, 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4, parse_uint }, 205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "bmap", NULL, NULL, 4, parse_bmap, FLAG_ARRAY }, 206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { 0, 0, 0, 0 } 207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}; 208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic struct field_set_info ext2_bg_fields[] = { 210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "block_bitmap", &set_gd.bg_block_bitmap, NULL, 4, parse_uint }, 21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "inode_bitmap", &set_gd.bg_inode_bitmap, NULL, 4, parse_uint }, 21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "inode_table", &set_gd.bg_inode_table, NULL, 4, parse_uint }, 21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "free_blocks_count", &set_gd.bg_free_blocks_count, NULL, 2, parse_uint }, 21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "free_inodes_count", &set_gd.bg_free_inodes_count, NULL, 2, parse_uint }, 21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "used_dirs_count", &set_gd.bg_used_dirs_count, NULL, 2, parse_uint }, 21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "flags", &set_gd.bg_flags, NULL, 2, parse_uint }, 21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "itable_unused", &set_gd.bg_itable_unused, NULL, 2, parse_uint }, 21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "checksum", &set_gd.bg_checksum, NULL, 2, parse_gd_csum }, 21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { 0, 0, 0, 0 } 22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static struct field_set_info ext4_bg_fields[] = { 22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "block_bitmap", &set_gd4.bg_block_bitmap, 22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &set_gd4.bg_block_bitmap_hi, 4, parse_uint }, 22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "inode_bitmap", &set_gd4.bg_inode_bitmap, 22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &set_gd4.bg_inode_bitmap_hi, 4, parse_uint }, 22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "inode_table", &set_gd4.bg_inode_table, 22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &set_gd4.bg_inode_table_hi, 4, parse_uint }, 22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "free_blocks_count", &set_gd4.bg_free_blocks_count, 23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &set_gd4.bg_free_blocks_count_hi, 2, parse_uint }, 23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "free_inodes_count", &set_gd4.bg_free_inodes_count, 23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &set_gd4.bg_free_inodes_count_hi, 2, parse_uint }, 23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "used_dirs_count", &set_gd4.bg_used_dirs_count, 23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &set_gd4.bg_used_dirs_count_hi, 2, parse_uint }, 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "flags", &set_gd4.bg_flags, NULL, 2, parse_uint }, 2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "exclude_bitmap", &set_gd4.bg_exclude_bitmap_lo, 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &set_gd4.bg_exclude_bitmap_hi, 4, parse_uint }, 23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "block_bitmap_csum", &set_gd4.bg_block_bitmap_csum_lo, 23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &set_gd4.bg_block_bitmap_csum_hi, 2, parse_uint }, 240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "inode_bitmap_csum", &set_gd4.bg_inode_bitmap_csum_lo, 241effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &set_gd4.bg_inode_bitmap_csum_hi, 2, parse_uint }, 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "itable_unused", &set_gd4.bg_itable_unused, 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &set_gd4.bg_itable_unused_hi, 2, parse_uint }, 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { "checksum", &set_gd4.bg_checksum, NULL, 2, parse_gd_csum }, 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { 0, 0, 0, 0 } 246effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}; 24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static struct field_set_info mmp_fields[] = { 249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) { "clear", &set_mmp.mmp_magic, NULL, sizeof(set_mmp), parse_mmp_clear }, 25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "magic", &set_mmp.mmp_magic, NULL, 4, parse_uint }, 25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { "seq", &set_mmp.mmp_seq, NULL, 4, parse_uint }, 252effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "time", &set_mmp.mmp_time, NULL, 8, parse_uint }, 253effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "nodename", &set_mmp.mmp_nodename, NULL, sizeof(set_mmp.mmp_nodename), 254effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch parse_string }, 255effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "bdevname", &set_mmp.mmp_bdevname, NULL, sizeof(set_mmp.mmp_bdevname), 256effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch parse_string }, 257effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { "check_interval", &set_mmp.mmp_check_interval, NULL, 2, parse_uint }, 258effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}; 259effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 260effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic int check_suffix(const char *field) 261effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch{ 262effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int len = strlen(field); 263effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 264effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (len <= 3) 265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return 0; 266effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch field += len-3; 267effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!strcmp(field, "_lo")) 268effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return 1; 269effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!strcmp(field, "_hi")) 270effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return 2; 271effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return 0; 272effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 273effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 274effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic struct field_set_info *find_field(struct field_set_info *fields, 275effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch char *field) 276effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch{ 277effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch struct field_set_info *ss; 278effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const char *prefix; 279effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch char *arg, *delim, *idx, *tmp; 280effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int suffix, prefix_len; 281effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 282effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (fields == super_fields) 283effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch prefix = "s_"; 284effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch else if (fields == inode_fields) 285effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch prefix = "i_"; 28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) else 28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) prefix = "bg_"; 28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) prefix_len = strlen(prefix); 28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (strncmp(field, prefix, prefix_len) == 0) 29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) field += prefix_len; 29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 292effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch arg = malloc(strlen(field)+1); 293effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!arg) 294effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return NULL; 295effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch strcpy(arg, field); 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 297effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch idx = strchr(arg, '['); 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (idx) { 299effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *idx++ = 0; 300effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch delim = idx + strlen(idx) - 1; 301effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!*idx || *delim != ']') 302effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch idx = 0; 303effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch else 304effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *delim = 0; 305effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 306effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch /* 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Can we parse the number? 308effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch */ 309effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (idx) { 310effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch array_idx = strtol(idx, &tmp, 0); 311effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (*tmp) 312effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch idx = 0; 313effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) /* 31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * If there is a valid _hi or a _lo suffix, strip it off 3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) suffix = check_suffix(arg); 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (suffix > 0) 32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) arg[strlen(arg)-3] = 0; 321effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (ss = fields ; ss->name ; ss++) { 323effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (suffix && ss->ptr2 == 0) 32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (ss->flags & FLAG_ARRAY) { 32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!idx || (strcmp(ss->name, arg) != 0)) 32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (ss->max_idx > 0 && array_idx >= ss->max_idx) 32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (strcmp(ss->name, arg) != 0) 33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 333effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 334effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch free(arg); 335effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return ss; 336effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 337effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch free(arg); 338effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return NULL; 339effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 340effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)/* 34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Note: info->size == 6 is special; this means a base size 4 bytes, 34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * and secondiory (high) size of 2 bytes. This is needed for the 34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * special case of i_blocks_high and i_file_acl_high. 34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) */ 34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t parse_uint(struct field_set_info *info, char *field, 3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) char *arg) 3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){ 3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unsigned long long n, num, mask, limit; 35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int suffix = check_suffix(field); 351effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch char *tmp; 3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void *field1 = info->ptr, *field2 = info->ptr2; 353effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int size = (info->size == 6) ? 4 : info->size; 35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) union { 35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) __u64 *ptr64; 35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) __u32 *ptr32; 35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) __u16 *ptr16; 35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) __u8 *ptr8; 35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } u; 36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (suffix == 1) 362effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch field2 = 0; 363effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (suffix == 2) { 364effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch field1 = field2; 365effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch field2 = 0; 366effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 368effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch u.ptr8 = (__u8 *) field1; 369effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (info->flags & FLAG_ARRAY) 3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) u.ptr8 += array_idx * info->size; 371effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 372effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch errno = 0; 373effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch num = STRTOULL(arg, &tmp, 0); 374effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (*tmp || errno) { 375effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch fprintf(stderr, "Couldn't parse '%s' for field %s.\n", 376effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch arg, info->name); 3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return EINVAL; 378effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 379effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch mask = ~0ULL >> ((8 - size) * 8); 380effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch limit = ~0ULL >> ((8 - info->size) * 8); 381effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (field2 && info->size != 6) 382effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch limit = ~0ULL >> ((8 - info->size*2) * 8); 383effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (num > limit) { 38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) fprintf(stderr, "Value '%s' exceeds field %s maximum %llu.\n", 38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) arg, info->name, limit); 387 return EINVAL; 388 } 389 n = num & mask; 390 switch (size) { 391 case 8: 392 /* Should never get here */ 393 fprintf(stderr, "64-bit field %s has a second 64-bit field\n" 394 "defined; BUG?!?\n", info->name); 395 *u.ptr64 = 0; 396 break; 397 case 4: 398 *u.ptr32 = n; 399 break; 400 case 2: 401 *u.ptr16 = n; 402 break; 403 case 1: 404 *u.ptr8 = n; 405 break; 406 } 407 if (!field2) 408 return 0; 409 n = num >> (size*8); 410 u.ptr8 = (__u8 *) field2; 411 if (info->size == 6) 412 size = 2; 413 switch (size) { 414 case 8: 415 *u.ptr64 = n; 416 break; 417 case 4: 418 *u.ptr32 = n; 419 break; 420 case 2: 421 *u.ptr16 = n; 422 break; 423 case 1: 424 *u.ptr8 = n; 425 break; 426 } 427 return 0; 428} 429 430static errcode_t parse_int(struct field_set_info *info, 431 char *field EXT2FS_ATTR((unused)), char *arg) 432{ 433 long num; 434 char *tmp; 435 __s32 *ptr32; 436 __s16 *ptr16; 437 __s8 *ptr8; 438 439 num = strtol(arg, &tmp, 0); 440 if (*tmp) { 441 fprintf(stderr, "Couldn't parse '%s' for field %s.\n", 442 arg, info->name); 443 return EINVAL; 444 } 445 switch (info->size) { 446 case 4: 447 ptr32 = (__s32 *) info->ptr; 448 *ptr32 = num; 449 break; 450 case 2: 451 ptr16 = (__s16 *) info->ptr; 452 *ptr16 = num; 453 break; 454 case 1: 455 ptr8 = (__s8 *) info->ptr; 456 *ptr8 = num; 457 break; 458 } 459 return 0; 460} 461 462static errcode_t parse_string(struct field_set_info *info, 463 char *field EXT2FS_ATTR((unused)), char *arg) 464{ 465 char *cp = (char *) info->ptr; 466 467 if (strlen(arg) >= info->size) { 468 fprintf(stderr, "Error maximum size for %s is %d.\n", 469 info->name, info->size); 470 return EINVAL; 471 } 472 strcpy(cp, arg); 473 return 0; 474} 475 476static errcode_t parse_time(struct field_set_info *info, 477 char *field EXT2FS_ATTR((unused)), char *arg) 478{ 479 time_t t; 480 __u32 *ptr32; 481 482 ptr32 = (__u32 *) info->ptr; 483 484 t = string_to_time(arg); 485 486 if (t == ((time_t) -1)) { 487 fprintf(stderr, "Couldn't parse '%s' for field %s.\n", 488 arg, info->name); 489 return EINVAL; 490 } 491 *ptr32 = t; 492 return 0; 493} 494 495static errcode_t parse_uuid(struct field_set_info *info, 496 char *field EXT2FS_ATTR((unused)), char *arg) 497{ 498 unsigned char * p = (unsigned char *) info->ptr; 499 500 if ((strcasecmp(arg, "null") == 0) || 501 (strcasecmp(arg, "clear") == 0)) { 502 uuid_clear(p); 503 } else if (strcasecmp(arg, "time") == 0) { 504 uuid_generate_time(p); 505 } else if (strcasecmp(arg, "random") == 0) { 506 uuid_generate(p); 507 } else if (uuid_parse(arg, p)) { 508 fprintf(stderr, "Invalid UUID format: %s\n", arg); 509 return EINVAL; 510 } 511 return 0; 512} 513 514static errcode_t parse_hashalg(struct field_set_info *info, 515 char *field EXT2FS_ATTR((unused)), char *arg) 516{ 517 int hashv; 518 unsigned char *p = (unsigned char *) info->ptr; 519 520 hashv = e2p_string2hash(arg); 521 if (hashv < 0) { 522 fprintf(stderr, "Invalid hash algorithm: %s\n", arg); 523 return EINVAL; 524 } 525 *p = hashv; 526 return 0; 527} 528 529static errcode_t parse_bmap(struct field_set_info *info, 530 char *field EXT2FS_ATTR((unused)), char *arg) 531{ 532 unsigned long num; 533 blk_t blk; 534 errcode_t retval; 535 char *tmp; 536 537 num = strtoul(arg, &tmp, 0); 538 if (*tmp) { 539 fprintf(stderr, "Couldn't parse '%s' for field %s.\n", 540 arg, info->name); 541 return EINVAL; 542 } 543 blk = num; 544 545 retval = ext2fs_bmap(current_fs, set_ino, 546 (struct ext2_inode *) &set_inode, 547 0, BMAP_SET, array_idx, &blk); 548 if (retval) { 549 com_err("set_inode", retval, "while setting block map"); 550 } 551 return retval; 552} 553 554static errcode_t parse_gd_csum(struct field_set_info *info, char *field, 555 char *arg) 556{ 557 558 if (strcmp(arg, "calc") == 0) { 559 ext2fs_group_desc_csum_set(current_fs, set_bg); 560 memcpy(&set_gd, ext2fs_group_desc(current_fs, 561 current_fs->group_desc, 562 set_bg), 563 sizeof(set_gd)); 564 printf("Checksum set to 0x%04x\n", 565 ext2fs_bg_checksum(current_fs, set_bg)); 566 return 0; 567 } 568 569 return parse_uint(info, field, arg); 570} 571 572static void print_possible_fields(struct field_set_info *fields) 573{ 574 struct field_set_info *ss; 575 const char *type, *cmd; 576 FILE *f; 577 char name[40], idx[40]; 578 579 if (fields == super_fields) { 580 type = "Superblock"; 581 cmd = "set_super_value"; 582 } else if (fields == inode_fields) { 583 type = "Inode"; 584 cmd = "set_inode"; 585 } else if (fields == mmp_fields) { 586 type = "MMP"; 587 cmd = "set_mmp_value"; 588 } else { 589 type = "Block group descriptor"; 590 cmd = "set_block_group"; 591 } 592 f = open_pager(); 593 594 fprintf(f, "%s fields supported by the %s command:\n", type, cmd); 595 596 for (ss = fields ; ss->name ; ss++) { 597 type = "unknown"; 598 if (ss->func == parse_string) 599 type = "string"; 600 else if (ss->func == parse_int) 601 type = "integer"; 602 else if (ss->func == parse_uint) 603 type = "unsigned integer"; 604 else if (ss->func == parse_uuid) 605 type = "UUID"; 606 else if (ss->func == parse_hashalg) 607 type = "hash algorithm"; 608 else if (ss->func == parse_time) 609 type = "date/time"; 610 else if (ss->func == parse_bmap) 611 type = "set physical->logical block map"; 612 else if (ss->func == parse_gd_csum) 613 type = "unsigned integer OR \"calc\""; 614 strcpy(name, ss->name); 615 if (ss->flags & FLAG_ARRAY) { 616 if (ss->max_idx > 0) 617 sprintf(idx, "[%d]", ss->max_idx); 618 else 619 strcpy(idx, "[]"); 620 strcat(name, idx); 621 } 622 if (ss->ptr2) 623 strcat(name, "[_hi|_lo]"); 624 fprintf(f, "\t%-25s\t%s\n", name, type); 625 } 626 close_pager(f); 627} 628 629 630void do_set_super(int argc, char *argv[]) 631{ 632 const char *usage = "<field> <value>\n" 633 "\t\"set_super_value -l\" will list the names of " 634 "superblock fields\n\twhich can be set."; 635 static struct field_set_info *ss; 636 637 if ((argc == 2) && !strcmp(argv[1], "-l")) { 638 print_possible_fields(super_fields); 639 return; 640 } 641 642 if (common_args_process(argc, argv, 3, 3, "set_super_value", 643 usage, CHECK_FS_RW)) 644 return; 645 646 if ((ss = find_field(super_fields, argv[1])) == 0) { 647 com_err(argv[0], 0, "invalid field specifier: %s", argv[1]); 648 return; 649 } 650 set_sb = *current_fs->super; 651 if (ss->func(ss, argv[1], argv[2]) == 0) { 652 *current_fs->super = set_sb; 653 ext2fs_mark_super_dirty(current_fs); 654 } 655} 656 657void do_set_inode(int argc, char *argv[]) 658{ 659 const char *usage = "<inode> <field> <value>\n" 660 "\t\"set_inode_field -l\" will list the names of " 661 "the fields in an ext2 inode\n\twhich can be set."; 662 static struct field_set_info *ss; 663 664 if ((argc == 2) && !strcmp(argv[1], "-l")) { 665 print_possible_fields(inode_fields); 666 return; 667 } 668 669 if (common_args_process(argc, argv, 4, 4, "set_inode", 670 usage, CHECK_FS_RW)) 671 return; 672 673 if ((ss = find_field(inode_fields, argv[2])) == 0) { 674 com_err(argv[0], 0, "invalid field specifier: %s", argv[2]); 675 return; 676 } 677 678 set_ino = string_to_inode(argv[1]); 679 if (!set_ino) 680 return; 681 682 if (debugfs_read_inode_full(set_ino, 683 (struct ext2_inode *) &set_inode, argv[1], 684 sizeof(set_inode))) 685 return; 686 687 if (ss->func(ss, argv[2], argv[3]) == 0) { 688 if (debugfs_write_inode_full(set_ino, 689 (struct ext2_inode *) &set_inode, 690 argv[1], sizeof(set_inode))) 691 return; 692 } 693} 694 695void do_set_block_group_descriptor(int argc, char *argv[]) 696{ 697 const char *usage = "<bg number> <field> <value>\n" 698 "\t\"set_block_group_descriptor -l\" will list the names of " 699 "the fields in a block group descriptor\n\twhich can be set."; 700 struct field_set_info *table; 701 struct field_set_info *ss; 702 char *end; 703 void *edit, *target; 704 int size; 705 706 /* 707 *Determine whether we are editing an ext2 or ext4 block 708 * group descriptor 709 */ 710 if (current_fs && current_fs->super->s_feature_incompat & 711 EXT4_FEATURE_INCOMPAT_64BIT) { 712 table = ext4_bg_fields; 713 edit = &set_gd4; 714 size = sizeof(set_gd4); 715 } else { 716 table = ext2_bg_fields; 717 edit = &set_gd; 718 size = sizeof(set_gd); 719 } 720 721 if ((argc == 2) && !strcmp(argv[1], "-l")) { 722 print_possible_fields(table); 723 return; 724 } 725 726 if (common_args_process(argc, argv, 4, 4, "set_block_group_descriptor", 727 usage, CHECK_FS_RW)) 728 return; 729 730 set_bg = strtoul(argv[1], &end, 0); 731 if (*end) { 732 com_err(argv[0], 0, "invalid block group number: %s", argv[1]); 733 return; 734 } 735 736 if (set_bg >= current_fs->group_desc_count) { 737 com_err(argv[0], 0, "block group number too big: %d", set_bg); 738 return; 739 } 740 741 if ((ss = find_field(table, argv[2])) == 0) { 742 com_err(argv[0], 0, "invalid field specifier: %s", argv[2]); 743 return; 744 } 745 746 target = ext2fs_group_desc(current_fs, current_fs->group_desc, set_bg); 747 memcpy(edit, target, size); 748 if (ss->func(ss, argv[2], argv[3]) == 0) { 749 memcpy(target, edit, size); 750 ext2fs_mark_super_dirty(current_fs); 751 } 752} 753 754static errcode_t parse_mmp_clear(struct field_set_info *info, 755 char *field EXT2FS_ATTR((unused)), 756 char *arg EXT2FS_ATTR((unused))) 757{ 758 errcode_t retval; 759 760 retval = ext2fs_mmp_clear(current_fs); 761 if (retval != 0) 762 com_err("set_mmp_value", retval, "while clearing MMP block\n"); 763 else 764 memcpy(info->ptr, current_fs->mmp_buf, info->size); 765 766 return 1; /* we don't need the MMP block written again */ 767} 768 769void do_set_mmp_value(int argc, char *argv[]) 770{ 771 const char *usage = "<field> <value>\n" 772 "\t\"set_mmp_value -l\" will list the names of " 773 "MMP fields\n\twhich can be set."; 774 static struct field_set_info *smmp; 775 struct mmp_struct *mmp_s; 776 errcode_t retval; 777 778 if (argc == 2 && strcmp(argv[1], "-l") == 0) { 779 print_possible_fields(mmp_fields); 780 return; 781 } 782 783 if (check_fs_open(argv[0])) 784 return; 785 786 if (current_fs->super->s_mmp_block == 0) { 787 com_err(argv[0], 0, "no MMP block allocated\n"); 788 return; 789 } 790 791 if (common_args_process(argc, argv, 2, 3, "set_mmp_value", 792 usage, CHECK_FS_RW)) 793 return; 794 795 mmp_s = current_fs->mmp_buf; 796 if (mmp_s == NULL) { 797 retval = ext2fs_get_mem(current_fs->blocksize, &mmp_s); 798 if (retval) { 799 com_err(argv[0], retval, "allocating MMP buffer\n"); 800 return; 801 } 802 retval = ext2fs_mmp_read(current_fs, 803 current_fs->super->s_mmp_block, mmp_s); 804 if (retval) { 805 com_err(argv[0], retval, "reading MMP block %llu.\n", 806 (long long)current_fs->super->s_mmp_block); 807 ext2fs_free_mem(mmp_s); 808 return; 809 } 810 current_fs->mmp_buf = mmp_s; 811 } 812 813 smmp = find_field(mmp_fields, argv[1]); 814 if (smmp == 0) { 815 com_err(argv[0], 0, "invalid field specifier: %s", argv[1]); 816 return; 817 } 818 819 set_mmp = *mmp_s; 820 if (smmp->func(smmp, argv[1], argv[2]) == 0) { 821 ext2fs_mmp_write(current_fs, current_fs->super->s_mmp_block, 822 &set_mmp); 823 *mmp_s = set_mmp; 824 } 825} 826 827