Whamcloud - gitweb
LU-8300 e2fsck: print out FID with dirent inode number
[tools/e2fsprogs.git] / e2fsck / message.c
index 4dab1a4..eca280a 100644 (file)
@@ -32,7 +32,7 @@
  *     %IM     <inode> -> i_mtime
  *     %IF     <inode> -> i_faddr
  *     %If     <inode> -> i_file_acl
- *     %Id     <inode> -> i_dir_acl
+ *     %Id     <inode> -> i_size_high
  *     %Iu     <inode> -> i_uid
  *     %Ig     <inode> -> i_gid
  *     %It     <inode type>
@@ -48,6 +48,9 @@
  *                     the containing directory.
  *     %r      <blkcount>              interpret blkcount as refcount
  *     %s      <str>                   miscellaneous string
+ *     %t      time (in <num>)
+ *     %T      current time
+ *     %U      quota type (in <num>)
  *     %S      backup superblock
  *     %X      <num> hexadecimal format
  *
 #include <string.h>
 #include <ctype.h>
 #include <termios.h>
+#include "support/quotaio.h"
 
 #include "e2fsck.h"
-
 #include "problem.h"
+#include "ext2fs/lfsck.h"
 
 #ifdef __GNUC__
 #define _INLINE_ __inline__
@@ -116,17 +120,17 @@ static const char *abbrevs[] = {
        N_("Bbitmap"),
        N_("ccompress"),
        N_("Cconflicts with some other fs @b"),
-       N_("iinode"),
-       N_("Iillegal"),
-       N_("jjournal"),
-       N_("Ddeleted"),
        N_("ddirectory"),
+       N_("Ddeleted"),
        N_("eentry"),
        N_("E@e '%Dn' in %p (%i)"),
        N_("ffilesystem"),
        N_("Ffor @i %i (%Q) is"),
        N_("ggroup"),
        N_("hHTREE @d @i"),
+       N_("iinode"),
+       N_("Iillegal"),
+       N_("jjournal"),
        N_("llost+found"),
        N_("Lis a link"),
        N_("mmultiply-claimed"),
@@ -168,7 +172,7 @@ static const char *special_inode_name[] =
  * 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)
+static void safe_print(FILE *f, const char *cp, int len)
 {
        unsigned char   ch;
 
@@ -178,14 +182,14 @@ static void safe_print(const char *cp, int len)
        while (len--) {
                ch = *cp++;
                if (ch > 128) {
-                       fputs("M-", stdout);
+                       fputs("M-", f);
                        ch -= 128;
                }
                if ((ch < 32) || (ch == 0x7f)) {
-                       fputc('^', stdout);
+                       fputc('^', f);
                        ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
                }
-               fputc(ch, stdout);
+               fputc(ch, f);
        }
 }
 
@@ -194,42 +198,44 @@ 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, ext2_ino_t dir, ext2_ino_t ino)
+static void print_pathname(FILE *f, ext2_filsys fs, ext2_ino_t dir,
+                          ext2_ino_t ino)
 {
-       errcode_t       retval;
+       errcode_t       retval = 0;
        char            *path;
 
        if (!dir && (ino < num_special_inodes)) {
-               fputs(_(special_inode_name[ino]), stdout);
+               fputs(_(special_inode_name[ino]), f);
                return;
        }
 
        if (fs)
                retval = ext2fs_get_pathname(fs, dir, ino, &path);
        if (!fs || retval)
-               fputs("???", stdout);
+               fputs("???", f);
        else {
-               safe_print(path, -1);
+               safe_print(f, path, -1);
                ext2fs_free_mem(&path);
        }
 }
 
-static void print_time(time_t t)
+static void print_time(FILE *f, time_t t)
 {
        const char *            time_str;
        static int              do_gmt = -1;
 
 #ifdef __dietlibc__
-               /* The diet libc doesn't respect the TZ environemnt variable */
+               /* The diet libc doesn't respect the TZ environment variable */
                if (do_gmt == -1) {
                        time_str = getenv("TZ");
                        if (!time_str)
                                time_str = "";
-                       do_gmt = !strcmp(time_str, "GMT0");
+                       do_gmt = !strcmp(time_str, "GMT") ||
+                               !strcmp(time_str, "GMT0");
                }
 #endif
                time_str = asctime((do_gmt > 0) ? gmtime(&t) : localtime(&t));
-               printf("%.24s", time_str);
+               fprintf(f, "%.24s", time_str);
 }
 
 /*
@@ -237,7 +243,7 @@ static void print_time(time_t t)
  * expansion; an @ expression can contain further '@' and '%'
  * expressions.
  */
