Whamcloud - gitweb
Remove trailing whitespace for the entire source tree
[tools/e2fsprogs.git] / e2fsck / message.c
index c839bbf..f79b73c 100644 (file)
  *     %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
- *     %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
@@ -31,6 +33,9 @@
  *     %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
        };
@@ -118,83 +144,116 @@ static const char *abbrevs[] = {
 /*
  * 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 */
 };
 
 /*
+ * This function does "safe" printing.  It will convert non-printable
+ * ASCII characters using '^' and M- notation.
+ */
+static void safe_print(const char *cp, int len)
+{
+       unsigned char   ch;
+
+       if (len < 0)
+               len = strlen(cp);
+
+       while (len--) {
+               ch = *cp++;
+               if (ch > 128) {
+                       fputs("M-", stdout);
+                       ch -= 128;
+               }
+               if ((ch < 32) || (ch == 0x7f)) {
+                       fputc('^', stdout);
+                       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 {
-               fputs(path, stdout);
-               ext2fs_free_mem((void **) &path);
+               safe_print(path, -1);
+               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;
+       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))
@@ -207,13 +266,21 @@ static _INLINE_ void expand_inode_expression(char ch,
                        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);
@@ -222,8 +289,15 @@ static _INLINE_ void expand_inode_expression(char ch,
                printf("0%o", inode->i_mode);
                break;
        case 'M':
+               /* 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, "GMT");
+               }
                t = inode->i_mtime;
-               time_str = ctime(&t);
+               time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
                printf("%.24s", time_str);
                break;
        case 'F':
@@ -236,6 +310,31 @@ static _INLINE_ void expand_inode_expression(char ch,
                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);
@@ -251,12 +350,12 @@ static _INLINE_ void expand_dirent_expression(char ch,
 {
        struct ext2_dir_entry   *dirent;
        int     len;
-       
+
        if (!ctx || !ctx->dirent)
                goto no_dirent;
-       
+
        dirent = ctx->dirent;
-       
+
        switch (ch) {
        case 'i':
                printf("%u", dirent->inode);
@@ -267,7 +366,7 @@ static _INLINE_ void expand_dirent_expression(char ch,
                        len = EXT2_NAME_LEN;
                if (len > dirent->rec_len)
                        len = dirent->rec_len;
-               printf("%.*s", len, dirent->name);
+               safe_print(dirent->name, len);
                break;
        case 'r':
                printf("%u", dirent->rec_len);
@@ -275,6 +374,9 @@ static _INLINE_ void expand_dirent_expression(char ch,
        case 'l':
                printf("%u", dirent->name_len & 0xFF);
                break;
+       case 't':
+               printf("%u", dirent->name_len >> 8);
+               break;
        default:
        no_dirent:
                printf("%%D%c", ch);
@@ -287,35 +389,43 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
 {
        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));
@@ -324,7 +434,7 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
 #ifdef EXT2_NO_64_TYPE
                printf("%u", ctx->num);
 #else
-               printf("%llu", ctx->num);
+               printf("%llu", (long long)ctx->num);
 #endif
                break;
        case 'p':
@@ -341,29 +451,38 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
                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;
        int             i;
-       
+
+       e2fsck_clear_progbar(ctx);
        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);