Whamcloud - gitweb
e2fsck: allow deleting or zeroing shared blocks
[tools/e2fsprogs.git] / e2fsck / message.c
index d560cf8..980dc4b 100644 (file)
@@ -76,6 +76,7 @@
  *     @n      invalid
  *     @o      orphaned
  *     @p      problem in
+ *     @q      quota
  *     @r      root inode
  *     @s      should be
  *     @S      superblock
@@ -85,6 +86,7 @@
  *     @z      zero-length
  */
 
+#include "config.h"
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
@@ -131,6 +133,7 @@ static const char *abbrevs[] = {
        N_("ninvalid"),
        N_("oorphaned"),
        N_("pproblem in"),
+       N_("qquota"),
        N_("rroot @i"),
        N_("sshould be"),
        N_("Ssuper@b"),
@@ -165,7 +168,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;
 
@@ -175,14 +178,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);
        }
 }
 
@@ -191,26 +194,28 @@ 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;
        char            *path;
 
        if (!dir && (ino < num_special_inodes)) {
-               fputs(_(special_inode_name[ino]), stdout);
+               fputs(_(special_inode_name[ino]), f);
                return;
        }
 
-       retval = ext2fs_get_pathname(fs, dir, ino, &path);
-       if (retval)
-               fputs("???", stdout);
+       if (fs)
+               retval = ext2fs_get_pathname(fs, dir, ino, &path);
+       if (!fs || retval)
+               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;
@@ -225,7 +230,7 @@ static void print_time(time_t t)
                }
 #endif
                time_str = asctime((do_gmt > 0) ? gmtime(&t) : localtime(&t));
-               printf("%.24s", time_str);
+               fprintf(f, "%.24s", time_str);
 }
 
 /*
@@ -233,7 +238,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)
 {
@@ -248,17 +253,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;
@@ -273,79 +278,78 @@ 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);
+                       fprintf(f, "%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);
+                               fprintf(f, "0x%x%08x", inode->i_size_high,
+                                       inode->i_size);
                        else
-                               printf("%u", inode->i_size);
+                               fprintf(f, "%u", inode->i_size);
 #else
-                       printf("%llu", inode->i_size |
-                                      ((long long)inode->i_size_high << 32));
+                       fprintf(f, "%llu", EXT2_I_SIZE(inode));
 #endif
                }
                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));
+                       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(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_dir_acl : 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;
        }
 }
@@ -353,7 +357,7 @@ static _INLINE_ void expand_inode_expression(ext2_filsys fs, char ch,
 /*
  * 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;
@@ -367,36 +371,34 @@ static _INLINE_ void expand_dirent_expression(ext2_filsys fs, char ch,
 
        switch (ch) {
        case 'i':
-               printf("%u", dirent->inode);
+               fprintf(f, "%u", dirent->inode);
                break;
        case 'n':
                len = dirent->name_len & 0xFF;
-               if (len > EXT2_NAME_LEN)
-                       len = EXT2_NAME_LEN;
                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", dirent->name_len & 0xFF);
                break;
        case 't':
-               printf("%u", dirent->name_len >> 8);
+               fprintf(f, "%u", dirent->name_len >> 8);
                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;
@@ -407,13 +409,13 @@ 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);
+               fprintf(f, "%*u", width, (unsigned long) ctx->blk);
 #else
-               printf("%llu", (unsigned long long) ctx->blk);
+               fprintf(f, "%*llu", width, (unsigned long long) ctx->blk);
 #endif
                break;
        case 'B':
@@ -428,118 +430,133 @@ 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);
+                       fputc(toupper(*m++), f);
+               fputs(m, f);
                if (ctx->blkcount >= 0) {
 #ifdef EXT2_NO_64_TYPE
-                       printf("%d", ctx->blkcount);
+                       fprintf(f, "%d", ctx->blkcount);
 #else
-                       printf("%lld", (long long) ctx->blkcount);
+                       fprintf(f, "%lld", (long long) ctx->blkcount);
 #endif
                }
                break;
        case 'c':
 #ifdef EXT2_NO_64_TYPE
-               printf("%u", (unsigned long) ctx->blk2);
+               fprintf(f, "%*u", width, (unsigned long) ctx->blk2);
 #else
-               printf("%llu", (unsigned long long) ctx->blk2);
+               fprintf(f, "%*llu", width, (unsigned long long) ctx->blk2);
 #endif
                break;
        case 'd':
-               printf("%u", ctx->dir);
+               fprintf(f, "%*u", width, ctx->dir);
                break;
        case 'g':
-               printf("%d", ctx->group);
+               fprintf(f, "%*d", 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);
+               fprintf(f, "%*u", width, ctx->num);
 #else
-               printf("%llu", (long long)ctx->num);
+               fprintf(f, "%*llu", width, (long long)ctx->num);
 #endif
                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);
+               fprintf(f, "%*d", width, ctx->blkcount);
 #else
-               printf("%lld", (long long) ctx->blkcount);
+               fprintf(f, "%*lld", width, (long long) ctx->blkcount);
 #endif
                break;
        case 'S':
-               printf("%u", get_backup_sb(NULL, fs, NULL, NULL));
+               fprintf(f, "%u", 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 'x':
+               fprintf(f, "0x%0*x", width, ctx->csum1);
                break;
        case 'X':
 #ifdef EXT2_NO_64_TYPE
-               printf("0x%x", ctx->num);
+               fprintf(f, "0x%0*x", width, ctx->num);
 #else
-               printf("0x%llx", (long long)ctx->num);
+               fprintf(f, "0x%0*llx", width, (long long)ctx->num);
 #endif
                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;