-static _INLINE_ void expand_at_expression(e2fsck_t ctx, char ch,
+static _INLINE_ void expand_at_expression(FILE *f, e2fsck_t ctx, char ch,
                                          struct problem_context *pctx,
                                          int *first, int recurse)
 {
@@ -252,17 +258,17 @@ static _INLINE_ void expand_at_expression(e2fsck_t ctx, char ch,
                str = _(*cpp) + 1;
                if (*first && islower(*str)) {
                        *first = 0;
-                       fputc(toupper(*str++), stdout);
+                       fputc(toupper(*str++), f);
                }
-               print_e2fsck_message(ctx, str, pctx, *first, recurse+1);
+               print_e2fsck_message(f, ctx, str, pctx, *first, recurse+1);
        } else
-               printf("@%c", ch);
+               fprintf(f, "@%c", ch);
 }
 
 /*
  * This function expands '%IX' expressions
  */
-static _INLINE_ void expand_inode_expression(ext2_filsys fs, char ch,
+static _INLINE_ void expand_inode_expression(FILE *f, ext2_filsys fs, char ch,
                                             struct problem_context *ctx)
 {
        struct ext2_inode       *inode;
@@ -277,91 +283,107 @@ static _INLINE_ void expand_inode_expression(ext2_filsys fs, char ch,
        switch (ch) {
        case 's':
                if (LINUX_S_ISDIR(inode->i_mode))
-                       printf("%u", inode->i_size);
-               else {
-#ifdef EXT2_NO_64_TYPE
-                       if (inode->i_size_high)
-                               printf("0x%x%08x", inode->i_size_high,
-                                      inode->i_size);
-                       else
-                               printf("%u", inode->i_size);
-#else
-                       printf("%llu", EXT2_I_SIZE(inode));
-#endif
-               }
+                       fprintf(f, "%u", inode->i_size);
+               else
+                       fprintf(f, "%llu", EXT2_I_SIZE(inode));
                break;
        case 'S':
-               printf("%u", large_inode->i_extra_isize);
+               fprintf(f, "%u", large_inode->i_extra_isize);
                break;
        case 'b':
-               if (fs->super->s_feature_ro_compat &
-                   EXT4_FEATURE_RO_COMPAT_HUGE_FILE) 
-                       printf("%llu", inode->i_blocks +
-                              (((long long) inode->osd2.linux2.l_i_blocks_hi)
-                               << 32));
+               if (ext2fs_has_feature_huge_file(fs->super))
+                       fprintf(f, "%llu", inode->i_blocks +
+                               (((long long) inode->osd2.linux2.l_i_blocks_hi)
+                                << 32));
                else
-                       printf("%u", inode->i_blocks);
+                       fprintf(f, "%u", inode->i_blocks);
                break;
        case 'l':
-               printf("%d", inode->i_links_count);
+               fprintf(f, "%d", inode->i_links_count);
                break;
        case 'm':
-               printf("0%o", inode->i_mode);
+               fprintf(f, "0%o", inode->i_mode);
                break;
        case 'M':
-               print_time(inode->i_mtime);
+               print_time(f, inode->i_mtime);
                break;
        case 'F':
-               printf("%u", inode->i_faddr);
+               fprintf(f, "%u", inode->i_faddr);
                break;
        case 'f':
-               printf("%llu", ext2fs_file_acl_block(fs, inode));
+               fprintf(f, "%llu", ext2fs_file_acl_block(fs, inode));
                break;
        case 'd':
-               printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
-                             inode->i_dir_acl : 0));
+               fprintf(f, "%u", (LINUX_S_ISDIR(inode->i_mode) ?
+                       inode->i_size_high : 0));
                break;
        case 'u':
-               printf("%d", inode_uid(*inode));
+               fprintf(f, "%d", inode_uid(*inode));
                break;
        case 'g':
-               printf("%d", inode_gid(*inode));
+               fprintf(f, "%d", inode_gid(*inode));
                break;
        case 't':
                if (LINUX_S_ISREG(inode->i_mode))
-                       printf(_("regular file"));
+                       fputs(_("regular file"), f);
                else if (LINUX_S_ISDIR(inode->i_mode))
-                       printf(_("directory"));
+                       fputs(_("directory"), f);
                else if (LINUX_S_ISCHR(inode->i_mode))
-                       printf(_("character device"));
+                       fputs(_("character device"), f);
                else if (LINUX_S_ISBLK(inode->i_mode))
-                       printf(_("block device"));
+                       fputs(_("block device"), f);
                else if (LINUX_S_ISFIFO(inode->i_mode))
-                       printf(_("named pipe"));
+                       fputs(_("named pipe"), f);
                else if (LINUX_S_ISLNK(inode->i_mode))
-                       printf(_("symbolic link"));
+                       fputs(_("symbolic link"), f);
                else if (LINUX_S_ISSOCK(inode->i_mode))
-                       printf(_("socket"));
+                       fputs(_("socket"), f);
                else
-                       printf(_("unknown file type with mode 0%o"),
-                              inode->i_mode);
+                       fprintf(f, _("unknown file type with mode 0%o"),
+                               inode->i_mode);
                break;
        default:
        no_inode:
-               printf("%%I%c", ch);
+               fprintf(f, "%%I%c", ch);
                break;
        }
 }
 
+const struct lu_fid *get_dirent_fid(struct ext2_dir_entry *dirent)
+{
+       unsigned char *data = (unsigned char *)dirent->name +
+                             (dirent->name_len & EXT2_NAME_LEN) + 1;
+       __u8 file_type = dirent->name_len >> 8;
+       struct lu_fid *fid = NULL;
+       __u8 dirdata_mask;
+
+       for (dirdata_mask = EXT2_FT_MASK + 1;
+            dirdata_mask != 0; dirdata_mask <<= 1) {
+               int dlen;
+
+               if ((dirdata_mask & file_type) == 0)
+                       continue;
+
+               dlen = data[0];
+               if (dirdata_mask == EXT2_DIRENT_LUFID) {
+                       fid = (struct lu_fid *)(data + 1);
+                       fid_be_to_cpu(fid, fid);
+                       break;
+               }
+               data += dlen;
+       }
+
+       return fid;
+}
+
 /*
  * This function expands '%dX' expressions
  */
-static _INLINE_ void expand_dirent_expression(ext2_filsys fs, char ch,
+static _INLINE_ void expand_dirent_expression(FILE *f, ext2_filsys fs, char ch,
                                              struct problem_context *ctx)
 {
        struct ext2_dir_entry   *dirent;
-       unsigned int rec_len;
-       int     len;
+       unsigned int rec_len, len;
 
        if (!ctx || !ctx->dirent)
                goto no_dirent;
@@ -369,35 +391,43 @@ static _INLINE_ void expand_dirent_expression(ext2_filsys fs, char ch,
        dirent = ctx->dirent;
 
        switch (ch) {
-       case 'i':
-               printf("%u", dirent->inode);
+       case 'i': {
+               const struct lu_fid *fid;
+
+               fprintf(f, "%u", dirent->inode);
+
+               fid = get_dirent_fid(dirent);
+               if (fid != NULL)
+                       fprintf(f, " fid="DFID, PFID(fid));
+
                break;
+       }
        case 'n':
-               len = dirent->name_len & 0xFF;
+               len = ext2fs_dirent_name_len(dirent);
                if ((ext2fs_get_rec_len(fs, dirent, &rec_len) == 0) &&
                    (len > rec_len))
                        len = rec_len;
-               safe_print(dirent->name, len);
+               safe_print(f, dirent->name, len);
                break;
        case 'r':
                (void) ext2fs_get_rec_len(fs, dirent, &rec_len);
-               printf("%u", rec_len);
+               fprintf(f, "%u", rec_len);
                break;
        case 'l':
-               printf("%u", dirent->name_len & 0xFF);
+               fprintf(f, "%u", ext2fs_dirent_name_len(dirent));
                break;
        case 't':
-               printf("%u", dirent->name_len >> 8);
+               fprintf(f, "%u", ext2fs_dirent_file_type(dirent));
                break;
        default:
        no_dirent:
-               printf("%%D%c", ch);
+               fprintf(f, "%%D%c", ch);
                break;
        }
 }
 
-static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
-                                              int *first,
+static _INLINE_ void expand_percent_expression(FILE *f, ext2_filsys fs,
+                                              char ch, int width, int *first,
                                               struct problem_context *ctx)
 {
        e2fsck_t e2fsck_ctx = fs ? (e2fsck_t) fs->priv_data : NULL;
@@ -408,14 +438,10 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
 
        switch (ch) {
        case '%':
-               fputc('%', stdout);
+               fputc('%', f);
                break;
        case 'b':
-#ifdef EXT2_NO_64_TYPE
-               printf("%u", (unsigned long) ctx->blk);
-#else
-               printf("%llu", (unsigned long long) ctx->blk);
-#endif
+               fprintf(f, "%*llu", width, (unsigned long long) ctx->blk);
                break;
        case 'B':
                if (ctx->blkcount == BLOCK_COUNT_IND)
@@ -429,118 +455,136 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
                else
                        m = _("block #");
                if (*first && islower(m[0]))
-                       fputc(toupper(*m++), stdout);
-               fputs(m, stdout);
-               if (ctx->blkcount >= 0) {
-#ifdef EXT2_NO_64_TYPE
-                       printf("%d", ctx->blkcount);
-#else
-                       printf("%lld", (long long) ctx->blkcount);
-#endif
-               }
+                       fputc(toupper(*m++), f);
+               fputs(m, f);
+               if (ctx->blkcount >= 0)
+                       fprintf(f, "%lld", (long long) ctx->blkcount);
                break;
        case 'c':
-#ifdef EXT2_NO_64_TYPE
-               printf("%u", (unsigned long) ctx->blk2);
-#else
-               printf("%llu", (unsigned long long) ctx->blk2);
-#endif
+               fprintf(f, "%*llu", width, (unsigned long long) ctx->blk2);
                break;
        case 'd':
-               printf("%u", ctx->dir);
+               fprintf(f, "%*u", width, ctx->dir);
                break;
        case 'g':
-               printf("%d", ctx->group);
+               fprintf(f, "%*u", width, ctx->group);
                break;
        case 'i':
-               printf("%u", ctx->ino);
+               fprintf(f, "%*u", width, ctx->ino);
                break;
        case 'j':
-               printf("%u", ctx->ino2);
+               fprintf(f, "%*u", width, ctx->ino2);
                break;
        case 'm':
-               printf("%s", error_message(ctx->errcode));
+               fprintf(f, "%*s", width, error_message(ctx->errcode));
                break;
        case 'N':
-#ifdef EXT2_NO_64_TYPE
-               printf("%u", ctx->num);
-#else
-               printf("%llu", (long long)ctx->num);
-#endif
+               fprintf(f, "%*llu", width, (long long)ctx->num);
+               break;
+       case 'n':
+               fprintf(f, "%*llu", width, (long long)ctx->num2);
                break;
        case 'p':
-               print_pathname(fs, ctx->ino, 0);
+               print_pathname(f, fs, ctx->ino, 0);
                break;
        case 'P':
-               print_pathname(fs, ctx->ino2,
+               print_pathname(f, fs, ctx->ino2,
                               ctx->dirent ? ctx->dirent->inode : 0);
                break;
        case 'q':
-               print_pathname(fs, ctx->dir, 0);
+               print_pathname(f, fs, ctx->dir, 0);
                break;
        case 'Q':
-               print_pathname(fs, ctx->dir, ctx->ino);
+               print_pathname(f, fs, ctx->dir, ctx->ino);
                break;
        case 'r':
-#ifdef EXT2_NO_64_TYPE
-               printf("%d", ctx->blkcount);
-#else
-               printf("%lld", (long long) ctx->blkcount);
-#endif
+               fprintf(f, "%*lld", width, (long long) ctx->blkcount);
                break;
        case 'S':
-               printf("%u", get_backup_sb(NULL, fs, NULL, NULL));
+               fprintf(f, "%llu", get_backup_sb(NULL, fs, NULL, NULL));
                break;
        case 's':
-               printf("%s", ctx->str ? ctx->str : "NULL");
+               fprintf(f, "%*s", width, ctx->str ? ctx->str : "NULL");
                break;
        case 't':
-               print_time((time_t) ctx->num);
+               print_time(f, (time_t) ctx->num);
                break;
        case 'T':
-               print_time(e2fsck_ctx ? e2fsck_ctx->now : time(0));
+               print_time(f, e2fsck_ctx ? e2fsck_ctx->now : time(0));
+               break;
+       case 'U':
+               switch (ctx->num) {
+               case USRQUOTA:
+                       m = _("user");
+                       break;
+               case GRPQUOTA:
+                       m = _("group");
+                       break;
+               case PRJQUOTA:
+                       m = _("project");
+                       break;
+               default:
+                       m = _("unknown quota type");
+                       break;
+               }
+               if (*first && islower(m[0]))
+                       fputc(toupper(*m++), f);
+               fputs(m, f);
+               if (ctx->num > PRJQUOTA)
+                       fprintf(f, " %d", (int) ctx->num);
+               break;
+       case 'x':
+               fprintf(f, "0x%0*x", width, ctx->csum1);
                break;
        case 'X':
-#ifdef EXT2_NO_64_TYPE
-               printf("0x%x", ctx->num);
-#else
-               printf("0x%llx", (long long)ctx->num);
-#endif
+               fprintf(f, "0x%0*llx", width, (long long)ctx->num);
+               break;
+       case 'y':
+               fprintf(f, "0x%0*x", width, ctx->csum2);
                break;
        default:
        no_context:
-               printf("%%%c", ch);
+               fprintf(f, "%%%c", ch);
                break;
        }
 }
 
-void print_e2fsck_message(e2fsck_t ctx, const char *msg,
+void print_e2fsck_message(FILE *f, e2fsck_t ctx, const char *msg,
                          struct problem_context *pctx, int first,
                          int recurse)
 {
        ext2_filsys fs = ctx->fs;
        const char *    cp;
-       int             i;
+       int             i, width;
 
        e2fsck_clear_progbar(ctx);
        for (cp = msg; *cp; cp++) {
                if (cp[0] == '@') {
                        cp++;
-                       expand_at_expression(ctx, *cp, pctx, &first, recurse);
-               } else if (cp[0] == '%' && cp[1] == 'I') {
-                       cp += 2;
-                       expand_inode_expression(fs, *cp, pctx);
-               } else if (cp[0] == '%' && cp[1] == 'D') {
-                       cp += 2;
-                       expand_dirent_expression(fs, *cp, pctx);
-               } else if ((cp[0] == '%')) {
+                       expand_at_expression(f, ctx, *cp, pctx, &first,
+                                            recurse);
+               } else if (cp[0] == '%') {
                        cp++;
-                       expand_percent_expression(fs, *cp, &first, pctx);
+                       width = 0;
+                       while (isdigit(cp[0])) {
+                               width = (width * 10) + cp[0] - '0';
+                               cp++;
+                       }
+                       if (cp[0] == 'I') {
+                               cp++;
+                               expand_inode_expression(f, fs, *cp, pctx);
+                       } else if (cp[0] == 'D') {
+                               cp++;
+                               expand_dirent_expression(f, fs, *cp, pctx);
+                       } else {
+                               expand_percent_expression(f, fs, *cp, width,
+                                                         &first, pctx);
+                       }
                } else {
                        for (i=0; cp[i]; i++)
                                if ((cp[i] == '@') || cp[i] == '%')
                                        break;
-                       printf("%.*s", i, cp);
+                       fprintf(f, "%.*s", i, cp);
                        cp += i-1;
                }
                first = 0;