* %End-Header%
*/
+#include "config.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
/* 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 */
/* Last mount time is in the future */
{ PR_0_FUTURE_SB_LAST_MOUNT,
- N_("@S last mount time is in the future. "),
+ 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. "),
+ N_("@S last write time (%t,\n\tnow = %T) is in the future.\n"),
PROMPT_FIX, PR_NO_OK },
{ PR_0_EXTERNAL_JOURNAL_HINT,
/* group descriptor N checksum is invalid. */
{ PR_0_GDT_CSUM,
- N_("@g descriptor %g checksum is invalid. "),
- PROMPT_FIX, PR_PREEN_OK },
+ N_("@g descriptor %g checksum is %04x, should be %04y. "),
+ 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. "),
/* 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 buggy init scripts) "),
+ "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 buggy init scripts). "),
+ "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 @i %i (%Q) hidden.\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},
+
+ /* Opening file system failed */
+ { PR_0_OPEN_FAILED,
+ N_("ext2fs_open2: %m\n"),
+ PROMPT_NONE, 0 },
+
+ /* Checking group descriptor failed */
+ { PR_0_CHECK_DESC_FAILED,
+ N_("ext2fs_check_desc: %m\n"),
+ PROMPT_NONE, 0 },
+
/* 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_("@i %i has an invalid extent node (blk %b, lblk %c)\n"),
PROMPT_CLEAR, 0 },
+ /* 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 },
+
+ /* Extent has zero length */
+ { PR_1_EXTENT_LENGTH_ZERO,
+ N_("@i %i has zero length extent\n\t(@n logical @b %c, physical @b %b)\n"),
+ PROMPT_CLEAR, 0 },
+
+ /*
+ * Interior extent node logical offset doesn't match first node below it
+ */
+ { PR_1_EXTENT_INDEX_START_INVALID,
+ N_("Interior @x node level %N of @i %i:\n"
+ "Logical start %b does not match logical start %c at next level. "),
+ PROMPT_FIX, 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 */
/* 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 */
/* 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 */
/* Free inodes count wrong */
{ PR_5_FREE_INODE_COUNT,
N_("Free @is count wrong (%i, counted=%j).\n"),
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+ PROMPT_FIX, PR_PREEN_OK | PR_NO_OK | PR_PREEN_NOMSG },
/* Free blocks count for group wrong */
{ PR_5_FREE_BLOCK_COUNT_GROUP,
/* Free blocks count wrong */
{ PR_5_FREE_BLOCK_COUNT,
N_("Free @bs count wrong (%b, counted=%c).\n"),
- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+ PROMPT_FIX, PR_PREEN_OK | PR_NO_OK | PR_PREEN_NOMSG },
/* Programming error: bitmap endpoints don't match */
{ PR_5_BMAP_ENDPOINTS,
N_("Recreate @j"),
PROMPT_NULL, PR_PREEN_OK | PR_NO_OK },
+ /* Update quota information if it is inconsistent */
+ { PR_6_UPDATE_QUOTAS,
+ N_("Update quota info for quota type %N"),
+ PROMPT_NULL, PR_PREEN_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 void reconfigure_bool(e2fsck_t ctx, struct e2fsck_problem *ptr,
const char *key, int mask, const char *name)
{
- int bool;
+ int val;
- bool = (ptr->flags & mask);
- profile_get_boolean(ctx->profile, "problems", key, name, bool, &bool);
- if (bool)
+ val = (ptr->flags & mask);
+ profile_get_boolean(ctx->profile, "problems", key, name, val, &val);
+ if (val)
ptr->flags |= mask;
else
ptr->flags &= ~mask;
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");
+ profile_get_integer(ctx->profile, "options",
+ "max_count_problems", 0, 0,
+ &ptr->max_count);
+ profile_get_integer(ctx->profile, "problems", key, "max_count",
+ ptr->max_count, &ptr->max_count);
ptr->flags |= PR_CONFIG;
}
def_yn = 1;
+ ptr->count++;
if ((ptr->flags & PR_NO_DEFAULT) ||
((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
(ctx->options & E2F_OPT_NO))
(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 (ptr->max_count && (ptr->count > ptr->max_count)) {
+ if (ctx->options & (E2F_OPT_NO | E2F_OPT_YES))
+ suppress++;
+ if ((ctx->options & E2F_OPT_PREEN) &&
+ (ptr->flags & PR_PREEN_OK))
+ suppress++;
+ if ((ptr->flags & PR_LATCH_MASK) &&
+ (ldesc->flags & (PRL_YES | PRL_NO)))
+ suppress++;
+ if (ptr->count == ptr->max_count + 1) {
+ printf("...problem 0x%06x suppressed\n",
+ ptr->e2p_code);
+ fflush(stdout);
+ }
+ }
+ message = ptr->e2p_description;
+ if (*message)
+ message = _(message);
if (!suppress) {
- message = ptr->e2p_description;
if ((ctx->options & E2F_OPT_PREEN) &&
!(ptr->flags & PR_PREEN_NOHDR)) {
printf("%s: ", ctx->device_name ?
ctx->device_name : ctx->filesystem_name);
}
if (*message)
- print_e2fsck_message(ctx, _(message), pctx, 1, 0);
+ print_e2fsck_message(stdout, ctx, message, pctx, 1, 0);
}
+ if (ctx->logf && message)
+ print_e2fsck_message(ctx->logf, ctx, message, pctx, 1, 0);
if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
preenhalt(ctx);
else
answer = def_yn;
} else {
- if (ctx->options & E2F_OPT_PREEN) {
+ if (ptr->flags & PR_FORCE_NO) {
+ answer = 0;
+ print_answer = 1;
+ } else if (ctx->options & E2F_OPT_PREEN) {
answer = def_yn;
if (!(ptr->flags & PR_PREEN_NOMSG))
print_answer = 1;
} else if ((ptr->flags & PR_LATCH_MASK) &&
(ldesc->flags & (PRL_YES | PRL_NO))) {
- if (!suppress)
- print_answer = 1;
+ print_answer = 1;
if (ldesc->flags & PRL_YES)
answer = 1;
else
if (!answer && !(ptr->flags & PR_NO_OK))
ext2fs_unmark_valid(fs);
- if (print_answer)
- printf("%s.\n", answer ?
- _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
-
+ if (print_answer) {
+ if (!suppress)
+ printf("%s.\n", answer ?
+ _(preen_msg[(int) ptr->prompt]) :
+ _("IGNORED"));
+ if (ctx->logf)
+ fprintf(ctx->logf, "%s.\n", answer ?
+ _(preen_msg[(int) ptr->prompt]) :
+ _("IGNORED"));
+ }
}
if ((ptr->prompt == PROMPT_ABORT) && answer)
return 0;
}
-void print_e2fsck_message(e2fsck_t ctx, const char *msg,
+errcode_t
+profile_get_integer(profile_t profile, const char *name, const char *subname,
+ const char *subsubname, int def_val, int *ret_int)
+{
+ return 0;
+}
+
+void print_e2fsck_message(FILE *f, e2fsck_t ctx, const char *msg,
struct problem_context *pctx, int first,
int recurse)
{
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");