* %End-Header%
*/
+#include "config.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define PROMPT_RELOCATE 3
#define PROMPT_ALLOCATE 4
#define PROMPT_EXPAND 5
-#define PROMPT_CONNECT 6
+#define PROMPT_CONNECT 6
#define PROMPT_CREATE 7
#define PROMPT_SALVAGE 8
#define PROMPT_TRUNCATE 9
#define PROMPT_CLEAR_INODE 10
-#define PROMPT_ABORT 11
-#define PROMPT_SPLIT 12
+#define PROMPT_ABORT 11
+#define PROMPT_SPLIT 12
#define PROMPT_CONTINUE 13
#define PROMPT_CLONE 14
-#define PROMPT_DELETE 15
+#define PROMPT_DELETE 15
#define PROMPT_SUPPRESS 16
#define PROMPT_UNLINK 17
#define PROMPT_CLEAR_HTREE 18
N_("Clear @j"),
PROMPT_NULL, PR_PREEN_NOMSG },
- /* Ask if we should run the journal anyway */
- { PR_0_JOURNAL_RUN,
- N_("Run @j anyway"),
- PROMPT_NULL, 0 },
-
- /* Run the journal by default */
- { PR_0_JOURNAL_RUN_DEFAULT,
- N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
- PROMPT_NONE, 0 },
+ /* Filesystem revision is 0, but feature flags are set */
+ { PR_0_FS_REV_LEVEL,
+ N_("@f has feature flag(s) set, but is a revision 0 @f. "),
+ PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
/* Clearing orphan inode */
{ PR_0_ORPHAN_CLEAR_INODE,
/* Illegal block found in orphaned inode */
{ PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
- N_("@I @b #%B (%b) found in @o @i %i.\n"),
+ N_("@I %B (%b) found in @o @i %i.\n"),
PROMPT_NONE, 0 },
/* Already cleared block found in orphaned inode */
{ PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
- N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
+ N_("Already cleared %B (%b) found in @o @i %i.\n"),
PROMPT_NONE, 0 },
/* Illegal orphan inode in superblock */
N_("@I @i %i in @o @i list.\n"),
PROMPT_NONE, 0 },
- /* Filesystem revision is 0, but feature flags are set */
- { PR_0_FS_REV_LEVEL,
- N_("@f has feature flag(s) set, but is a revision 0 @f. "),
- PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
-
/* Journal superblock has an unknown read-only feature flag set */
{ PR_0_JOURNAL_UNSUPP_ROCOMPAT,
N_("@j @S has an unknown read-only feature flag set.\n"),
"Clearing fields beyond the V1 @j @S...\n\n"),
PROMPT_NONE, 0 },
+ /* Ask if we should run the journal anyway */
+ { PR_0_JOURNAL_RUN,
+ N_("Run @j anyway"),
+ PROMPT_NULL, 0 },
+
+ /* Run the journal by default */
+ { PR_0_JOURNAL_RUN_DEFAULT,
+ N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
+ PROMPT_NONE, 0 },
+
/* Backup journal inode blocks */
{ PR_0_BACKUP_JNL,
N_("Backing up @j @i @b information.\n\n"),
/* Last mount time is in the future */
{ PR_0_FUTURE_SB_LAST_MOUNT,
- N_("@S last mount time is in the future. "),
- PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
+ N_("@S last mount time (%t,\n\tnow = %T) is in the future.\n"),
+ PROMPT_FIX, PR_NO_OK },
/* Last write time is in the future */
{ PR_0_FUTURE_SB_LAST_WRITE,
- N_("@S last write time is in the future. "),
- PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
+ N_("@S last write time (%t,\n\tnow = %T) is in the future.\n"),
+ PROMPT_FIX, PR_NO_OK },
{ PR_0_EXTERNAL_JOURNAL_HINT,
N_("@S hint for external superblock @s %X. "),
/* group descriptor N checksum is invalid. */
{ PR_0_GDT_CSUM,
N_("@g descriptor %g checksum is invalid. "),
- PROMPT_FIX, PR_PREEN_OK },
+ PROMPT_FIX, PR_LATCH_BG_CHECKSUM },
/* group descriptor N marked uninitialized without feature set. */
{ PR_0_GDT_UNINIT,
N_("@g descriptor %g marked uninitialized without feature set.\n"),
PROMPT_FIX, PR_PREEN_OK },
- /* group N block bitmap uninitialized but inode bitmap in use. */
- { PR_0_BB_UNINIT_IB_INIT,
- N_("@g %g @b @B uninitialized but @i @B in use.\n"),
- PROMPT_FIX, PR_PREEN_OK },
-
/* Group descriptor N has invalid unused inodes count. */
{ PR_0_GDT_ITABLE_UNUSED,
N_("@g descriptor %g has invalid unused inodes count %b. "),
N_("The test_fs flag is set (and ext4 is available). "),
PROMPT_CLEAR, PR_PREEN_OK },
+ /* Last mount time is in the future (fudged) */
+ { PR_0_FUTURE_SB_LAST_MOUNT_FUDGED,
+ N_("@S last mount time is in the future.\n\t(by less than a day, "
+ "probably due to the hardware clock being incorrectly set) "),
+ PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
+
+ /* Last write time is in the future (fudged) */
+ { PR_0_FUTURE_SB_LAST_WRITE_FUDGED,
+ N_("@S last write time is in the future.\n\t(by less than a day, "
+ "probably due to the hardware clock being incorrectly set). "),
+ PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
+
+ /* Block group checksum (latch question) is invalid. */
+ { PR_0_GDT_CSUM_LATCH,
+ N_("One or more @b @g descriptor checksums are invalid. "),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* Free inodes count wrong */
+ { PR_0_FREE_INODE_COUNT,
+ N_("Setting free @is count to %j (was %i)\n"),
+ PROMPT_NONE, PR_PREEN_NOMSG },
+
+ /* Free blocks count wrong */
+ { PR_0_FREE_BLOCK_COUNT,
+ N_("Setting free @bs count to %c (was %b)\n"),
+ PROMPT_NONE, PR_PREEN_NOMSG },
+
+ /* Making quota file hidden */
+ { PR_0_HIDE_QUOTA,
+ N_("Making @q @is hidden.\n\n"),
+ PROMPT_NONE, PR_PREEN_OK },
+
+ /* Superblock has invalid MMP block. */
+ { PR_0_MMP_INVALID_BLK,
+ N_("@S has invalid MMP block. "),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* Superblock has invalid MMP magic. */
+ { PR_0_MMP_INVALID_MAGIC,
+ N_("@S has invalid MMP magic. "),
+ PROMPT_FIX, PR_PREEN_OK | PR_NO_OK},
+
/* Pass 1 errors */
/* Pass 1: Checking inodes, blocks, and sizes */
/* Illegal blocknumber in inode */
{ PR_1_ILLEGAL_BLOCK_NUM,
- N_("@I @b #%B (%b) in @i %i. "),
+ N_("@I %B (%b) in @i %i. "),
PROMPT_CLEAR, PR_LATCH_BLOCK },
/* Block number overlaps fs metadata */
{ PR_1_BLOCK_OVERLAPS_METADATA,
- N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
+ N_("%B (%b) overlaps @f metadata in @i %i. "),
PROMPT_CLEAR, PR_LATCH_BLOCK },
/* Inode has illegal blocks (latch question) */
/* Illegal block number in bad block inode */
{ PR_1_BB_ILLEGAL_BLOCK_NUM,
- N_("@I @b #%B (%b) in bad @b @i. "),
+ N_("@I %B (%b) in bad @b @i. "),
PROMPT_CLEAR, PR_LATCH_BBLOCK },
/* Bad block inode has illegal blocks (latch question) */
/* Error reading Extended Attribute block while fixing refcount */
{ PR_1_EXTATTR_READ_ABORT,
N_("Error reading @a @b %b (%m). "),
- PROMPT_ABORT, 0 },
+ PROMPT_NONE, PR_FATAL },
/* Extended attribute reference count incorrect */
{ PR_1_EXTATTR_REFCOUNT,
- N_("@a @b %b has reference count %B, @s %N. "),
+ N_("@a @b %b has reference count %r, @s %N. "),
PROMPT_FIX, 0 },
/* Error writing Extended Attribute block while fixing refcount */
- { PR_1_EXTATTR_WRITE,
+ { PR_1_EXTATTR_WRITE_ABORT,
N_("Error writing @a @b %b (%m). "),
- PROMPT_ABORT, 0 },
+ PROMPT_NONE, PR_FATAL },
/* Multiple EA blocks not supported */
{ PR_1_EA_MULTI_BLOCK,
PROMPT_CLEAR, 0},
/* Error allocating EA region allocation structure */
- { PR_1_EA_ALLOC_REGION,
+ { PR_1_EA_ALLOC_REGION_ABORT,
N_("@A @a @b %b. "),
- PROMPT_ABORT, 0},
+ PROMPT_NONE, PR_FATAL},
/* Error EA allocation collision */
{ PR_1_EA_ALLOC_COLLISION,
/* Directory too big */
{ PR_1_TOOBIG_DIR,
- N_("@b #%B (%b) causes @d to be too big. "),
+ N_("%B (%b) causes @d to be too big. "),
PROMPT_CLEAR, PR_LATCH_TOOBIG },
/* Regular file too big */
{ PR_1_TOOBIG_REG,
- N_("@b #%B (%b) causes file to be too big. "),
+ N_("%B (%b) causes file to be too big. "),
PROMPT_CLEAR, PR_LATCH_TOOBIG },
/* Symlink too big */
{ PR_1_TOOBIG_SYMLINK,
- N_("@b #%B (%b) causes symlink to be too big. "),
+ N_("%B (%b) causes symlink to be too big. "),
PROMPT_CLEAR, PR_LATCH_TOOBIG },
/* INDEX_FL flag set on a non-HTREE filesystem */
/* Resize inode failed */
{ PR_1_RESIZE_INODE_CREATE,
N_("Resize @i (re)creation failed: %m."),
- PROMPT_ABORT, 0 },
+ PROMPT_CONTINUE, 0 },
/* invalid inode->i_extra_isize */
{ PR_1_EXTRA_ISIZE,
N_("@a in @i %i has a namelen (%N) which is @n\n"),
PROMPT_CLEAR, PR_PREEN_OK },
- /* invalid ea entry->e_value_size */
- { PR_1_ATTR_VALUE_SIZE,
- N_("@a in @i %i has a value size (%N) which is @n\n"),
- PROMPT_CLEAR, PR_PREEN_OK },
-
/* invalid ea entry->e_value_offs */
{ PR_1_ATTR_VALUE_OFFSET,
N_("@a in @i %i has a value offset (%N) which is @n\n"),
N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
PROMPT_CLEAR, PR_PREEN_OK },
+ /* invalid ea entry->e_value_size */
+ { PR_1_ATTR_VALUE_SIZE,
+ N_("@a in @i %i has a value size (%N) which is @n\n"),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
/* invalid ea entry->e_hash */
{ PR_1_ATTR_HASH,
N_("@a in @i %i has a hash (%N) which is @n\n"),
N_("@i %i has an invalid extent node (blk %b, lblk %c)\n"),
PROMPT_CLEAR, 0 },
+ { PR_1_EOFBLOCKS_FL_SET,
+ N_("@i %i should not have EOFBLOCKS_FL set "
+ "(size %Is, lblk %r)\n"),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* Failed to convert subcluster bitmap */
+ { PR_1_CONVERT_SUBCLUSTER,
+ N_("Error converting subcluster @b @B: %m\n"),
+ PROMPT_NONE, PR_FATAL },
+
+ /* Quota inode has bad mode */
+ { PR_1_QUOTA_BAD_MODE,
+ N_("@q @i is not regular file. "),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* Quota inode is not in use, but contains data */
+ { PR_1_QUOTA_INODE_NOT_CLEAR,
+ N_("@q @i is not in use, but contains data. "),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* Quota inode is user visible */
+ { PR_1_QUOTA_INODE_NOT_HIDDEN,
+ N_("@q @i is visible to the user. "),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* Invalid bad inode */
+ { PR_1_INVALID_BAD_INODE,
+ N_("The bad @b @i looks @n. "),
+ PROMPT_CLEAR, 0 },
+
/* Pass 1b errors */
/* Pass 1B: Rescan for duplicate/bad blocks */
N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
PROMPT_NONE, 0 },
-
/* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
{ PR_1C_PASS_HEADER,
N_("Pass 1C: Scanning directories for @is with @m @bs\n"),
/* File has duplicate blocks */
{ PR_1D_DUP_FILE,
N_("File %Q (@i #%i, mod time %IM) \n"
- " has %B @m @b(s), shared with %N file(s):\n"),
+ " has %r @m @b(s), shared with %N file(s):\n"),
PROMPT_NONE, 0 },
/* List of files sharing duplicate blocks */
N_("i_faddr @F %IF, @s zero.\n"),
PROMPT_CLEAR, 0 },
- /* i_file_acl should be zero */
+ /* i_file_acl should be zero */
{ PR_2_FILE_ACL_ZERO,
N_("i_file_acl @F %If, @s zero.\n"),
PROMPT_CLEAR, 0 },
- /* i_dir_acl should be zero */
+ /* i_dir_acl should be zero */
{ PR_2_DIR_ACL_ZERO,
N_("i_dir_acl @F %Id, @s zero.\n"),
PROMPT_CLEAR, 0 },
- /* i_frag should be zero */
+ /* i_frag should be zero */
{ PR_2_FRAG_ZERO,
N_("i_frag @F %N, @s zero.\n"),
PROMPT_CLEAR, 0 },
- /* i_fsize should be zero */
+ /* i_fsize should be zero */
{ PR_2_FSIZE_ZERO,
N_("i_fsize @F %N, @s zero.\n"),
PROMPT_CLEAR, 0 },
/* directory corrupted */
{ PR_2_DIR_CORRUPTED,
- N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
+ N_("@d @i %i, %B, offset %N: @d corrupted\n"),
PROMPT_SALVAGE, 0 },
/* filename too long */
{ PR_2_FILENAME_LONG,
- N_("@d @i %i, @b %B, offset %N: filename too long\n"),
+ N_("@d @i %i, %B, offset %N: filename too long\n"),
PROMPT_TRUNCATE, 0 },
/* Directory inode has a missing block (hole) */
{ PR_2_DIRECTORY_HOLE,
- N_("@d @i %i has an unallocated @b #%B. "),
+ N_("@d @i %i has an unallocated %B. "),
PROMPT_ALLOCATE, 0 },
/* '.' is not NULL terminated */
N_("Symlink %Q (@i #%i) is @n.\n"),
PROMPT_CLEAR, 0 },
- /* i_file_acl (extended attribute block) is bad */
+ /* i_file_acl (extended attribute block) is bad */
{ PR_2_FILE_ACL_BAD,
N_("@a @b @F @n (%If).\n"),
PROMPT_CLEAR, 0 },
/* Node in HTREE directory not referenced */
{ PR_2_HTREE_NOTREF,
- N_("@p @h %d: node (%B) not referenced\n"),
+ N_("@p @h %d: %B not referenced\n"),
PROMPT_NONE, 0 },
/* Node in HTREE directory referenced twice */
{ PR_2_HTREE_DUPREF,
- N_("@p @h %d: node (%B) referenced twice\n"),
+ N_("@p @h %d: %B referenced twice\n"),
PROMPT_NONE, 0 },
/* Node in HTREE directory has bad min hash */
{ PR_2_HTREE_MIN_HASH,
- N_("@p @h %d: node (%B) has bad min hash\n"),
+ N_("@p @h %d: %B has bad min hash\n"),
PROMPT_NONE, 0 },
/* Node in HTREE directory has bad max hash */
{ PR_2_HTREE_MAX_HASH,
- N_("@p @h %d: node (%B) has bad max hash\n"),
+ N_("@p @h %d: %B has bad max hash\n"),
PROMPT_NONE, 0 },
/* Clear invalid HTREE directory */
/* Invalid HTREE limit */
{ PR_2_HTREE_BAD_LIMIT,
- N_("@p @h %d: node (%B) has @n limit (%N)\n"),
+ N_("@p @h %d: %B has @n limit (%N)\n"),
PROMPT_CLEAR_HTREE, PR_PREEN_OK },
/* Invalid HTREE count */
{ PR_2_HTREE_BAD_COUNT,
- N_("@p @h %d: node (%B) has @n count (%N)\n"),
+ N_("@p @h %d: %B has @n count (%N)\n"),
PROMPT_CLEAR_HTREE, PR_PREEN_OK },
/* HTREE interior node has out-of-order hashes in table */
{ PR_2_HTREE_HASH_ORDER,
- N_("@p @h %d: node (%B) has an unordered hash table\n"),
+ N_("@p @h %d: %B has an unordered hash table\n"),
PROMPT_CLEAR_HTREE, PR_PREEN_OK },
/* Node in HTREE directory has invalid depth */
{ PR_2_HTREE_BAD_DEPTH,
- N_("@p @h %d: node (%B) has @n depth (%N)\n"),
+ N_("@p @h %d: %B has @n depth (%N)\n"),
PROMPT_NONE, 0 },
/* Duplicate directory entry found */
N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
PROMPT_NONE, 0 },
- /* i_blocks_hi should be zero */
+ /* i_blocks_hi should be zero */
{ PR_2_BLOCKS_HI_ZERO,
N_("i_blocks_hi @F %N, @s zero.\n"),
PROMPT_CLEAR, 0 },
N_("@E references @i %Di found in @g %g's unused inodes area.\n"),
PROMPT_FIX, PR_PREEN_OK },
+ /* i_blocks_hi should be zero */
+ { PR_2_I_FILE_ACL_HI_ZERO,
+ N_("i_file_acl_hi @F %N, @s zero.\n"),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
/* Pass 3 errors */
/* Pass 3: Checking directory connectivity */
/* Error iterating over directories */
{ PR_3A_OPTIMIZE_ITER,
- N_("Failed to create dirs_to_hash iterator: %m"),
+ N_("Failed to create dirs_to_hash iterator: %m\n"),
PROMPT_NONE, 0 },
/* Error rehash directory */
{ PR_3A_OPTIMIZE_DIR_ERR,
- N_("Failed to optimize directory %q (%d): %m"),
+ N_("Failed to optimize directory %q (%d): %m\n"),
PROMPT_NONE, 0 },
/* Rehashing dir header */
" +(%i--%j)",
PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
- /* Recreate journal if E2F_FLAG_JOURNAL_INODE flag is set */
- { PR_6_RECREATE_JOURNAL,
- N_("Recreate @j"),
- PROMPT_NULL, PR_PREEN_OK | PR_NO_OK },
-
/* Group N block(s) in use but group is marked BLOCK_UNINIT */
{ PR_5_BLOCK_UNINIT,
N_("@g %g @b(s) in use but @g is marked BLOCK_UNINIT\n"),
N_("@g %g @i(s) in use but @g is marked INODE_UNINIT\n"),
PROMPT_FIX, PR_PREEN_OK },
+ /* Post-Pass 5 errors */
+
+ /* Recreate journal if E2F_FLAG_JOURNAL_INODE flag is set */
+ { PR_6_RECREATE_JOURNAL,
+ N_("Recreate @j"),
+ PROMPT_NULL, PR_PREEN_OK | PR_NO_OK },
+
{ 0 }
};
{ PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
{ PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
{ PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
+ { PR_LATCH_BG_CHECKSUM, PR_0_GDT_CSUM_LATCH, 0 },
{ -1, 0, 0 },
};
static struct e2fsck_problem *find_problem(problem_t code)
{
- int i;
+ int i;
for (i=0; problem_table[i].e2p_code; i++) {
if (problem_table[i].e2p_code == code)
struct e2fsck_problem *ptr;
struct latch_descr *ldesc = 0;
const char *message;
- int def_yn, answer, ans;
+ int def_yn, answer, ans;
int print_answer = 0;
int suppress = 0;
reconfigure_bool(ctx, ptr, key, PR_NOCOLLATE, "no_collate");
reconfigure_bool(ctx, ptr, key, PR_NO_NOMSG, "no_nomsg");
reconfigure_bool(ctx, ptr, key, PR_PREEN_NOHDR, "preen_noheader");
+ reconfigure_bool(ctx, ptr, key, PR_FORCE_NO, "force_no");
ptr->flags |= PR_CONFIG;
}
(ctx->options & E2F_OPT_PREEN))
suppress++;
if ((ptr->flags & PR_NO_NOMSG) &&
- (ctx->options & E2F_OPT_NO))
+ ((ctx->options & E2F_OPT_NO) || (ptr->flags & PR_FORCE_NO)))
suppress++;
if (!suppress) {
message = ptr->e2p_description;
else
answer = def_yn;
} else {
- if (ctx->options & E2F_OPT_PREEN) {
+ if (ptr->flags & PR_FORCE_NO) {
+ answer = 0;
+ if (!suppress)
+ print_answer = 1;
+ } else if (ctx->options & E2F_OPT_PREEN) {
answer = def_yn;
if (!(ptr->flags & PR_PREEN_NOMSG))
print_answer = 1;
return answer;
}
+
+#ifdef UNITTEST
+
+#include <stdlib.h>
+#include <stdio.h>
+
+errcode_t
+profile_get_boolean(profile_t profile, const char *name, const char *subname,
+ const char *subsubname, int def_val, int *ret_boolean)
+{
+ return 0;
+}
+
+void print_e2fsck_message(e2fsck_t ctx, const char *msg,
+ struct problem_context *pctx, int first,
+ int recurse)
+{
+ return;
+}
+
+void fatal_error(e2fsck_t ctx, const char *msg)
+{
+ return;
+}
+
+void preenhalt(e2fsck_t ctx)
+{
+ return;
+}
+
+errcode_t
+profile_get_string(profile_t profile, const char *name, const char *subname,
+ const char *subsubname, const char *def_val,
+ char **ret_string)
+{
+ return 0;
+}
+
+int ask (e2fsck_t ctx, const char * string, int def)
+{
+ return 0;
+}
+
+int verify_problem_table(e2fsck_t ctx)
+{
+ struct e2fsck_problem *curr, *prev = NULL;
+ int rc = 0;
+
+ for (prev = NULL, curr = problem_table; curr->e2p_code; prev = curr++) {
+ if (prev == NULL)
+ continue;
+
+ if (curr->e2p_code > prev->e2p_code)
+ continue;
+
+ if (curr->e2p_code == prev->e2p_code)
+ fprintf(stderr, "*** Duplicate in problem table:\n");
+ else
+ fprintf(stderr, "*** Unordered problem table:\n");
+
+ fprintf(stderr, "curr code = 0x%08x: %s\n",
+ curr->e2p_code, curr->e2p_description);
+ fprintf(stderr, "*** prev code = 0x%08x: %s\n",
+ prev->e2p_code, prev->e2p_description);
+
+ fprintf(stderr, "*** This is a %sprogramming error in e2fsck\n",
+ (curr->e2p_code == prev->e2p_code) ? "fatal " : "");
+
+ rc = 1;
+ }
+
+ return rc;
+}
+
+int main(int argc, char *argv[])
+{
+ e2fsck_t ctx;
+ int rc;
+
+ memset(&ctx, 0, sizeof(ctx)); /* just to quiet compiler */
+ rc = verify_problem_table(ctx);
+ if (rc == 0)
+ printf("e2fsck problem table verified\n");
+
+ return rc;
+}
+#endif /* UNITTEST */