Whamcloud - gitweb
e2fsck: optimize loop counter when fixing bitmap padding
[tools/e2fsprogs.git] / e2fsck / message.c
index 87ce118..3f85916 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
- *     %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
@@ -32,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
        };
@@ -119,16 +144,20 @@ 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 */
 };
 
 /*
@@ -148,9 +177,9 @@ static void safe_print(const char *cp, int len)
                        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);
        }
@@ -161,67 +190,70 @@ static void safe_print(const char *cp, int len)
  * 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))
@@ -234,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);
@@ -249,8 +289,17 @@ static _INLINE_ void expand_inode_expression(char ch,
                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':
@@ -263,6 +312,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);
@@ -273,17 +347,18 @@ static _INLINE_ void expand_inode_expression(char 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);
@@ -292,12 +367,14 @@ static _INLINE_ void expand_dirent_expression(char ch,
                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);
@@ -317,35 +394,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));
@@ -354,7 +439,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':
@@ -371,20 +456,28 @@ 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;
@@ -394,13 +487,13 @@ void print_e2fsck_message(e2fsck_t ctx, const char *msg,
        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);