* %b <blk> block number
* %B <blkcount> integer
* %c <blk2> block number
- * %di <dirent>->ino inode number
- * %dn <dirent>->name string
- * %dr <dirent>->rec_len
- * %dl <dirent>->name_len
- * %dt <dirent>->filetype
- * %D <dir> inode number
+ * %Di <dirent>->ino inode number
+ * %Dn <dirent>->name string
+ * %Dr <dirent>->rec_len
+ * %Dl <dirent>->name_len
+ * %Dt <dirent>->filetype
+ * %d <dir> inode number
* %g <group> integer
* %i <ino> inode number
* %Is <inode> -> i_size
+ * %IS <inode> -> i_extra_isize
* %Ib <inode> -> i_blocks
* %Il <inode> -> i_links_count
* %Im <inode> -> i_mode
* %IF <inode> -> i_faddr
* %If <inode> -> i_file_acl
* %Id <inode> -> i_dir_acl
+ * %Iu <inode> -> i_uid
+ * %Ig <inode> -> i_gid
+ * %It <inode type>
* %j <ino2> inode number
* %m <com_err error message>
* %N <num>
* the containing directory.
* %s <str> miscellaneous string
* %S backup superblock
+ * %X <num> hexadecimal format
*
* The following '@' expansions are supported:
*
+ * @a extended attribute
* @A error allocating
* @b block
* @B bitmap
+ * @c compress
* @C conflicts with some other fs block
- * @i inode
- * @I illegal
* @D deleted
* @d directory
* @e entry
* @f filesystem
* @F for @i %i (%Q) is
* @g group
+ * @h HTREE directory inode
+ * @i inode
+ * @I illegal
+ * @j journal
* @l lost+found
* @L is a link
- * @u unattached
+ * @m multiply-claimed
+ * @n invalid
+ * @o orphaned
+ * @p problem in
* @r root inode
- * @s should be
+ * @s should be
* @S superblock
+ * @u unattached
+ * @v device
+ * @x extent
* @z zero-length
*/
* letter <i> in the table below.
*/
static const char *abbrevs[] = {
- "Aerror allocating",
- "bblock",
- "Bbitmap",
- "Cconflicts with some other fs @b",
- "iinode",
- "Iillegal",
- "Ddeleted",
- "ddirectory",
- "eentry",
- "E@e '%Dn' in %p (%i)",
- "ffilesystem",
- "Ffor @i %i (%Q) is",
- "ggroup",
- "llost+found",
- "Lis a link",
- "uunattached",
- "rroot @i",
- "sshould be",
- "Ssuper@b",
- "zzero-length",
+ N_("aextended attribute"),
+ N_("Aerror allocating"),
+ N_("bblock"),
+ N_("Bbitmap"),
+ N_("ccompress"),
+ N_("Cconflicts with some other fs @b"),
+ N_("iinode"),
+ N_("Iillegal"),
+ N_("jjournal"),
+ N_("Ddeleted"),
+ N_("ddirectory"),
+ N_("eentry"),
+ N_("E@e '%Dn' in %p (%i)"),
+ N_("ffilesystem"),
+ N_("Ffor @i %i (%Q) is"),
+ N_("ggroup"),
+ N_("hHTREE @d @i"),
+ N_("llost+found"),
+ N_("Lis a link"),
+ N_("mmultiply-claimed"),
+ N_("ninvalid"),
+ N_("oorphaned"),
+ N_("pproblem in"),
+ N_("rroot @i"),
+ N_("sshould be"),
+ N_("Ssuper@b"),
+ N_("uunattached"),
+ N_("vdevice"),
+ N_("xextent"),
+ N_("zzero-length"),
"@@",
0
};
/*
* Give more user friendly names to the "special" inodes.
*/
-#define num_special_inodes 7
+#define num_special_inodes 11
static const char *special_inode_name[] =
{
- "<The NULL inode>", /* 0 */
- "<The bad blocks inode>", /* 1 */
+ N_("<The NULL inode>"), /* 0 */
+ N_("<The bad blocks inode>"), /* 1 */
"/", /* 2 */
- "<The ACL index inode>", /* 3 */
- "<The ACL data inode>", /* 4 */
- "<The boot loader inode>", /* 5 */
- "<The undelete directory inode>" /* 6 */
+ N_("<The ACL index inode>"), /* 3 */
+ N_("<The ACL data inode>"), /* 4 */
+ N_("<The boot loader inode>"), /* 5 */
+ N_("<The undelete directory inode>"), /* 6 */
+ N_("<The group descriptor inode>"), /* 7 */
+ N_("<The journal inode>"), /* 8 */
+ N_("<Reserved inode 9>"), /* 9 */
+ N_("<Reserved inode 10>"), /* 10 */
};
/*
fputs("M-", stdout);
ch -= 128;
}
- if (ch < 32) {
+ if ((ch < 32) || (ch == 0x7f)) {
fputc('^', stdout);
- ch += 32;
+ ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
}
fputc(ch, stdout);
}
* This function prints a pathname, using the ext2fs_get_pathname
* function
*/
-static void print_pathname(ext2_filsys fs, ino_t dir, ino_t ino)
+static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
{
errcode_t retval;
char *path;
if (!dir && (ino < num_special_inodes)) {
- fputs(special_inode_name[ino], stdout);
+ fputs(_(special_inode_name[ino]), stdout);
return;
}
-
+
retval = ext2fs_get_pathname(fs, dir, ino, &path);
if (retval)
fputs("???", stdout);
else {
safe_print(path, -1);
- ext2fs_free_mem((void **) &path);
+ ext2fs_free_mem(&path);
}
}
/*
* This function handles the '@' expansion. We allow recursive
* expansion; an @ expression can contain further '@' and '%'
- * expressions.
+ * expressions.
*/
static _INLINE_ void expand_at_expression(e2fsck_t ctx, char ch,
struct problem_context *pctx,
- int *first)
+ int *first, int recurse)
{
const char **cpp, *str;
-
+
/* Search for the abbreviation */
for (cpp = abbrevs; *cpp; cpp++) {
if (ch == *cpp[0])
break;
}
- if (*cpp) {
- str = (*cpp) + 1;
+ if (*cpp && recurse < 10) {
+ str = _(*cpp) + 1;
if (*first && islower(*str)) {
*first = 0;
fputc(toupper(*str++), stdout);
}
- print_e2fsck_message(ctx, str, pctx, *first);
+ print_e2fsck_message(ctx, str, pctx, *first, recurse+1);
} else
printf("@%c", ch);
}
/*
- * This function expands '%kX' expressions
+ * This function expands '%IX' expressions
*/
static _INLINE_ void expand_inode_expression(char ch,
- struct problem_context *ctx)
+ struct problem_context *ctx)
{
struct ext2_inode *inode;
- char * time_str;
+ struct ext2_inode_large *large_inode;
+ const char * time_str;
time_t t;
+ static int do_gmt = -1;
if (!ctx || !ctx->inode)
goto no_inode;
-
+
inode = ctx->inode;
-
+ large_inode = (struct ext2_inode_large *) inode;
+
switch (ch) {
case 's':
if (LINUX_S_ISDIR(inode->i_mode))
else
printf("%u", inode->i_size);
#else
- printf("%llu", (inode->i_size |
- ((__u64) inode->i_size_high << 32)));
+ printf("%llu", inode->i_size |
+ ((long long)inode->i_size_high << 32));
#endif
}
break;
+ case 'S':
+ printf("%u", large_inode->i_extra_isize);
+ break;
case 'b':
- printf("%u", inode->i_blocks);
+ if (inode->i_flags & EXT4_HUGE_FILE_FL)
+ printf("%llu", inode->i_blocks +
+ (((long long) inode->osd2.linux2.l_i_blocks_hi)
+ << 32));
+ else
+ printf("%u", inode->i_blocks);
break;
case 'l':
printf("%d", inode->i_links_count);
printf("0%o", inode->i_mode);
break;
case 'M':
+#ifdef __dietlibc__
+ /* The diet libc doesn't respect the TZ environemnt variable */
+ if (do_gmt == -1) {
+ time_str = getenv("TZ");
+ if (!time_str)
+ time_str = "";
+ do_gmt = !strcmp(time_str, "GMT0");
+ }
+#endif
t = inode->i_mtime;
- time_str = ctime(&t);
+ time_str = asctime((do_gmt > 0) ? gmtime(&t) : localtime(&t));
printf("%.24s", time_str);
break;
case 'F':
printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
inode->i_dir_acl : 0));
break;
+ case 'u':
+ printf("%d", inode_uid(*inode));
+ break;
+ case 'g':
+ printf("%d", inode_gid(*inode));
+ break;
+ case 't':
+ if (LINUX_S_ISREG(inode->i_mode))
+ printf(_("regular file"));
+ else if (LINUX_S_ISDIR(inode->i_mode))
+ printf(_("directory"));
+ else if (LINUX_S_ISCHR(inode->i_mode))
+ printf(_("character device"));
+ else if (LINUX_S_ISBLK(inode->i_mode))
+ printf(_("block device"));
+ else if (LINUX_S_ISFIFO(inode->i_mode))
+ printf(_("named pipe"));
+ else if (LINUX_S_ISLNK(inode->i_mode))
+ printf(_("symbolic link"));
+ else if (LINUX_S_ISSOCK(inode->i_mode))
+ printf(_("socket"));
+ else
+ printf(_("unknown file type with mode 0%o"),
+ inode->i_mode);
+ break;
default:
no_inode:
printf("%%I%c", ch);
/*
* This function expands '%dX' expressions
*/
-static _INLINE_ void expand_dirent_expression(char ch,
+static _INLINE_ void expand_dirent_expression(ext2_filsys fs, char ch,
struct problem_context *ctx)
{
struct ext2_dir_entry *dirent;
+ unsigned int rec_len;
int len;
-
+
if (!ctx || !ctx->dirent)
goto no_dirent;
-
+
dirent = ctx->dirent;
-
+
switch (ch) {
case 'i':
printf("%u", dirent->inode);
len = dirent->name_len & 0xFF;
if (len > EXT2_NAME_LEN)
len = EXT2_NAME_LEN;
- if (len > dirent->rec_len)
- len = dirent->rec_len;
+ if ((ext2fs_get_rec_len(fs, dirent, &rec_len) == 0) &&
+ (len > rec_len))
+ len = rec_len;
safe_print(dirent->name, len);
break;
case 'r':
- printf("%u", dirent->rec_len);
+ (void) ext2fs_get_rec_len(fs, dirent, &rec_len);
+ printf("%u", rec_len);
break;
case 'l':
printf("%u", dirent->name_len & 0xFF);
{
if (!ctx)
goto no_context;
-
+
switch (ch) {
case '%':
fputc('%', stdout);
break;
case 'b':
- printf("%u", ctx->blk);
+#ifdef EXT2_NO_64_TYPE
+ printf("%u", (unsigned long) ctx->blk);
+#else
+ printf("%llu", (unsigned long long) ctx->blk);
+#endif
break;
case 'B':
#ifdef EXT2_NO_64_TYPE
printf("%d", ctx->blkcount);
#else
- printf("%lld", ctx->blkcount);
+ printf("%lld", (long long)ctx->blkcount);
#endif
break;
case 'c':
- printf("%u", ctx->blk2);
+#ifdef EXT2_NO_64_TYPE
+ printf("%u", (unsigned long) ctx->blk2);
+#else
+ printf("%llu", (unsigned long long) ctx->blk2);
+#endif
break;
case 'd':
- printf("%lu", ctx->dir);
+ printf("%u", ctx->dir);
break;
case 'g':
printf("%d", ctx->group);
break;
case 'i':
- printf("%lu", ctx->ino);
+ printf("%u", ctx->ino);
break;
case 'j':
- printf("%lu", ctx->ino2);
+ printf("%u", ctx->ino2);
break;
case 'm':
printf("%s", error_message(ctx->errcode));
#ifdef EXT2_NO_64_TYPE
printf("%u", ctx->num);
#else
- printf("%llu", ctx->num);
+ printf("%llu", (long long)ctx->num);
#endif
break;
case 'p':
print_pathname(fs, ctx->dir, ctx->ino);
break;
case 'S':
- printf("%d", get_backup_sb(fs));
+ printf("%u", get_backup_sb(NULL, fs, NULL, NULL));
break;
case 's':
- printf("%s", ctx->str);
+ printf("%s", ctx->str ? ctx->str : "NULL");
+ break;
+ case 'X':
+#ifdef EXT2_NO_64_TYPE
+ printf("0x%x", ctx->num);
+#else
+ printf("0x%llx", (long long)ctx->num);
+#endif
break;
default:
no_context:
printf("%%%c", ch);
break;
}
-}
+}
void print_e2fsck_message(e2fsck_t ctx, const char *msg,
- struct problem_context *pctx, int first)
+ struct problem_context *pctx, int first,
+ int recurse)
{
ext2_filsys fs = ctx->fs;
const char * cp;
for (cp = msg; *cp; cp++) {
if (cp[0] == '@') {
cp++;
- expand_at_expression(ctx, *cp, pctx, &first);
+ expand_at_expression(ctx, *cp, pctx, &first, recurse);
} else if (cp[0] == '%' && cp[1] == 'I') {
cp += 2;
expand_inode_expression(*cp, pctx);
} else if (cp[0] == '%' && cp[1] == 'D') {
cp += 2;
- expand_dirent_expression(*cp, pctx);
+ expand_dirent_expression(fs, *cp, pctx);
} else if ((cp[0] == '%')) {
cp++;
expand_percent_expression(fs, *cp, pctx);