paul@181 | 1 | /* |
paul@181 | 2 | * ls.c - List the contents of an ext2fs superblock |
paul@181 | 3 | * |
paul@181 | 4 | * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr> |
paul@181 | 5 | * Laboratoire MASI, Institut Blaise Pascal |
paul@181 | 6 | * Universite Pierre et Marie Curie (Paris VI) |
paul@181 | 7 | * |
paul@181 | 8 | * Copyright (C) 1995, 1996, 1997 Theodore Ts'o <tytso@mit.edu> |
paul@181 | 9 | * |
paul@181 | 10 | * %Begin-Header% |
paul@181 | 11 | * This file may be redistributed under the terms of the GNU Library |
paul@181 | 12 | * General Public License, version 2. |
paul@181 | 13 | * %End-Header% |
paul@181 | 14 | */ |
paul@181 | 15 | |
paul@181 | 16 | #include "config.h" |
paul@181 | 17 | #include <stdio.h> |
paul@181 | 18 | #include <stdlib.h> |
paul@181 | 19 | #include <sys/types.h> |
paul@181 | 20 | #include <string.h> |
paul@181 | 21 | #include <grp.h> |
paul@181 | 22 | #include <pwd.h> |
paul@181 | 23 | #include <time.h> |
paul@181 | 24 | |
paul@181 | 25 | #include "e2p.h" |
paul@181 | 26 | #include "support/quotaio.h" |
paul@181 | 27 | |
paul@181 | 28 | static void print_user (unsigned short uid, FILE *f) |
paul@181 | 29 | { |
paul@181 | 30 | struct passwd *pw; |
paul@181 | 31 | |
paul@181 | 32 | fprintf(f, "%u ", uid); |
paul@181 | 33 | pw = getpwuid (uid); |
paul@181 | 34 | if (pw == NULL) |
paul@181 | 35 | fprintf(f, "(user unknown)\n"); |
paul@181 | 36 | else |
paul@181 | 37 | fprintf(f, "(user %s)\n", pw->pw_name); |
paul@181 | 38 | } |
paul@181 | 39 | |
paul@181 | 40 | static void print_group (unsigned short gid, FILE *f) |
paul@181 | 41 | { |
paul@181 | 42 | struct group *gr; |
paul@181 | 43 | |
paul@181 | 44 | fprintf(f, "%u ", gid); |
paul@181 | 45 | gr = getgrgid (gid); |
paul@181 | 46 | if (gr == NULL) |
paul@181 | 47 | fprintf(f, "(group unknown)\n"); |
paul@181 | 48 | else |
paul@181 | 49 | fprintf(f, "(group %s)\n", gr->gr_name); |
paul@181 | 50 | } |
paul@181 | 51 | |
paul@181 | 52 | #define MONTH_INT (86400 * 30) |
paul@181 | 53 | #define WEEK_INT (86400 * 7) |
paul@181 | 54 | #define DAY_INT (86400) |
paul@181 | 55 | #define HOUR_INT (60 * 60) |
paul@181 | 56 | #define MINUTE_INT (60) |
paul@181 | 57 | |
paul@181 | 58 | static const char *interval_string(unsigned int secs) |
paul@181 | 59 | { |
paul@181 | 60 | static char buf[256], tmp[80]; |
paul@181 | 61 | int hr, min, num; |
paul@181 | 62 | |
paul@181 | 63 | buf[0] = 0; |
paul@181 | 64 | |
paul@181 | 65 | if (secs == 0) |
paul@181 | 66 | return "<none>"; |
paul@181 | 67 | |
paul@181 | 68 | if (secs >= MONTH_INT) { |
paul@181 | 69 | num = secs / MONTH_INT; |
paul@181 | 70 | secs -= num*MONTH_INT; |
paul@181 | 71 | sprintf(buf, "%d month%s", num, (num>1) ? "s" : ""); |
paul@181 | 72 | } |
paul@181 | 73 | if (secs >= WEEK_INT) { |
paul@181 | 74 | num = secs / WEEK_INT; |
paul@181 | 75 | secs -= num*WEEK_INT; |
paul@181 | 76 | sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "", |
paul@181 | 77 | num, (num>1) ? "s" : ""); |
paul@181 | 78 | strcat(buf, tmp); |
paul@181 | 79 | } |
paul@181 | 80 | if (secs >= DAY_INT) { |
paul@181 | 81 | num = secs / DAY_INT; |
paul@181 | 82 | secs -= num*DAY_INT; |
paul@181 | 83 | sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "", |
paul@181 | 84 | num, (num>1) ? "s" : ""); |
paul@181 | 85 | strcat(buf, tmp); |
paul@181 | 86 | } |
paul@181 | 87 | if (secs > 0) { |
paul@181 | 88 | hr = secs / HOUR_INT; |
paul@181 | 89 | secs -= hr*HOUR_INT; |
paul@181 | 90 | min = secs / MINUTE_INT; |
paul@181 | 91 | secs -= min*MINUTE_INT; |
paul@181 | 92 | sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "", |
paul@181 | 93 | hr, min, secs); |
paul@181 | 94 | strcat(buf, tmp); |
paul@181 | 95 | } |
paul@181 | 96 | return buf; |
paul@181 | 97 | } |
paul@181 | 98 | |
paul@181 | 99 | static void print_features(struct ext2_super_block * s, FILE *f) |
paul@181 | 100 | { |
paul@181 | 101 | #ifdef EXT2_DYNAMIC_REV |
paul@181 | 102 | int i, j, printed=0; |
paul@181 | 103 | __u32 *mask = &s->s_feature_compat, m; |
paul@181 | 104 | |
paul@181 | 105 | fprintf(f, "Filesystem features: "); |
paul@181 | 106 | for (i=0; i <3; i++,mask++) { |
paul@181 | 107 | for (j=0,m=1; j < 32; j++, m<<=1) { |
paul@181 | 108 | if (*mask & m) { |
paul@181 | 109 | fprintf(f, " %s", e2p_feature2string(i, m)); |
paul@181 | 110 | printed++; |
paul@181 | 111 | } |
paul@181 | 112 | } |
paul@181 | 113 | } |
paul@181 | 114 | if (printed == 0) |
paul@181 | 115 | fprintf(f, " (none)"); |
paul@181 | 116 | fprintf(f, "\n"); |
paul@181 | 117 | #endif |
paul@181 | 118 | } |
paul@181 | 119 | |
paul@181 | 120 | static void print_mntopts(struct ext2_super_block * s, FILE *f) |
paul@181 | 121 | { |
paul@181 | 122 | #ifdef EXT2_DYNAMIC_REV |
paul@181 | 123 | int i, printed=0; |
paul@181 | 124 | __u32 mask = s->s_default_mount_opts, m; |
paul@181 | 125 | |
paul@181 | 126 | fprintf(f, "Default mount options: "); |
paul@181 | 127 | if (mask & EXT3_DEFM_JMODE) { |
paul@181 | 128 | fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE)); |
paul@181 | 129 | printed++; |
paul@181 | 130 | } |
paul@181 | 131 | for (i=0,m=1; i < 32; i++, m<<=1) { |
paul@181 | 132 | if (m & EXT3_DEFM_JMODE) |
paul@181 | 133 | continue; |
paul@181 | 134 | if (mask & m) { |
paul@181 | 135 | fprintf(f, " %s", e2p_mntopt2string(m)); |
paul@181 | 136 | printed++; |
paul@181 | 137 | } |
paul@181 | 138 | } |
paul@181 | 139 | if (printed == 0) |
paul@181 | 140 | fprintf(f, " (none)"); |
paul@181 | 141 | fprintf(f, "\n"); |
paul@181 | 142 | #endif |
paul@181 | 143 | } |
paul@181 | 144 | |
paul@181 | 145 | static void print_super_flags(struct ext2_super_block * s, FILE *f) |
paul@181 | 146 | { |
paul@181 | 147 | int flags_found = 0; |
paul@181 | 148 | |
paul@181 | 149 | if (s->s_flags == 0) |
paul@181 | 150 | return; |
paul@181 | 151 | |
paul@181 | 152 | fputs("Filesystem flags: ", f); |
paul@181 | 153 | if (s->s_flags & EXT2_FLAGS_SIGNED_HASH) { |
paul@181 | 154 | fputs("signed_directory_hash ", f); |
paul@181 | 155 | flags_found++; |
paul@181 | 156 | } |
paul@181 | 157 | if (s->s_flags & EXT2_FLAGS_UNSIGNED_HASH) { |
paul@181 | 158 | fputs("unsigned_directory_hash ", f); |
paul@181 | 159 | flags_found++; |
paul@181 | 160 | } |
paul@181 | 161 | if (s->s_flags & EXT2_FLAGS_TEST_FILESYS) { |
paul@181 | 162 | fputs("test_filesystem ", f); |
paul@181 | 163 | flags_found++; |
paul@181 | 164 | } |
paul@181 | 165 | if (flags_found) |
paul@181 | 166 | fputs("\n", f); |
paul@181 | 167 | else |
paul@181 | 168 | fputs("(none)\n", f); |
paul@181 | 169 | } |
paul@181 | 170 | |
paul@181 | 171 | static __u64 e2p_blocks_count(struct ext2_super_block *super) |
paul@181 | 172 | { |
paul@181 | 173 | return super->s_blocks_count | |
paul@181 | 174 | (ext2fs_has_feature_64bit(super) ? |
paul@181 | 175 | (__u64) super->s_blocks_count_hi << 32 : 0); |
paul@181 | 176 | } |
paul@181 | 177 | |
paul@181 | 178 | static __u64 e2p_r_blocks_count(struct ext2_super_block *super) |
paul@181 | 179 | { |
paul@181 | 180 | return super->s_r_blocks_count | |
paul@181 | 181 | (ext2fs_has_feature_64bit(super) ? |
paul@181 | 182 | (__u64) super->s_r_blocks_count_hi << 32 : 0); |
paul@181 | 183 | } |
paul@181 | 184 | |
paul@181 | 185 | static __u64 e2p_free_blocks_count(struct ext2_super_block *super) |
paul@181 | 186 | { |
paul@181 | 187 | return super->s_free_blocks_count | |
paul@181 | 188 | (ext2fs_has_feature_64bit(super) ? |
paul@181 | 189 | (__u64) super->s_free_blocks_hi << 32 : 0); |
paul@181 | 190 | } |
paul@181 | 191 | |
paul@181 | 192 | #ifndef EXT2_INODE_SIZE |
paul@181 | 193 | #define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode) |
paul@181 | 194 | #endif |
paul@181 | 195 | |
paul@181 | 196 | #ifndef EXT2_GOOD_OLD_REV |
paul@181 | 197 | #define EXT2_GOOD_OLD_REV 0 |
paul@181 | 198 | #endif |
paul@181 | 199 | |
paul@181 | 200 | static const char *checksum_type(__u8 type) |
paul@181 | 201 | { |
paul@181 | 202 | switch (type) { |
paul@181 | 203 | case EXT2_CRC32C_CHKSUM: |
paul@181 | 204 | return "crc32c"; |
paul@181 | 205 | default: |
paul@181 | 206 | return "unknown"; |
paul@181 | 207 | } |
paul@181 | 208 | } |
paul@181 | 209 | |
paul@181 | 210 | static const char *quota_prefix[MAXQUOTAS] = { |
paul@181 | 211 | [USRQUOTA] = "User quota inode:", |
paul@181 | 212 | [GRPQUOTA] = "Group quota inode:", |
paul@181 | 213 | [PRJQUOTA] = "Project quota inode:", |
paul@181 | 214 | }; |
paul@181 | 215 | |
paul@181 | 216 | /** |
paul@181 | 217 | * Convert type of quota to written representation |
paul@181 | 218 | */ |
paul@181 | 219 | static const char *quota_type2prefix(enum quota_type qtype) |
paul@181 | 220 | { |
paul@181 | 221 | return quota_prefix[qtype]; |
paul@181 | 222 | } |
paul@181 | 223 | |
paul@181 | 224 | void list_super2(struct ext2_super_block * sb, FILE *f) |
paul@181 | 225 | { |
paul@181 | 226 | int inode_blocks_per_group; |
paul@181 | 227 | char buf[80], *str; |
paul@181 | 228 | time_t tm; |
paul@181 | 229 | enum quota_type qtype; |
paul@181 | 230 | |
paul@181 | 231 | inode_blocks_per_group = (((sb->s_inodes_per_group * |
paul@181 | 232 | EXT2_INODE_SIZE(sb)) + |
paul@181 | 233 | EXT2_BLOCK_SIZE(sb) - 1) / |
paul@181 | 234 | EXT2_BLOCK_SIZE(sb)); |
paul@181 | 235 | if (sb->s_volume_name[0]) { |
paul@181 | 236 | memset(buf, 0, sizeof(buf)); |
paul@181 | 237 | strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name)); |
paul@181 | 238 | } else |
paul@181 | 239 | strcpy(buf, "<none>"); |
paul@181 | 240 | fprintf(f, "Filesystem volume name: %s\n", buf); |
paul@181 | 241 | if (sb->s_last_mounted[0]) { |
paul@181 | 242 | memset(buf, 0, sizeof(buf)); |
paul@181 | 243 | strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted)); |
paul@181 | 244 | } else |
paul@181 | 245 | strcpy(buf, "<not available>"); |
paul@181 | 246 | fprintf(f, "Last mounted on: %s\n", buf); |
paul@181 | 247 | fprintf(f, "Filesystem UUID: %s\n", e2p_uuid2str(sb->s_uuid)); |
paul@181 | 248 | fprintf(f, "Filesystem magic number: 0x%04X\n", sb->s_magic); |
paul@181 | 249 | fprintf(f, "Filesystem revision #: %d", sb->s_rev_level); |
paul@181 | 250 | if (sb->s_rev_level == EXT2_GOOD_OLD_REV) { |
paul@181 | 251 | fprintf(f, " (original)\n"); |
paul@181 | 252 | #ifdef EXT2_DYNAMIC_REV |
paul@181 | 253 | } else if (sb->s_rev_level == EXT2_DYNAMIC_REV) { |
paul@181 | 254 | fprintf(f, " (dynamic)\n"); |
paul@181 | 255 | #endif |
paul@181 | 256 | } else |
paul@181 | 257 | fprintf(f, " (unknown)\n"); |
paul@181 | 258 | print_features(sb, f); |
paul@181 | 259 | print_super_flags(sb, f); |
paul@181 | 260 | print_mntopts(sb, f); |
paul@181 | 261 | if (sb->s_mount_opts[0]) |
paul@181 | 262 | fprintf(f, "Mount options: %s\n", sb->s_mount_opts); |
paul@181 | 263 | fprintf(f, "Filesystem state: "); |
paul@181 | 264 | print_fs_state (f, sb->s_state); |
paul@181 | 265 | fprintf(f, "\n"); |
paul@181 | 266 | fprintf(f, "Errors behavior: "); |
paul@181 | 267 | print_fs_errors(f, sb->s_errors); |
paul@181 | 268 | fprintf(f, "\n"); |
paul@181 | 269 | str = e2p_os2string(sb->s_creator_os); |
paul@181 | 270 | fprintf(f, "Filesystem OS type: %s\n", str); |
paul@181 | 271 | free(str); |
paul@181 | 272 | fprintf(f, "Inode count: %u\n", sb->s_inodes_count); |
paul@181 | 273 | fprintf(f, "Block count: %llu\n", e2p_blocks_count(sb)); |
paul@181 | 274 | fprintf(f, "Reserved block count: %llu\n", e2p_r_blocks_count(sb)); |
paul@181 | 275 | if (sb->s_overhead_blocks) |
paul@181 | 276 | fprintf(f, "Overhead blocks: %u\n", |
paul@181 | 277 | sb->s_overhead_blocks); |
paul@181 | 278 | fprintf(f, "Free blocks: %llu\n", e2p_free_blocks_count(sb)); |
paul@181 | 279 | fprintf(f, "Free inodes: %u\n", sb->s_free_inodes_count); |
paul@181 | 280 | fprintf(f, "First block: %u\n", sb->s_first_data_block); |
paul@181 | 281 | fprintf(f, "Block size: %u\n", EXT2_BLOCK_SIZE(sb)); |
paul@181 | 282 | if (ext2fs_has_feature_bigalloc(sb)) |
paul@181 | 283 | fprintf(f, "Cluster size: %u\n", |
paul@181 | 284 | EXT2_CLUSTER_SIZE(sb)); |
paul@181 | 285 | else |
paul@181 | 286 | fprintf(f, "Fragment size: %u\n", |
paul@181 | 287 | EXT2_CLUSTER_SIZE(sb)); |
paul@181 | 288 | if (ext2fs_has_feature_64bit(sb)) |
paul@181 | 289 | fprintf(f, "Group descriptor size: %u\n", sb->s_desc_size); |
paul@181 | 290 | if (sb->s_reserved_gdt_blocks) |
paul@181 | 291 | fprintf(f, "Reserved GDT blocks: %u\n", |
paul@181 | 292 | sb->s_reserved_gdt_blocks); |
paul@181 | 293 | fprintf(f, "Blocks per group: %u\n", sb->s_blocks_per_group); |
paul@181 | 294 | if (ext2fs_has_feature_bigalloc(sb)) |
paul@181 | 295 | fprintf(f, "Clusters per group: %u\n", |
paul@181 | 296 | sb->s_clusters_per_group); |
paul@181 | 297 | else |
paul@181 | 298 | fprintf(f, "Fragments per group: %u\n", |
paul@181 | 299 | sb->s_clusters_per_group); |
paul@181 | 300 | fprintf(f, "Inodes per group: %u\n", sb->s_inodes_per_group); |
paul@181 | 301 | fprintf(f, "Inode blocks per group: %u\n", inode_blocks_per_group); |
paul@181 | 302 | if (sb->s_raid_stride) |
paul@181 | 303 | fprintf(f, "RAID stride: %u\n", |
paul@181 | 304 | sb->s_raid_stride); |
paul@181 | 305 | if (sb->s_raid_stripe_width) |
paul@181 | 306 | fprintf(f, "RAID stripe width: %u\n", |
paul@181 | 307 | sb->s_raid_stripe_width); |
paul@181 | 308 | if (sb->s_first_meta_bg) |
paul@181 | 309 | fprintf(f, "First meta block group: %u\n", |
paul@181 | 310 | sb->s_first_meta_bg); |
paul@181 | 311 | if (sb->s_log_groups_per_flex) |
paul@181 | 312 | fprintf(f, "Flex block group size: %u\n", |
paul@181 | 313 | 1 << sb->s_log_groups_per_flex); |
paul@181 | 314 | if (sb->s_mkfs_time) { |
paul@181 | 315 | tm = sb->s_mkfs_time; |
paul@181 | 316 | fprintf(f, "Filesystem created: %s", ctime(&tm)); |
paul@181 | 317 | } |
paul@181 | 318 | tm = sb->s_mtime; |
paul@181 | 319 | fprintf(f, "Last mount time: %s", |
paul@181 | 320 | sb->s_mtime ? ctime(&tm) : "n/a\n"); |
paul@181 | 321 | tm = sb->s_wtime; |
paul@181 | 322 | fprintf(f, "Last write time: %s", ctime(&tm)); |
paul@181 | 323 | fprintf(f, "Mount count: %u\n", sb->s_mnt_count); |
paul@181 | 324 | fprintf(f, "Maximum mount count: %d\n", sb->s_max_mnt_count); |
paul@181 | 325 | tm = sb->s_lastcheck; |
paul@181 | 326 | fprintf(f, "Last checked: %s", ctime(&tm)); |
paul@181 | 327 | fprintf(f, "Check interval: %u (%s)\n", sb->s_checkinterval, |
paul@181 | 328 | interval_string(sb->s_checkinterval)); |
paul@181 | 329 | if (sb->s_checkinterval) |
paul@181 | 330 | { |
paul@181 | 331 | time_t next; |
paul@181 | 332 | |
paul@181 | 333 | next = sb->s_lastcheck + sb->s_checkinterval; |
paul@181 | 334 | fprintf(f, "Next check after: %s", ctime(&next)); |
paul@181 | 335 | } |
paul@181 | 336 | #define POW2(x) ((__u64) 1 << (x)) |
paul@181 | 337 | if (sb->s_kbytes_written) { |
paul@181 | 338 | fprintf(f, "Lifetime writes: "); |
paul@181 | 339 | if (sb->s_kbytes_written < POW2(13)) |
paul@181 | 340 | fprintf(f, "%llu kB\n", sb->s_kbytes_written); |
paul@181 | 341 | else if (sb->s_kbytes_written < POW2(23)) |
paul@181 | 342 | fprintf(f, "%llu MB\n", |
paul@181 | 343 | (sb->s_kbytes_written + POW2(9)) >> 10); |
paul@181 | 344 | else if (sb->s_kbytes_written < POW2(33)) |
paul@181 | 345 | fprintf(f, "%llu GB\n", |
paul@181 | 346 | (sb->s_kbytes_written + POW2(19)) >> 20); |
paul@181 | 347 | else if (sb->s_kbytes_written < POW2(43)) |
paul@181 | 348 | fprintf(f, "%llu TB\n", |
paul@181 | 349 | (sb->s_kbytes_written + POW2(29)) >> 30); |
paul@181 | 350 | else |
paul@181 | 351 | fprintf(f, "%llu PB\n", |
paul@181 | 352 | (sb->s_kbytes_written + POW2(39)) >> 40); |
paul@181 | 353 | } |
paul@181 | 354 | fprintf(f, "Reserved blocks uid: "); |
paul@181 | 355 | print_user(sb->s_def_resuid, f); |
paul@181 | 356 | fprintf(f, "Reserved blocks gid: "); |
paul@181 | 357 | print_group(sb->s_def_resgid, f); |
paul@181 | 358 | if (sb->s_rev_level >= EXT2_DYNAMIC_REV) { |
paul@181 | 359 | fprintf(f, "First inode: %d\n", sb->s_first_ino); |
paul@181 | 360 | fprintf(f, "Inode size: %d\n", sb->s_inode_size); |
paul@181 | 361 | if (sb->s_min_extra_isize) |
paul@181 | 362 | fprintf(f, "Required extra isize: %d\n", |
paul@181 | 363 | sb->s_min_extra_isize); |
paul@181 | 364 | if (sb->s_want_extra_isize) |
paul@181 | 365 | fprintf(f, "Desired extra isize: %d\n", |
paul@181 | 366 | sb->s_want_extra_isize); |
paul@181 | 367 | } |
paul@181 | 368 | if (!e2p_is_null_uuid(sb->s_journal_uuid)) |
paul@181 | 369 | fprintf(f, "Journal UUID: %s\n", |
paul@181 | 370 | e2p_uuid2str(sb->s_journal_uuid)); |
paul@181 | 371 | if (sb->s_journal_inum) |
paul@181 | 372 | fprintf(f, "Journal inode: %u\n", |
paul@181 | 373 | sb->s_journal_inum); |
paul@181 | 374 | if (sb->s_journal_dev) |
paul@181 | 375 | fprintf(f, "Journal device: 0x%04x\n", |
paul@181 | 376 | sb->s_journal_dev); |
paul@181 | 377 | if (sb->s_last_orphan) |
paul@181 | 378 | fprintf(f, "First orphan inode: %u\n", |
paul@181 | 379 | sb->s_last_orphan); |
paul@181 | 380 | if (ext2fs_has_feature_dir_index(sb) || |
paul@181 | 381 | sb->s_def_hash_version) |
paul@181 | 382 | fprintf(f, "Default directory hash: %s\n", |
paul@181 | 383 | e2p_hash2string(sb->s_def_hash_version)); |
paul@181 | 384 | if (!e2p_is_null_uuid(sb->s_hash_seed)) |
paul@181 | 385 | fprintf(f, "Directory Hash Seed: %s\n", |
paul@181 | 386 | e2p_uuid2str(sb->s_hash_seed)); |
paul@181 | 387 | if (sb->s_jnl_backup_type) { |
paul@181 | 388 | fprintf(f, "Journal backup: "); |
paul@181 | 389 | switch (sb->s_jnl_backup_type) { |
paul@181 | 390 | case 1: |
paul@181 | 391 | fprintf(f, "inode blocks\n"); |
paul@181 | 392 | break; |
paul@181 | 393 | default: |
paul@181 | 394 | fprintf(f, "type %u\n", sb->s_jnl_backup_type); |
paul@181 | 395 | } |
paul@181 | 396 | } |
paul@181 | 397 | if (sb->s_backup_bgs[0] || sb->s_backup_bgs[1]) { |
paul@181 | 398 | fprintf(f, "Backup block groups: "); |
paul@181 | 399 | if (sb->s_backup_bgs[0]) |
paul@181 | 400 | fprintf(f, "%u ", sb->s_backup_bgs[0]); |
paul@181 | 401 | if (sb->s_backup_bgs[1]) |
paul@181 | 402 | fprintf(f, "%u ", sb->s_backup_bgs[1]); |
paul@181 | 403 | fputc('\n', f); |
paul@181 | 404 | } |
paul@181 | 405 | if (sb->s_snapshot_inum) { |
paul@181 | 406 | fprintf(f, "Snapshot inode: %u\n", |
paul@181 | 407 | sb->s_snapshot_inum); |
paul@181 | 408 | fprintf(f, "Snapshot ID: %u\n", |
paul@181 | 409 | sb->s_snapshot_id); |
paul@181 | 410 | fprintf(f, "Snapshot reserved blocks: %llu\n", |
paul@181 | 411 | sb->s_snapshot_r_blocks_count); |
paul@181 | 412 | } |
paul@181 | 413 | if (sb->s_snapshot_list) |
paul@181 | 414 | fprintf(f, "Snapshot list head: %u\n", |
paul@181 | 415 | sb->s_snapshot_list); |
paul@181 | 416 | if (sb->s_error_count) |
paul@181 | 417 | fprintf(f, "FS Error count: %u\n", |
paul@181 | 418 | sb->s_error_count); |
paul@181 | 419 | if (sb->s_first_error_time) { |
paul@181 | 420 | tm = sb->s_first_error_time; |
paul@181 | 421 | fprintf(f, "First error time: %s", ctime(&tm)); |
paul@181 | 422 | memset(buf, 0, sizeof(buf)); |
paul@181 | 423 | strncpy(buf, (char *)sb->s_first_error_func, |
paul@181 | 424 | sizeof(sb->s_first_error_func)); |
paul@181 | 425 | fprintf(f, "First error function: %s\n", buf); |
paul@181 | 426 | fprintf(f, "First error line #: %u\n", |
paul@181 | 427 | sb->s_first_error_line); |
paul@181 | 428 | fprintf(f, "First error inode #: %u\n", |
paul@181 | 429 | sb->s_first_error_ino); |
paul@181 | 430 | fprintf(f, "First error block #: %llu\n", |
paul@181 | 431 | sb->s_first_error_block); |
paul@181 | 432 | } |
paul@181 | 433 | if (sb->s_last_error_time) { |
paul@181 | 434 | tm = sb->s_last_error_time; |
paul@181 | 435 | fprintf(f, "Last error time: %s", ctime(&tm)); |
paul@181 | 436 | memset(buf, 0, sizeof(buf)); |
paul@181 | 437 | strncpy(buf, (char *)sb->s_last_error_func, |
paul@181 | 438 | sizeof(sb->s_last_error_func)); |
paul@181 | 439 | fprintf(f, "Last error function: %s\n", buf); |
paul@181 | 440 | fprintf(f, "Last error line #: %u\n", |
paul@181 | 441 | sb->s_last_error_line); |
paul@181 | 442 | fprintf(f, "Last error inode #: %u\n", |
paul@181 | 443 | sb->s_last_error_ino); |
paul@181 | 444 | fprintf(f, "Last error block #: %llu\n", |
paul@181 | 445 | sb->s_last_error_block); |
paul@181 | 446 | } |
paul@181 | 447 | if (ext2fs_has_feature_mmp(sb)) { |
paul@181 | 448 | fprintf(f, "MMP block number: %llu\n", |
paul@181 | 449 | (long long)sb->s_mmp_block); |
paul@181 | 450 | fprintf(f, "MMP update interval: %u\n", |
paul@181 | 451 | sb->s_mmp_update_interval); |
paul@181 | 452 | } |
paul@181 | 453 | for (qtype = 0; qtype < MAXQUOTAS; qtype++) { |
paul@181 | 454 | if (*quota_sb_inump(sb, qtype) != 0) |
paul@181 | 455 | fprintf(f, "%-26s%u\n", |
paul@181 | 456 | quota_type2prefix(qtype), |
paul@181 | 457 | *quota_sb_inump(sb, qtype)); |
paul@181 | 458 | } |
paul@181 | 459 | |
paul@181 | 460 | if (ext2fs_has_feature_metadata_csum(sb)) { |
paul@181 | 461 | fprintf(f, "Checksum type: %s\n", |
paul@181 | 462 | checksum_type(sb->s_checksum_type)); |
paul@181 | 463 | fprintf(f, "Checksum: 0x%08x\n", |
paul@181 | 464 | sb->s_checksum); |
paul@181 | 465 | } |
paul@181 | 466 | if (!e2p_is_null_uuid(sb->s_encrypt_pw_salt)) |
paul@181 | 467 | fprintf(f, "Encryption PW Salt: %s\n", |
paul@181 | 468 | e2p_uuid2str(sb->s_encrypt_pw_salt)); |
paul@181 | 469 | |
paul@181 | 470 | if (ext2fs_has_feature_csum_seed(sb)) |
paul@181 | 471 | fprintf(f, "Checksum seed: 0x%08x\n", |
paul@181 | 472 | sb->s_checksum_seed); |
paul@181 | 473 | } |
paul@181 | 474 | |
paul@181 | 475 | void list_super (struct ext2_super_block * s) |
paul@181 | 476 | { |
paul@181 | 477 | list_super2(s, stdout); |
paul@181 | 478 | } |
paul@181 | 479 | |