2 * set_fields.c --- set a superblock value
4 * Copyright (C) 2000, 2001, 2002, 2003, 2004 by Theodore Ts'o.
7 * This file may be redistributed under the terms of the GNU Public
12 #define _XOPEN_SOURCE 600 /* for inclusion of strptime() and strtoull */
15 #define STRTOULL strtoull
17 #define STRTOULL strtoul
27 #include <sys/types.h>
39 #include "uuid/uuid.h"
42 static struct ext2_super_block set_sb
;
43 static struct ext2_inode_large set_inode
;
44 static struct ext2_group_desc set_gd
;
45 static struct ext4_group_desc set_gd4
;
47 static ext2_ino_t set_ino
;
50 #define FLAG_ARRAY 0x0001
52 struct field_set_info
{
57 errcode_t (*func
)(struct field_set_info
*info
, char *field
, char *arg
);
62 static errcode_t
parse_uint(struct field_set_info
*info
, char *field
, char *arg
);
63 static errcode_t
parse_int(struct field_set_info
*info
, char *field
, char *arg
);
64 static errcode_t
parse_string(struct field_set_info
*info
, char *field
, char *arg
);
65 static errcode_t
parse_uuid(struct field_set_info
*info
, char *field
, char *arg
);
66 static errcode_t
parse_hashalg(struct field_set_info
*info
, char *field
, char *arg
);
67 static errcode_t
parse_time(struct field_set_info
*info
, char *field
, char *arg
);
68 static errcode_t
parse_bmap(struct field_set_info
*info
, char *field
, char *arg
);
69 static errcode_t
parse_gd_csum(struct field_set_info
*info
, char *field
, char *arg
);
71 static struct field_set_info super_fields
[] = {
72 { "inodes_count", &set_sb
.s_inodes_count
, NULL
, 4, parse_uint
},
73 { "blocks_count", &set_sb
.s_blocks_count
, &set_sb
.s_blocks_count_hi
,
75 { "r_blocks_count", &set_sb
.s_r_blocks_count
,
76 &set_sb
.s_r_blocks_count_hi
, 4, parse_uint
},
77 { "free_blocks_count", &set_sb
.s_free_blocks_count
,
78 &set_sb
.s_free_blocks_hi
, 4, parse_uint
},
79 { "free_inodes_count", &set_sb
.s_free_inodes_count
, NULL
, 4, parse_uint
},
80 { "first_data_block", &set_sb
.s_first_data_block
, NULL
, 4, parse_uint
},
81 { "log_block_size", &set_sb
.s_log_block_size
, NULL
, 4, parse_uint
},
82 { "log_cluster_size", &set_sb
.s_log_cluster_size
, NULL
, 4, parse_int
},
83 { "blocks_per_group", &set_sb
.s_blocks_per_group
, NULL
, 4, parse_uint
},
84 { "clusters_per_group", &set_sb
.s_clusters_per_group
, NULL
, 4, parse_uint
},
85 { "inodes_per_group", &set_sb
.s_inodes_per_group
, NULL
, 4, parse_uint
},
86 { "mtime", &set_sb
.s_mtime
, NULL
, 4, parse_time
},
87 { "wtime", &set_sb
.s_wtime
, NULL
, 4, parse_time
},
88 { "mnt_count", &set_sb
.s_mnt_count
, NULL
, 2, parse_uint
},
89 { "max_mnt_count", &set_sb
.s_max_mnt_count
, NULL
, 2, parse_int
},
91 { "state", &set_sb
.s_state
, NULL
, 2, parse_uint
},
92 { "errors", &set_sb
.s_errors
, NULL
, 2, parse_uint
},
93 { "minor_rev_level", &set_sb
.s_minor_rev_level
, NULL
, 2, parse_uint
},
94 { "lastcheck", &set_sb
.s_lastcheck
, NULL
, 4, parse_time
},
95 { "checkinterval", &set_sb
.s_checkinterval
, NULL
, 4, parse_uint
},
96 { "creator_os", &set_sb
.s_creator_os
, NULL
, 4, parse_uint
},
97 { "rev_level", &set_sb
.s_rev_level
, NULL
, 4, parse_uint
},
98 { "def_resuid", &set_sb
.s_def_resuid
, NULL
, 2, parse_uint
},
99 { "def_resgid", &set_sb
.s_def_resgid
, NULL
, 2, parse_uint
},
100 { "first_ino", &set_sb
.s_first_ino
, NULL
, 4, parse_uint
},
101 { "inode_size", &set_sb
.s_inode_size
, NULL
, 2, parse_uint
},
102 { "block_group_nr", &set_sb
.s_block_group_nr
, NULL
, 2, parse_uint
},
103 { "feature_compat", &set_sb
.s_feature_compat
, NULL
, 4, parse_uint
},
104 { "feature_incompat", &set_sb
.s_feature_incompat
, NULL
, 4, parse_uint
},
105 { "feature_ro_compat", &set_sb
.s_feature_ro_compat
, NULL
, 4, parse_uint
},
106 { "uuid", &set_sb
.s_uuid
, NULL
, 16, parse_uuid
},
107 { "volume_name", &set_sb
.s_volume_name
, NULL
, 16, parse_string
},
108 { "last_mounted", &set_sb
.s_last_mounted
, NULL
, 64, parse_string
},
109 { "lastcheck", &set_sb
.s_lastcheck
, NULL
, 4, parse_uint
},
110 { "algorithm_usage_bitmap", &set_sb
.s_algorithm_usage_bitmap
, NULL
,
112 { "prealloc_blocks", &set_sb
.s_prealloc_blocks
, NULL
, 1, parse_uint
},
113 { "prealloc_dir_blocks", &set_sb
.s_prealloc_dir_blocks
, NULL
, 1,
115 { "reserved_gdt_blocks", &set_sb
.s_reserved_gdt_blocks
, NULL
, 2,
117 { "journal_uuid", &set_sb
.s_journal_uuid
, NULL
, 16, parse_uuid
},
118 { "journal_inum", &set_sb
.s_journal_inum
, NULL
, 4, parse_uint
},
119 { "journal_dev", &set_sb
.s_journal_dev
, NULL
, 4, parse_uint
},
120 { "last_orphan", &set_sb
.s_last_orphan
, NULL
, 4, parse_uint
},
121 { "hash_seed", &set_sb
.s_hash_seed
, NULL
, 16, parse_uuid
},
122 { "def_hash_version", &set_sb
.s_def_hash_version
, NULL
, 1, parse_hashalg
},
123 { "jnl_backup_type", &set_sb
.s_jnl_backup_type
, NULL
, 1, parse_uint
},
124 { "desc_size", &set_sb
.s_desc_size
, NULL
, 2, parse_uint
},
125 { "default_mount_opts", &set_sb
.s_default_mount_opts
, NULL
, 4, parse_uint
},
126 { "first_meta_bg", &set_sb
.s_first_meta_bg
, NULL
, 4, parse_uint
},
127 { "mkfs_time", &set_sb
.s_mkfs_time
, NULL
, 4, parse_time
},
128 { "jnl_blocks", &set_sb
.s_jnl_blocks
[0], NULL
, 4, parse_uint
, FLAG_ARRAY
,
130 { "min_extra_isize", &set_sb
.s_min_extra_isize
, NULL
, 2, parse_uint
},
131 { "want_extra_isize", &set_sb
.s_want_extra_isize
, NULL
, 2, parse_uint
},
132 { "flags", &set_sb
.s_flags
, NULL
, 4, parse_uint
},
133 { "raid_stride", &set_sb
.s_raid_stride
, NULL
, 2, parse_uint
},
134 { "min_extra_isize", &set_sb
.s_min_extra_isize
, NULL
, 4, parse_uint
},
135 { "mmp_interval", &set_sb
.s_mmp_interval
, NULL
, 2, parse_uint
},
136 { "mmp_block", &set_sb
.s_mmp_block
, NULL
, 8, parse_uint
},
137 { "raid_stripe_width", &set_sb
.s_raid_stripe_width
, NULL
, 4, parse_uint
},
138 { "log_groups_per_flex", &set_sb
.s_log_groups_per_flex
, NULL
, 1, parse_uint
},
139 { "kbytes_written", &set_sb
.s_kbytes_written
, NULL
, 8, parse_uint
},
140 { "snapshot_inum", &set_sb
.s_snapshot_inum
, NULL
, 4, parse_uint
},
141 { "snapshot_id", &set_sb
.s_snapshot_id
, NULL
, 4, parse_uint
},
142 { "snapshot_r_blocks_count", &set_sb
.s_snapshot_r_blocks_count
,
143 NULL
, 8, parse_uint
},
144 { "snapshot_list", &set_sb
.s_snapshot_list
, NULL
, 4, parse_uint
},
145 { "mount_opts", &set_sb
.s_mount_opts
, NULL
, 64, parse_string
},
146 { "usr_quota_inum", &set_sb
.s_usr_quota_inum
, NULL
, 4, parse_uint
},
147 { "grp_quota_inum", &set_sb
.s_grp_quota_inum
, NULL
, 4, parse_uint
},
148 { "overhead_blocks", &set_sb
.s_overhead_blocks
, NULL
, 4, parse_uint
},
149 { "checksum", &set_sb
.s_checksum
, NULL
, 4, parse_uint
},
153 static struct field_set_info inode_fields
[] = {
154 { "inodes_count", &set_sb
.s_inodes_count
, NULL
, 4, parse_uint
},
155 { "mode", &set_inode
.i_mode
, NULL
, 2, parse_uint
},
156 { "uid", &set_inode
.i_uid
, &set_inode
.osd2
.linux2
.l_i_uid_high
,
158 { "size", &set_inode
.i_size
, &set_inode
.i_size_high
, 4, parse_uint
},
159 { "atime", &set_inode
.i_atime
, NULL
, 4, parse_time
},
160 { "ctime", &set_inode
.i_ctime
, NULL
, 4, parse_time
},
161 { "mtime", &set_inode
.i_mtime
, NULL
, 4, parse_time
},
162 { "dtime", &set_inode
.i_dtime
, NULL
, 4, parse_time
},
163 { "gid", &set_inode
.i_gid
, &set_inode
.osd2
.linux2
.l_i_gid_high
,
165 { "links_count", &set_inode
.i_links_count
, NULL
, 2, parse_uint
},
166 /* Special case: i_blocks is 4 bytes, i_blocks_high is 2 bytes */
167 { "blocks", &set_inode
.i_blocks
, &set_inode
.osd2
.linux2
.l_i_blocks_hi
,
169 { "flags", &set_inode
.i_flags
, NULL
, 4, parse_uint
},
170 { "version", &set_inode
.osd1
.linux1
.l_i_version
,
171 &set_inode
.i_version_hi
, 4, parse_uint
},
172 { "translator", &set_inode
.osd1
.hurd1
.h_i_translator
, NULL
, 4, parse_uint
},
173 { "block", &set_inode
.i_block
[0], NULL
, 4, parse_uint
, FLAG_ARRAY
,
175 { "block[IND]", &set_inode
.i_block
[EXT2_IND_BLOCK
], NULL
, 4, parse_uint
},
176 { "block[DIND]", &set_inode
.i_block
[EXT2_DIND_BLOCK
], NULL
, 4, parse_uint
},
177 { "block[TIND]", &set_inode
.i_block
[EXT2_TIND_BLOCK
], NULL
, 4, parse_uint
},
178 { "generation", &set_inode
.i_generation
, NULL
, 4, parse_uint
},
179 /* Special case: i_file_acl_high is 2 bytes */
180 { "file_acl", &set_inode
.i_file_acl
,
181 &set_inode
.osd2
.linux2
.l_i_file_acl_high
, 6, parse_uint
},
182 { "dir_acl", &set_inode
.i_dir_acl
, NULL
, 4, parse_uint
},
183 { "faddr", &set_inode
.i_faddr
, NULL
, 4, parse_uint
},
184 { "frag", &set_inode
.osd2
.hurd2
.h_i_frag
, NULL
, 1, parse_uint
},
185 { "fsize", &set_inode
.osd2
.hurd2
.h_i_fsize
, NULL
, 1, parse_uint
},
186 { "checksum", &set_inode
.osd2
.linux2
.l_i_checksum_lo
,
187 &set_inode
.i_checksum_hi
, 2, parse_uint
},
188 { "author", &set_inode
.osd2
.hurd2
.h_i_author
, NULL
,
190 { "extra_isize", &set_inode
.i_extra_isize
, NULL
,
192 { "ctime_extra", &set_inode
.i_ctime_extra
, NULL
,
194 { "mtime_extra", &set_inode
.i_mtime_extra
, NULL
,
196 { "atime_extra", &set_inode
.i_atime_extra
, NULL
,
198 { "crtime", &set_inode
.i_crtime
, NULL
, 4, parse_uint
},
199 { "crtime_extra", &set_inode
.i_crtime_extra
, NULL
,
201 { "bmap", NULL
, NULL
, 4, parse_bmap
, FLAG_ARRAY
},
205 static struct field_set_info ext2_bg_fields
[] = {
206 { "block_bitmap", &set_gd
.bg_block_bitmap
, NULL
, 4, parse_uint
},
207 { "inode_bitmap", &set_gd
.bg_inode_bitmap
, NULL
, 4, parse_uint
},
208 { "inode_table", &set_gd
.bg_inode_table
, NULL
, 4, parse_uint
},
209 { "free_blocks_count", &set_gd
.bg_free_blocks_count
, NULL
, 2, parse_uint
},
210 { "free_inodes_count", &set_gd
.bg_free_inodes_count
, NULL
, 2, parse_uint
},
211 { "used_dirs_count", &set_gd
.bg_used_dirs_count
, NULL
, 2, parse_uint
},
212 { "flags", &set_gd
.bg_flags
, NULL
, 2, parse_uint
},
213 { "itable_unused", &set_gd
.bg_itable_unused
, NULL
, 2, parse_uint
},
214 { "checksum", &set_gd
.bg_checksum
, NULL
, 2, parse_gd_csum
},
218 static struct field_set_info ext4_bg_fields
[] = {
219 { "block_bitmap", &set_gd4
.bg_block_bitmap
,
220 &set_gd4
.bg_block_bitmap_hi
, 4, parse_uint
},
221 { "inode_bitmap", &set_gd4
.bg_inode_bitmap
,
222 &set_gd4
.bg_inode_bitmap_hi
, 4, parse_uint
},
223 { "inode_table", &set_gd4
.bg_inode_table
,
224 &set_gd4
.bg_inode_table_hi
, 4, parse_uint
},
225 { "free_blocks_count", &set_gd4
.bg_free_blocks_count
,
226 &set_gd4
.bg_free_blocks_count_hi
, 2, parse_uint
},
227 { "free_inodes_count", &set_gd4
.bg_free_inodes_count
,
228 &set_gd4
.bg_free_inodes_count_hi
, 2, parse_uint
},
229 { "used_dirs_count", &set_gd4
.bg_used_dirs_count
,
230 &set_gd4
.bg_used_dirs_count_hi
, 2, parse_uint
},
231 { "flags", &set_gd4
.bg_flags
, NULL
, 2, parse_uint
},
232 { "exclude_bitmap", &set_gd4
.bg_exclude_bitmap_lo
,
233 &set_gd4
.bg_exclude_bitmap_hi
, 4, parse_uint
},
234 { "block_bitmap_csum", &set_gd4
.bg_block_bitmap_csum_lo
,
235 &set_gd4
.bg_block_bitmap_csum_hi
, 2, parse_uint
},
236 { "inode_bitmap_csum", &set_gd4
.bg_inode_bitmap_csum_lo
,
237 &set_gd4
.bg_inode_bitmap_csum_hi
, 2, parse_uint
},
238 { "itable_unused", &set_gd4
.bg_itable_unused
,
239 &set_gd4
.bg_itable_unused_hi
, 2, parse_uint
},
240 { "checksum", &set_gd4
.bg_checksum
, NULL
, 2, parse_gd_csum
},
244 static int check_suffix(const char *field
)
246 int len
= strlen(field
);
251 if (!strcmp(field
, "_lo"))
253 if (!strcmp(field
, "_hi"))
258 static struct field_set_info
*find_field(struct field_set_info
*fields
,
261 struct field_set_info
*ss
;
263 char *arg
, *delim
, *idx
, *tmp
;
264 int suffix
, prefix_len
;
266 if (fields
== super_fields
)
268 else if (fields
== inode_fields
)
272 prefix_len
= strlen(prefix
);
273 if (strncmp(field
, prefix
, prefix_len
) == 0)
276 arg
= malloc(strlen(field
)+1);
281 idx
= strchr(arg
, '[');
284 delim
= idx
+ strlen(idx
) - 1;
285 if (!*idx
|| *delim
!= ']')
291 * Can we parse the number?
294 array_idx
= strtol(idx
, &tmp
, 0);
300 * If there is a valid _hi or a _lo suffix, strip it off
302 suffix
= check_suffix(arg
);
304 arg
[strlen(arg
)-3] = 0;
306 for (ss
= fields
; ss
->name
; ss
++) {
307 if (suffix
&& ss
->ptr2
== 0)
309 if (ss
->flags
& FLAG_ARRAY
) {
310 if (!idx
|| (strcmp(ss
->name
, arg
) != 0))
312 if (ss
->max_idx
> 0 && array_idx
>= ss
->max_idx
)
315 if (strcmp(ss
->name
, arg
) != 0)
326 * Note: info->size == 6 is special; this means a base size 4 bytes,
327 * and secondiory (high) size of 2 bytes. This is needed for the
328 * special case of i_blocks_high and i_file_acl_high.
330 static errcode_t
parse_uint(struct field_set_info
*info
, char *field
,
333 unsigned long long n
, num
, mask
, limit
;
334 int suffix
= check_suffix(field
);
336 void *field1
= info
->ptr
, *field2
= info
->ptr2
;
337 int size
= (info
->size
== 6) ? 4 : info
->size
;
352 u
.ptr8
= (__u8
*) field1
;
353 if (info
->flags
& FLAG_ARRAY
)
354 u
.ptr8
+= array_idx
* info
->size
;
357 num
= STRTOULL(arg
, &tmp
, 0);
359 fprintf(stderr
, "Couldn't parse '%s' for field %s.\n",
363 mask
= ~0ULL >> ((8 - size
) * 8);
364 limit
= ~0ULL >> ((8 - info
->size
) * 8);
365 if (field2
&& info
->size
!= 6)
366 limit
= ~0ULL >> ((8 - info
->size
*2) * 8);
369 fprintf(stderr
, "Value '%s' exceeds field %s maximum %llu.\n",
370 arg
, info
->name
, limit
);
391 u
.ptr8
= (__u8
*) field2
;
411 static errcode_t
parse_int(struct field_set_info
*info
, char *field
, char *arg
)
419 num
= strtol(arg
, &tmp
, 0);
421 fprintf(stderr
, "Couldn't parse '%s' for field %s.\n",
425 switch (info
->size
) {
427 ptr32
= (__s32
*) info
->ptr
;
431 ptr16
= (__s16
*) info
->ptr
;
435 ptr8
= (__s8
*) info
->ptr
;
442 static errcode_t
parse_string(struct field_set_info
*info
, char *field
,
445 char *cp
= (char *) info
->ptr
;
447 if (strlen(arg
) >= info
->size
) {
448 fprintf(stderr
, "Error maximum size for %s is %d.\n",
449 info
->name
, info
->size
);
456 static errcode_t
parse_time(struct field_set_info
*info
, char *field
, char *arg
)
461 ptr32
= (__u32
*) info
->ptr
;
463 t
= string_to_time(arg
);
465 if (t
== ((time_t) -1)) {
466 fprintf(stderr
, "Couldn't parse '%s' for field %s.\n",
474 static errcode_t
parse_uuid(struct field_set_info
*info
, char *field
, char *arg
)
476 unsigned char * p
= (unsigned char *) info
->ptr
;
478 if ((strcasecmp(arg
, "null") == 0) ||
479 (strcasecmp(arg
, "clear") == 0)) {
481 } else if (strcasecmp(arg
, "time") == 0) {
482 uuid_generate_time(p
);
483 } else if (strcasecmp(arg
, "random") == 0) {
485 } else if (uuid_parse(arg
, p
)) {
486 fprintf(stderr
, "Invalid UUID format: %s\n", arg
);
492 static errcode_t
parse_hashalg(struct field_set_info
*info
, char *field
,
496 unsigned char *p
= (unsigned char *) info
->ptr
;
498 hashv
= e2p_string2hash(arg
);
500 fprintf(stderr
, "Invalid hash algorithm: %s\n", arg
);
507 static errcode_t
parse_bmap(struct field_set_info
*info
, char *field
,
515 num
= strtoul(arg
, &tmp
, 0);
517 fprintf(stderr
, "Couldn't parse '%s' for field %s.\n",
523 retval
= ext2fs_bmap(current_fs
, set_ino
,
524 (struct ext2_inode
*) &set_inode
,
525 0, BMAP_SET
, array_idx
, &blk
);
527 com_err("set_inode", retval
, "while setting block map");
532 static errcode_t
parse_gd_csum(struct field_set_info
*info
, char *field
,
536 if (strcmp(arg
, "calc") == 0) {
537 ext2fs_group_desc_csum_set(current_fs
, set_bg
);
538 memcpy(&set_gd
, ext2fs_group_desc(current_fs
,
539 current_fs
->group_desc
,
542 printf("Checksum set to 0x%04x\n",
543 ext2fs_bg_checksum(current_fs
, set_bg
));
547 return parse_uint(info
, field
, arg
);
550 static void print_possible_fields(struct field_set_info
*fields
)
552 struct field_set_info
*ss
;
553 const char *type
, *cmd
;
555 char name
[40], idx
[40];
557 if (fields
== super_fields
) {
559 cmd
= "set_super_value";
560 } else if (fields
== inode_fields
) {
564 type
= "Block group descriptor";
565 cmd
= "set_block_group";
569 fprintf(f
, "%s fields supported by the %s command:\n", type
, cmd
);
571 for (ss
= fields
; ss
->name
; ss
++) {
573 if (ss
->func
== parse_string
)
575 else if (ss
->func
== parse_int
)
577 else if (ss
->func
== parse_uint
)
578 type
= "unsigned integer";
579 else if (ss
->func
== parse_uuid
)
581 else if (ss
->func
== parse_hashalg
)
582 type
= "hash algorithm";
583 else if (ss
->func
== parse_time
)
585 else if (ss
->func
== parse_bmap
)
586 type
= "set physical->logical block map";
587 else if (ss
->func
== parse_gd_csum
)
588 type
= "unsigned integer OR \"calc\"";
589 strcpy(name
, ss
->name
);
590 if (ss
->flags
& FLAG_ARRAY
) {
592 sprintf(idx
, "[%d]", ss
->max_idx
);
598 strcat(name
, "[_hi|_lo]");
599 fprintf(f
, "\t%-25s\t%s\n", name
, type
);
605 void do_set_super(int argc
, char *argv
[])
607 const char *usage
= "<field> <value>\n"
608 "\t\"set_super_value -l\" will list the names of "
609 "superblock fields\n\twhich can be set.";
610 static struct field_set_info
*ss
;
612 if ((argc
== 2) && !strcmp(argv
[1], "-l")) {
613 print_possible_fields(super_fields
);
617 if (common_args_process(argc
, argv
, 3, 3, "set_super_value",
621 if ((ss
= find_field(super_fields
, argv
[1])) == 0) {
622 com_err(argv
[0], 0, "invalid field specifier: %s", argv
[1]);
625 set_sb
= *current_fs
->super
;
626 if (ss
->func(ss
, argv
[1], argv
[2]) == 0) {
627 *current_fs
->super
= set_sb
;
628 ext2fs_mark_super_dirty(current_fs
);
632 void do_set_inode(int argc
, char *argv
[])
634 const char *usage
= "<inode> <field> <value>\n"
635 "\t\"set_inode_field -l\" will list the names of "
636 "the fields in an ext2 inode\n\twhich can be set.";
637 static struct field_set_info
*ss
;
639 if ((argc
== 2) && !strcmp(argv
[1], "-l")) {
640 print_possible_fields(inode_fields
);
644 if (common_args_process(argc
, argv
, 4, 4, "set_inode",
648 if ((ss
= find_field(inode_fields
, argv
[2])) == 0) {
649 com_err(argv
[0], 0, "invalid field specifier: %s", argv
[2]);
653 set_ino
= string_to_inode(argv
[1]);
657 if (debugfs_read_inode_full(set_ino
,
658 (struct ext2_inode
*) &set_inode
, argv
[1],
662 if (ss
->func(ss
, argv
[2], argv
[3]) == 0) {
663 if (debugfs_write_inode_full(set_ino
,
664 (struct ext2_inode
*) &set_inode
,
665 argv
[1], sizeof(set_inode
)))
670 void do_set_block_group_descriptor(int argc
, char *argv
[])
672 const char *usage
= "<bg number> <field> <value>\n"
673 "\t\"set_block_group_descriptor -l\" will list the names of "
674 "the fields in a block group descriptor\n\twhich can be set.";
675 struct field_set_info
*table
;
676 struct field_set_info
*ss
;
682 *Determine whether we are editing an ext2 or ext4 block
685 if (current_fs
&& current_fs
->super
->s_feature_incompat
&
686 EXT4_FEATURE_INCOMPAT_64BIT
) {
687 table
= ext4_bg_fields
;
689 size
= sizeof(set_gd4
);
691 table
= ext2_bg_fields
;
693 size
= sizeof(set_gd
);
696 if ((argc
== 2) && !strcmp(argv
[1], "-l")) {
697 print_possible_fields(table
);
701 if (common_args_process(argc
, argv
, 4, 4, "set_block_group_descriptor",
705 set_bg
= strtoul(argv
[1], &end
, 0);
707 com_err(argv
[0], 0, "invalid block group number: %s", argv
[1]);
711 if (set_bg
>= current_fs
->group_desc_count
) {
712 com_err(argv
[0], 0, "block group number too big: %d", set_bg
);
716 if ((ss
= find_field(table
, argv
[2])) == 0) {
717 com_err(argv
[0], 0, "invalid field specifier: %s", argv
[2]);
721 target
= ext2fs_group_desc(current_fs
, current_fs
->group_desc
, set_bg
);
722 memcpy(edit
, target
, size
);
723 if (ss
->func(ss
, argv
[2], argv
[3]) == 0) {
724 memcpy(target
, edit
, size
);
725 ext2fs_mark_super_dirty(current_fs
);